Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb56955fff | ||
|
|
cbb7cc93e9 | ||
|
|
8b608c5cce | ||
|
|
163fb14d0e | ||
|
|
e4f87bd805 | ||
|
|
864c7d96f1 | ||
|
|
e35e87fb05 | ||
|
|
3246bdbc8b | ||
|
|
710bb5fe1c | ||
|
|
53a52da709 | ||
|
|
4afbfc6e57 | ||
|
|
f7aa9efe13 | ||
|
|
1fce0ee551 | ||
|
|
ee695f9000 | ||
|
|
8f99ebb577 | ||
|
|
5bfafaf241 | ||
|
|
64e1a2ce4b | ||
|
|
27883c5beb | ||
|
|
2772725fe3 | ||
|
|
3f58a64827 | ||
|
|
cb37c7d218 | ||
|
|
45d951071f | ||
|
|
2ac60684fa | ||
|
|
af71742110 | ||
|
|
1adf27427a | ||
|
|
082f78eefa | ||
|
|
a8a9ec0023 | ||
|
|
df4f945bc6 | ||
|
|
ad756a5b86 | ||
|
|
2ca99ba669 | ||
|
|
6443575114 | ||
|
|
52a51d81f1 | ||
|
|
7d20b06e52 | ||
|
|
ad9d8a7200 | ||
|
|
44da699343 | ||
|
|
0a542f9be9 | ||
|
|
8f1601ca55 | ||
|
|
ff0ce164da | ||
|
|
3650c38aa9 | ||
|
|
61d97338e2 | ||
|
|
e27bb4de50 | ||
|
|
4462d8bf22 | ||
|
|
f23a8ac928 | ||
|
|
9e1750ee13 | ||
|
|
5cd284cb36 | ||
|
|
5ea58430fe | ||
|
|
acfbda0d91 | ||
|
|
437e5a62f1 | ||
|
|
bbb5aea77d | ||
|
|
b5d04f84e7 | ||
|
|
93b12eb14f | ||
|
|
0aa67c4cf2 | ||
|
|
1c1affac5c | ||
|
|
0919797edc | ||
|
|
94ac8fd837 | ||
|
|
ecc82b5b51 | ||
|
|
add021fd67 | ||
|
|
2daf309d7d | ||
|
|
20be4a40ea | ||
|
|
7de91da87a | ||
|
|
b8b48b533b | ||
|
|
535f981739 | ||
|
|
0404ac0395 | ||
|
|
f961625f03 | ||
|
|
7909bae065 | ||
|
|
7e6e117b17 | ||
|
|
314e64d7b1 | ||
|
|
77eb6b358f | ||
|
|
25f86e2542 | ||
|
|
8bc0461463 | ||
|
|
c9dd1ea71d | ||
|
|
85d3529bc3 | ||
|
|
3aac8bb072 | ||
|
|
e9a7e21aca | ||
|
|
fc0e4da33c | ||
|
|
ef3c1315dd | ||
|
|
5c12890faf | ||
|
|
c4fd5e0999 | ||
|
|
d3c56d635d | ||
|
|
c53cb49034 | ||
|
|
d38463c5d9 | ||
|
|
bc4b424f0e | ||
|
|
6bd4f3b7b4 | ||
|
|
d91d83f115 | ||
|
|
584b6ab219 | ||
|
|
04b155dbfb | ||
|
|
ddc5488db7 | ||
|
|
5c6906d5fd | ||
|
|
56fee5d286 | ||
|
|
c4dcab04b6 | ||
|
|
8dd9a96769 | ||
|
|
6864015af6 | ||
|
|
ebaa60e929 | ||
|
|
ac9962c624 | ||
|
|
ccd1773643 | ||
|
|
ac970ff768 | ||
|
|
53ff45425d | ||
|
|
de435c741f | ||
|
|
1dc9a44aec | ||
|
|
0206379315 | ||
|
|
c39adbbbc5 | ||
|
|
061a15d4f7 | ||
|
|
7c2518f027 | ||
|
|
a07459454b | ||
|
|
752f9d2694 | ||
|
|
0a180f9e20 | ||
|
|
6fff2e1c2f | ||
|
|
4266900d2e | ||
|
|
a2a1d84bc0 | ||
|
|
7648c562f1 | ||
|
|
403fd30926 | ||
|
|
17ccddf541 | ||
|
|
c24366fcec | ||
|
|
9a258a6265 | ||
|
|
4542ccbdc2 | ||
|
|
41d8ad2b86 | ||
|
|
a3a2ee118e | ||
|
|
f285efc277 | ||
|
|
fbaf87ec6c | ||
|
|
a005a468a7 | ||
|
|
c8d01549ba | ||
|
|
23af4505dd | ||
|
|
53cb6a5b3e | ||
|
|
765384ace1 | ||
|
|
d39e3e2f69 | ||
|
|
d75124066e | ||
|
|
f4400876da | ||
|
|
c222c5127f | ||
|
|
90d04956e6 | ||
|
|
5d3b918339 | ||
|
|
eba0091764 | ||
|
|
7999cbbea3 | ||
|
|
cee7987b35 | ||
|
|
d475c08024 | ||
|
|
d78f83ae49 | ||
|
|
df694f01e7 | ||
|
|
f5d9cbb11b | ||
|
|
d802588abe | ||
|
|
927d6d2fc6 | ||
|
|
bab7595078 | ||
|
|
1ea9a6c57f | ||
|
|
f479d415d8 | ||
|
|
f41e7be726 | ||
|
|
c1fe28124f | ||
|
|
01a1e506e4 | ||
|
|
e61aebb55d | ||
|
|
bae5bafc62 | ||
|
|
be6cb266de | ||
|
|
6f72edc2d9 | ||
|
|
29f66bdfed | ||
|
|
c1c6f5682c | ||
|
|
a8a74a0246 | ||
|
|
f9b867c3eb | ||
|
|
6c07f9a048 | ||
|
|
573e0acafa | ||
|
|
530c664967 | ||
|
|
12c29c8387 | ||
|
|
6c7f61d90f | ||
|
|
eb6d8d0bb3 | ||
|
|
ef462973c7 | ||
|
|
aa7e49cfde | ||
|
|
186048676a | ||
|
|
0f40721cff | ||
|
|
3799dd92fd | ||
|
|
9ea1a2b1de | ||
|
|
d8b27d122e | ||
|
|
15c3a6eae4 | ||
|
|
4fcc90d53e | ||
|
|
2619a50976 | ||
|
|
de116c95d4 | ||
|
|
47594c9b07 | ||
|
|
1b9098b564 | ||
|
|
b0306eac87 | ||
|
|
125e813d25 | ||
|
|
8e0d4a70f2 | ||
|
|
0556fc68b0 | ||
|
|
e9e2313159 | ||
|
|
dbb2f03a43 | ||
|
|
ed0dc2d887 | ||
|
|
0a93f2d0b0 | ||
|
|
fd581cd65c | ||
|
|
36702bc971 | ||
|
|
0fc3eb38f1 | ||
|
|
73c8e945e9 | ||
|
|
b8420303ba | ||
|
|
532bfcf937 | ||
|
|
f6d892023e | ||
|
|
7f2977f4af | ||
|
|
e246a2753b | ||
|
|
6d06a26c31 | ||
|
|
7cda21b60f | ||
|
|
1db740039b | ||
|
|
df462774aa | ||
|
|
f55fa789c4 | ||
|
|
488541f26e | ||
|
|
b404b1cf50 | ||
|
|
69370aa806 | ||
|
|
b3ddd85b09 | ||
|
|
033221fd01 | ||
|
|
1201fa38a8 | ||
|
|
32059c376e | ||
|
|
511d393c78 | ||
|
|
237601cf29 | ||
|
|
928f14872e | ||
|
|
c6a9adf96c | ||
|
|
cdd00e0bd4 | ||
|
|
2503d13402 | ||
|
|
2d97970d24 | ||
|
|
d8945e53ba | ||
|
|
f18012d07b | ||
|
|
104f8603b9 | ||
|
|
19bb083030 | ||
|
|
ae575a19a0 | ||
|
|
5f94d0a5c2 | ||
|
|
f2fe1a7c17 | ||
|
|
618e6a1604 | ||
|
|
cef294513a | ||
|
|
8550abadef | ||
|
|
25c8b2d631 | ||
|
|
e7b690205e | ||
|
|
2403f8833a | ||
|
|
9f25743b4d | ||
|
|
f1c76f65cf | ||
|
|
7b39533410 | ||
|
|
1fe9c39dd5 | ||
|
|
2b7be2e3f1 | ||
|
|
1ee9a3f279 | ||
|
|
679acfb239 | ||
|
|
3c7ab4b49b | ||
|
|
3f062e1c0a | ||
|
|
0a497d8c3f | ||
|
|
462351f485 | ||
|
|
c4cbb631a9 | ||
|
|
76f2d15b1b | ||
|
|
5d63865ae5 | ||
|
|
ad7c88fb45 | ||
|
|
1af3877758 | ||
|
|
146ce3b12b | ||
|
|
bf67721ac4 | ||
|
|
436f736a8e | ||
|
|
1446e90dd9 | ||
|
|
54716c03d1 | ||
|
|
fad5e97e0a | ||
|
|
8cf79590c5 | ||
|
|
c6aafac6c8 | ||
|
|
94a5995197 | ||
|
|
74081dc981 | ||
|
|
7a593b13a7 | ||
|
|
25dc38b2b1 | ||
|
|
403b12f7b7 | ||
|
|
cd223be88a | ||
|
|
a6a3fca1e7 | ||
|
|
63815eb5c2 | ||
|
|
4444264830 | ||
|
|
255f91f7ca | ||
|
|
700207d29b | ||
|
|
72d96e9a3b | ||
|
|
a55b6de1b4 | ||
|
|
9faac05666 | ||
|
|
7bf408aba0 | ||
|
|
70ee391b33 | ||
|
|
f5eb1158db | ||
|
|
81916d0f45 | ||
|
|
03dccbe613 | ||
|
|
1ccec65619 | ||
|
|
b78e9062a1 | ||
|
|
dc87354702 | ||
|
|
033e8583db | ||
|
|
d46b51fa9a | ||
|
|
dd1dfdcfeb | ||
|
|
c0233c803d | ||
|
|
1fa8c88f6b | ||
|
|
195b109a36 | ||
|
|
994ac3fc8e | ||
|
|
a8ec5cf5e9 | ||
|
|
b4263aa3ec | ||
|
|
6456809a72 | ||
|
|
024c0a3186 | ||
|
|
560b1d48bc | ||
|
|
bb2d860807 | ||
|
|
6f1c0fa4a8 | ||
|
|
35808e7bde | ||
|
|
1b4eeb35b3 | ||
|
|
cee032bbc9 | ||
|
|
ac193cd97a | ||
|
|
7355a60f16 | ||
|
|
fb6f6325b5 | ||
|
|
0f767d9dfc | ||
|
|
d1addcab91 | ||
|
|
7a02cd794b | ||
|
|
258cd9209f | ||
|
|
700f6022d9 | ||
|
|
d98e247665 | ||
|
|
15f6f6a90a | ||
|
|
05814e9351 | ||
|
|
b6c0b1b396 | ||
|
|
30edd9e8dd | ||
|
|
8dbbe34dfc | ||
|
|
e1bcf6c47e | ||
|
|
02e71c23de | ||
|
|
ec5454de44 |
@@ -17,3 +17,4 @@ Tests/Manual/**/*.xcodeproj
|
|||||||
*.sublime-project
|
*.sublime-project
|
||||||
*.sublime-workspace
|
*.sublime-workspace
|
||||||
*.tm_properties
|
*.tm_properties
|
||||||
|
*.idea
|
||||||
@@ -216,7 +216,7 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ([_delegate respondsToSelector:@selector(applicationShouldTerminate:)])
|
if ([_delegate respondsToSelector:@selector(applicationShouldTerminate:)])
|
||||||
_implementedDelegateMethods |= CPApplicationDelegate_applicationShouldTerminate_
|
_implementedDelegateMethods |= CPApplicationDelegate_applicationShouldTerminate_;
|
||||||
|
|
||||||
if ([_delegate respondsToSelector:@selector(applicationShouldTerminateMessage:)])
|
if ([_delegate respondsToSelector:@selector(applicationShouldTerminateMessage:)])
|
||||||
_implementedDelegateMethods |= CPApplicationDelegate_applicationShouldTerminateMessage_
|
_implementedDelegateMethods |= CPApplicationDelegate_applicationShouldTerminateMessage_
|
||||||
|
|||||||
@@ -563,7 +563,7 @@
|
|||||||
*/
|
*/
|
||||||
- (BOOL)setSelectionIndexes:(CPIndexSet)indexes
|
- (BOOL)setSelectionIndexes:(CPIndexSet)indexes
|
||||||
{
|
{
|
||||||
[self _selectionWillChange]
|
[self _selectionWillChange];
|
||||||
var r = [self __setSelectionIndexes:indexes avoidEmpty:NO];
|
var r = [self __setSelectionIndexes:indexes avoidEmpty:NO];
|
||||||
[self _selectionDidChange];
|
[self _selectionDidChange];
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@@ -378,7 +378,7 @@ CPButtonImageOffset = 3.0;
|
|||||||
|
|
||||||
- (void)setImage:(CPImage)anImage
|
- (void)setImage:(CPImage)anImage
|
||||||
{
|
{
|
||||||
[self setValue:anImage forThemeAttribute:@"image"];
|
[self setValue:anImage forThemeAttribute:@"image" inState:CPThemeStateNormal];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CPImage)image
|
- (CPImage)image
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ var CPCollectionViewDelegate_collectionView_acceptDrop_index_dropOperation_
|
|||||||
- (CPData)collectionView:(CPCollectionView)collectionView dataForItemsAtIndexes:(CPIndexSet)indices forType:(CPString)aType;
|
- (CPData)collectionView:(CPCollectionView)collectionView dataForItemsAtIndexes:(CPIndexSet)indices forType:(CPString)aType;
|
||||||
- (CPDragOperation)collectionView:(CPCollectionView)collectionView validateDrop:(id)draggingInfo proposedIndex:(CPInteger)proposedDropIndex dropOperation:(CPCollectionViewDropOperation)proposedDropOperation;
|
- (CPDragOperation)collectionView:(CPCollectionView)collectionView validateDrop:(id)draggingInfo proposedIndex:(CPInteger)proposedDropIndex dropOperation:(CPCollectionViewDropOperation)proposedDropOperation;
|
||||||
- (CPMenu)collectionView:(CPCollectionView)collectionView menuForItemAtIndex:(CPInteger)anIndex;
|
- (CPMenu)collectionView:(CPCollectionView)collectionView menuForItemAtIndex:(CPInteger)anIndex;
|
||||||
- (CPView)collectionView:(CPCollectionView)collectionView dragginViewForItemsAtIndexes:(CPIndexSet)indexes withEvent:(CPEvent)event offset:(CGPoint)dragImageOffset;
|
- (CPView)collectionView:(CPCollectionView)collectionView draggingViewForItemsAtIndexes:(CPIndexSet)indexes withEvent:(CPEvent)event offset:(CGPoint)dragImageOffset;
|
||||||
- (void)collectionView:(CPCollectionView)collectionView didDoubleClickOnItemAtIndex:(int)index;
|
- (void)collectionView:(CPCollectionView)collectionView didDoubleClickOnItemAtIndex:(int)index;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -103,7 +103,8 @@ var cachedBlackColor,
|
|||||||
@"alternate-selected-control-color": [CPNull null],
|
@"alternate-selected-control-color": [CPNull null],
|
||||||
@"secondary-selected-control-color": [CPNull null],
|
@"secondary-selected-control-color": [CPNull null],
|
||||||
@"selected-text-background-color": [CPNull null],
|
@"selected-text-background-color": [CPNull null],
|
||||||
@"selected-text-inactive-background-color": [CPNull null]
|
@"selected-text-inactive-background-color": [CPNull null],
|
||||||
|
@"css-based": NO
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -876,9 +877,221 @@ url("data:image/png;base64,BASE64ENCODEDDATA") // if there is a pattern image
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark CSS Theming
|
||||||
|
|
||||||
|
// The code below adds support for CSS theming with 100% compatibility with current theming system.
|
||||||
|
// The idea is to extend CPColor (and CPImage) with CSS components and adapt low level UI components to
|
||||||
|
// support this new kind of CPColor/CPImage. See CPImageView, CPView and _CPImageAndTextView.
|
||||||
|
//
|
||||||
|
// To create a CPColor that uses CSS, simply use the new class method :
|
||||||
|
// + (CPColor)colorWithCSSDictionary:(CPDictionary)aDictionary beforeDictionary:(CPDictionary)beforeDictionary afterDictionary:(CPDictionary)afterDictionary
|
||||||
|
// where beforeDictionary & afterDictionary are related to ::before & ::after pseudo-elements.
|
||||||
|
// If you don't need them, just use the simplified class method :
|
||||||
|
// + (CPColor)colorWithCSSDictionary:(CPDictionary)aDictionary
|
||||||
|
//
|
||||||
|
// Example :
|
||||||
|
// buttonCssColor = [CPColor colorWithCSSDictionary:@{
|
||||||
|
// @"background-color": A3ColorBackgroundWhite,
|
||||||
|
// @"border-color": A3ColorActiveBorder,
|
||||||
|
// @"border-style": @"solid",
|
||||||
|
// @"border-width": @"1px",
|
||||||
|
// @"border-radius": @"3px",
|
||||||
|
// @"box-sizing": @"border-box"
|
||||||
|
// }
|
||||||
|
// beforeDictionary:@{
|
||||||
|
// @"background-color": @"rgb(225,225,225)",
|
||||||
|
// @"bottom": @"3px",
|
||||||
|
// @"content": @"''",
|
||||||
|
// @"position": @"absolute",
|
||||||
|
// @"right": @"21px",
|
||||||
|
// @"top": @"3px",
|
||||||
|
// @"width": @"1px"
|
||||||
|
// }
|
||||||
|
// afterDictionary:@{
|
||||||
|
// @"content": @"''",
|
||||||
|
// @"bottom": @"3px",
|
||||||
|
// @"right": @"6px",
|
||||||
|
// @"top": @"1px",
|
||||||
|
// @"position": @"absolute",
|
||||||
|
// @"height": @"14px",
|
||||||
|
// @"width": @"9px",
|
||||||
|
// @"margin": @"2px 0px 2px 0px",
|
||||||
|
// @"background-image": @"url(%%packed.png)",
|
||||||
|
// @"background-position": @"0px -64px",
|
||||||
|
// @"background-repeat": @"no-repeat",
|
||||||
|
// @"background-size": @"100px 400px"
|
||||||
|
// }];
|
||||||
|
//
|
||||||
|
// Remark : Please note the special URL of the background image used in this example : url(%%packed.png)
|
||||||
|
// During theme loading, "%%" will be replaced by the path to the theme blend resources folder.
|
||||||
|
// Typically, a CSS theme will use some (rare) images all packed together in a single image resource (see packed.png in Aristo3 theme)
|
||||||
|
//
|
||||||
|
// Also, please note that if you don't use one of the CSS components, you can either set it to nil (best solution) or to an empty dictionary, like :
|
||||||
|
// aCssColor = [CPColor colorWithCSSDictionary:@{} beforeDictionary:nil afterDictionary:@{ ... }];
|
||||||
|
//
|
||||||
|
// You can use -(BOOL)isCSSBased to determine how to cope with it in your code.
|
||||||
|
// -(BOOL)hasCSSDictionary, -(BOOL)hasCSSBeforeDictionary and -(BOOL)hasCSSAfterDictionary are convience methods you can use.
|
||||||
|
//
|
||||||
|
// Remark : -(void)restorePreviousCSSState and -(DOMElement)applyCSSColorForView are meant to be used by low level UI widgets (like CPView) to implement
|
||||||
|
// CSS theme support.
|
||||||
|
|
||||||
|
@implementation CPColor (CSSTheming)
|
||||||
|
{
|
||||||
|
CPDictionary _cssDictionary @accessors(property=cssDictionary);
|
||||||
|
CPDictionary _cssBeforeDictionary @accessors(property=cssBeforeDictionary);
|
||||||
|
CPDictionary _cssAfterDictionary @accessors(property=cssAfterDictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (CPColor)colorWithCSSDictionary:(CPDictionary)aDictionary
|
||||||
|
{
|
||||||
|
return [[CPColor alloc] _initWithCSSDictionary:aDictionary beforeDictionary:nil afterDictionary:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (CPColor)colorWithCSSDictionary:(CPDictionary)aDictionary beforeDictionary:(CPDictionary)beforeDictionary afterDictionary:(CPDictionary)afterDictionary
|
||||||
|
{
|
||||||
|
return [[CPColor alloc] _initWithCSSDictionary:aDictionary beforeDictionary:beforeDictionary afterDictionary:afterDictionary];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)_initWithCSSDictionary:(CPDictionary)aDictionary beforeDictionary:(CPDictionary)beforeDictionary afterDictionary:(CPDictionary)afterDictionary
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
|
||||||
|
if (self)
|
||||||
|
{
|
||||||
|
_cssDictionary = aDictionary;
|
||||||
|
_cssBeforeDictionary = beforeDictionary;
|
||||||
|
_cssAfterDictionary = afterDictionary;
|
||||||
|
_components = [0.0, 0.0, 0.0, 1.0];
|
||||||
|
|
||||||
|
_theme = [CPTheme defaultTheme];
|
||||||
|
_themeState = CPThemeStateNormal;
|
||||||
|
[self _loadThemeAttributes];
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isCSSBased
|
||||||
|
{
|
||||||
|
return !!(_cssDictionary || _cssBeforeDictionary || _cssAfterDictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)hasCSSDictionary
|
||||||
|
{
|
||||||
|
return ([_cssDictionary count] > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)hasCSSBeforeDictionary
|
||||||
|
{
|
||||||
|
return ([_cssBeforeDictionary count] > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)hasCSSAfterDictionary
|
||||||
|
{
|
||||||
|
return ([_cssAfterDictionary count] > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)restorePreviousCSSState:(CPArrayRef)aPreviousStateRef forDOMElement:(DOMElement)aDOMElement
|
||||||
|
{
|
||||||
|
#if PLATFORM(DOM)
|
||||||
|
var aPreviousState = @deref(aPreviousStateRef);
|
||||||
|
|
||||||
|
for (var i = 0, count = aPreviousState.length; i < count; i++)
|
||||||
|
aDOMElement.style[aPreviousState[i][0]] = aPreviousState[i][1];
|
||||||
|
|
||||||
|
@deref(aPreviousStateRef) = @[];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
- (DOMElement)applyCSSColorForView:(CPView)aView onDOMElement:(DOMElement)aDOMElement styleNode:(DOMElement)aStyleNode previousState:(CPArrayRef)aPreviousStateRef
|
||||||
|
{
|
||||||
|
#if PLATFORM(DOM)
|
||||||
|
var aPreviousState = @deref(aPreviousStateRef);
|
||||||
|
|
||||||
|
[_cssDictionary enumerateKeysAndObjectsUsingBlock:function(aKey, anObject, stop)
|
||||||
|
{
|
||||||
|
[aPreviousState addObject:@[aKey, aDOMElement.style[aKey]]];
|
||||||
|
aDOMElement.style[aKey] = anObject;
|
||||||
|
}];
|
||||||
|
|
||||||
|
if ([self hasCSSBeforeDictionary] || [self hasCSSAfterDictionary])
|
||||||
|
{
|
||||||
|
// We need to create a unique class name
|
||||||
|
|
||||||
|
var styleClassName = @".CP" + [aView UID],
|
||||||
|
styleContent = @"";
|
||||||
|
|
||||||
|
if ([self hasCSSBeforeDictionary])
|
||||||
|
{
|
||||||
|
styleContent += styleClassName + @"::before { ";
|
||||||
|
|
||||||
|
[_cssBeforeDictionary enumerateKeysAndObjectsUsingBlock:function(aKey, anObject, stop)
|
||||||
|
{
|
||||||
|
styleContent += aKey + ": " + anObject + "; ";
|
||||||
|
}];
|
||||||
|
|
||||||
|
styleContent += "} ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([self hasCSSAfterDictionary])
|
||||||
|
{
|
||||||
|
styleContent += styleClassName + @"::after { ";
|
||||||
|
|
||||||
|
[_cssAfterDictionary enumerateKeysAndObjectsUsingBlock:function(aKey, anObject, stop)
|
||||||
|
{
|
||||||
|
styleContent += aKey + ": " + anObject + "; ";
|
||||||
|
}];
|
||||||
|
|
||||||
|
styleContent += "} ";
|
||||||
|
}
|
||||||
|
|
||||||
|
var styleDescription = document.createTextNode(styleContent);
|
||||||
|
|
||||||
|
if (!aStyleNode)
|
||||||
|
{
|
||||||
|
aStyleNode = document.createElement("style");
|
||||||
|
|
||||||
|
aView._DOMElement.insertBefore(aStyleNode, aView._DOMElement.firstChild);
|
||||||
|
|
||||||
|
aStyleNode.appendChild(styleDescription);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aStyleNode.replaceChild(styleDescription, aStyleNode.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
[aView setDOMClassName:@"CP"+[aView UID]];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// no before/after so remove aStyleNode if existing
|
||||||
|
|
||||||
|
if (aStyleNode)
|
||||||
|
{
|
||||||
|
aView._DOMElement.removeChild(aStyleNode);
|
||||||
|
aStyleNode = nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return actualised values
|
||||||
|
|
||||||
|
@deref(aPreviousStateRef) = aPreviousState;
|
||||||
|
|
||||||
|
return aStyleNode;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
|
||||||
/// @cond IGNORE
|
/// @cond IGNORE
|
||||||
var CPColorComponentsKey = @"CPColorComponentsKey",
|
var CPColorComponentsKey = @"CPColorComponentsKey",
|
||||||
CPColorPatternImageKey = @"CPColorPatternImageKey";
|
CPColorPatternImageKey = @"CPColorPatternImageKey",
|
||||||
|
CPColorCssDictionaryKey = @"CPColorCssDictionaryKey",
|
||||||
|
CPColorCssBeforeDictionaryKey = @"CPColorCssBeforeDictionaryKey",
|
||||||
|
CPColorCssAfterDictionaryKey = @"CPColorCssAfterDictionaryKey";
|
||||||
/// @endcond
|
/// @endcond
|
||||||
|
|
||||||
@implementation CPColor (CPCoding)
|
@implementation CPColor (CPCoding)
|
||||||
@@ -891,6 +1104,10 @@ var CPColorComponentsKey = @"CPColorComponentsKey",
|
|||||||
{
|
{
|
||||||
if ([aCoder containsValueForKey:CPColorPatternImageKey])
|
if ([aCoder containsValueForKey:CPColorPatternImageKey])
|
||||||
self = [self _initWithPatternImage:[aCoder decodeObjectForKey:CPColorPatternImageKey]];
|
self = [self _initWithPatternImage:[aCoder decodeObjectForKey:CPColorPatternImageKey]];
|
||||||
|
else if ([aCoder containsValueForKey:CPColorCssDictionaryKey])
|
||||||
|
self = [self _initWithCSSDictionary:[aCoder decodeObjectForKey:CPColorCssDictionaryKey]
|
||||||
|
beforeDictionary:[aCoder decodeObjectForKey:CPColorCssBeforeDictionaryKey]
|
||||||
|
afterDictionary:[aCoder decodeObjectForKey:CPColorCssAfterDictionaryKey]];
|
||||||
else
|
else
|
||||||
self = [self _initWithRGBA:[aCoder decodeObjectForKey:CPColorComponentsKey]];
|
self = [self _initWithRGBA:[aCoder decodeObjectForKey:CPColorComponentsKey]];
|
||||||
|
|
||||||
@@ -907,6 +1124,12 @@ var CPColorComponentsKey = @"CPColorComponentsKey",
|
|||||||
{
|
{
|
||||||
if (_patternImage)
|
if (_patternImage)
|
||||||
[aCoder encodeObject:_patternImage forKey:CPColorPatternImageKey];
|
[aCoder encodeObject:_patternImage forKey:CPColorPatternImageKey];
|
||||||
|
else if (_cssDictionary)
|
||||||
|
{
|
||||||
|
[aCoder encodeObject:_cssDictionary forKey:CPColorCssDictionaryKey];
|
||||||
|
[aCoder encodeObject:_cssBeforeDictionary forKey:CPColorCssBeforeDictionaryKey];
|
||||||
|
[aCoder encodeObject:_cssAfterDictionary forKey:CPColorCssAfterDictionaryKey];
|
||||||
|
}
|
||||||
else
|
else
|
||||||
[aCoder encodeObject:_components forKey:CPColorComponentsKey];
|
[aCoder encodeObject:_components forKey:CPColorComponentsKey];
|
||||||
|
|
||||||
@@ -1247,7 +1470,8 @@ var patternColorsFromPattern = function(pattern, attributes, imageFactory)
|
|||||||
bottomHeight,
|
bottomHeight,
|
||||||
centerWidthHeight,
|
centerWidthHeight,
|
||||||
centerIsNil,
|
centerIsNil,
|
||||||
numParts;
|
numParts,
|
||||||
|
isVertical;
|
||||||
|
|
||||||
// positions are mandatory
|
// positions are mandatory
|
||||||
if (pattern.indexOf("{position}") < 0)
|
if (pattern.indexOf("{position}") < 0)
|
||||||
|
|||||||
@@ -247,7 +247,7 @@
|
|||||||
_blackWheelImage = new Image();
|
_blackWheelImage = new Image();
|
||||||
_blackWheelImage.src = path;
|
_blackWheelImage.src = path;
|
||||||
_blackWheelImage.style.opacity = "0";
|
_blackWheelImage.style.opacity = "0";
|
||||||
_blackWheelImage.style.filter = "alpha(opacity=0)"
|
_blackWheelImage.style.filter = "alpha(opacity=0)";
|
||||||
_blackWheelImage.style.position = "absolute";
|
_blackWheelImage.style.position = "absolute";
|
||||||
|
|
||||||
_DOMElement.appendChild(_wheelImage);
|
_DOMElement.appendChild(_wheelImage);
|
||||||
|
|||||||
@@ -1057,14 +1057,21 @@ var CPControlBlackColor = [CPColor blackColor];
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation CPControl (CPTrackingArea)
|
@implementation CPControl (CPTrackingArea)
|
||||||
|
{
|
||||||
|
CPTrackingArea _controlTrackingArea;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)updateTrackingAreas
|
- (void)updateTrackingAreas
|
||||||
{
|
{
|
||||||
[self removeAllTrackingAreas];
|
if (_controlTrackingArea)
|
||||||
[self addTrackingArea:[[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
[self removeTrackingArea:_controlTrackingArea];
|
||||||
options:CPTrackingMouseEnteredAndExited | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
|
|
||||||
owner:self
|
_controlTrackingArea = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||||
userInfo:nil]];
|
options:CPTrackingMouseEnteredAndExited | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
|
||||||
|
owner:self
|
||||||
|
userInfo:nil];
|
||||||
|
[self addTrackingArea:_controlTrackingArea];
|
||||||
|
[super updateTrackingAreas];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -352,8 +352,8 @@ CPEraDatePickerElementFlag = 0x0100;
|
|||||||
if (_implementedCDatePickerDelegateMethods & CPDatePicker_validateProposedDateValue_timeInterval)
|
if (_implementedCDatePickerDelegateMethods & CPDatePicker_validateProposedDateValue_timeInterval)
|
||||||
{
|
{
|
||||||
// constrain timeInterval also
|
// constrain timeInterval also
|
||||||
var aStartDateRef = function(x){if (typeof x == 'undefined') return aDateValue; aDateValue = x;}
|
var aStartDateRef = function(x){if (typeof x == 'undefined') return aDateValue; aDateValue = x;};
|
||||||
var aTimeIntervalRef = function(x){if (typeof x == 'undefined') return aTimeInterval; aTimeInterval = x;}
|
var aTimeIntervalRef = function(x){if (typeof x == 'undefined') return aTimeInterval; aTimeInterval = x;};
|
||||||
|
|
||||||
[_delegate datePicker:self validateProposedDateValue:aStartDateRef timeInterval:aTimeIntervalRef];
|
[_delegate datePicker:self validateProposedDateValue:aStartDateRef timeInterval:aTimeIntervalRef];
|
||||||
}
|
}
|
||||||
@@ -694,7 +694,7 @@ var CPDatePickerModeKey = @"CPDatePickerModeKey",
|
|||||||
[aCoder encodeInt:_datePickerStyle forKey:CPDatePickerStyleKey];
|
[aCoder encodeInt:_datePickerStyle forKey:CPDatePickerStyleKey];
|
||||||
[aCoder encodeInt:_datePickerElements forKey:CPDatePickerElementsKey];
|
[aCoder encodeInt:_datePickerElements forKey:CPDatePickerElementsKey];
|
||||||
[aCoder encodeObject:_minDate forKey:CPMinDateKey];
|
[aCoder encodeObject:_minDate forKey:CPMinDateKey];
|
||||||
[aCoder encodeObject:_maxDate forKey:CPMaxDateKey]
|
[aCoder encodeObject:_maxDate forKey:CPMaxDateKey];
|
||||||
[aCoder encodeObject:_dateValue forKey:CPDateValueKey];;
|
[aCoder encodeObject:_dateValue forKey:CPDateValueKey];;
|
||||||
[aCoder encodeObject:_textFont forKey:CPTextFontKey];
|
[aCoder encodeObject:_textFont forKey:CPTextFontKey];
|
||||||
[aCoder encodeObject:_locale forKey:CPLocaleKey];
|
[aCoder encodeObject:_locale forKey:CPLocaleKey];
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
|||||||
{
|
{
|
||||||
if (self = [super initWithFrame:aFrame])
|
if (self = [super initWithFrame:aFrame])
|
||||||
{
|
{
|
||||||
_datePicker = aDatePicker
|
_datePicker = aDatePicker;
|
||||||
[self _init];
|
[self _init];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -435,7 +435,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return CPShortWeekDayNameArrayEn
|
return CPShortWeekDayNameArrayEn;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -464,7 +464,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return CPShortMonthNameArrayEn
|
return CPShortMonthNameArrayEn;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -526,11 +526,11 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
|||||||
var dayLabel = _dayLabels[i];
|
var dayLabel = _dayLabels[i];
|
||||||
|
|
||||||
[dayLabel setStringValue:dayNames[i]];
|
[dayLabel setStringValue:dayNames[i]];
|
||||||
[dayLabel sizeToFit]
|
[dayLabel sizeToFit];
|
||||||
[dayLabel setFrameOrigin:CGPointMake(sizeTileWidth * (i + 1) - sizeTileWidth / 2 - [dayLabel frameSize].width / 2, 23)];
|
[dayLabel setFrameOrigin:CGPointMake(sizeTileWidth * (i + 1) - sizeTileWidth / 2 - [dayLabel frameSize].width / 2, 23)];
|
||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
firstDayTileX = sizeTileWidth * (i + 1) - sizeTileWidth / 2 - [dayLabel frameSize].width / 2
|
firstDayTileX = sizeTileWidth * (i + 1) - sizeTileWidth / 2 - [dayLabel frameSize].width / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Title
|
// Title
|
||||||
@@ -769,7 +769,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
|||||||
tileDate = [[tile date] copy],
|
tileDate = [[tile date] copy],
|
||||||
selected = NO;
|
selected = NO;
|
||||||
|
|
||||||
[tileDate _resetToMidnight]
|
[tileDate _resetToMidnight];
|
||||||
|
|
||||||
if (aStartDate)
|
if (aStartDate)
|
||||||
selected = tileDate >= aStartDate && tileDate <= endDate;
|
selected = tileDate >= aStartDate && tileDate <= endDate;
|
||||||
@@ -845,7 +845,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
|||||||
|
|
||||||
// Very usefull to avoid to have a line of two pixels instead one
|
// Very usefull to avoid to have a line of two pixels instead one
|
||||||
if (!isBorderPair)
|
if (!isBorderPair)
|
||||||
y += 0.5
|
y += 0.5;
|
||||||
|
|
||||||
CGContextMoveToPoint(context, 0, y);
|
CGContextMoveToPoint(context, 0, y);
|
||||||
CGContextAddLineToPoint(context, [self bounds].size.width, y);
|
CGContextAddLineToPoint(context, [self bounds].size.width, y);
|
||||||
@@ -857,7 +857,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
|||||||
|
|
||||||
// Very usefull to avoid to have a line of two pixels instead one
|
// Very usefull to avoid to have a line of two pixels instead one
|
||||||
if (!isBorderPair)
|
if (!isBorderPair)
|
||||||
x += 0.5
|
x += 0.5;
|
||||||
|
|
||||||
CGContextMoveToPoint(context, x, 0);
|
CGContextMoveToPoint(context, x, 0);
|
||||||
CGContextAddLineToPoint(context, x, [self bounds].size.height);
|
CGContextAddLineToPoint(context, x, [self bounds].size.height);
|
||||||
@@ -869,7 +869,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
|||||||
|
|
||||||
// Very usefull to avoid to have a line of two pixels instead one
|
// Very usefull to avoid to have a line of two pixels instead one
|
||||||
if (!isBorderPair)
|
if (!isBorderPair)
|
||||||
y += 0.5
|
y += 0.5;
|
||||||
|
|
||||||
CGContextMoveToPoint(context, 0, y);
|
CGContextMoveToPoint(context, 0, y);
|
||||||
CGContextAddLineToPoint(context, [self bounds].size.width, y);
|
CGContextAddLineToPoint(context, [self bounds].size.width, y);
|
||||||
@@ -897,7 +897,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
|||||||
_clickDate = [dateTile copy];
|
_clickDate = [dateTile copy];
|
||||||
_dragDate = nil;
|
_dragDate = nil;
|
||||||
_indexDayTile = -1;
|
_indexDayTile = -1;
|
||||||
_eventDragged = nil
|
_eventDragged = nil;
|
||||||
|
|
||||||
_datePicker._invokedByUserEvent = YES;
|
_datePicker._invokedByUserEvent = YES;
|
||||||
|
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ var RADIANS = Math.PI / 180;
|
|||||||
if ([_datePicker _isAmericanFormat])
|
if ([_datePicker _isAmericanFormat])
|
||||||
{
|
{
|
||||||
if (dateValue.getHours() > 11)
|
if (dateValue.getHours() > 11)
|
||||||
[_PMAMTextField setStringValue:@"PM"]
|
[_PMAMTextField setStringValue:@"PM"];
|
||||||
else
|
else
|
||||||
[_PMAMTextField setStringValue:@"AM"];
|
[_PMAMTextField setStringValue:@"AM"];
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ var CPZeroKeyCode = 48,
|
|||||||
{
|
{
|
||||||
if (self = [super initWithFrame:aFrame])
|
if (self = [super initWithFrame:aFrame])
|
||||||
{
|
{
|
||||||
_datePicker = aDatePicker
|
_datePicker = aDatePicker;
|
||||||
[self _init];
|
[self _init];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
|||||||
CPWindow _window;
|
CPWindow _window;
|
||||||
Number _windowNumber;
|
Number _windowNumber;
|
||||||
CPString _characters;
|
CPString _characters;
|
||||||
CPString _charactersIgnoringModifiers
|
CPString _charactersIgnoringModifiers;
|
||||||
BOOL _isARepeat;
|
BOOL _isARepeat;
|
||||||
unsigned _keyCode;
|
unsigned _keyCode;
|
||||||
DOMEvent _DOMEvent;
|
DOMEvent _DOMEvent;
|
||||||
@@ -642,7 +642,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
|||||||
- (CPTrackingArea)trackingArea
|
- (CPTrackingArea)trackingArea
|
||||||
{
|
{
|
||||||
if ((_type !== CPMouseEntered) && (_type !== CPMouseExited) && (_type !== CPCursorUpdate))
|
if ((_type !== CPMouseEntered) && (_type !== CPMouseExited) && (_type !== CPCursorUpdate))
|
||||||
[CPException raise:CPInternalInconsistencyException format:@"You can't call trackingArea for events of type %#x", _type]
|
[CPException raise:CPInternalInconsistencyException format:@"You can't call trackingArea for events of type %#x", _type];
|
||||||
|
|
||||||
return _trackingArea;
|
return _trackingArea;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ var IEFlashCLSID = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
|
|||||||
|
|
||||||
- (id)initWithFrame:(CGRect)aFrame
|
- (id)initWithFrame:(CGRect)aFrame
|
||||||
{
|
{
|
||||||
|
|
||||||
|
CPLog.warn("CPFlashView is not supported by Cappuccino, this is now deprecated and it will be removed in the version 1.1 of Cappuccino");
|
||||||
|
|
||||||
self = [super initWithFrame:aFrame];
|
self = [super initWithFrame:aFrame];
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ following:
|
|||||||
if (normalizedFaces === _CPFontSystemFontFace)
|
if (normalizedFaces === _CPFontSystemFontFace)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[self _invalidateSystemFontCache]
|
[self _invalidateSystemFontCache];
|
||||||
_CPFontSystemFontFace = aFace;
|
_CPFontSystemFontFace = aFace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -246,7 +246,7 @@ function CPAppKitImage(aFilename, aSize)
|
|||||||
var canvas = document.createElement("canvas"),
|
var canvas = document.createElement("canvas"),
|
||||||
ctx = canvas.getContext("2d");
|
ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
canvas.width = _image.width,
|
canvas.width = _image.width;
|
||||||
canvas.height = _image.height;
|
canvas.height = _image.height;
|
||||||
|
|
||||||
ctx.drawImage(_image, 0, 0);
|
ctx.drawImage(_image, 0, 0);
|
||||||
@@ -509,6 +509,212 @@ function CPAppKitImage(aFilename, aSize)
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark CSS Theming
|
||||||
|
|
||||||
|
// The code below adds support for CSS theming with 100% compatibility with current theming system.
|
||||||
|
// The idea is to extend CPImage (and CPColor) with CSS components and adapt low level UI components to
|
||||||
|
// support this new kind of CPColor/CPImage. See CPImageView, CPView and _CPImageAndTextView.
|
||||||
|
//
|
||||||
|
// To create a CPImage that uses CSS, simply use the new class method :
|
||||||
|
// + (CPImage)imageWithCSSDictionary:(CPDictionary)aDictionary beforeDictionary:(CPDictionary)beforeDictionary afterDictionary:(CPDictionary)afterDictionary size:(CGSize)aSize
|
||||||
|
// where beforeDictionary & afterDictionary are related to ::before & ::after pseudo-elements.
|
||||||
|
// If you don't need them, just use the simplified class method :
|
||||||
|
// + (CPImage)imageWithCSSDictionary:(CPDictionary)aDictionary size:(CGSize)aSize
|
||||||
|
//
|
||||||
|
// Examples :
|
||||||
|
// regularImageNormal = [CPImage imageWithCSSDictionary:@{
|
||||||
|
// @"border-color": A3ColorActiveBorder,
|
||||||
|
// @"border-style": @"solid",
|
||||||
|
// @"border-width": @"1px",
|
||||||
|
// @"border-radius": @"50%",
|
||||||
|
// @"box-sizing": @"border-box",
|
||||||
|
// @"background-color": A3ColorBackgroundWhite,
|
||||||
|
// @"transition-duration": @"0.35s",
|
||||||
|
// @"transition-property": @"all",
|
||||||
|
// @"transition-timing-function": @"ease"
|
||||||
|
// }
|
||||||
|
// size:CGSizeMake(16,16)];
|
||||||
|
//
|
||||||
|
// imageSearch = [CPImage imageWithCSSDictionary:@{
|
||||||
|
// @"background-image": @"url(%%packed.png)",
|
||||||
|
// @"background-position": @"-16px -32px",
|
||||||
|
// @"background-repeat": @"no-repeat",
|
||||||
|
// @"background-size": @"100px 400px"
|
||||||
|
// }
|
||||||
|
// size:CGSizeMake(16,16)];
|
||||||
|
//
|
||||||
|
// Remark : Please note the special URL of the background image used in this example : url(%%packed.png)
|
||||||
|
// During theme loading, "%%" will be replaced by the path to the theme blend resources folder.
|
||||||
|
// Typically, a CSS theme will use some (rare) images all packed together in a single image resource (see packed.png in Aristo3 theme)
|
||||||
|
//
|
||||||
|
// Also, please note that if you don't use one of the CSS components, you can either set it to nil (best solution) or to an empty dictionary, like :
|
||||||
|
// aCssImage = [CPImage imageWithCSSDictionary:@{} beforeDictionary:nil afterDictionary:@{ ... }];
|
||||||
|
//
|
||||||
|
// You can use -(BOOL)isCSSBased to determine how to cope with it in your code.
|
||||||
|
// -(BOOL)hasCSSDictionary, -(BOOL)hasCSSBeforeDictionary and -(BOOL)hasCSSAfterDictionary are convience methods you can use.
|
||||||
|
//
|
||||||
|
// Remark : -(DOMElement)applyCSSImageForView is meant to be used by low level UI widgets (like CPImageView and _CPImageAndTextView) to implement CSS theme support.
|
||||||
|
//
|
||||||
|
// In some circumstances, you may have to clear a CSS image. You can do this easily by replacing your current image with the special dummy empty CSS image :
|
||||||
|
// [CPImage dummyCSSImageOfSize:CGSizeMake(someWidth, someHeight)]
|
||||||
|
|
||||||
|
@implementation CPImage (CSSTheming)
|
||||||
|
{
|
||||||
|
CPDictionary _cssDictionary @accessors(property=cssDictionary);
|
||||||
|
CPDictionary _cssBeforeDictionary @accessors(property=cssBeforeDictionary);
|
||||||
|
CPDictionary _cssAfterDictionary @accessors(property=cssAfterDictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (CPImage)imageWithCSSDictionary:(CPDictionary)aDictionary size:(CGSize)aSize
|
||||||
|
{
|
||||||
|
return [[CPImage alloc] initWithCSSDictionary:aDictionary beforeDictionary:nil afterDictionary:nil size:aSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (CPImage)imageWithCSSDictionary:(CPDictionary)aDictionary beforeDictionary:(CPDictionary)beforeDictionary afterDictionary:(CPDictionary)afterDictionary size:(CGSize)aSize
|
||||||
|
{
|
||||||
|
return [[CPImage alloc] initWithCSSDictionary:aDictionary beforeDictionary:beforeDictionary afterDictionary:afterDictionary size:aSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (CPImage)dummyCSSImageOfSize:(CGSize)aSize
|
||||||
|
{
|
||||||
|
// This is used to clear a previous CSS image
|
||||||
|
return [[CPImage alloc] initWithCSSDictionary:@{} beforeDictionary:nil afterDictionary:nil size:aSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)initWithCSSDictionary:(CPDictionary)aDictionary beforeDictionary:(CPDictionary)beforeDictionary afterDictionary:(CPDictionary)afterDictionary size:(CGSize)aSize
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
|
||||||
|
if (self)
|
||||||
|
{
|
||||||
|
_size = CGSizeMakeCopy(aSize);
|
||||||
|
_filename = @"CSS image";
|
||||||
|
_loadStatus = CPImageLoadStatusCompleted;
|
||||||
|
_cssDictionary = aDictionary;
|
||||||
|
_cssBeforeDictionary = beforeDictionary;
|
||||||
|
_cssAfterDictionary = afterDictionary;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isCSSBased
|
||||||
|
{
|
||||||
|
return !!(_cssDictionary || _cssBeforeDictionary || _cssAfterDictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)hasCSSDictionary
|
||||||
|
{
|
||||||
|
return ([_cssDictionary count] > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)hasCSSBeforeDictionary
|
||||||
|
{
|
||||||
|
return ([_cssBeforeDictionary count] > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)hasCSSAfterDictionary
|
||||||
|
{
|
||||||
|
return ([_cssAfterDictionary count] > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (DOMElement)applyCSSImageForView:(CPView)aView onDOMElement:(DOMElement)aDOMElement styleNode:(DOMElement)aStyleNode previousState:(CPArrayRef)aPreviousStateRef
|
||||||
|
{
|
||||||
|
#if PLATFORM(DOM)
|
||||||
|
// First, restore previous CSS styling before applying the new one
|
||||||
|
|
||||||
|
var aPreviousState = @deref(aPreviousStateRef);
|
||||||
|
|
||||||
|
for (var i = 0, count = aPreviousState.length; i < count; i++)
|
||||||
|
aDOMElement.style[aPreviousState[i][0]] = aPreviousState[i][1];
|
||||||
|
|
||||||
|
aPreviousState = @[];
|
||||||
|
|
||||||
|
// Then apply new CSS styling
|
||||||
|
|
||||||
|
[_cssDictionary enumerateKeysAndObjectsUsingBlock:function(aKey, anObject, stop)
|
||||||
|
{
|
||||||
|
[aPreviousState addObject:@[aKey, aDOMElement.style[aKey]]];
|
||||||
|
aDOMElement.style[aKey] = anObject;
|
||||||
|
}];
|
||||||
|
|
||||||
|
if (_cssBeforeDictionary || _cssAfterDictionary)
|
||||||
|
{
|
||||||
|
// We need to create a unique class name
|
||||||
|
|
||||||
|
var styleClassName = @".CP" + [aView UID],
|
||||||
|
styleContent = @"";
|
||||||
|
|
||||||
|
if (_cssBeforeDictionary)
|
||||||
|
{
|
||||||
|
styleContent += styleClassName + @"::before { ";
|
||||||
|
|
||||||
|
[_cssBeforeDictionary enumerateKeysAndObjectsUsingBlock:function(aKey, anObject, stop)
|
||||||
|
{
|
||||||
|
styleContent += aKey + ": " + anObject + "; ";
|
||||||
|
}];
|
||||||
|
|
||||||
|
styleContent += "} ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_cssAfterDictionary)
|
||||||
|
{
|
||||||
|
styleContent += styleClassName + @"::after { ";
|
||||||
|
|
||||||
|
[_cssAfterDictionary enumerateKeysAndObjectsUsingBlock:function(aKey, anObject, stop)
|
||||||
|
{
|
||||||
|
styleContent += aKey + ": " + anObject + "; ";
|
||||||
|
}];
|
||||||
|
|
||||||
|
styleContent += "} ";
|
||||||
|
}
|
||||||
|
|
||||||
|
var styleDescription = document.createTextNode(styleContent);
|
||||||
|
|
||||||
|
if (!aStyleNode)
|
||||||
|
{
|
||||||
|
aStyleNode = document.createElement("style");
|
||||||
|
|
||||||
|
aView._DOMElement.insertBefore(aStyleNode, aView._DOMElement.firstChild);
|
||||||
|
|
||||||
|
aStyleNode.appendChild(styleDescription);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aStyleNode.replaceChild(styleDescription, aStyleNode.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
[aView setDOMClassName:@"CP"+[aView UID]];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// no before/after so remove aStyleNode if existing
|
||||||
|
|
||||||
|
if (aStyleNode)
|
||||||
|
{
|
||||||
|
aView._DOMElement.removeChild(aStyleNode);
|
||||||
|
aStyleNode = nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Return actualised values
|
||||||
|
|
||||||
|
@deref(aPreviousStateRef) = aPreviousState;
|
||||||
|
|
||||||
|
return aStyleNode;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
var CPImageCSSDictionaryKey = @"CPImageCSSDictionaryKey",
|
||||||
|
CPImageCSSBeforeDictionaryKey = @"CPImageCSSBeforeDictionaryKey",
|
||||||
|
CPImageCSSAfterDictionaryKey = @"CPImageCSSAfterDictionaryKey";
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
|
||||||
@implementation CPImage (CPCoding)
|
@implementation CPImage (CPCoding)
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -518,7 +724,10 @@ function CPAppKitImage(aFilename, aSize)
|
|||||||
*/
|
*/
|
||||||
- (id)initWithCoder:(CPCoder)aCoder
|
- (id)initWithCoder:(CPCoder)aCoder
|
||||||
{
|
{
|
||||||
return [self initWithContentsOfFile:[aCoder decodeObjectForKey:@"CPFilename"] size:[aCoder decodeSizeForKey:@"CPSize"]];
|
if ([aCoder containsValueForKey:CPImageCSSDictionaryKey])
|
||||||
|
return [self initWithCSSDictionary:[aCoder decodeObjectForKey:CPImageCSSDictionaryKey] beforeDictionary:[aCoder decodeObjectForKey:CPImageCSSBeforeDictionaryKey] afterDictionary:[aCoder decodeObjectForKey:CPImageCSSAfterDictionaryKey] size:[aCoder decodeSizeForKey:@"CPSize"]];
|
||||||
|
else
|
||||||
|
return [self initWithContentsOfFile:[aCoder decodeObjectForKey:@"CPFilename"] size:[aCoder decodeSizeForKey:@"CPSize"]];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -529,6 +738,14 @@ function CPAppKitImage(aFilename, aSize)
|
|||||||
{
|
{
|
||||||
[aCoder encodeObject:_filename forKey:@"CPFilename"];
|
[aCoder encodeObject:_filename forKey:@"CPFilename"];
|
||||||
[aCoder encodeSize:_size forKey:@"CPSize"];
|
[aCoder encodeSize:_size forKey:@"CPSize"];
|
||||||
|
|
||||||
|
// CSS Styling
|
||||||
|
if ([self isCSSBased])
|
||||||
|
{
|
||||||
|
[aCoder encodeObject:_cssDictionary forKey:CPImageCSSDictionaryKey];
|
||||||
|
[aCoder encodeObject:_cssBeforeDictionary forKey:CPImageCSSBeforeDictionaryKey];
|
||||||
|
[aCoder encodeObject:_cssAfterDictionary forKey:CPImageCSSAfterDictionaryKey];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -98,10 +98,32 @@ var CPImageViewEmptyPlaceholderImage = nil;
|
|||||||
- (void)_createDOMImageElement
|
- (void)_createDOMImageElement
|
||||||
{
|
{
|
||||||
#if PLATFORM(DOM)
|
#if PLATFORM(DOM)
|
||||||
if (_DOMImageElement)
|
var image = [self objectValue],
|
||||||
return;
|
isCSSBasedImage = [image isCSSBased],
|
||||||
|
isIMGImageElement = _DOMImageElement && (_DOMImageElement.nodeName == "IMG");
|
||||||
|
|
||||||
_DOMImageElement = document.createElement("img");
|
// First, check if we need to destroy a current DOM image element. This is the case if :
|
||||||
|
// - we have one but not the right one (that is a DIV but needing an IMG, and vice versa)
|
||||||
|
|
||||||
|
if (_DOMImageElement)
|
||||||
|
{
|
||||||
|
if ((isIMGImageElement && isCSSBasedImage) || (!isIMGImageElement && !isCSSBasedImage))
|
||||||
|
{
|
||||||
|
// OK, destroy it
|
||||||
|
|
||||||
|
_DOMElement.removeChild(_DOMImageElement);
|
||||||
|
|
||||||
|
_DOMImageElement = nil;
|
||||||
|
|
||||||
|
// CSS styling cleaning
|
||||||
|
_cssStylePreviousState = @[];
|
||||||
|
_cssStyleNode = nil;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_DOMImageElement = document.createElement(isCSSBasedImage ? "div" : "img");
|
||||||
_DOMImageElement.style.position = "absolute";
|
_DOMImageElement.style.position = "absolute";
|
||||||
_DOMImageElement.style.left = "0px";
|
_DOMImageElement.style.left = "0px";
|
||||||
_DOMImageElement.style.top = "0px";
|
_DOMImageElement.style.top = "0px";
|
||||||
@@ -150,10 +172,15 @@ var CPImageViewEmptyPlaceholderImage = nil;
|
|||||||
var newImage = [self objectValue];
|
var newImage = [self objectValue];
|
||||||
|
|
||||||
#if PLATFORM(DOM)
|
#if PLATFORM(DOM)
|
||||||
if (!_DOMImageElement)
|
[self _createDOMImageElement];
|
||||||
[self _createDOMImageElement];
|
|
||||||
|
|
||||||
_DOMImageElement.src = newImage ? [newImage filename] : [CPImageViewEmptyPlaceholderImage filename];
|
if ([newImage isCSSBased])
|
||||||
|
_cssStyleNode = [newImage applyCSSImageForView:self
|
||||||
|
onDOMElement:_DOMImageElement
|
||||||
|
styleNode:_cssStyleNode
|
||||||
|
previousState:@ref(_cssStylePreviousState)];
|
||||||
|
else
|
||||||
|
_DOMImageElement.src = newImage ? [newImage filename] : [CPImageViewEmptyPlaceholderImage filename];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var size = [newImage size];
|
var size = [newImage size];
|
||||||
|
|||||||
@@ -857,7 +857,7 @@ var CPBindingOperationAnd = 0,
|
|||||||
- (id)initWithName:(CPString)aName
|
- (id)initWithName:(CPString)aName
|
||||||
{
|
{
|
||||||
if (self = [super init])
|
if (self = [super init])
|
||||||
_name = aName
|
_name = aName;
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -292,7 +292,7 @@ CPRatingLevelIndicatorStyle = 3;
|
|||||||
[self setNeedsLayout];
|
[self setNeedsLayout];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setWarningValue:(double)warningValue;
|
- (void)setWarningValue:(double)warningValue
|
||||||
{
|
{
|
||||||
if (_warningValue === warningValue)
|
if (_warningValue === warningValue)
|
||||||
return;
|
return;
|
||||||
@@ -301,7 +301,7 @@ CPRatingLevelIndicatorStyle = 3;
|
|||||||
[self setNeedsLayout];
|
[self setNeedsLayout];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setCriticalValue:(double)criticalValue;
|
- (void)setCriticalValue:(double)criticalValue
|
||||||
{
|
{
|
||||||
if (_criticalValue === criticalValue)
|
if (_criticalValue === criticalValue)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -505,7 +505,7 @@ CPOffState
|
|||||||
if (_submenu)
|
if (_submenu)
|
||||||
{
|
{
|
||||||
[_submenu setSupermenu:_menu];
|
[_submenu setSupermenu:_menu];
|
||||||
[_submenu setTitle:[self title]]
|
[_submenu setTitle:[self title]];
|
||||||
|
|
||||||
[self setTarget:_menu];
|
[self setTarget:_menu];
|
||||||
[self setAction:@selector(submenuAction:)];
|
[self setAction:@selector(submenuAction:)];
|
||||||
@@ -843,7 +843,7 @@ CPControlKeyMask
|
|||||||
[item setTarget:_target];
|
[item setTarget:_target];
|
||||||
[item setAction:_action];
|
[item setAction:_action];
|
||||||
[item setEnabled:_isEnabled];
|
[item setEnabled:_isEnabled];
|
||||||
[item setHidden:_isHidden]
|
[item setHidden:_isHidden];
|
||||||
[item setTag:_tag];
|
[item setTag:_tag];
|
||||||
[item setState:_state];
|
[item setState:_state];
|
||||||
[item setImage:_image];
|
[item setImage:_image];
|
||||||
|
|||||||
@@ -55,6 +55,7 @@
|
|||||||
@"menu-item-selection-color": [CPNull null],
|
@"menu-item-selection-color": [CPNull null],
|
||||||
@"menu-item-text-shadow-color": [CPNull null],
|
@"menu-item-text-shadow-color": [CPNull null],
|
||||||
@"menu-item-text-color": [CPNull null],
|
@"menu-item-text-color": [CPNull null],
|
||||||
|
@"menu-item-disabled-text-color": [CPColor lightGrayColor],
|
||||||
@"menu-item-default-off-state-image": [CPNull null],
|
@"menu-item-default-off-state-image": [CPNull null],
|
||||||
@"menu-item-default-off-state-highlighted-image": [CPNull null],
|
@"menu-item-default-off-state-highlighted-image": [CPNull null],
|
||||||
@"menu-item-default-on-state-image": [CPNull null],
|
@"menu-item-default-on-state-image": [CPNull null],
|
||||||
@@ -124,7 +125,7 @@
|
|||||||
- (CPColor)textColor
|
- (CPColor)textColor
|
||||||
{
|
{
|
||||||
if (![_menuItem isEnabled])
|
if (![_menuItem isEnabled])
|
||||||
return [CPColor lightGrayColor];
|
return [self valueForThemeAttribute:@"menu-item-disabled-text-color"];
|
||||||
|
|
||||||
if (_highlighted)
|
if (_highlighted)
|
||||||
return [CPColor whiteColor];
|
return [CPColor whiteColor];
|
||||||
|
|||||||
@@ -1923,7 +1923,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
|
|||||||
|
|
||||||
while (index !== CPNotFound)
|
while (index !== CPNotFound)
|
||||||
{
|
{
|
||||||
[items addObject:[_outlineView itemAtRow:index]]
|
[items addObject:[_outlineView itemAtRow:index]];
|
||||||
index = [theIndexes indexGreaterThanIndex:index];
|
index = [theIndexes indexGreaterThanIndex:index];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1957,7 +1957,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
|
|||||||
- (void)_parentItemForDropOperation:(CPTableViewDropOperation)theDropOperation row:(CPInteger)theRow offset:(CGPoint)theOffset
|
- (void)_parentItemForDropOperation:(CPTableViewDropOperation)theDropOperation row:(CPInteger)theRow offset:(CGPoint)theOffset
|
||||||
{
|
{
|
||||||
if (theDropOperation === CPTableViewDropAbove)
|
if (theDropOperation === CPTableViewDropAbove)
|
||||||
return [_outlineView _parentItemForUpperRow:theRow - 1 andLowerRow:theRow atMouseOffset:theOffset]
|
return [_outlineView _parentItemForUpperRow:theRow - 1 andLowerRow:theRow atMouseOffset:theOffset];
|
||||||
|
|
||||||
return [_outlineView itemAtRow:theRow];
|
return [_outlineView itemAtRow:theRow];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ CPURLPboardType = @"CPURLPboardType";
|
|||||||
CPImagesPboardType = @"CPImagesPboardType";
|
CPImagesPboardType = @"CPImagesPboardType";
|
||||||
CPVideosPboardType = @"CPVideosPboardType";
|
CPVideosPboardType = @"CPVideosPboardType";
|
||||||
CPRTFPboardType = @"CPRTFPboardType";
|
CPRTFPboardType = @"CPRTFPboardType";
|
||||||
|
_CPSmartPboardType = @"_CPSmartPboardType";
|
||||||
|
|
||||||
UTF8PboardType = @"public.utf8-plain-text";
|
UTF8PboardType = @"public.utf8-plain-text";
|
||||||
|
|
||||||
|
|||||||
@@ -463,13 +463,13 @@ var CPProgressIndicatorSpinningStyleColors = [];
|
|||||||
var midX = CGRectGetMidX(rect),
|
var midX = CGRectGetMidX(rect),
|
||||||
midY = CGRectGetMidY(rect),
|
midY = CGRectGetMidY(rect),
|
||||||
endAngle = Math.PI * 2 * (([self doubleValue] - [self minValue]) / ([self maxValue] - [self minValue])) - Math.PI / 2,
|
endAngle = Math.PI * 2 * (([self doubleValue] - [self minValue]) / ([self maxValue] - [self minValue])) - Math.PI / 2,
|
||||||
radius = MIN(rect.size.width / 2, rect.size.height / 2)
|
radius = MIN(rect.size.width / 2, rect.size.height / 2);
|
||||||
|
|
||||||
CGContextBeginPath(context);
|
CGContextBeginPath(context);
|
||||||
CGContextSetLineWidth(context, borderSize);
|
CGContextSetLineWidth(context, borderSize);
|
||||||
CGContextSetFillColor(context, [self currentValueForThemeAttribute:@"circular-color"])
|
CGContextSetFillColor(context, [self currentValueForThemeAttribute:@"circular-color"]);
|
||||||
CGContextMoveToPoint(context, midX, midY);
|
CGContextMoveToPoint(context, midX, midY);
|
||||||
CGContextAddArc(context, midX, midY, radius, 3 * Math.PI / 2, endAngle, YES)
|
CGContextAddArc(context, midX, midY, radius, 3 * Math.PI / 2, endAngle, YES);
|
||||||
CGContextAddLineToPoint(context, midX, midY);
|
CGContextAddLineToPoint(context, midX, midY);
|
||||||
CGContextClosePath(context);
|
CGContextClosePath(context);
|
||||||
CGContextFillPath(context);
|
CGContextFillPath(context);
|
||||||
@@ -478,7 +478,7 @@ var CPProgressIndicatorSpinningStyleColors = [];
|
|||||||
else if ([self doubleValue] == [self maxValue])
|
else if ([self doubleValue] == [self maxValue])
|
||||||
{
|
{
|
||||||
CGContextBeginPath(context);
|
CGContextBeginPath(context);
|
||||||
CGContextSetFillColor(context, [self currentValueForThemeAttribute:@"circular-color"])
|
CGContextSetFillColor(context, [self currentValueForThemeAttribute:@"circular-color"]);
|
||||||
CGContextAddEllipseInRect(context, rect);
|
CGContextAddEllipseInRect(context, rect);
|
||||||
CGContextClosePath(context);
|
CGContextClosePath(context);
|
||||||
CGContextFillPath(context);
|
CGContextFillPath(context);
|
||||||
|
|||||||
@@ -209,8 +209,7 @@
|
|||||||
|
|
||||||
- (void)_reconfigureSubviews
|
- (void)_reconfigureSubviews
|
||||||
{
|
{
|
||||||
var ruleItems,
|
var criteria,
|
||||||
criteria,
|
|
||||||
repObject,
|
repObject,
|
||||||
menuItem,
|
menuItem,
|
||||||
ruleView,
|
ruleView,
|
||||||
|
|||||||
@@ -35,6 +35,11 @@
|
|||||||
CPArray _allowedFileTypes @accessors(property=allowedFileTypes);
|
CPArray _allowedFileTypes @accessors(property=allowedFileTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (CPURL)proposedFileURLWithDocumentName:(CPString)aDocumentName
|
||||||
|
{
|
||||||
|
return [CPURL URLWithString:aDocumentName];
|
||||||
|
}
|
||||||
|
|
||||||
+ (id)savePanel
|
+ (id)savePanel
|
||||||
{
|
{
|
||||||
return [[CPSavePanel alloc] init];
|
return [[CPSavePanel alloc] init];
|
||||||
|
|||||||
@@ -1253,7 +1253,7 @@ Notifies the delegate when the scroll view has finished scrolling.
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_timerScrollersHide)
|
if (_timerScrollersHide)
|
||||||
[_timerScrollersHide invalidate]
|
[_timerScrollersHide invalidate];
|
||||||
|
|
||||||
_timerScrollersHide = [CPTimer scheduledTimerWithTimeInterval:CPScrollViewFadeOutTime target:self selector:@selector(_hideScrollers:) userInfo:nil repeats:NO];
|
_timerScrollersHide = [CPTimer scheduledTimerWithTimeInterval:CPScrollViewFadeOutTime target:self selector:@selector(_hideScrollers:) userInfo:nil repeats:NO];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -380,9 +380,10 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
|
|||||||
effectiveIncrementLineHeight = incrementLineSize.height + trackInset.bottom,
|
effectiveIncrementLineHeight = incrementLineSize.height + trackInset.bottom,
|
||||||
slotSize = height - effectiveDecrementLineHeight - effectiveIncrementLineHeight,
|
slotSize = height - effectiveDecrementLineHeight - effectiveIncrementLineHeight,
|
||||||
minimumKnobLength = [self currentValueForThemeAttribute:"minimum-knob-length"],
|
minimumKnobLength = [self currentValueForThemeAttribute:"minimum-knob-length"],
|
||||||
|
knobVerticalInset = knobInset.top + knobInset.bottom,
|
||||||
knobWidth = width - knobInset.left - knobInset.right,
|
knobWidth = width - knobInset.left - knobInset.right,
|
||||||
knobHeight = MAX(minimumKnobLength, (slotSize * _knobProportion)),
|
knobHeight = MAX(minimumKnobLength, ((slotSize - knobVerticalInset) * _knobProportion)),
|
||||||
knobLocation = effectiveDecrementLineHeight + (slotSize - knobHeight) * [self floatValue];
|
knobLocation = effectiveDecrementLineHeight + (slotSize - knobHeight - knobVerticalInset) * [self floatValue] + knobInset.top;
|
||||||
|
|
||||||
_partRects[CPScrollerDecrementPage] = CGRectMake(0.0, effectiveDecrementLineHeight, width, knobLocation - effectiveDecrementLineHeight);
|
_partRects[CPScrollerDecrementPage] = CGRectMake(0.0, effectiveDecrementLineHeight, width, knobLocation - effectiveDecrementLineHeight);
|
||||||
_partRects[CPScrollerKnob] = CGRectMake(knobInset.left, knobLocation, knobWidth, knobHeight);
|
_partRects[CPScrollerKnob] = CGRectMake(knobInset.left, knobLocation, knobWidth, knobHeight);
|
||||||
@@ -409,9 +410,10 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
|
|||||||
effectiveIncrementLineWidth = incrementLineSize.width + trackInset.right,
|
effectiveIncrementLineWidth = incrementLineSize.width + trackInset.right,
|
||||||
slotSize = width - effectiveDecrementLineWidth - effectiveIncrementLineWidth,
|
slotSize = width - effectiveDecrementLineWidth - effectiveIncrementLineWidth,
|
||||||
minimumKnobLength = [self currentValueForThemeAttribute:"minimum-knob-length"],
|
minimumKnobLength = [self currentValueForThemeAttribute:"minimum-knob-length"],
|
||||||
knobWidth = MAX(minimumKnobLength, (slotSize * _knobProportion)),
|
knobHorizontalInset = knobInset.left + knobInset.right,
|
||||||
|
knobWidth = MAX(minimumKnobLength, ((slotSize - knobHorizontalInset) * _knobProportion)),
|
||||||
knobHeight = height - knobInset.top - knobInset.bottom,
|
knobHeight = height - knobInset.top - knobInset.bottom,
|
||||||
knobLocation = effectiveDecrementLineWidth + (slotSize - knobWidth) * [self floatValue];
|
knobLocation = effectiveDecrementLineWidth + (slotSize - knobWidth - knobHorizontalInset) * [self floatValue] + knobInset.left;
|
||||||
|
|
||||||
_partRects[CPScrollerDecrementPage] = CGRectMake(effectiveDecrementLineWidth, 0.0, knobLocation - effectiveDecrementLineWidth, height);
|
_partRects[CPScrollerDecrementPage] = CGRectMake(effectiveDecrementLineWidth, 0.0, knobLocation - effectiveDecrementLineWidth, height);
|
||||||
_partRects[CPScrollerKnob] = CGRectMake(knobLocation, knobInset.top, knobWidth, knobHeight);
|
_partRects[CPScrollerKnob] = CGRectMake(knobLocation, knobInset.top, knobWidth, knobHeight);
|
||||||
@@ -460,9 +462,6 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
|
|||||||
*/
|
*/
|
||||||
- (void)fadeOut
|
- (void)fadeOut
|
||||||
{
|
{
|
||||||
if ([self hasThemeState:CPThemeStateScrollViewLegacy])
|
|
||||||
return;
|
|
||||||
|
|
||||||
[_animationScroller startAnimation];
|
[_animationScroller startAnimation];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -765,7 +764,10 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
|
|||||||
if (_timerFadeOut)
|
if (_timerFadeOut)
|
||||||
[_timerFadeOut invalidate];
|
[_timerFadeOut invalidate];
|
||||||
|
|
||||||
_timerFadeOut = [CPTimer scheduledTimerWithTimeInterval:1.2 target:self selector:@selector(_performFadeOut:) userInfo:nil repeats:NO];
|
if ([self hasThemeState:CPThemeStateScrollViewLegacy])
|
||||||
|
[self unsetThemeState:CPThemeStateSelected];
|
||||||
|
else
|
||||||
|
_timerFadeOut = [CPTimer scheduledTimerWithTimeInterval:1.2 target:self selector:@selector(_performFadeOut:) userInfo:nil repeats:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -73,10 +73,19 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
|
|||||||
@"image-cancel": [CPNull null],
|
@"image-cancel": [CPNull null],
|
||||||
@"image-cancel-pressed": [CPNull null],
|
@"image-cancel-pressed": [CPNull null],
|
||||||
@"image-search-inset" : CGInsetMake(0, 0, 0, 5),
|
@"image-search-inset" : CGInsetMake(0, 0, 0, 5),
|
||||||
@"image-cancel-inset" : CGInsetMake(0, 5, 0, 0)
|
@"image-cancel-inset" : CGInsetMake(0, 5, 0, 0),
|
||||||
|
@"search-right-margin": 2
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (Class)_binderClassForBinding:(CPString)aBinding
|
||||||
|
{
|
||||||
|
if (aBinding === CPPredicateBinding)
|
||||||
|
return [_CPSearchFieldPredicateBinder class];
|
||||||
|
|
||||||
|
return [super _binderClassForBinding:aBinding];
|
||||||
|
}
|
||||||
|
|
||||||
- (id)initWithFrame:(CGRect)frame
|
- (id)initWithFrame:(CGRect)frame
|
||||||
{
|
{
|
||||||
if (self = [super initWithFrame:frame])
|
if (self = [super initWithFrame:frame])
|
||||||
@@ -87,10 +96,6 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
|
|||||||
_recentsAutosaveName = nil;
|
_recentsAutosaveName = nil;
|
||||||
|
|
||||||
[self _init];
|
[self _init];
|
||||||
#if PLATFORM(DOM)
|
|
||||||
_cancelButton._DOMElement.style.cursor = "default";
|
|
||||||
_searchButton._DOMElement.style.cursor = "default";
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
@@ -177,7 +182,7 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
|
|||||||
- (void)resetSearchButton
|
- (void)resetSearchButton
|
||||||
{
|
{
|
||||||
var button = [self searchButton],
|
var button = [self searchButton],
|
||||||
searchButtonImage = (_searchMenuTemplate === nil) ? [self valueForThemeAttribute:@"image-search"] : [self valueForThemeAttribute:@"image-find"];
|
searchButtonImage = (_searchMenuTemplate === nil) ? [self currentValueForThemeAttribute:@"image-search"] : [self currentValueForThemeAttribute:@"image-find"];
|
||||||
|
|
||||||
[button setBordered:NO];
|
[button setBordered:NO];
|
||||||
[button setImageScaling:CPImageScaleAxesIndependently];
|
[button setImageScaling:CPImageScaleAxesIndependently];
|
||||||
@@ -246,8 +251,9 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
|
|||||||
|
|
||||||
if (_searchButton)
|
if (_searchButton)
|
||||||
{
|
{
|
||||||
var searchBounds = [self searchButtonRectForBounds:bounds];
|
var searchBounds = [self searchButtonRectForBounds:bounds],
|
||||||
leftOffset = CGRectGetMaxX(searchBounds) + 2;
|
rightMargin = [self currentValueForThemeAttribute:@"search-right-margin"];
|
||||||
|
leftOffset = CGRectGetMaxX(searchBounds) + rightMargin;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_cancelButton)
|
if (_cancelButton)
|
||||||
@@ -386,9 +392,9 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
|
|||||||
*/
|
*/
|
||||||
- (void)setRecentSearches:(CPArray)searches
|
- (void)setRecentSearches:(CPArray)searches
|
||||||
{
|
{
|
||||||
var max = MIN([self maximumRecents], [searches count]),
|
var max = MIN([self maximumRecents], [searches count]);
|
||||||
searches = [searches subarrayWithRange:CPMakeRange(0, max)];
|
|
||||||
|
|
||||||
|
searches = [searches subarrayWithRange:CPMakeRange(0, max)];
|
||||||
_recentSearches = searches;
|
_recentSearches = searches;
|
||||||
[self _autosaveRecentSearchList];
|
[self _autosaveRecentSearchList];
|
||||||
}
|
}
|
||||||
@@ -531,19 +537,16 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Provides the common case items for a recent searches menu. If there are not recent searches,
|
Provides the common case items for a recent searches menu.
|
||||||
displays a single disabled item:
|
|
||||||
|
|
||||||
No Recent Searches
|
|
||||||
|
|
||||||
If there are 1 more recent searches, it displays:
|
If there are 1 more recent searches, it displays:
|
||||||
|
|
||||||
Recent Searches
|
Clear
|
||||||
recent search 1
|
|
||||||
recent search 2
|
|
||||||
etc.
|
|
||||||
---------------------
|
---------------------
|
||||||
Clear Recent Searches
|
Recent Searches
|
||||||
|
recent search 1
|
||||||
|
recent search 2
|
||||||
|
etc.
|
||||||
|
|
||||||
If you wish to add items before or after the template, you can. If you put items
|
If you wish to add items before or after the template, you can. If you put items
|
||||||
before, a separator will automatically be placed before the default template item.
|
before, a separator will automatically be placed before the default template item.
|
||||||
@@ -568,6 +571,13 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
|
|||||||
var template = [[CPMenu alloc] init],
|
var template = [[CPMenu alloc] init],
|
||||||
item;
|
item;
|
||||||
|
|
||||||
|
item = [[CPMenuItem alloc] initWithTitle:@"Clear"
|
||||||
|
action:@selector(_searchFieldClearRecents:)
|
||||||
|
keyEquivalent:@""];
|
||||||
|
[item setTag:CPSearchFieldClearRecentsMenuItemTag];
|
||||||
|
[item setTarget:self];
|
||||||
|
[template addItem:item];
|
||||||
|
|
||||||
item = [[CPMenuItem alloc] initWithTitle:@"Recent Searches"
|
item = [[CPMenuItem alloc] initWithTitle:@"Recent Searches"
|
||||||
action:nil
|
action:nil
|
||||||
keyEquivalent:@""];
|
keyEquivalent:@""];
|
||||||
@@ -582,20 +592,6 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
|
|||||||
[item setTarget:self];
|
[item setTarget:self];
|
||||||
[template addItem:item];
|
[template addItem:item];
|
||||||
|
|
||||||
item = [[CPMenuItem alloc] initWithTitle:@"Clear Recent Searches"
|
|
||||||
action:@selector(_searchFieldClearRecents:)
|
|
||||||
keyEquivalent:@""];
|
|
||||||
[item setTag:CPSearchFieldClearRecentsMenuItemTag];
|
|
||||||
[item setTarget:self];
|
|
||||||
[template addItem:item];
|
|
||||||
|
|
||||||
item = [[CPMenuItem alloc] initWithTitle:@"No Recent Searches"
|
|
||||||
action:nil
|
|
||||||
keyEquivalent:@""];
|
|
||||||
[item setTag:CPSearchFieldNoRecentsMenuItemTag];
|
|
||||||
[item setEnabled:NO];
|
|
||||||
[template addItem:item];
|
|
||||||
|
|
||||||
return template;
|
return template;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -608,6 +604,8 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
|
|||||||
countOfRecents = [_recentSearches count],
|
countOfRecents = [_recentSearches count],
|
||||||
numberOfItems = [_searchMenuTemplate numberOfItems];
|
numberOfItems = [_searchMenuTemplate numberOfItems];
|
||||||
|
|
||||||
|
[menu setAutoenablesItems:NO];
|
||||||
|
|
||||||
for (var i = 0; i < numberOfItems; i++)
|
for (var i = 0; i < numberOfItems; i++)
|
||||||
{
|
{
|
||||||
var item = [[_searchMenuTemplate itemAtIndex:i] copy];
|
var item = [[_searchMenuTemplate itemAtIndex:i] copy];
|
||||||
@@ -631,7 +629,6 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
|
|||||||
var recentItem = [[CPMenuItem alloc] initWithTitle:[_recentSearches objectAtIndex:recentIndex]
|
var recentItem = [[CPMenuItem alloc] initWithTitle:[_recentSearches objectAtIndex:recentIndex]
|
||||||
action:itemAction
|
action:itemAction
|
||||||
keyEquivalent:[item keyEquivalent]];
|
keyEquivalent:[item keyEquivalent]];
|
||||||
[recentItem setIndentationLevel:1];
|
|
||||||
[item setTarget:self];
|
[item setTarget:self];
|
||||||
[menu addItem:recentItem];
|
[menu addItem:recentItem];
|
||||||
}
|
}
|
||||||
@@ -689,7 +686,7 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
|
|||||||
|
|
||||||
- (void)_showMenu
|
- (void)_showMenu
|
||||||
{
|
{
|
||||||
if (_searchMenu === nil || [_searchMenu numberOfItems] === 0 || ![self isEnabled])
|
if (_searchMenu === nil || [_searchMenu numberOfItems] === 0 || ![self isEnabled] || ([_recentSearches count] === 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var aFrame = [[self superview] convertRect:[self frame] toView:nil],
|
var aFrame = [[self superview] convertRect:[self frame] toView:nil],
|
||||||
@@ -771,8 +768,75 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
|
|||||||
_recentSearches = list;
|
_recentSearches = list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)unbind:(CPString)aBinding
|
||||||
|
{
|
||||||
|
[super unbind:aBinding];
|
||||||
|
|
||||||
|
// our CPPredicateBinding binder adds a binding to the value.
|
||||||
|
// this private binding has to be also removed
|
||||||
|
if (aBinding === CPPredicateBinding)
|
||||||
|
[[[self class] _binderClassForBinding:aBinding] unbind:CPValueBinding forObject:self];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
|
||||||
|
@implementation CPSearchField (CPTrackingArea)
|
||||||
|
{
|
||||||
|
CPTrackingArea _searchButtonTrackingArea;
|
||||||
|
CPTrackingArea _cancelButtonTrackingArea;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)updateTrackingAreas
|
||||||
|
{
|
||||||
|
if (_searchButtonTrackingArea)
|
||||||
|
{
|
||||||
|
[self removeTrackingArea:_searchButtonTrackingArea];
|
||||||
|
_searchButtonTrackingArea = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_cancelButtonTrackingArea)
|
||||||
|
{
|
||||||
|
[self removeTrackingArea:_cancelButtonTrackingArea];
|
||||||
|
_cancelButtonTrackingArea = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_searchButton)
|
||||||
|
{
|
||||||
|
_searchButtonTrackingArea = [[CPTrackingArea alloc] initWithRect:[_searchButton frame]
|
||||||
|
options:CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow
|
||||||
|
owner:self
|
||||||
|
userInfo:@{ @"isButton": YES }];
|
||||||
|
|
||||||
|
[self addTrackingArea:_searchButtonTrackingArea];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_cancelButton)
|
||||||
|
{
|
||||||
|
_cancelButtonTrackingArea = [[CPTrackingArea alloc] initWithRect:[_cancelButton frame]
|
||||||
|
options:CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow
|
||||||
|
owner:self
|
||||||
|
userInfo:@{ @"isButton": YES }];
|
||||||
|
|
||||||
|
[self addTrackingArea:_cancelButtonTrackingArea];
|
||||||
|
}
|
||||||
|
|
||||||
|
[super updateTrackingAreas];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)cursorUpdate:(CPEvent)anEvent
|
||||||
|
{
|
||||||
|
if ([[[anEvent trackingArea] userInfo] objectForKey:@"isButton"])
|
||||||
|
[[CPCursor arrowCursor] set];
|
||||||
|
else
|
||||||
|
[super cursorUpdate:anEvent];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
|
||||||
var CPRecentsAutosaveNameKey = @"CPRecentsAutosaveNameKey",
|
var CPRecentsAutosaveNameKey = @"CPRecentsAutosaveNameKey",
|
||||||
CPSendsWholeSearchStringKey = @"CPSendsWholeSearchStringKey",
|
CPSendsWholeSearchStringKey = @"CPSendsWholeSearchStringKey",
|
||||||
CPSendsSearchStringImmediatelyKey = @"CPSendsSearchStringImmediatelyKey",
|
CPSendsSearchStringImmediatelyKey = @"CPSendsSearchStringImmediatelyKey",
|
||||||
@@ -825,3 +889,44 @@ var CPRecentsAutosaveNameKey = @"CPRecentsAutosaveNameKey",
|
|||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@implementation _CPSearchFieldPredicateBinder : CPBinder
|
||||||
|
{
|
||||||
|
CPArrayController _controller;
|
||||||
|
CPString _predicateFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setValue:(id)aValue forBinding:(CPString)aBinding
|
||||||
|
{
|
||||||
|
if (aBinding === CPPredicateBinding)
|
||||||
|
{
|
||||||
|
var options = [_info objectForKey:CPOptionsKey];
|
||||||
|
|
||||||
|
_controller = [_info objectForKey:CPObservedObjectKey];
|
||||||
|
_predicateFormat = [options objectForKey:"CPPredicateFormat"];
|
||||||
|
[_source bind:CPValueBinding toObject:self withKeyPath:"searchFieldValue" options:nil];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setSearchFieldValue:(CPString)aValue
|
||||||
|
{
|
||||||
|
var destination = [_info objectForKey:CPObservedObjectKey],
|
||||||
|
keyPath = [_info objectForKey:CPObservedKeyPathKey];
|
||||||
|
|
||||||
|
var formatString = _predicateFormat.replace(/\$value/g, "%@");
|
||||||
|
[self suppressSpecificNotificationFromObject:destination keyPath:keyPath];
|
||||||
|
|
||||||
|
if (aValue)
|
||||||
|
[_controller setFilterPredicate:[CPPredicate predicateWithFormat:formatString, aValue]];
|
||||||
|
else
|
||||||
|
[_controller setFilterPredicate:nil];
|
||||||
|
|
||||||
|
[self unsuppressSpecificNotificationFromObject:destination keyPath:keyPath];
|
||||||
|
}
|
||||||
|
- (CPString)searchFieldValue
|
||||||
|
{
|
||||||
|
return [_source stringValue];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -872,64 +872,68 @@ CPSegmentSwitchTrackingMomentary = 2;
|
|||||||
var type = [anEvent type],
|
var type = [anEvent type],
|
||||||
location = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
location = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
||||||
|
|
||||||
if (type == CPLeftMouseUp)
|
switch (type)
|
||||||
{
|
{
|
||||||
if (_trackingSegment == -1)
|
case CPLeftMouseUp:
|
||||||
|
|
||||||
|
if (_trackingSegment === CPNotFound)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_trackingSegment === [self testSegment:location])
|
||||||
|
{
|
||||||
|
if (_trackingMode == CPSegmentSwitchTrackingSelectAny)
|
||||||
|
{
|
||||||
|
[self setSelected:![self isSelectedForSegment:_trackingSegment] forSegment:_trackingSegment];
|
||||||
|
|
||||||
|
// With ANY, _selectedSegment means last pressed.
|
||||||
|
_selectedSegment = _trackingSegment;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
[self setSelected:YES forSegment:_trackingSegment];
|
||||||
|
|
||||||
|
[self sendAction:[self action] to:[self target]];
|
||||||
|
|
||||||
|
if (_trackingMode == CPSegmentSwitchTrackingMomentary)
|
||||||
|
{
|
||||||
|
[self setSelected:NO forSegment:_trackingSegment];
|
||||||
|
|
||||||
|
_selectedSegment = CPNotFound;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[self drawSegmentBezel:_trackingSegment highlight:NO];
|
||||||
|
|
||||||
|
_trackingSegment = CPNotFound;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_trackingSegment === [self testSegment:location])
|
case CPLeftMouseDown:
|
||||||
{
|
|
||||||
if (_trackingMode == CPSegmentSwitchTrackingSelectAny)
|
var trackingSegment = [self testSegment:location];
|
||||||
|
if (trackingSegment > CPNotFound && [self isEnabledForSegment:trackingSegment])
|
||||||
{
|
{
|
||||||
[self setSelected:![self isSelectedForSegment:_trackingSegment] forSegment:_trackingSegment];
|
_trackingHighlighted = YES;
|
||||||
|
_trackingSegment = trackingSegment;
|
||||||
// With ANY, _selectedSegment means last pressed.
|
[self drawSegmentBezel:_trackingSegment highlight:YES];
|
||||||
_selectedSegment = _trackingSegment;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
[self setSelected:YES forSegment:_trackingSegment];
|
|
||||||
|
|
||||||
[self sendAction:[self action] to:[self target]];
|
break;
|
||||||
|
|
||||||
if (_trackingMode == CPSegmentSwitchTrackingMomentary)
|
case CPLeftMouseDragged:
|
||||||
|
|
||||||
|
if (_trackingSegment === CPNotFound)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var highlighted = [self testSegment:location] === _trackingSegment;
|
||||||
|
|
||||||
|
if (highlighted != _trackingHighlighted)
|
||||||
{
|
{
|
||||||
[self setSelected:NO forSegment:_trackingSegment];
|
_trackingHighlighted = highlighted;
|
||||||
|
|
||||||
_selectedSegment = CPNotFound;
|
[self drawSegmentBezel:_trackingSegment highlight:_trackingHighlighted];
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
[self drawSegmentBezel:_trackingSegment highlight:NO];
|
break;
|
||||||
|
|
||||||
_trackingSegment = -1;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == CPLeftMouseDown)
|
|
||||||
{
|
|
||||||
var trackingSegment = [self testSegment:location];
|
|
||||||
if (trackingSegment > -1 && [self isEnabledForSegment:trackingSegment])
|
|
||||||
{
|
|
||||||
_trackingHighlighted = YES;
|
|
||||||
_trackingSegment = trackingSegment;
|
|
||||||
[self drawSegmentBezel:_trackingSegment highlight:YES];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (type == CPLeftMouseDragged)
|
|
||||||
{
|
|
||||||
if (_trackingSegment == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var highlighted = [self testSegment:location] === _trackingSegment;
|
|
||||||
|
|
||||||
if (highlighted != _trackingHighlighted)
|
|
||||||
{
|
|
||||||
_trackingHighlighted = highlighted;
|
|
||||||
|
|
||||||
[self drawSegmentBezel:_trackingSegment highlight:_trackingHighlighted];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[CPApp setTarget:self selector:@selector(trackSegment:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
|
[CPApp setTarget:self selector:@selector(trackSegment:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
|
||||||
|
|||||||
@@ -117,6 +117,7 @@ var ShouldSuppressResizeNotifications = 1,
|
|||||||
CPArray _DOMDividerElements;
|
CPArray _DOMDividerElements;
|
||||||
CPString _dividerImagePath;
|
CPString _dividerImagePath;
|
||||||
int _drawingDivider;
|
int _drawingDivider;
|
||||||
|
BOOL _isTracking;
|
||||||
|
|
||||||
CPString _autosaveName;
|
CPString _autosaveName;
|
||||||
BOOL _shouldAutosave;
|
BOOL _shouldAutosave;
|
||||||
@@ -158,6 +159,7 @@ var ShouldSuppressResizeNotifications = 1,
|
|||||||
_buttonBars = [];
|
_buttonBars = [];
|
||||||
|
|
||||||
_shouldAutosave = YES;
|
_shouldAutosave = YES;
|
||||||
|
_isTracking = NO;
|
||||||
|
|
||||||
[self _setVertical:YES];
|
[self _setVertical:YES];
|
||||||
}
|
}
|
||||||
@@ -213,6 +215,9 @@ var ShouldSuppressResizeNotifications = 1,
|
|||||||
[_subviews[index] setFrame:CGRectMake(0, ROUND((eachSize + dividerThickness) * index), frame.size.width, eachSize)];
|
[_subviews[index] setFrame:CGRectMake(0, ROUND((eachSize + dividerThickness) * index), frame.size.width, eachSize)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_DOMDividerElements[_drawingDivider])
|
||||||
|
[self _setupDOMDivider];
|
||||||
|
|
||||||
[self setNeedsDisplay:YES];
|
[self setNeedsDisplay:YES];
|
||||||
[self _postNotificationDidResize];
|
[self _postNotificationDidResize];
|
||||||
|
|
||||||
@@ -363,9 +368,9 @@ var ShouldSuppressResizeNotifications = 1,
|
|||||||
_DOMDividerElements[_drawingDivider].style.backgroundRepeat = "repeat";
|
_DOMDividerElements[_drawingDivider].style.backgroundRepeat = "repeat";
|
||||||
|
|
||||||
CPDOMDisplayServerAppendChild(_DOMElement, _DOMDividerElements[_drawingDivider]);
|
CPDOMDisplayServerAppendChild(_DOMElement, _DOMDividerElements[_drawingDivider]);
|
||||||
|
[self _setupDOMDivider];
|
||||||
}
|
}
|
||||||
|
|
||||||
[self _setupDOMDivider];
|
|
||||||
CPDOMDisplayServerSetStyleLeftTop(_DOMDividerElements[_drawingDivider], NULL, CGRectGetMinX(aRect), CGRectGetMinY(aRect));
|
CPDOMDisplayServerSetStyleLeftTop(_DOMDividerElements[_drawingDivider], NULL, CGRectGetMinX(aRect), CGRectGetMinY(aRect));
|
||||||
CPDOMDisplayServerSetStyleSize(_DOMDividerElements[_drawingDivider], CGRectGetWidth(aRect), CGRectGetHeight(aRect));
|
CPDOMDisplayServerSetStyleSize(_DOMDividerElements[_drawingDivider], CGRectGetWidth(aRect), CGRectGetHeight(aRect));
|
||||||
#endif
|
#endif
|
||||||
@@ -452,17 +457,26 @@ var ShouldSuppressResizeNotifications = 1,
|
|||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
var point = [self convertPoint:aPoint fromView:[self superview]],
|
var point = [self convertPoint:aPoint fromView:[self superview]],
|
||||||
count = [_subviews count] - 1;
|
dividerIndex = [self _dividerAtPoint:point];
|
||||||
|
|
||||||
for (var i = 0; i < count; i++)
|
if (dividerIndex !== CPNotFound)
|
||||||
{
|
return self;
|
||||||
if ([self cursorAtPoint:point hitDividerAtIndex:i])
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
return [super hitTest:aPoint];
|
return [super hitTest:aPoint];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (CPInteger)_dividerAtPoint:(CGPoint)aPoint
|
||||||
|
{
|
||||||
|
var count = [_subviews count] - 1;
|
||||||
|
|
||||||
|
for (var i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
if ([self cursorAtPoint:aPoint hitDividerAtIndex:i])
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CPNotFound;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
Tracks the divider.
|
Tracks the divider.
|
||||||
@param anEvent the input event
|
@param anEvent the input event
|
||||||
@@ -473,12 +487,13 @@ var ShouldSuppressResizeNotifications = 1,
|
|||||||
|
|
||||||
if (type == CPLeftMouseUp)
|
if (type == CPLeftMouseUp)
|
||||||
{
|
{
|
||||||
// We disabled autosaving during tracking.
|
if ([anEvent clickCount] == 2 || (_isTracking && _currentDivider != CPNotFound))
|
||||||
_shouldAutosave = YES;
|
|
||||||
|
|
||||||
if (_currentDivider != CPNotFound)
|
|
||||||
{
|
{
|
||||||
|
// We disabled autosaving during tracking.
|
||||||
|
_shouldAutosave = YES;
|
||||||
_currentDivider = CPNotFound;
|
_currentDivider = CPNotFound;
|
||||||
|
_isTracking = NO;
|
||||||
|
|
||||||
[self _autosave];
|
[self _autosave];
|
||||||
[self _updateResizeCursor:anEvent];
|
[self _updateResizeCursor:anEvent];
|
||||||
}
|
}
|
||||||
@@ -488,59 +503,55 @@ var ShouldSuppressResizeNotifications = 1,
|
|||||||
|
|
||||||
if (type == CPLeftMouseDown)
|
if (type == CPLeftMouseDown)
|
||||||
{
|
{
|
||||||
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil],
|
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
||||||
count = [_subviews count] - 1;
|
_currentDivider = [self _dividerAtPoint:point];
|
||||||
|
|
||||||
_currentDivider = CPNotFound;
|
var frame = [_subviews[_currentDivider] frame],
|
||||||
|
startPosition = frame.origin[_originComponent] + frame.size[_sizeComponent];
|
||||||
|
|
||||||
for (var i = 0; i < count; i++)
|
if ([anEvent clickCount] == 2 &&
|
||||||
|
[self _delegateRespondsToSplitViewCanCollapseSubview] &&
|
||||||
|
[self _delegateRespondsToSplitViewshouldCollapseSubviewForDoubleClickOnDividerAtIndex])
|
||||||
{
|
{
|
||||||
var frame = [_subviews[i] frame],
|
var minPosition = [self minPossiblePositionOfDividerAtIndex:_currentDivider],
|
||||||
startPosition = frame.origin[_originComponent] + frame.size[_sizeComponent];
|
maxPosition = [self maxPossiblePositionOfDividerAtIndex:_currentDivider],
|
||||||
|
preCollapsePosition = [_preCollapsePositions objectForKey:"" + _currentDivider] || 0;
|
||||||
|
|
||||||
if ([self cursorAtPoint:point hitDividerAtIndex:i])
|
if ([self _sendDelegateSplitViewCanCollapseSubview:_subviews[_currentDivider]] && [self _sendDelegateSplitViewShouldCollapseSubview:_subviews[_currentDivider] forDoubleClickOnDividerAtIndex:_currentDivider])
|
||||||
{
|
{
|
||||||
if ([anEvent clickCount] == 2 &&
|
if ([self isSubviewCollapsed:_subviews[_currentDivider]])
|
||||||
[self _delegateRespondsToSplitViewCanCollapseSubview] &&
|
[self setPosition:preCollapsePosition ? preCollapsePosition : (minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:_currentDivider];
|
||||||
[self _delegateRespondsToSplitViewshouldCollapseSubviewForDoubleClickOnDividerAtIndex])
|
|
||||||
{
|
|
||||||
var minPosition = [self minPossiblePositionOfDividerAtIndex:i],
|
|
||||||
maxPosition = [self maxPossiblePositionOfDividerAtIndex:i],
|
|
||||||
preCollapsePosition = [_preCollapsePositions objectForKey:"" + i] || 0;
|
|
||||||
|
|
||||||
if ([self _sendDelegateSplitViewCanCollapseSubview:_subviews[i]] && [self _sendDelegateSplitViewShouldCollapseSubview:_subviews[i] forDoubleClickOnDividerAtIndex:i])
|
|
||||||
{
|
|
||||||
if ([self isSubviewCollapsed:_subviews[i]])
|
|
||||||
[self setPosition:preCollapsePosition ? preCollapsePosition : (minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i];
|
|
||||||
else
|
|
||||||
[self setPosition:minPosition ofDividerAtIndex:i];
|
|
||||||
}
|
|
||||||
else if ([self _sendDelegateSplitViewCanCollapseSubview:_subviews[i + 1]] && [self _sendDelegateSplitViewShouldCollapseSubview:_subviews[i + 1] forDoubleClickOnDividerAtIndex:i])
|
|
||||||
{
|
|
||||||
if ([self isSubviewCollapsed:_subviews[i + 1]])
|
|
||||||
[self setPosition:preCollapsePosition ? preCollapsePosition : (minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i];
|
|
||||||
else
|
|
||||||
[self setPosition:maxPosition ofDividerAtIndex:i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
[self setPosition:minPosition ofDividerAtIndex:_currentDivider];
|
||||||
_currentDivider = i;
|
}
|
||||||
_initialOffset = startPosition - point[_originComponent];
|
else if ([self _sendDelegateSplitViewCanCollapseSubview:_subviews[_currentDivider + 1]] && [self _sendDelegateSplitViewShouldCollapseSubview:_subviews[_currentDivider + 1] forDoubleClickOnDividerAtIndex:_currentDivider])
|
||||||
|
{
|
||||||
// Don't autosave during a resize. We'll wait until it's done.
|
if ([self isSubviewCollapsed:_subviews[_currentDivider + 1]])
|
||||||
_shouldAutosave = NO;
|
[self setPosition:preCollapsePosition ? preCollapsePosition : (minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:_currentDivider];
|
||||||
[self _postNotificationWillResize];
|
else
|
||||||
}
|
[self setPosition:maxPosition ofDividerAtIndex:_currentDivider];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_initialOffset = startPosition - point[_originComponent];
|
||||||
|
// Don't autosave during a resize. We'll wait until it's done.
|
||||||
|
_shouldAutosave = NO;
|
||||||
|
[self _postNotificationWillResize];
|
||||||
|
}
|
||||||
|
|
||||||
if (_currentDivider === CPNotFound)
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (type == CPLeftMouseDragged && _currentDivider != CPNotFound)
|
else if (type == CPLeftMouseDragged && _currentDivider != CPNotFound)
|
||||||
{
|
{
|
||||||
|
if (!_isTracking)
|
||||||
|
{
|
||||||
|
// Don't autosave during a resize. We'll wait until it's done.
|
||||||
|
_shouldAutosave = NO;
|
||||||
|
[self _postNotificationWillResize];
|
||||||
|
|
||||||
|
_isTracking = YES;
|
||||||
|
}
|
||||||
|
|
||||||
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
||||||
|
|
||||||
[self setPosition:(point[_originComponent] + _initialOffset) ofDividerAtIndex:_currentDivider];
|
[self setPosition:(point[_originComponent] + _initialOffset) ofDividerAtIndex:_currentDivider];
|
||||||
@@ -553,8 +564,11 @@ var ShouldSuppressResizeNotifications = 1,
|
|||||||
|
|
||||||
- (void)mouseDown:(CPEvent)anEvent
|
- (void)mouseDown:(CPEvent)anEvent
|
||||||
{
|
{
|
||||||
// FIXME: This should not trap events if not on a divider!
|
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil],
|
||||||
[self trackDivider:anEvent];
|
dividerIndex = [self _dividerAtPoint:point];
|
||||||
|
|
||||||
|
if (dividerIndex !== CPNotFound)
|
||||||
|
[self trackDivider:anEvent];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewDidMoveToWindow
|
- (void)viewDidMoveToWindow
|
||||||
@@ -1187,18 +1201,35 @@ The sum of the views and the sum of the dividers should be equal to the size of
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation CPSplitView (CPTrackingArea)
|
@implementation CPSplitView (CPTrackingArea)
|
||||||
|
{
|
||||||
|
CPMutableArray _splitViewTrackingAreas;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)updateTrackingAreas
|
- (void)updateTrackingAreas
|
||||||
{
|
{
|
||||||
[self removeAllTrackingAreas];
|
if (_splitViewTrackingAreas)
|
||||||
|
{
|
||||||
|
for (var i = 0, count = [_splitViewTrackingAreas count]; i < count; i++)
|
||||||
|
[self removeTrackingArea:_splitViewTrackingAreas[i]];
|
||||||
|
|
||||||
|
_splitViewTrackingAreas = nil;
|
||||||
|
}
|
||||||
|
|
||||||
var options = CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow;
|
var options = CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow;
|
||||||
|
|
||||||
|
_splitViewTrackingAreas = @[];
|
||||||
|
|
||||||
for (var i = 0; i < _subviews.length - 1; i++)
|
for (var i = 0; i < _subviews.length - 1; i++)
|
||||||
[self addTrackingArea:[[CPTrackingArea alloc] initWithRect:[self effectiveRectOfDividerAtIndex:i]
|
{
|
||||||
options:options
|
[_splitViewTrackingAreas addObject:[[CPTrackingArea alloc] initWithRect:[self effectiveRectOfDividerAtIndex:i]
|
||||||
owner:self
|
options:options
|
||||||
userInfo:nil]];
|
owner:self
|
||||||
|
userInfo:nil]];
|
||||||
|
|
||||||
|
[self addTrackingArea:_splitViewTrackingAreas[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
[super updateTrackingAreas];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)cursorUpdate:(CPEvent)anEvent
|
- (void)cursorUpdate:(CPEvent)anEvent
|
||||||
@@ -1438,6 +1469,7 @@ var CPSplitViewDelegateKey = "CPSplitViewDelegateKey",
|
|||||||
|
|
||||||
_currentDivider = CPNotFound;
|
_currentDivider = CPNotFound;
|
||||||
_shouldAutosave = YES;
|
_shouldAutosave = YES;
|
||||||
|
_isTracking = NO;
|
||||||
|
|
||||||
_DOMDividerElements = [];
|
_DOMDividerElements = [];
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ CPNoTabsLineBorder = 5; //Has no tabs and displays a line border.
|
|||||||
CPNoTabsNoBorder = 6; //Displays no tabs and no border.
|
CPNoTabsNoBorder = 6; //Displays no tabs and no border.
|
||||||
|
|
||||||
@class _CPTabViewBox
|
@class _CPTabViewBox
|
||||||
|
@class _CPSegmentedControl
|
||||||
|
|
||||||
var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
|
var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
|
||||||
CPTabViewShouldSelectTabViewItemSelector = 1 << 2,
|
CPTabViewShouldSelectTabViewItemSelector = 1 << 2,
|
||||||
@@ -65,9 +66,9 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
|
|||||||
{
|
{
|
||||||
CPArray _items;
|
CPArray _items;
|
||||||
|
|
||||||
CPSegmentedControl _tabs;
|
_CPSegmentedControl _tabs;
|
||||||
_CPTabViewBox _box;
|
_CPTabViewBox _box;
|
||||||
CPView _placeHolderView;
|
CPView _placeholderView @accessors;
|
||||||
|
|
||||||
CPTabViewItem _selectedTabViewItem;
|
CPTabViewItem _selectedTabViewItem;
|
||||||
|
|
||||||
@@ -92,8 +93,8 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
|
|||||||
|
|
||||||
- (void)_init
|
- (void)_init
|
||||||
{
|
{
|
||||||
_tabs = [[CPSegmentedControl alloc] initWithFrame:CGRectMakeZero()];
|
_tabs = [[_CPSegmentedControl alloc] initWithFrame:CGRectMakeZero()];
|
||||||
[_tabs setHitTests:NO];
|
[_tabs setTabView:self];
|
||||||
[_tabs setSegments:[CPArray array]];
|
[_tabs setSegments:[CPArray array]];
|
||||||
|
|
||||||
var height = [_tabs valueForThemeAttribute:@"min-size"].height;
|
var height = [_tabs valueForThemeAttribute:@"min-size"].height;
|
||||||
@@ -106,7 +107,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
|
|||||||
[self addSubview:_box];
|
[self addSubview:_box];
|
||||||
[self addSubview:_tabs];
|
[self addSubview:_tabs];
|
||||||
|
|
||||||
_placeHolderView = nil;
|
_placeholderView = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CPArray)items
|
- (CPArray)items
|
||||||
@@ -525,14 +526,6 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
|
|||||||
return [_box backgroundColor];
|
return [_box backgroundColor];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)mouseDown:(CPEvent)anEvent
|
|
||||||
{
|
|
||||||
var segmentIndex = [_tabs testSegment:[_tabs convertPoint:[anEvent locationInWindow] fromView:nil]];
|
|
||||||
|
|
||||||
if (segmentIndex != CPNotFound && [self selectTabViewItemAtIndex:segmentIndex])
|
|
||||||
[_tabs trackSegment:anEvent];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)_repositionTabs
|
- (void)_repositionTabs
|
||||||
{
|
{
|
||||||
var horizontalCenterOfSelf = CGRectGetWidth([self bounds]) / 2,
|
var horizontalCenterOfSelf = CGRectGetWidth([self bounds]) / 2,
|
||||||
@@ -617,7 +610,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
|
|||||||
|
|
||||||
- (CPBinder)binderForBinding:(CPString)aBinding
|
- (CPBinder)binderForBinding:(CPString)aBinding
|
||||||
{
|
{
|
||||||
var cls = [[self class] _binderClassForBinding:aBinding]
|
var cls = [[self class] _binderClassForBinding:aBinding];
|
||||||
return [cls getBinding:aBinding forObject:self];
|
return [cls getBinding:aBinding forObject:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -652,17 +645,17 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
|
|||||||
|
|
||||||
- (void)_displayPlaceholder:(CPString)aPlaceholder
|
- (void)_displayPlaceholder:(CPString)aPlaceholder
|
||||||
{
|
{
|
||||||
if (_placeHolderView == nil)
|
if (_placeholderView == nil)
|
||||||
{
|
{
|
||||||
_placeHolderView = [[CPView alloc] initWithFrame:CGRectMakeZero()];
|
_placeholderView = [[CPView alloc] initWithFrame:CGRectMakeZero()];
|
||||||
var textField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
|
var textField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
|
||||||
[textField setTag:1000];
|
[textField setTag:1000];
|
||||||
[textField setTextColor:[CPColor whiteColor]];
|
[textField setTextColor:[CPColor whiteColor]];
|
||||||
[textField setFont:[CPFont boldFontWithName:@"Geneva" size:18 italic:YES]];
|
[textField setFont:[CPFont boldFontWithName:@"Geneva" size:18 italic:YES]];
|
||||||
[_placeHolderView addSubview:textField];
|
[_placeholderView addSubview:textField];
|
||||||
}
|
}
|
||||||
|
|
||||||
var textField = [_placeHolderView viewWithTag:1000];
|
var textField = [_placeholderView viewWithTag:1000];
|
||||||
[textField setStringValue:aPlaceholder];
|
[textField setStringValue:aPlaceholder];
|
||||||
[textField sizeToFit];
|
[textField sizeToFit];
|
||||||
|
|
||||||
@@ -672,7 +665,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
|
|||||||
|
|
||||||
[textField setFrameOrigin:origin];
|
[textField setFrameOrigin:origin];
|
||||||
|
|
||||||
[self _displayItemView:_placeHolderView];
|
[self _displayItemView:_placeholderView];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
@@ -887,3 +880,77 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
|
|||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
# pragma mark -
|
||||||
|
|
||||||
|
// This subclass of CPSegmentedControl implements specific behaviour needed by CPTabView, which
|
||||||
|
// differs in some ways from normal CPSegmentedControl habits :
|
||||||
|
//
|
||||||
|
// - all items are enabled
|
||||||
|
// - when you select a tab (mouse down, holding) and drag upon another tab, the second one reacts
|
||||||
|
// (showing a pushed state) and can then be selected by releasing the mouse over it.
|
||||||
|
// - a delegate has the opportunity to accept or not the selection of an item
|
||||||
|
|
||||||
|
@implementation _CPSegmentedControl : CPSegmentedControl
|
||||||
|
{
|
||||||
|
CPTabView _tabView @accessors(property=tabView);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)trackSegment:(CPEvent)anEvent
|
||||||
|
{
|
||||||
|
var type = [anEvent type],
|
||||||
|
location = [self convertPoint:[anEvent locationInWindow] fromView:nil],
|
||||||
|
currentSegment = [self testSegment:location];
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case CPLeftMouseUp:
|
||||||
|
|
||||||
|
if (_trackingSegment === CPNotFound)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((_trackingSegment !== _selectedSegment) &&
|
||||||
|
[_tabView _sendDelegateShouldSelectTabViewItem:[_tabView tabViewItemAtIndex:_trackingSegment]])
|
||||||
|
{
|
||||||
|
[self setSelected:YES forSegment:_trackingSegment];
|
||||||
|
_selectedSegment = _trackingSegment;
|
||||||
|
[_tabView selectTabViewItemAtIndex:_selectedSegment];
|
||||||
|
}
|
||||||
|
|
||||||
|
[self drawSegmentBezel:_trackingSegment highlight:NO];
|
||||||
|
|
||||||
|
_trackingSegment = CPNotFound;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
case CPLeftMouseDown:
|
||||||
|
|
||||||
|
if (currentSegment > CPNotFound)
|
||||||
|
{
|
||||||
|
_trackingSegment = currentSegment;
|
||||||
|
[self drawSegmentBezel:_trackingSegment highlight:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CPLeftMouseDragged:
|
||||||
|
|
||||||
|
if (_trackingSegment !== currentSegment)
|
||||||
|
{
|
||||||
|
if (_trackingSegment > CPNotFound)
|
||||||
|
[self drawSegmentBezel:_trackingSegment highlight:NO];
|
||||||
|
|
||||||
|
_trackingSegment = currentSegment;
|
||||||
|
|
||||||
|
if (_trackingSegment > CPNotFound)
|
||||||
|
[self drawSegmentBezel:_trackingSegment highlight:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CPApp setTarget:self selector:@selector(trackSegment:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
|||||||
if (width < [self minWidth])
|
if (width < [self minWidth])
|
||||||
[self setMinWidth:width];
|
[self setMinWidth:width];
|
||||||
else if (width > [self maxWidth])
|
else if (width > [self maxWidth])
|
||||||
[self setMaxWidth:width]
|
[self setMaxWidth:width];
|
||||||
|
|
||||||
if (_width !== width)
|
if (_width !== width)
|
||||||
[self setWidth:width];
|
[self setWidth:width];
|
||||||
@@ -499,7 +499,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
|||||||
*/
|
*/
|
||||||
- (void)setHidden:(BOOL)shouldBeHidden
|
- (void)setHidden:(BOOL)shouldBeHidden
|
||||||
{
|
{
|
||||||
shouldBeHidden = !!shouldBeHidden
|
shouldBeHidden = !!shouldBeHidden;
|
||||||
|
|
||||||
if (_isHidden === shouldBeHidden)
|
if (_isHidden === shouldBeHidden)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -89,7 +89,7 @@
|
|||||||
var inset = [self currentValueForThemeAttribute:@"text-inset"],
|
var inset = [self currentValueForThemeAttribute:@"text-inset"],
|
||||||
bounds = [self bounds];
|
bounds = [self bounds];
|
||||||
|
|
||||||
[_textField setFrame:CGRectMake(inset.right, inset.top, bounds.size.width - inset.right - inset.left, bounds.size.height - inset.top - inset.bottom)];
|
[_textField setFrame:CGRectMake(inset.left, inset.top, bounds.size.width - inset.right - inset.left, bounds.size.height - inset.top - inset.bottom)];
|
||||||
[_textField setTextColor:[self currentValueForThemeAttribute:@"text-color"]];
|
[_textField setTextColor:[self currentValueForThemeAttribute:@"text-color"]];
|
||||||
[_textField setFont:[self currentValueForThemeAttribute:@"font"]];
|
[_textField setFont:[self currentValueForThemeAttribute:@"font"]];
|
||||||
[_textField setTextShadowColor:[self currentValueForThemeAttribute:@"text-shadow-color"]];
|
[_textField setTextShadowColor:[self currentValueForThemeAttribute:@"text-shadow-color"]];
|
||||||
@@ -461,21 +461,38 @@ var CPTableHeaderViewResizeZone = 3.0,
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation CPTableHeaderView (CPTrackingArea)
|
@implementation CPTableHeaderView (CPTrackingArea)
|
||||||
|
{
|
||||||
|
CPMutableArray _tableHeaderViewTrackingAreas;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)updateTrackingAreas
|
- (void)updateTrackingAreas
|
||||||
{
|
{
|
||||||
[self removeAllTrackingAreas];
|
if (_tableHeaderViewTrackingAreas)
|
||||||
|
{
|
||||||
|
for (var i = 0, count = [_tableHeaderViewTrackingAreas count]; i < count; i++)
|
||||||
|
[self removeTrackingArea:_tableHeaderViewTrackingAreas[i]];
|
||||||
|
|
||||||
|
_tableHeaderViewTrackingAreas = nil;
|
||||||
|
}
|
||||||
|
|
||||||
var options = CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow;
|
var options = CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow;
|
||||||
|
|
||||||
if (!_tableView)
|
if (!_tableView)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
_tableHeaderViewTrackingAreas = @[];
|
||||||
|
|
||||||
for (var i = 0; i < _tableView._tableColumns.length; i++)
|
for (var i = 0; i < _tableView._tableColumns.length; i++)
|
||||||
[self addTrackingArea:[[CPTrackingArea alloc] initWithRect:[self _cursorRectForColumn:i]
|
{
|
||||||
options:options
|
[_tableHeaderViewTrackingAreas addObject:[[CPTrackingArea alloc] initWithRect:[self _cursorRectForColumn:i]
|
||||||
owner:self
|
options:options
|
||||||
userInfo:nil]];
|
owner:self
|
||||||
|
userInfo:nil]];
|
||||||
|
|
||||||
|
[self addTrackingArea:_tableHeaderViewTrackingAreas[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
[super updateTrackingAreas];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)cursorUpdate:(CPEvent)anEvent
|
- (void)cursorUpdate:(CPEvent)anEvent
|
||||||
|
|||||||
@@ -346,8 +346,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
|||||||
+ (CPDictionary)themeAttributes
|
+ (CPDictionary)themeAttributes
|
||||||
{
|
{
|
||||||
return @{
|
return @{
|
||||||
@"alternating-row-colors": [CPNull null],
|
@"alternating-row-colors": @[[CPColor whiteColor], [CPColor colorWithRed:245.0 / 255.0 green:249.0 / 255.0 blue:252.0 / 255.0 alpha:1.0]],
|
||||||
@"grid-color": [CPNull null],
|
@"grid-color": [CPColor colorWithHexString:@"dce0e2"],
|
||||||
@"grid-line-thickness": 1.0,
|
@"grid-line-thickness": 1.0,
|
||||||
@"highlighted-grid-color": [CPNull null],
|
@"highlighted-grid-color": [CPNull null],
|
||||||
@"selection-color": [CPNull null],
|
@"selection-color": [CPNull null],
|
||||||
@@ -368,7 +368,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
|||||||
@"dropview-above-border-color": [CPNull null],
|
@"dropview-above-border-color": [CPNull null],
|
||||||
@"dropview-above-border-width": [CPNull null],
|
@"dropview-above-border-width": [CPNull null],
|
||||||
@"dropview-above-selected-border-color": [CPNull null],
|
@"dropview-above-selected-border-color": [CPNull null],
|
||||||
@"dropview-above-selected-border-width": [CPNull null]
|
@"dropview-above-selected-border-width": [CPNull null],
|
||||||
|
@"header-view-height": 25.0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,8 +391,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
|||||||
_selectionHighlightStyle = CPTableViewSelectionHighlightStyleRegular;
|
_selectionHighlightStyle = CPTableViewSelectionHighlightStyleRegular;
|
||||||
|
|
||||||
[self setUsesAlternatingRowBackgroundColors:NO];
|
[self setUsesAlternatingRowBackgroundColors:NO];
|
||||||
[self setAlternatingRowBackgroundColors:
|
[self setAlternatingRowBackgroundColors:[self valueForThemeAttribute:@"alternating-row-colors"]];
|
||||||
[[CPColor whiteColor], [CPColor colorWithRed:245.0 / 255.0 green:249.0 / 255.0 blue:252.0 / 255.0 alpha:1.0]]];
|
|
||||||
|
|
||||||
_tableColumns = [];
|
_tableColumns = [];
|
||||||
_tableColumnRanges = [];
|
_tableColumnRanges = [];
|
||||||
@@ -401,10 +401,10 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
|||||||
_intercellSpacing = CGSizeMake(3.0, 2.0);
|
_intercellSpacing = CGSizeMake(3.0, 2.0);
|
||||||
_rowHeight = [self valueForThemeAttribute:@"default-row-height"];
|
_rowHeight = [self valueForThemeAttribute:@"default-row-height"];
|
||||||
|
|
||||||
[self setGridColor:[CPColor colorWithHexString:@"dce0e2"]];
|
[self setGridColor:[self valueForThemeAttribute:@"grid-color"]];
|
||||||
[self setGridStyleMask:CPTableViewGridNone];
|
[self setGridStyleMask:CPTableViewGridNone];
|
||||||
|
|
||||||
[self setHeaderView:[[CPTableHeaderView alloc] initWithFrame:CGRectMake(0, 0, [self bounds].size.width, _rowHeight)]];
|
[self setHeaderView:[[CPTableHeaderView alloc] initWithFrame:CGRectMake(0, 0, [self bounds].size.width, [self valueForThemeAttribute:@"header-view-height"])]];
|
||||||
[self setCornerView:[[_CPCornerView alloc] initWithFrame:CGRectMake(0, 0, [CPScroller scrollerWidth], CGRectGetHeight([_headerView frame]))]];
|
[self setCornerView:[[_CPCornerView alloc] initWithFrame:CGRectMake(0, 0, [CPScroller scrollerWidth], CGRectGetHeight([_headerView frame]))]];
|
||||||
|
|
||||||
_currentHighlightedTableColumn = nil;
|
_currentHighlightedTableColumn = nil;
|
||||||
@@ -3096,10 +3096,15 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
|||||||
*/
|
*/
|
||||||
- (CPView)dragViewForRowsWithIndexes:(CPIndexSet)theDraggedRows tableColumns:(CPArray)theTableColumns event:(CPEvent)theDragEvent offset:(CGPoint)dragViewOffset
|
- (CPView)dragViewForRowsWithIndexes:(CPIndexSet)theDraggedRows tableColumns:(CPArray)theTableColumns event:(CPEvent)theDragEvent offset:(CGPoint)dragViewOffset
|
||||||
{
|
{
|
||||||
var bounds = [self bounds],
|
var firstRowFrame = [self frameOfDataViewAtColumn:0 row:[theDraggedRows firstIndex]],
|
||||||
|
lastRowFrame = [self frameOfDataViewAtColumn:0 row:[theDraggedRows lastIndex]],
|
||||||
|
dragViewHeight = CGRectGetMaxY(lastRowFrame) - CGRectGetMinY(firstRowFrame);
|
||||||
|
|
||||||
|
var bounds = CGRectMake(0, 0, CGRectGetWidth([self bounds]), dragViewHeight),
|
||||||
dragView = [[CPView alloc] initWithFrame:bounds];
|
dragView = [[CPView alloc] initWithFrame:bounds];
|
||||||
|
|
||||||
[dragView setAlphaValue:0.7];
|
[dragView setAlphaValue:0.7];
|
||||||
|
// [dragView setBackgroundColor:[CPColor colorWithWhite:1 alpha:0.5]];
|
||||||
|
|
||||||
// We have to fetch all the data views for the selected rows and columns
|
// We have to fetch all the data views for the selected rows and columns
|
||||||
// After that we can copy these add them to a transparent drag view and use that drag view
|
// After that we can copy these add them to a transparent drag view and use that drag view
|
||||||
@@ -3107,7 +3112,11 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
|||||||
[self _enumerateViewsInRows:theDraggedRows tableColumns:theTableColumns usingBlock:function(v, row, tableColumn, stop)
|
[self _enumerateViewsInRows:theDraggedRows tableColumns:theTableColumns usingBlock:function(v, row, tableColumn, stop)
|
||||||
{
|
{
|
||||||
var column = [_tableColumns indexOfObjectIdenticalTo:tableColumn],
|
var column = [_tableColumns indexOfObjectIdenticalTo:tableColumn],
|
||||||
newDataView = [self preparedViewAtColumn:column row:row];
|
newDataView = [self preparedViewAtColumn:column row:row],
|
||||||
|
origin = [newDataView frame].origin;
|
||||||
|
|
||||||
|
origin.y -= CGRectGetMinY(firstRowFrame);
|
||||||
|
[newDataView setFrameOrigin:origin];
|
||||||
|
|
||||||
[dragView addSubview:newDataView];
|
[dragView addSubview:newDataView];
|
||||||
}];
|
}];
|
||||||
@@ -3751,7 +3760,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
|||||||
{
|
{
|
||||||
if (!dataViewsForRow)
|
if (!dataViewsForRow)
|
||||||
{
|
{
|
||||||
dataViewsForRow = {}
|
dataViewsForRow = {};
|
||||||
_dataViewsForRows[row] = dataViewsForRow;
|
_dataViewsForRows[row] = dataViewsForRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4600,7 +4609,9 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
|||||||
}
|
}
|
||||||
|
|
||||||
var bounds = [view bounds],
|
var bounds = [view bounds],
|
||||||
viewLocation = CGPointMake(aPoint.x - CGRectGetWidth(bounds) / 2 + offset.x, aPoint.y - CGRectGetHeight(bounds) / 2 + offset.y);
|
firstRowFrame = [self frameOfDataViewAtColumn:0 row:[_draggedRowIndexes firstIndex]],
|
||||||
|
viewLocation = CGPointMake(aPoint.x - CGRectGetWidth(bounds) / 2 + offset.x, aPoint.y - CGRectGetHeight(bounds) / 2 + offset.y + CGRectGetMinY(firstRowFrame));
|
||||||
|
|
||||||
[self dragView:view at:viewLocation offset:CGPointMakeZero() event:[CPApp currentEvent] pasteboard:pboard source:self slideBack:YES];
|
[self dragView:view at:viewLocation offset:CGPointMakeZero() event:[CPApp currentEvent] pasteboard:pboard source:self slideBack:YES];
|
||||||
_startTrackingPoint = nil;
|
_startTrackingPoint = nil;
|
||||||
|
|
||||||
@@ -4896,7 +4907,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
|||||||
row = _retargetedDropRow;
|
row = _retargetedDropRow;
|
||||||
|
|
||||||
if (row === nil)
|
if (row === nil)
|
||||||
var row = [self _proposedRowAtPoint:location];
|
row = [self _proposedRowAtPoint:location];
|
||||||
|
|
||||||
return [self _sendDataSourceAcceptDrop:sender row:row dropOperation:operation];
|
return [self _sendDataSourceAcceptDrop:sender row:row dropOperation:operation];
|
||||||
}
|
}
|
||||||
@@ -5128,7 +5139,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
|||||||
{
|
{
|
||||||
[super viewWillMoveToWindow:aWindow];
|
[super viewWillMoveToWindow:aWindow];
|
||||||
|
|
||||||
[self _stopObservingFirstResponderForWindow:aWindow];
|
[self _stopObservingFirstResponderForWindow:[self window]];
|
||||||
|
|
||||||
if (aWindow)
|
if (aWindow)
|
||||||
[self _startObservingFirstResponderForWindow:aWindow];
|
[self _startObservingFirstResponderForWindow:aWindow];
|
||||||
@@ -6107,7 +6118,6 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey",
|
|||||||
CPTableViewGridStyleMaskKey = @"CPTableViewGridStyleMaskKey",
|
CPTableViewGridStyleMaskKey = @"CPTableViewGridStyleMaskKey",
|
||||||
CPTableViewUsesAlternatingBackgroundKey = @"CPTableViewUsesAlternatingBackgroundKey",
|
CPTableViewUsesAlternatingBackgroundKey = @"CPTableViewUsesAlternatingBackgroundKey",
|
||||||
CPTableViewAlternatingRowColorsKey = @"CPTableViewAlternatingRowColorsKey",
|
CPTableViewAlternatingRowColorsKey = @"CPTableViewAlternatingRowColorsKey",
|
||||||
CPTableViewHeaderViewKey = @"CPTableViewHeaderViewKey",
|
|
||||||
CPTableViewCornerViewKey = @"CPTableViewCornerViewKey",
|
CPTableViewCornerViewKey = @"CPTableViewCornerViewKey",
|
||||||
CPTableViewAutosaveNameKey = @"CPTableViewAutosaveNameKey",
|
CPTableViewAutosaveNameKey = @"CPTableViewAutosaveNameKey",
|
||||||
CPTableViewArchivedReusableViewsKey = @"CPTableViewArchivedReusableViewsKey";
|
CPTableViewArchivedReusableViewsKey = @"CPTableViewArchivedReusableViewsKey";
|
||||||
|
|||||||
@@ -33,11 +33,14 @@
|
|||||||
@import "CPView.j"
|
@import "CPView.j"
|
||||||
|
|
||||||
@global CPStringPboardType
|
@global CPStringPboardType
|
||||||
|
@global _CPSmartPboardType
|
||||||
|
|
||||||
@class CPAttributedString
|
@class CPAttributedString
|
||||||
@class _CPRTFParser
|
@class _CPRTFParser
|
||||||
|
|
||||||
@protocol CPTextDelegate <CPObject>
|
@protocol CPTextDelegate <CPObject>
|
||||||
|
|
||||||
|
@optional
|
||||||
- (BOOL)textShouldBeginEditing:(CPText)aTextObject;
|
- (BOOL)textShouldBeginEditing:(CPText)aTextObject;
|
||||||
- (BOOL)textShouldEndEditing:(CPText)aTextObject;
|
- (BOOL)textShouldEndEditing:(CPText)aTextObject;
|
||||||
- (void)textDidBeginEditing:(CPNotification)aNotification;
|
- (void)textDidBeginEditing:(CPNotification)aNotification;
|
||||||
@@ -175,6 +178,11 @@ CPKernAttributeName = @"CPKernAttributeName";
|
|||||||
return stringForPasting;
|
return stringForPasting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)_shouldUseSmartPasting
|
||||||
|
{
|
||||||
|
return parseInt([[CPPasteboard generalPasteboard] stringForType:_CPSmartPboardType], 10) > 0 || NO;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)paste:(id)sender
|
- (void)paste:(id)sender
|
||||||
{
|
{
|
||||||
var stringForPasting = [self _stringForPasting];
|
var stringForPasting = [self _stringForPasting];
|
||||||
|
|||||||
@@ -331,7 +331,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
[CPTextFieldInputOwner keyUp:cappEvent];
|
[CPTextFieldInputOwner keyUp:cappEvent];
|
||||||
|
|
||||||
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
||||||
}
|
};
|
||||||
|
|
||||||
CPTextFieldDOMPasswordInputElement.oninput = CPTextFieldInputFunction;
|
CPTextFieldDOMPasswordInputElement.oninput = CPTextFieldInputFunction;
|
||||||
CPTextFieldDOMPasswordInputElement.onblur = CPTextFieldBlurHandler;
|
CPTextFieldDOMPasswordInputElement.onblur = CPTextFieldBlurHandler;
|
||||||
@@ -873,12 +873,18 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
if (!CPTextFieldInputDidBlur)
|
if (!CPTextFieldInputDidBlur)
|
||||||
CPTextFieldBlurHandler();
|
CPTextFieldBlurHandler();
|
||||||
|
|
||||||
CPTextFieldInputDidBlur = NO;
|
|
||||||
CPTextFieldInputResigning = NO;
|
|
||||||
|
|
||||||
if (element.parentNode == _DOMElement)
|
if (element.parentNode == _DOMElement)
|
||||||
element.parentNode.removeChild(element);
|
element.parentNode.removeChild(element);
|
||||||
|
|
||||||
|
// Previosly, we unflagged CPTextFieldInputDidBlur and CPTextFieldInputResigning before
|
||||||
|
// the call to removeChild. This resulted in DOM exceptions in Chrome under certain conditions.
|
||||||
|
// See https://stackoverflow.com/questions/21926083/failed-to-execute-removechild-on-node
|
||||||
|
// for why we need to unflag CPTextFieldInputDidBlur and CPTextFieldInputResigning
|
||||||
|
// only after removing the element.
|
||||||
|
|
||||||
|
CPTextFieldInputDidBlur = NO;
|
||||||
|
CPTextFieldInputResigning = NO;
|
||||||
|
|
||||||
CPTextFieldInputIsActive = NO;
|
CPTextFieldInputIsActive = NO;
|
||||||
|
|
||||||
if (document.attachEvent)
|
if (document.attachEvent)
|
||||||
@@ -1034,7 +1040,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
[[self window] platformWindow]._DOMBodyElement.ondrag = CPTextFieldCachedDragFunction;
|
[[self window] platformWindow]._DOMBodyElement.ondrag = CPTextFieldCachedDragFunction;
|
||||||
[[self window] platformWindow]._DOMBodyElement.onselectstart = CPTextFieldCachedSelectStartFunction;
|
[[self window] platformWindow]._DOMBodyElement.onselectstart = CPTextFieldCachedSelectStartFunction;
|
||||||
|
|
||||||
CPTextFieldCachedSelectStartFunction = nil
|
CPTextFieldCachedSelectStartFunction = nil;
|
||||||
CPTextFieldCachedDragFunction = nil;
|
CPTextFieldCachedDragFunction = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1237,7 +1243,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidBeginEditing_)
|
if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidBeginEditing_)
|
||||||
[_delegate controlTextDidBeginEditing:[[CPNotification alloc] initWithName:CPControlTextDidBeginEditingNotification object:self userInfo:@{"CPFieldEditor": [note object]}]]
|
[_delegate controlTextDidBeginEditing:[[CPNotification alloc] initWithName:CPControlTextDidBeginEditingNotification object:self userInfo:@{"CPFieldEditor": [note object]}]];
|
||||||
|
|
||||||
[super textDidBeginEditing:note];
|
[super textDidBeginEditing:note];
|
||||||
}
|
}
|
||||||
@@ -1784,7 +1790,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
|||||||
_implementedDelegateMethods = 0;
|
_implementedDelegateMethods = 0;
|
||||||
|
|
||||||
if ([_delegate respondsToSelector:@selector(control:didFailToFormatString:errorDescription:)])
|
if ([_delegate respondsToSelector:@selector(control:didFailToFormatString:errorDescription:)])
|
||||||
_implementedDelegateMethods |= CPTextFieldDelegate_control_didFailToFormatString_errorDescription_
|
_implementedDelegateMethods |= CPTextFieldDelegate_control_didFailToFormatString_errorDescription_;
|
||||||
|
|
||||||
if ([_delegate respondsToSelector:@selector(controlTextDidBeginEditing:)])
|
if ([_delegate respondsToSelector:@selector(controlTextDidBeginEditing:)])
|
||||||
_implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidBeginEditing_;
|
_implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidBeginEditing_;
|
||||||
@@ -2177,21 +2183,32 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation CPTextField (CPTrackingArea)
|
@implementation CPTextField (CPTrackingArea)
|
||||||
|
{
|
||||||
|
CPTrackingArea _textFieldTrackingArea;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)updateTrackingAreas
|
- (void)updateTrackingAreas
|
||||||
{
|
{
|
||||||
[self removeAllTrackingAreas];
|
if (_textFieldTrackingArea)
|
||||||
|
{
|
||||||
|
[self removeTrackingArea:_textFieldTrackingArea];
|
||||||
|
_textFieldTrackingArea = nil;
|
||||||
|
}
|
||||||
|
|
||||||
if ([self isEnabled] && (_isEditable || _isSelectable))
|
if ([self isEnabled] && (_isEditable || _isSelectable))
|
||||||
{
|
{
|
||||||
var myBounds = CGRectMakeCopy([self bounds]),
|
var myBounds = CGRectMakeCopy([self bounds]),
|
||||||
contentInset = [self currentValueForThemeAttribute:@"content-inset"];
|
contentInset = [self currentValueForThemeAttribute:@"content-inset"];
|
||||||
|
|
||||||
|
_textFieldTrackingArea = [[CPTrackingArea alloc] initWithRect:CGRectInsetByInset(myBounds, contentInset)
|
||||||
|
options:CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow
|
||||||
|
owner:self
|
||||||
|
userInfo:nil];
|
||||||
|
|
||||||
[self addTrackingArea:[[CPTrackingArea alloc] initWithRect:CGRectInsetByInset(myBounds, contentInset)
|
[self addTrackingArea:_textFieldTrackingArea];
|
||||||
options:CPTrackingMouseEnteredAndExited | CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow
|
|
||||||
owner:self
|
|
||||||
userInfo:nil]];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[super updateTrackingAreas];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)cursorUpdate:(CPEvent)anEvent
|
- (void)cursorUpdate:(CPEvent)anEvent
|
||||||
|
|||||||
@@ -412,7 +412,7 @@ var _availableTraits= [@"Normal", @"Italic", @"Bold", @"Bold Italic"],
|
|||||||
return [_availableFonts count];
|
return [_availableFonts count];
|
||||||
|
|
||||||
if (aBrowser === _traitBrowser)
|
if (aBrowser === _traitBrowser)
|
||||||
return [_availableTraits count]
|
return [_availableTraits count];
|
||||||
|
|
||||||
return [_availableSizes count]
|
return [_availableSizes count]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1179,7 +1179,7 @@ var _objectsInRange = function(aList, aRange)
|
|||||||
for (var i = 0; i < count; i++)
|
for (var i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
_glyphsFrames[i] = CGRectMake(origin.x, origin.y, someAdvancements[i].width, height);
|
_glyphsFrames[i] = CGRectMake(origin.x, origin.y, someAdvancements[i].width, height);
|
||||||
_glyphsFrames[i]._descent = someAdvancements[i].descent
|
_glyphsFrames[i]._descent = someAdvancements[i].descent;
|
||||||
_glyphsOffsets[i] = height - someAdvancements[i].height;
|
_glyphsOffsets[i] = height - someAdvancements[i].height;
|
||||||
origin.x += someAdvancements[i].width;
|
origin.x += someAdvancements[i].width;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ CPLineMovesUp = 4;
|
|||||||
@implementation CPTextContainer : CPObject
|
@implementation CPTextContainer : CPObject
|
||||||
{
|
{
|
||||||
float _lineFragmentPadding @accessors(property=lineFragmentPadding);
|
float _lineFragmentPadding @accessors(property=lineFragmentPadding);
|
||||||
CGSize _size @accessors(property=containerSize)
|
CGSize _size @accessors(property=containerSize);
|
||||||
CPLayoutManager _layoutManager @accessors(property=layoutManager);
|
CPLayoutManager _layoutManager @accessors(property=layoutManager);
|
||||||
CPTextView _textView @accessors(property=textView);
|
CPTextView _textView @accessors(property=textView);
|
||||||
BOOL _inResizing;
|
BOOL _inResizing;
|
||||||
@@ -168,10 +168,7 @@ CPLineMovesUp = 4;
|
|||||||
- (void)setTextView:(CPTextView)aTextView
|
- (void)setTextView:(CPTextView)aTextView
|
||||||
{
|
{
|
||||||
if (_textView)
|
if (_textView)
|
||||||
{
|
|
||||||
[self _removeAllLines];
|
|
||||||
[_textView setTextContainer:nil];
|
[_textView setTextContainer:nil];
|
||||||
}
|
|
||||||
|
|
||||||
_textView = aTextView;
|
_textView = aTextView;
|
||||||
|
|
||||||
@@ -252,4 +249,4 @@ var CPTextContainerSizeKey = @"CPTextContainerSizeKey",
|
|||||||
[aCoder encodeObject:_layoutManager forKey:CPTextContainerLayoutManagerKey];
|
[aCoder encodeObject:_layoutManager forKey:CPTextContainerLayoutManagerKey];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
|
|
||||||
@protocol CPTextViewDelegate <CPTextDelegate>
|
@protocol CPTextViewDelegate <CPTextDelegate>
|
||||||
|
|
||||||
|
@optional
|
||||||
- (BOOL)textView:(CPTextView)aTextView doCommandBySelector:(SEL)aSelector;
|
- (BOOL)textView:(CPTextView)aTextView doCommandBySelector:(SEL)aSelector;
|
||||||
- (BOOL)textView:(CPTextView)aTextView shouldChangeTextInRange:(CPRange)affectedCharRange replacementString:(CPString)replacementString;
|
- (BOOL)textView:(CPTextView)aTextView shouldChangeTextInRange:(CPRange)affectedCharRange replacementString:(CPString)replacementString;
|
||||||
- (CPDictionary)textView:(CPTextView)textView shouldChangeTypingAttributes:(CPDictionary)oldTypingAttributes toAttributes:(CPDictionary)newTypingAttributes;
|
- (CPDictionary)textView:(CPTextView)textView shouldChangeTypingAttributes:(CPDictionary)oldTypingAttributes toAttributes:(CPDictionary)newTypingAttributes;
|
||||||
@@ -94,13 +95,16 @@ CPSelectByWord = 1;
|
|||||||
CPSelectByParagraph = 2;
|
CPSelectByParagraph = 2;
|
||||||
|
|
||||||
var kDelegateRespondsTo_textShouldBeginEditing = 1 << 0,
|
var kDelegateRespondsTo_textShouldBeginEditing = 1 << 0,
|
||||||
kDelegateRespondsTo_textView_doCommandBySelector = 1 << 1,
|
kDelegateRespondsTo_textShouldEndEditing = 1 << 1,
|
||||||
kDelegateRespondsTo_textView_willChangeSelectionFromCharacterRange_toCharacterRange = 1 << 2,
|
kDelegateRespondsTo_textView_doCommandBySelector = 1 << 2,
|
||||||
kDelegateRespondsTo_textView_shouldChangeTextInRange_replacementString = 1 << 3,
|
kDelegateRespondsTo_textView_willChangeSelectionFromCharacterRange_toCharacterRange = 1 << 3,
|
||||||
kDelegateRespondsTo_textView_shouldChangeTypingAttributes_toAttributes = 1 << 4,
|
kDelegateRespondsTo_textView_shouldChangeTextInRange_replacementString = 1 << 4,
|
||||||
kDelegateRespondsTo_textView_textDidChange = 1 << 5,
|
kDelegateRespondsTo_textView_shouldChangeTypingAttributes_toAttributes = 1 << 5,
|
||||||
kDelegateRespondsTo_textView_didChangeSelection = 1 << 6,
|
kDelegateRespondsTo_textView_textDidChange = 1 << 6,
|
||||||
kDelegateRespondsTo_textView_didChangeTypingAttributes = 1 << 7;
|
kDelegateRespondsTo_textView_didChangeSelection = 1 << 7,
|
||||||
|
kDelegateRespondsTo_textView_didChangeTypingAttributes = 1 << 8,
|
||||||
|
kDelegateRespondsTo_textView_textDidBeginEditing = 1 << 9,
|
||||||
|
kDelegateRespondsTo_textView_textDidEndEditing = 1 << 10;
|
||||||
|
|
||||||
@class _CPCaret;
|
@class _CPCaret;
|
||||||
|
|
||||||
@@ -128,7 +132,6 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
CPSelectionGranularity _selectionGranularity @accessors(property=selectionGranularity);
|
CPSelectionGranularity _selectionGranularity @accessors(property=selectionGranularity);
|
||||||
|
|
||||||
CPSelectionGranularity _previousSelectionGranularity; // private
|
CPSelectionGranularity _previousSelectionGranularity; // private
|
||||||
CPSelectionGranularity _copySelectionGranularity; // private
|
|
||||||
|
|
||||||
CPTextContainer _textContainer @accessors(property=textContainer);
|
CPTextContainer _textContainer @accessors(property=textContainer);
|
||||||
CPTextStorage _textStorage @accessors(getter=textStorage);
|
CPTextStorage _textStorage @accessors(getter=textStorage);
|
||||||
@@ -153,6 +156,10 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
CPTimer _scrollingTimer;
|
CPTimer _scrollingTimer;
|
||||||
|
|
||||||
CPString _placeholderString;
|
CPString _placeholderString;
|
||||||
|
|
||||||
|
BOOL _firstResponderButNotEditingYet;
|
||||||
|
|
||||||
|
CPRange _mouseDownOldSelection;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (Class)_binderClassForBinding:(CPString)aBinding
|
+ (Class)_binderClassForBinding:(CPString)aBinding
|
||||||
@@ -234,7 +241,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
_selectedTextAttributes = [CPMutableDictionary new];
|
_selectedTextAttributes = [CPMutableDictionary new];
|
||||||
|
|
||||||
_caret = [[_CPCaret alloc] initWithTextView:self];
|
_caret = [[_CPCaret alloc] initWithTextView:self];
|
||||||
[_caret setRect:CGRectMake(0, 0, 1, 11)]
|
[_caret setRect:CGRectMake(0, 0, 1, 11)];
|
||||||
|
|
||||||
var pboardTypes = [CPStringPboardType, CPColorDragType];
|
var pboardTypes = [CPStringPboardType, CPColorDragType];
|
||||||
|
|
||||||
@@ -265,6 +272,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
|
|
||||||
[super _removeObservers];
|
[super _removeObservers];
|
||||||
[self _setObserveWindowKeyNotifications:NO];
|
[self _setObserveWindowKeyNotifications:NO];
|
||||||
|
[self _removeDelegateObservers];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_addObservers
|
- (void)_addObservers
|
||||||
@@ -275,7 +283,53 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
[super _addObservers];
|
[super _addObservers];
|
||||||
[self _setObserveWindowKeyNotifications:YES];
|
[self _setObserveWindowKeyNotifications:YES];
|
||||||
[self _startObservingClipView];
|
[self _startObservingClipView];
|
||||||
|
[self _addDelegateObservers];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)_addDelegateObservers
|
||||||
|
{
|
||||||
|
if (!_delegate) return;
|
||||||
|
|
||||||
|
var nc = [CPNotificationCenter defaultCenter];
|
||||||
|
|
||||||
|
if (_delegateRespondsToSelectorMask & kDelegateRespondsTo_textView_textDidBeginEditing)
|
||||||
|
[nc addObserver:_delegate selector:@selector(textDidBeginEditing:) name:CPTextDidBeginEditingNotification object:self];
|
||||||
|
|
||||||
|
if (_delegateRespondsToSelectorMask & kDelegateRespondsTo_textView_textDidChange)
|
||||||
|
[nc addObserver:_delegate selector:@selector(textDidChange:) name:CPTextDidChangeNotification object:self];
|
||||||
|
|
||||||
|
if (_delegateRespondsToSelectorMask & kDelegateRespondsTo_textView_textDidEndEditing)
|
||||||
|
[nc addObserver:_delegate selector:@selector(textDidEndEditing:) name:CPTextDidEndEditingNotification object:self];
|
||||||
|
|
||||||
|
if (_delegateRespondsToSelectorMask & kDelegateRespondsTo_textView_didChangeSelection)
|
||||||
|
[nc addObserver:_delegate selector:@selector(textViewDidChangeSelection:) name:CPTextViewDidChangeSelectionNotification object:self];
|
||||||
|
|
||||||
|
if (_delegateRespondsToSelectorMask & kDelegateRespondsTo_textView_didChangeTypingAttributes)
|
||||||
|
[nc addObserver:_delegate selector:@selector(textViewDidChangeTypingAttributes:) name:CPTextViewDidChangeTypingAttributesNotification object:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)_removeDelegateObservers
|
||||||
|
{
|
||||||
|
if (!_delegate) return;
|
||||||
|
|
||||||
|
var nc = [CPNotificationCenter defaultCenter];
|
||||||
|
|
||||||
|
if (_delegateRespondsToSelectorMask & kDelegateRespondsTo_textView_textDidBeginEditing)
|
||||||
|
[nc removeObserver:_delegate name:CPTextDidBeginEditingNotification object:self];
|
||||||
|
|
||||||
|
if (_delegateRespondsToSelectorMask & kDelegateRespondsTo_textView_textDidChange)
|
||||||
|
[nc removeObserver:_delegate name:CPTextDidChangeNotification object:self];
|
||||||
|
|
||||||
|
if (_delegateRespondsToSelectorMask & kDelegateRespondsTo_textView_textDidEndEditing)
|
||||||
|
[nc removeObserver:_delegate name:CPTextDidEndEditingNotification object:self];
|
||||||
|
|
||||||
|
if (_delegateRespondsToSelectorMask & kDelegateRespondsTo_textView_didChangeSelection)
|
||||||
|
[nc removeObserver:_delegate name:CPTextViewDidChangeSelectionNotification object:self];
|
||||||
|
|
||||||
|
if (_delegateRespondsToSelectorMask & kDelegateRespondsTo_textView_didChangeTypingAttributes)
|
||||||
|
[nc removeObserver:_delegate name:CPTextViewDidChangeTypingAttributesNotification object:self];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)_startObservingClipView
|
- (void)_startObservingClipView
|
||||||
{
|
{
|
||||||
if (!_observedClipView)
|
if (!_observedClipView)
|
||||||
@@ -359,7 +413,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
- (void)_windowDidResignKey:(CPNotification)aNotification
|
- (void)_windowDidResignKey:(CPNotification)aNotification
|
||||||
{
|
{
|
||||||
if (![[self window] isKeyWindow])
|
if (![[self window] isKeyWindow])
|
||||||
[self resignFirstResponder];
|
[self _resignFirstResponder];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_windowDidBecomeKey:(CPNotification)aNotification
|
- (void)_windowDidBecomeKey:(CPNotification)aNotification
|
||||||
@@ -373,7 +427,6 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
|
|
||||||
- (void)copy:(id)sender
|
- (void)copy:(id)sender
|
||||||
{
|
{
|
||||||
_copySelectionGranularity = _previousSelectionGranularity;
|
|
||||||
[super copy:sender];
|
[super copy:sender];
|
||||||
|
|
||||||
if (![self isRichText])
|
if (![self isRichText])
|
||||||
@@ -387,6 +440,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
[pasteboard declareTypes:[CPStringPboardType, CPRTFPboardType] owner:nil];
|
[pasteboard declareTypes:[CPStringPboardType, CPRTFPboardType] owner:nil];
|
||||||
[pasteboard setString:stringForPasting._string forType:CPStringPboardType];
|
[pasteboard setString:stringForPasting._string forType:CPStringPboardType];
|
||||||
[pasteboard setString:richData forType:CPRTFPboardType];
|
[pasteboard setString:richData forType:CPRTFPboardType];
|
||||||
|
[pasteboard setString:_previousSelectionGranularity + '' forType:_CPSmartPboardType];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_pasteString:(id)stringForPasting
|
- (void)_pasteString:(id)stringForPasting
|
||||||
@@ -394,7 +448,9 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
if (!stringForPasting)
|
if (!stringForPasting)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_copySelectionGranularity > 0 && _selectionRange.location > 0)
|
var shouldUseSmartPasting = [self _shouldUseSmartPasting];
|
||||||
|
|
||||||
|
if (shouldUseSmartPasting && _selectionRange.location > 0)
|
||||||
{
|
{
|
||||||
if (!_isWhitespaceCharacter([[_textStorage string] characterAtIndex:_selectionRange.location - 1]) &&
|
if (!_isWhitespaceCharacter([[_textStorage string] characterAtIndex:_selectionRange.location - 1]) &&
|
||||||
_selectionRange.location != [_layoutManager numberOfCharacters])
|
_selectionRange.location != [_layoutManager numberOfCharacters])
|
||||||
@@ -403,29 +459,9 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_copySelectionGranularity == CPSelectByParagraph)
|
|
||||||
{
|
|
||||||
var peekStr = stringForPasting,
|
|
||||||
i = 0;
|
|
||||||
|
|
||||||
if (![stringForPasting isKindOfClass:[CPString class]])
|
|
||||||
peekStr = stringForPasting._string;
|
|
||||||
|
|
||||||
while (_isWhitespaceCharacter([peekStr characterAtIndex:i]))
|
|
||||||
i++;
|
|
||||||
|
|
||||||
if (i)
|
|
||||||
{
|
|
||||||
if ([stringForPasting isKindOfClass:[CPString class]])
|
|
||||||
stringForPasting = [stringForPasting stringByReplacingCharactersInRange:CPMakeRange(0, i) withString:''];
|
|
||||||
else
|
|
||||||
[stringForPasting replaceCharactersInRange:CPMakeRange(0, i) withString:''];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[self insertText:stringForPasting];
|
[self insertText:stringForPasting];
|
||||||
|
|
||||||
if (_copySelectionGranularity > 0)
|
if (shouldUseSmartPasting)
|
||||||
{
|
{
|
||||||
if (!_isWhitespaceCharacter([[_textStorage string] characterAtIndex:CPMaxRange(_selectionRange)]) &&
|
if (!_isWhitespaceCharacter([[_textStorage string] characterAtIndex:CPMaxRange(_selectionRange)]) &&
|
||||||
!_isNewlineCharacter([[_textStorage string] characterAtIndex:MAX(0, _selectionRange.location - 1)]) &&
|
!_isNewlineCharacter([[_textStorage string] characterAtIndex:MAX(0, _selectionRange.location - 1)]) &&
|
||||||
@@ -471,17 +507,33 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
- (BOOL)becomeFirstResponder
|
- (BOOL)becomeFirstResponder
|
||||||
{
|
{
|
||||||
[super becomeFirstResponder];
|
[super becomeFirstResponder];
|
||||||
|
_firstResponderButNotEditingYet = YES;
|
||||||
[self _becomeFirstResponder];
|
[self _becomeFirstResponder];
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)resignFirstResponder
|
- (void)_resignFirstResponder
|
||||||
{
|
{
|
||||||
[self _reverseSetBinding];
|
[self _reverseSetBinding];
|
||||||
[_caret stopBlinking];
|
[_caret stopBlinking];
|
||||||
[self setNeedsDisplay:YES];
|
[self setNeedsDisplay:YES];
|
||||||
[_CPNativeInputManager cancelCurrentInputSessionIfNeeded];
|
[_CPNativeInputManager cancelCurrentInputSessionIfNeeded];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)resignFirstResponder
|
||||||
|
{
|
||||||
|
if (_firstResponderButNotEditingYet)
|
||||||
|
_firstResponderButNotEditingYet = NO;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ([self _sendDelegateTextShouldEndEditing])
|
||||||
|
[[CPNotificationCenter defaultCenter] postNotificationName:CPTextDidEndEditingNotification object:self];
|
||||||
|
else
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
[self _resignFirstResponder];
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
@@ -498,6 +550,8 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
if (aDelegate === _delegate)
|
if (aDelegate === _delegate)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
[self _removeDelegateObservers];
|
||||||
|
|
||||||
_delegateRespondsToSelectorMask = 0;
|
_delegateRespondsToSelectorMask = 0;
|
||||||
_delegate = aDelegate;
|
_delegate = aDelegate;
|
||||||
|
|
||||||
@@ -512,12 +566,21 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
if ([_delegate respondsToSelector:@selector(textViewDidChangeTypingAttributes:)])
|
if ([_delegate respondsToSelector:@selector(textViewDidChangeTypingAttributes:)])
|
||||||
_delegateRespondsToSelectorMask |= kDelegateRespondsTo_textView_didChangeTypingAttributes;
|
_delegateRespondsToSelectorMask |= kDelegateRespondsTo_textView_didChangeTypingAttributes;
|
||||||
|
|
||||||
|
if ([_delegate respondsToSelector:@selector(textDidBeginEditing:)])
|
||||||
|
_delegateRespondsToSelectorMask |= kDelegateRespondsTo_textView_textDidBeginEditing;
|
||||||
|
|
||||||
|
if ([_delegate respondsToSelector:@selector(textDidEndEditing:)])
|
||||||
|
_delegateRespondsToSelectorMask |= kDelegateRespondsTo_textView_textDidEndEditing;
|
||||||
|
|
||||||
if ([_delegate respondsToSelector:@selector(textView:doCommandBySelector:)])
|
if ([_delegate respondsToSelector:@selector(textView:doCommandBySelector:)])
|
||||||
_delegateRespondsToSelectorMask |= kDelegateRespondsTo_textView_doCommandBySelector;
|
_delegateRespondsToSelectorMask |= kDelegateRespondsTo_textView_doCommandBySelector;
|
||||||
|
|
||||||
if ([_delegate respondsToSelector:@selector(textShouldBeginEditing:)])
|
if ([_delegate respondsToSelector:@selector(textShouldBeginEditing:)])
|
||||||
_delegateRespondsToSelectorMask |= kDelegateRespondsTo_textShouldBeginEditing;
|
_delegateRespondsToSelectorMask |= kDelegateRespondsTo_textShouldBeginEditing;
|
||||||
|
|
||||||
|
if ([_delegate respondsToSelector:@selector(textShouldEndEditing:)])
|
||||||
|
_delegateRespondsToSelectorMask |= kDelegateRespondsTo_textShouldEndEditing;
|
||||||
|
|
||||||
if ([_delegate respondsToSelector:@selector(textView:willChangeSelectionFromCharacterRange:toCharacterRange:)])
|
if ([_delegate respondsToSelector:@selector(textView:willChangeSelectionFromCharacterRange:toCharacterRange:)])
|
||||||
_delegateRespondsToSelectorMask |= kDelegateRespondsTo_textView_willChangeSelectionFromCharacterRange_toCharacterRange;
|
_delegateRespondsToSelectorMask |= kDelegateRespondsTo_textView_willChangeSelectionFromCharacterRange_toCharacterRange;
|
||||||
|
|
||||||
@@ -526,6 +589,9 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
|
|
||||||
if ([_delegate respondsToSelector:@selector(textView:shouldChangeTypingAttributes:toAttributes:)])
|
if ([_delegate respondsToSelector:@selector(textView:shouldChangeTypingAttributes:toAttributes:)])
|
||||||
_delegateRespondsToSelectorMask |= kDelegateRespondsTo_textView_shouldChangeTypingAttributes_toAttributes;
|
_delegateRespondsToSelectorMask |= kDelegateRespondsTo_textView_shouldChangeTypingAttributes_toAttributes;
|
||||||
|
|
||||||
|
if (_superview)
|
||||||
|
[self _addDelegateObservers];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -662,9 +728,21 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
- (void)didChangeText
|
- (void)didChangeText
|
||||||
{
|
{
|
||||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPTextDidChangeNotification object:self];
|
[[CPNotificationCenter defaultCenter] postNotificationName:CPTextDidChangeNotification object:self];
|
||||||
|
}
|
||||||
|
|
||||||
if (_delegateRespondsToSelectorMask & kDelegateRespondsTo_textView_textDidChange)
|
- (BOOL)_didBeginEditing
|
||||||
[_delegate textDidChange:[[CPNotification alloc] initWithName:CPTextDidChangeNotification object:self userInfo:nil]];
|
{
|
||||||
|
if (_firstResponderButNotEditingYet)
|
||||||
|
{
|
||||||
|
if ([self _sendDelegateTextShouldBeginEditing])
|
||||||
|
{
|
||||||
|
[[CPNotificationCenter defaultCenter] postNotificationName:CPTextDidBeginEditingNotification object:self];
|
||||||
|
_firstResponderButNotEditingYet = NO;
|
||||||
|
} else
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)shouldChangeTextInRange:(CPRange)aRange replacementString:(CPString)aString
|
- (BOOL)shouldChangeTextInRange:(CPRange)aRange replacementString:(CPString)aString
|
||||||
@@ -672,7 +750,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
if (![self isEditable])
|
if (![self isEditable])
|
||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
return [self _sendDelegateTextShouldBeginEditing] && [self _sendDelegateShouldChangeTextInRange:aRange replacementString:aString];
|
return [self _sendDelegateShouldChangeTextInRange:aRange replacementString:aString];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -704,7 +782,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
var isAttributed = [aString isKindOfClass:CPAttributedString],
|
var isAttributed = [aString isKindOfClass:CPAttributedString],
|
||||||
string = isAttributed ? [aString string]:aString;
|
string = isAttributed ? [aString string]:aString;
|
||||||
|
|
||||||
if (![self shouldChangeTextInRange:CPMakeRangeCopy(_selectionRange) replacementString:string])
|
if (![self _didBeginEditing] || ![self shouldChangeTextInRange:CPMakeRangeCopy(_selectionRange) replacementString:string])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!isAttributed)
|
if (!isAttributed)
|
||||||
@@ -806,53 +884,80 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Sets the selection to a range of characters in response to user action.
|
||||||
|
@param range The range of characters to select. This range must begin and end on glyph boundaries and not split base glyphs and their nonspacing marks.
|
||||||
|
*/
|
||||||
- (void)setSelectedRange:(CPRange)range
|
- (void)setSelectedRange:(CPRange)range
|
||||||
{
|
{
|
||||||
[_CPNativeInputManager cancelCurrentInputSessionIfNeeded];
|
[_CPNativeInputManager cancelCurrentInputSessionIfNeeded];
|
||||||
[self setSelectedRange:range affinity:0 stillSelecting:NO];
|
[self setSelectedRange:range affinity:0 stillSelecting:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Sets the selection to a range of characters in response to user action.
|
||||||
|
@param range The range of characters to select. This range must begin and end on glyph boundaries and not split base glyphs and their nonspacing marks.
|
||||||
|
@param affinity The selection affinity for the selection. See selectionAffinity for more information about how affinities work.
|
||||||
|
@param selecting YES to behave appropriately for a continuing selection where the user is still dragging the mouse, NO otherwise. If YES, the receiver doesn’t send notifications or remove the marking from its marked text. If NO, the receiver posts an NSTextViewDidChangeSelectionNotification to the default notification center and removes the marking from marked text if the new selection is greater than the marked region.
|
||||||
|
*/
|
||||||
- (void)setSelectedRange:(CPRange)range affinity:(CPSelectionAffinity)affinity stillSelecting:(BOOL)selecting
|
- (void)setSelectedRange:(CPRange)range affinity:(CPSelectionAffinity)affinity stillSelecting:(BOOL)selecting
|
||||||
{
|
{
|
||||||
[self _setSelectedRange:range affinity:affinity stillSelecting:selecting overwriteTypingAttributes:YES];
|
[self _setSelectedRange:range affinity:affinity stillSelecting:selecting overwriteTypingAttributes:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Sets the selection to a range of characters in response to user action.
|
||||||
|
@param range The range of characters to select. This range must begin and end on glyph boundaries and not split base glyphs and their nonspacing marks.
|
||||||
|
@param affinity The selection affinity for the selection. See selectionAffinity for more information about how affinities work.
|
||||||
|
@param selecting YES to behave appropriately for a continuing selection where the user is still dragging the mouse, NO otherwise. If YES, the receiver doesn’t send notifications or remove the marking from its marked text. If NO, the receiver posts an NSTextViewDidChangeSelectionNotification to the default notification center and removes the marking from marked text if the new selection is greater than the marked region.
|
||||||
|
@param doOverwrite YES to override typing attributes. NO to not override.
|
||||||
|
*/
|
||||||
- (void)_setSelectedRange:(CPRange)range affinity:(CPSelectionAffinity)affinity stillSelecting:(BOOL)selecting overwriteTypingAttributes:(BOOL)doOverwrite
|
- (void)_setSelectedRange:(CPRange)range affinity:(CPSelectionAffinity)affinity stillSelecting:(BOOL)selecting overwriteTypingAttributes:(BOOL)doOverwrite
|
||||||
{
|
{
|
||||||
var maxRange = CPMakeRange(0, [_layoutManager numberOfCharacters]);
|
var maxRange = CPMakeRange(0, [_layoutManager numberOfCharacters]),
|
||||||
|
newSelectionRange;
|
||||||
|
|
||||||
range = CPIntersectionRange(maxRange, range);
|
range = CPIntersectionRange(maxRange, range);
|
||||||
|
|
||||||
if (!selecting && [self _delegateRespondsToWillChangeSelectionFromCharacterRangeToCharacterRange])
|
if (!selecting && [self _delegateRespondsToWillChangeSelectionFromCharacterRangeToCharacterRange])
|
||||||
{
|
{
|
||||||
_selectionRange = [self _sendDelegateWillChangeSelectionFromCharacterRange:_selectionRange toCharacterRange:range];
|
newSelectionRange = [self _sendDelegateWillChangeSelectionFromCharacterRange:_selectionRange toCharacterRange:range];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_selectionRange = CPMakeRangeCopy(range);
|
newSelectionRange = [self selectionRangeForProposedRange:range granularity:[self selectionGranularity]];
|
||||||
_selectionRange = [self selectionRangeForProposedRange:_selectionRange granularity:[self selectionGranularity]];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_selectionRange.length)
|
var isNewSelection = !CPEqualRanges(newSelectionRange, _selectionRange);
|
||||||
[_layoutManager invalidateDisplayForGlyphRange:_selectionRange];
|
|
||||||
|
if (isNewSelection)
|
||||||
|
_selectionRange = newSelectionRange;
|
||||||
|
|
||||||
|
if (newSelectionRange.length)
|
||||||
|
{
|
||||||
|
if (isNewSelection)
|
||||||
|
[_layoutManager invalidateDisplayForGlyphRange:newSelectionRange];
|
||||||
|
}
|
||||||
else
|
else
|
||||||
[self setNeedsDisplay:YES];
|
[self setNeedsDisplay:YES];
|
||||||
|
|
||||||
if (!selecting)
|
if (!selecting)
|
||||||
{
|
{
|
||||||
if ([self _isFirstResponder])
|
if ([self _isFirstResponder])
|
||||||
[self updateInsertionPointStateAndRestartTimer:((_selectionRange.length === 0) && ![_caret isBlinking])];
|
[self updateInsertionPointStateAndRestartTimer:((newSelectionRange.length === 0) && ![_caret isBlinking])];
|
||||||
|
|
||||||
if (doOverwrite && _placeholderString === nil)
|
// If there is no new selection but the pervious mouseDown has saved a selection we check against the saved selection instead
|
||||||
|
if (!isNewSelection && _mouseDownOldSelection)
|
||||||
|
isNewSelection = !CPEqualRanges(newSelectionRange, _mouseDownOldSelection);
|
||||||
|
|
||||||
|
if (doOverwrite && _placeholderString === nil && isNewSelection)
|
||||||
[self setTypingAttributes:[_textStorage attributesAtIndex:CPMaxRange(range) effectiveRange:nil]];
|
[self setTypingAttributes:[_textStorage attributesAtIndex:CPMaxRange(range) effectiveRange:nil]];
|
||||||
|
|
||||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPTextViewDidChangeSelectionNotification object:self];
|
[[CPNotificationCenter defaultCenter] postNotificationName:CPTextViewDidChangeSelectionNotification object:self];
|
||||||
|
|
||||||
if (_delegateRespondsToSelectorMask & kDelegateRespondsTo_textView_didChangeSelection)
|
|
||||||
[_delegate textViewDidChangeSelection:[[CPNotification alloc] initWithName:CPTextViewDidChangeSelectionNotification object:self userInfo:nil]];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!selecting && _selectionRange.length > 0)
|
if (!selecting && newSelectionRange.length > 0)
|
||||||
[_CPNativeInputManager focusForClipboardOfTextView:self];
|
[_CPNativeInputManager focusForClipboardOfTextView:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -936,18 +1041,18 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
{
|
{
|
||||||
var fraction = [],
|
var fraction = [],
|
||||||
point = [self convertPoint:point fromView:nil];
|
point = [self convertPoint:point fromView:nil];
|
||||||
|
|
||||||
// convert to container coordinate
|
// convert to container coordinate
|
||||||
point.x -= _textContainerOrigin.x;
|
point.x -= _textContainerOrigin.x;
|
||||||
point.y -= _textContainerOrigin.y;
|
point.y -= _textContainerOrigin.y;
|
||||||
|
|
||||||
var index = [_layoutManager glyphIndexForPoint:point inTextContainer:_textContainer fractionOfDistanceThroughGlyph:fraction];
|
var index = [_layoutManager glyphIndexForPoint:point inTextContainer:_textContainer fractionOfDistanceThroughGlyph:fraction];
|
||||||
|
|
||||||
if (index === CPNotFound)
|
if (index === CPNotFound)
|
||||||
index = [_layoutManager numberOfCharacters];
|
index = [_layoutManager numberOfCharacters];
|
||||||
else if (fraction[0] > 0.5)
|
else if (fraction[0] > 0.5)
|
||||||
index++;
|
index++;
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
- (CGPoint)_characterIndexFromEvent:(CPEvent)event
|
- (CGPoint)_characterIndexFromEvent:(CPEvent)event
|
||||||
@@ -970,9 +1075,9 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
|
|
||||||
[_CPNativeInputManager cancelCurrentInputSessionIfNeeded];
|
[_CPNativeInputManager cancelCurrentInputSessionIfNeeded];
|
||||||
[_caret setVisibility:NO];
|
[_caret setVisibility:NO];
|
||||||
|
|
||||||
_startTrackingLocation = [self _characterIndexFromEvent:event];
|
_startTrackingLocation = [self _characterIndexFromEvent:event];
|
||||||
|
|
||||||
var granularities = [CPNotFound, CPSelectByCharacter, CPSelectByWord, CPSelectByParagraph];
|
var granularities = [CPNotFound, CPSelectByCharacter, CPSelectByWord, CPSelectByParagraph];
|
||||||
[self setSelectionGranularity:granularities[[event clickCount]]];
|
[self setSelectionGranularity:granularities[[event clickCount]]];
|
||||||
|
|
||||||
@@ -985,20 +1090,20 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
placeholderFrame = CGRectIntersection([_layoutManager boundingRectForGlyphRange:placeholderRange inTextContainer:_textContainer], _frame),
|
placeholderFrame = CGRectIntersection([_layoutManager boundingRectForGlyphRange:placeholderRange inTextContainer:_textContainer], _frame),
|
||||||
rangeToHide = CPMakeRange(0, _selectionRange.location - lineBeginningIndex),
|
rangeToHide = CPMakeRange(0, _selectionRange.location - lineBeginningIndex),
|
||||||
dragPlaceholder;
|
dragPlaceholder;
|
||||||
|
|
||||||
// hide the left part of the first line of the selection that is not included
|
// hide the left part of the first line of the selection that is not included
|
||||||
[placeholderString addAttribute:CPForegroundColorAttributeName
|
[placeholderString addAttribute:CPForegroundColorAttributeName
|
||||||
value:[CPColor colorWithRed:1 green:1 blue:1 alpha:0]
|
value:[CPColor colorWithRed:1 green:1 blue:1 alpha:0]
|
||||||
range:rangeToHide];
|
range:rangeToHide];
|
||||||
|
|
||||||
_movingSelection = CPMakeRange(_startTrackingLocation, 0);
|
_movingSelection = CPMakeRange(_startTrackingLocation, 0);
|
||||||
|
|
||||||
dragPlaceholder = [[CPTextView alloc] initWithFrame:placeholderFrame];
|
dragPlaceholder = [[CPTextView alloc] initWithFrame:placeholderFrame];
|
||||||
[dragPlaceholder._textStorage replaceCharactersInRange:CPMakeRange(0, 0) withAttributedString:placeholderString];
|
[dragPlaceholder._textStorage replaceCharactersInRange:CPMakeRange(0, 0) withAttributedString:placeholderString];
|
||||||
|
|
||||||
[dragPlaceholder setBackgroundColor:[CPColor colorWithRed:1 green:1 blue:1 alpha:0]];
|
[dragPlaceholder setBackgroundColor:[CPColor colorWithRed:1 green:1 blue:1 alpha:0]];
|
||||||
[dragPlaceholder setAlphaValue:0.5];
|
[dragPlaceholder setAlphaValue:0.5];
|
||||||
|
|
||||||
var stringForPasting = [_textStorage attributedSubstringFromRange:CPMakeRangeCopy(_selectionRange)],
|
var stringForPasting = [_textStorage attributedSubstringFromRange:CPMakeRangeCopy(_selectionRange)],
|
||||||
richData = [_CPRTFProducer produceRTF:stringForPasting documentAttributes:@{}],
|
richData = [_CPRTFProducer produceRTF:stringForPasting documentAttributes:@{}],
|
||||||
draggingPasteboard = [CPPasteboard pasteboardWithName:CPDragPboard];
|
draggingPasteboard = [CPPasteboard pasteboardWithName:CPDragPboard];
|
||||||
@@ -1013,17 +1118,19 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
pasteboard:draggingPasteboard
|
pasteboard:draggingPasteboard
|
||||||
source:self
|
source:self
|
||||||
slideBack:YES];
|
slideBack:YES];
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var setRange = CPMakeRange(_startTrackingLocation, 0);
|
var setRange = CPMakeRange(_startTrackingLocation, 0);
|
||||||
|
|
||||||
if ([event modifierFlags] & CPShiftKeyMask)
|
if ([event modifierFlags] & CPShiftKeyMask)
|
||||||
setRange = _MakeRangeFromAbs(_startTrackingLocation < _MidRange(_selectionRange) ? CPMaxRange(_selectionRange) : _selectionRange.location, _startTrackingLocation);
|
setRange = _MakeRangeFromAbs(_startTrackingLocation < _MidRange(_selectionRange) ? CPMaxRange(_selectionRange) : _selectionRange.location, _startTrackingLocation);
|
||||||
else
|
else
|
||||||
_scrollingTimer = [CPTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(_supportScrolling:) userInfo:nil repeats:YES]; // fixme: only start if we are in the scrolling areas
|
_scrollingTimer = [CPTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(_supportScrolling:) userInfo:nil repeats:YES]; // fixme: only start if we are in the scrolling areas
|
||||||
|
|
||||||
|
// Save old selection so we can only send textViewDidChangeTypingAttribute notification when selection is changed on mouse up.
|
||||||
|
_mouseDownOldSelection = _selectionRange;
|
||||||
[self setSelectedRange:setRange affinity:0 stillSelecting:YES];
|
[self setSelectedRange:setRange affinity:0 stillSelecting:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1039,7 +1146,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
|
|
||||||
if (_movingSelection)
|
if (_movingSelection)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var oldRange = [self selectedRange],
|
var oldRange = [self selectedRange],
|
||||||
index = [self _characterIndexFromEvent:event];
|
index = [self _characterIndexFromEvent:event];
|
||||||
|
|
||||||
@@ -1066,6 +1173,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
_previousSelectionGranularity = [self selectionGranularity];
|
_previousSelectionGranularity = [self selectionGranularity];
|
||||||
[self setSelectionGranularity:CPSelectByCharacter];
|
[self setSelectionGranularity:CPSelectByCharacter];
|
||||||
[self setSelectedRange:[self selectedRange] affinity:0 stillSelecting:NO];
|
[self setSelectedRange:[self selectedRange] affinity:0 stillSelecting:NO];
|
||||||
|
_mouseDownOldSelection = nil;
|
||||||
|
|
||||||
var point = [_layoutManager locationForGlyphAtIndex:[self selectedRange].location];
|
var point = [_layoutManager locationForGlyphAtIndex:[self selectedRange].location];
|
||||||
_stickyXLocation = point.x;
|
_stickyXLocation = point.x;
|
||||||
@@ -1478,7 +1586,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
- (void)moveWordLeft:(id)sender
|
- (void)moveWordLeft:(id)sender
|
||||||
{
|
{
|
||||||
if ([self isSelectable])
|
if ([self isSelectable])
|
||||||
[self _moveSelectionIntoDirection:-1 granularity:CPSelectByWord]
|
[self _moveSelectionIntoDirection:-1 granularity:CPSelectByWord];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)moveRight:(id)sender
|
- (void)moveRight:(id)sender
|
||||||
@@ -1489,7 +1597,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
|
|
||||||
- (void)_deleteForRange:(CPRange)changedRange
|
- (void)_deleteForRange:(CPRange)changedRange
|
||||||
{
|
{
|
||||||
if (![self shouldChangeTextInRange:changedRange replacementString:@""])
|
if (![self _didBeginEditing] || ![self shouldChangeTextInRange:changedRange replacementString:@""])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
changedRange = CPIntersectionRange(CPMakeRange(0, [_layoutManager numberOfCharacters]), changedRange);
|
changedRange = CPIntersectionRange(CPMakeRange(0, [_layoutManager numberOfCharacters]), changedRange);
|
||||||
@@ -1506,6 +1614,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
[self didChangeText];
|
[self didChangeText];
|
||||||
[_layoutManager _validateLayoutAndGlyphs];
|
[_layoutManager _validateLayoutAndGlyphs];
|
||||||
[self sizeToFit];
|
[self sizeToFit];
|
||||||
|
[self scrollRangeToVisible:CPMakeRange(changedRange.location, 0)];
|
||||||
_stickyXLocation = _caret._rect.origin.x;
|
_stickyXLocation = _caret._rect.origin.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1514,7 +1623,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
[_CPNativeInputManager cancelCurrentInputSessionIfNeeded]; // handle ESC during native input
|
[_CPNativeInputManager cancelCurrentInputSessionIfNeeded]; // handle ESC during native input
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)deleteBackward:(id)sender ignoreSmart:(BOOL)ignoreFlag
|
- (void)deleteBackward:(id)sender handleSmart:(BOOL)handleSmart
|
||||||
{
|
{
|
||||||
var changedRange;
|
var changedRange;
|
||||||
|
|
||||||
@@ -1524,7 +1633,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
changedRange = _selectionRange;
|
changedRange = _selectionRange;
|
||||||
|
|
||||||
// smart delete
|
// smart delete
|
||||||
if (!ignoreFlag && _copySelectionGranularity > 0 &&
|
if (handleSmart &&
|
||||||
changedRange.location > 0 && _isWhitespaceCharacter([[_textStorage string] characterAtIndex:_selectionRange.location - 1]) &&
|
changedRange.location > 0 && _isWhitespaceCharacter([[_textStorage string] characterAtIndex:_selectionRange.location - 1]) &&
|
||||||
changedRange.location < [[self string] length] && _isWhitespaceCharacter([[_textStorage string] characterAtIndex:CPMaxRange(changedRange)]))
|
changedRange.location < [[self string] length] && _isWhitespaceCharacter([[_textStorage string] characterAtIndex:CPMaxRange(changedRange)]))
|
||||||
changedRange.length++;
|
changedRange.length++;
|
||||||
@@ -1535,8 +1644,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
|
|
||||||
- (void)deleteBackward:(id)sender
|
- (void)deleteBackward:(id)sender
|
||||||
{
|
{
|
||||||
_copySelectionGranularity = _previousSelectionGranularity; // smart delete
|
[self deleteBackward:self handleSmart:[self _shouldUseSmartPasting] && _selectionRange.length > 0];
|
||||||
[self deleteBackward:self ignoreSmart:_selectionRange.length > 0? NO:YES];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)deleteForward:(id)sender
|
- (void)deleteForward:(id)sender
|
||||||
@@ -1559,7 +1667,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
[self copy:sender];
|
[self copy:sender];
|
||||||
[self deleteBackward:sender ignoreSmart:NO];
|
[self deleteBackward:sender handleSmart:_previousSelectionGranularity];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)insertLineBreak:(id)sender
|
- (void)insertLineBreak:(id)sender
|
||||||
@@ -1612,11 +1720,11 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
[self _enrichEssentialTypingAttributes:_typingAttributes];
|
[self _enrichEssentialTypingAttributes:_typingAttributes];
|
||||||
}
|
}
|
||||||
|
|
||||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPTextViewDidChangeTypingAttributesNotification
|
[[CPNotificationCenter defaultCenter] postNotificationName:CPTextViewDidChangeTypingAttributesNotification object:self];
|
||||||
object:self];
|
|
||||||
|
|
||||||
if (_delegateRespondsToSelectorMask & kDelegateRespondsTo_textView_didChangeTypingAttributes)
|
// We always clear the saved selection range from the last mouse down event here.
|
||||||
[_delegate textViewDidChangeTypingAttributes:[[CPNotification alloc] initWithName:CPTextViewDidChangeTypingAttributesNotification object:self userInfo:nil]];
|
// This is normally done in mouseUp: but this is if that event was never sent.
|
||||||
|
_mouseDownOldSelection = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CPDictionary)_attributesForFontPanel
|
- (CPDictionary)_attributesForFontPanel
|
||||||
@@ -1759,7 +1867,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
|
|
||||||
- (void)underline:(id)sender
|
- (void)underline:(id)sender
|
||||||
{
|
{
|
||||||
if (![self shouldChangeTextInRange:_selectionRange replacementString:nil])
|
if (![self _didBeginEditing] || ![self shouldChangeTextInRange:_selectionRange replacementString:nil])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!CPEmptyRange(_selectionRange))
|
if (!CPEmptyRange(_selectionRange))
|
||||||
@@ -1999,7 +2107,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
|
|
||||||
- (BOOL)shouldDrawInsertionPoint
|
- (BOOL)shouldDrawInsertionPoint
|
||||||
{
|
{
|
||||||
return (_selectionRange.length === 0 && [self _isFocused]);
|
return (_selectionRange.length === 0 && [self _isFocused] && !_placeholderString);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateInsertionPointStateAndRestartTimer:(BOOL)flag
|
- (void)updateInsertionPointStateAndRestartTimer:(BOOL)flag
|
||||||
@@ -2060,7 +2168,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
{
|
{
|
||||||
var point = [info draggingLocation],
|
var point = [info draggingLocation],
|
||||||
location = [self _characterIndexFromRawPoint:CGPointCreateCopy(point)];
|
location = [self _characterIndexFromRawPoint:CGPointCreateCopy(point)];
|
||||||
|
|
||||||
_movingSelection = CPMakeRange(location, 0);
|
_movingSelection = CPMakeRange(location, 0);
|
||||||
[_caret _drawCaretAtLocation:_movingSelection.location];
|
[_caret _drawCaretAtLocation:_movingSelection.location];
|
||||||
[_caret setVisibility:YES];
|
[_caret setVisibility:YES];
|
||||||
@@ -2073,11 +2181,11 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
{
|
{
|
||||||
var location = [self convertPoint:[aSender draggingLocation] fromView:nil],
|
var location = [self convertPoint:[aSender draggingLocation] fromView:nil],
|
||||||
pasteboard = [aSender draggingPasteboard];
|
pasteboard = [aSender draggingPasteboard];
|
||||||
|
|
||||||
if ([pasteboard availableTypeFromArray:[CPRTFPboardType, CPStringPboardType]])
|
if ([pasteboard availableTypeFromArray:[CPRTFPboardType, CPStringPboardType]])
|
||||||
{
|
{
|
||||||
[_caret setVisibility:NO];
|
[_caret setVisibility:NO];
|
||||||
|
|
||||||
if (CPLocationInRange(_movingSelection.location, _selectionRange))
|
if (CPLocationInRange(_movingSelection.location, _selectionRange))
|
||||||
{
|
{
|
||||||
[self setSelectedRange:_movingSelection];
|
[self setSelectedRange:_movingSelection];
|
||||||
@@ -2102,7 +2210,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
[self insertText:dataForPasting];
|
[self insertText:dataForPasting];
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([pasteboard availableTypeFromArray:[CPColorDragType]])
|
if ([pasteboard availableTypeFromArray:[CPColorDragType]])
|
||||||
[self setTextColor:[CPKeyedUnarchiver unarchiveObjectWithData:[pasteboard dataForType:CPColorDragType]] range:_selectionRange];
|
[self setTextColor:[CPKeyedUnarchiver unarchiveObjectWithData:[pasteboard dataForType:CPColorDragType]] range:_selectionRange];
|
||||||
}
|
}
|
||||||
@@ -2142,7 +2250,8 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
[[self class] _binderClassForBinding:CPValueBinding],
|
[[self class] _binderClassForBinding:CPValueBinding],
|
||||||
theBinding = [binderClass getBinding:CPAttributedStringBinding forObject:self] || [binderClass getBinding:CPValueBinding forObject:self];
|
theBinding = [binderClass getBinding:CPAttributedStringBinding forObject:self] || [binderClass getBinding:CPValueBinding forObject:self];
|
||||||
|
|
||||||
[theBinding reverseSetValueFor:@"objectValue"];
|
if (theBinding && [self isEditable])
|
||||||
|
[theBinding reverseSetValueFor:@"objectValue"];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -2176,6 +2285,14 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
return [_delegate textShouldBeginEditing:self];
|
return [_delegate textShouldBeginEditing:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)_sendDelegateTextShouldEndEditing
|
||||||
|
{
|
||||||
|
if (!(_delegateRespondsToSelectorMask & kDelegateRespondsTo_textShouldEndEditing))
|
||||||
|
return YES;
|
||||||
|
|
||||||
|
return [_delegate textShouldEndEditing:self];
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL)_sendDelegateShouldChangeTextInRange:(CPRange)aRange replacementString:(CPString)aString
|
- (BOOL)_sendDelegateShouldChangeTextInRange:(CPRange)aRange replacementString:(CPString)aString
|
||||||
{
|
{
|
||||||
if (!(_delegateRespondsToSelectorMask & kDelegateRespondsTo_textView_shouldChangeTextInRange_replacementString))
|
if (!(_delegateRespondsToSelectorMask & kDelegateRespondsTo_textView_shouldChangeTextInRange_replacementString))
|
||||||
@@ -2186,7 +2303,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
|||||||
|
|
||||||
- (CPDictionary)_sendDelegateShouldChangeTypingAttributes:(CPDictionary)typingAttributes toAttributes:(CPDictionary)attributes
|
- (CPDictionary)_sendDelegateShouldChangeTypingAttributes:(CPDictionary)typingAttributes toAttributes:(CPDictionary)attributes
|
||||||
{
|
{
|
||||||
if (!(_delegateRespondsToSelectorMask & kDelegateRespondsTo_textView_doCommandBySelector))
|
if (!(_delegateRespondsToSelectorMask & kDelegateRespondsTo_textView_shouldChangeTypingAttributes_toAttributes))
|
||||||
return [CPDictionary dictionary];
|
return [CPDictionary dictionary];
|
||||||
|
|
||||||
return [_delegate textView:self shouldChangeTypingAttributes:typingAttributes toAttributes:attributes];
|
return [_delegate textView:self shouldChangeTypingAttributes:typingAttributes toAttributes:attributes];
|
||||||
@@ -2275,7 +2392,7 @@ var CPTextViewAllowsUndoKey = @"CPTextViewAllowsUndoKey",
|
|||||||
{
|
{
|
||||||
DOMElement _selectionBoxDOM;
|
DOMElement _selectionBoxDOM;
|
||||||
CGRect _rect;
|
CGRect _rect;
|
||||||
CPColor _color
|
CPColor _color;
|
||||||
CPTextView _textView;
|
CPTextView _textView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2419,13 +2536,13 @@ var CPTextViewAllowsUndoKey = @"CPTextViewAllowsUndoKey",
|
|||||||
_caretTimer = nil;
|
_caretTimer = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_drawCaretAtLocation:(int)aLoc
|
- (void)_drawCaretAtLocation:(int)aLoc
|
||||||
{
|
{
|
||||||
var rect = [_textView._layoutManager boundingRectForGlyphRange:CPMakeRange(aLoc, 1) inTextContainer:_textView._textContainer];
|
var rect = [_textView._layoutManager boundingRectForGlyphRange:CPMakeRange(aLoc, 1) inTextContainer:_textView._textContainer];
|
||||||
|
|
||||||
if (aLoc >= [_textView._layoutManager numberOfCharacters])
|
if (aLoc >= [_textView._layoutManager numberOfCharacters])
|
||||||
rect.origin.x = CGRectGetMaxX(rect)
|
rect.origin.x = CGRectGetMaxX(rect);
|
||||||
|
|
||||||
[self setRect:rect];
|
[self setRect:rect];
|
||||||
}
|
}
|
||||||
@@ -2606,7 +2723,7 @@ var _CPCopyPlaceholder = '-';
|
|||||||
isPlain = YES;
|
isPlain = YES;
|
||||||
|
|
||||||
// this is the rich chrome / FF codepath (where we can use RTF directly)
|
// this is the rich chrome / FF codepath (where we can use RTF directly)
|
||||||
if ((richtext = nativeClipboard.getData('text/rtf')) && !(!!window.event.shiftKey) && !isPlain)
|
if ((richtext = nativeClipboard.getData('text/rtf')) && !(!!(e.originalEvent || e).shiftKey) && !isPlain)
|
||||||
{
|
{
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
@@ -2634,7 +2751,7 @@ var _CPCopyPlaceholder = '-';
|
|||||||
}, 20);
|
}, 20);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
};
|
||||||
|
|
||||||
if (CPBrowserIsEngine(CPGeckoBrowserEngine))
|
if (CPBrowserIsEngine(CPGeckoBrowserEngine))
|
||||||
{
|
{
|
||||||
@@ -2650,7 +2767,7 @@ var _CPCopyPlaceholder = '-';
|
|||||||
e.clipboardData.setData('text/plain', stringForPasting);
|
e.clipboardData.setData('text/plain', stringForPasting);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
};
|
||||||
|
|
||||||
_CPNativeInputField.oncut = function(e)
|
_CPNativeInputField.oncut = function(e)
|
||||||
{
|
{
|
||||||
@@ -2752,6 +2869,3 @@ var _CPCopyPlaceholder = '-';
|
|||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ var CPSystemTypesetterFactory,
|
|||||||
rect = CGRectMake(lineOrigin.x, lineOrigin.y, _lineWidth, _lineHeight),
|
rect = CGRectMake(lineOrigin.x, lineOrigin.y, _lineWidth, _lineHeight),
|
||||||
containerSize = aContainer._size;
|
containerSize = aContainer._size;
|
||||||
|
|
||||||
[_layoutManager _appendNewLineFragmentInTextContainer:_currentTextContainer forGlyphRange:lineRange]
|
[_layoutManager _appendNewLineFragmentInTextContainer:_currentTextContainer forGlyphRange:lineRange];
|
||||||
|
|
||||||
var fragment = [_layoutManager._lineFragments lastObject];
|
var fragment = [_layoutManager._lineFragments lastObject];
|
||||||
fragment._isLast = !sameLine;
|
fragment._isLast = !sameLine;
|
||||||
@@ -293,8 +293,8 @@ var CPSystemTypesetterFactory,
|
|||||||
if (!currentFont)
|
if (!currentFont)
|
||||||
currentFont = [_textStorage font] || [CPFont systemFontOfSize:12.0];
|
currentFont = [_textStorage font] || [CPFont systemFontOfSize:12.0];
|
||||||
|
|
||||||
ascent = [currentFont ascender]
|
ascent = [currentFont ascender];
|
||||||
descent = [currentFont descender]
|
descent = [currentFont descender];
|
||||||
leading = (ascent - descent) * 0.2; // FAKE leading
|
leading = (ascent - descent) * 0.2; // FAKE leading
|
||||||
|
|
||||||
currentFontLineHeight = ascent - descent + leading;
|
currentFontLineHeight = ascent - descent + leading;
|
||||||
|
|||||||
@@ -113,13 +113,13 @@ var hexTable = [];
|
|||||||
|
|
||||||
- (CPNumber)script
|
- (CPNumber)script
|
||||||
{
|
{
|
||||||
return [CPNumber numberWithInt: script];
|
return [CPNumber numberWithInt:script];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CPNumber)underline
|
- (CPNumber)underline
|
||||||
{
|
{
|
||||||
if (underline != 0)
|
if (underline != 0)
|
||||||
return [CPNumber numberWithInteger: underline];
|
return [CPNumber numberWithInt:underline];
|
||||||
else
|
else
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
@@ -127,7 +127,7 @@ var hexTable = [];
|
|||||||
- (CPNumber)strikethrough
|
- (CPNumber)strikethrough
|
||||||
{
|
{
|
||||||
if (strikethrough != 0)
|
if (strikethrough != 0)
|
||||||
return [CPNumber numberWithInteger: strikethrough];
|
return [CPNumber numberWithInt:strikethrough];
|
||||||
else
|
else
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
@@ -657,7 +657,7 @@ var kRgsymRtf = {
|
|||||||
}
|
}
|
||||||
- (CPAttributedString)parseRTF:(CPString)rtf
|
- (CPAttributedString)parseRTF:(CPString)rtf
|
||||||
{
|
{
|
||||||
rtf = rtf.replace(/\\\n/g, "\\par\n")
|
rtf = rtf.replace(/\\\n/g, "\\par\n");
|
||||||
|
|
||||||
if (rtf.length == 0)
|
if (rtf.length == 0)
|
||||||
return '';
|
return '';
|
||||||
@@ -718,7 +718,7 @@ var kRgsymRtf = {
|
|||||||
_freename = "";
|
_freename = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
[self _flushCurrentRun]
|
[self _flushCurrentRun];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "\\":
|
case "\\":
|
||||||
@@ -751,7 +751,7 @@ var kRgsymRtf = {
|
|||||||
if (hexTable && hexTable[hex.toUpperCase()] !== undefined)
|
if (hexTable && hexTable[hex.toUpperCase()] !== undefined)
|
||||||
temp = parseInt(hexTable[hex.toUpperCase()], 16);
|
temp = parseInt(hexTable[hex.toUpperCase()], 16);
|
||||||
|
|
||||||
[self _appendPlainString: String.fromCharCode(temp)]
|
[self _appendPlainString: String.fromCharCode(temp)];
|
||||||
hex = '';
|
hex = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
RTFProducer.j
|
_CPRTFProducer.j
|
||||||
|
|
||||||
Serialize CPAttributedString to a RTF String
|
Serialize CPAttributedString to a RTF String
|
||||||
|
|
||||||
@@ -189,11 +189,9 @@ function _points2twips(a) { return (a) * 20.0; }
|
|||||||
|
|
||||||
if (val)
|
if (val)
|
||||||
{
|
{
|
||||||
var size = [val sizeValue];
|
|
||||||
|
|
||||||
detail = [CPString stringWithFormat:@"\\paperw%d \\paperh%d",
|
detail = [CPString stringWithFormat:@"\\paperw%d \\paperh%d",
|
||||||
_points2twips(size.width),
|
_points2twips(val.width),
|
||||||
_points2twips(size.height)];
|
_points2twips(val.height)];
|
||||||
|
|
||||||
result += detail;
|
result += detail;
|
||||||
}
|
}
|
||||||
@@ -612,4 +610,4 @@ function _points2twips(a) { return (a) * 20.0; }
|
|||||||
output += trailerString;
|
output += trailerString;
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -24,9 +24,12 @@
|
|||||||
@import <Foundation/CPMutableArray.j>
|
@import <Foundation/CPMutableArray.j>
|
||||||
@import <Foundation/CPString.j>
|
@import <Foundation/CPString.j>
|
||||||
@import <Foundation/CPKeyedUnarchiver.j>
|
@import <Foundation/CPKeyedUnarchiver.j>
|
||||||
|
@import <Foundation/CPBundle.j>
|
||||||
|
|
||||||
@class CPView
|
@class CPView
|
||||||
@class _CPThemeAttribute
|
@class _CPThemeAttribute
|
||||||
|
@class CPImage
|
||||||
|
@class CPColor
|
||||||
|
|
||||||
var CPThemesByName = { },
|
var CPThemesByName = { },
|
||||||
CPThemeDefaultTheme = nil,
|
CPThemeDefaultTheme = nil,
|
||||||
@@ -313,6 +316,71 @@ var CPThemeNameKey = @"CPThemeNameKey",
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark CSS Theming
|
||||||
|
|
||||||
|
// The code below adds support for CSS theming with 100% compatibility with current theming system.
|
||||||
|
// The idea is to extend CPColor and CPImage with CSS components and adapt low level UI components to
|
||||||
|
// support this new kind of CPColor/CPImage. See CPImageView, CPView and _CPImageAndTextView.
|
||||||
|
//
|
||||||
|
// To be considered and treated as CSS based, a theme must set to YES the attribute "css-based" for CPView
|
||||||
|
// in the theDescriptor (default value is NO), like in the example below :
|
||||||
|
//
|
||||||
|
// + (CPView)themedView
|
||||||
|
// {
|
||||||
|
// var view = [[CPView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
|
||||||
|
//
|
||||||
|
// [self registerThemeValues:[[@"css-based", YES]] forView:view];
|
||||||
|
//
|
||||||
|
// return view;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// You can use the method -(BOOL)isCSSBased on a theme to determine how to cope with it in your own code.
|
||||||
|
//
|
||||||
|
// The method -(void)setCSSResourcesPath is meant to be used only by CPThemeBlend during theme loading in order to
|
||||||
|
// replace the special path "%%" in CSS components (like in url(%%packed.png) ) with the path to the theme blend resources folder.
|
||||||
|
|
||||||
|
@implementation CPTheme (CSSTheming)
|
||||||
|
|
||||||
|
- (void)setCSSResourcesPath:(CPString)pathToResources
|
||||||
|
{
|
||||||
|
[_attributes enumerateKeysAndObjectsUsingBlock:function(aKey, anObject, stop)
|
||||||
|
{
|
||||||
|
[anObject enumerateKeysAndObjectsUsingBlock:function(aKey2, anObject2, stop2)
|
||||||
|
{
|
||||||
|
// anObject2 is now a _CPThemeAttribute
|
||||||
|
|
||||||
|
[[anObject2 values] enumerateKeysAndObjectsUsingBlock:function(aKey3, anObject3, stop3)
|
||||||
|
{
|
||||||
|
if (anObject3.isa && ([anObject3 isKindOfClass:CPImage] || [anObject3 isKindOfClass:CPColor]) && [anObject3 cssDictionary])
|
||||||
|
{
|
||||||
|
// We have a CSS defined image or color
|
||||||
|
[self _fixPathInCSSDictionary:[anObject3 cssDictionary] withPathToResources:pathToResources];
|
||||||
|
[self _fixPathInCSSDictionary:[anObject3 cssBeforeDictionary] withPathToResources:pathToResources];
|
||||||
|
[self _fixPathInCSSDictionary:[anObject3 cssAfterDictionary] withPathToResources:pathToResources];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)_fixPathInCSSDictionary:(CPDictionary)aDictionary withPathToResources:(CPString)pathToResources
|
||||||
|
{
|
||||||
|
[aDictionary enumerateKeysAndObjectsUsingBlock:function(aKey, anObject, stop)
|
||||||
|
{
|
||||||
|
[aDictionary setObject:[anObject stringByReplacingOccurrencesOfString:@"%%" withString:pathToResources] forKey:aKey];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isCSSBased
|
||||||
|
{
|
||||||
|
return !![self valueForAttributeWithName:@"css-based" forClass:[CPView class]];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* ThemeStates are immutable objects representing a particular ThemeState. Applications should never be creating
|
* ThemeStates are immutable objects representing a particular ThemeState. Applications should never be creating
|
||||||
* ThemeStates directly but should instead use the CPThemeState function.
|
* ThemeStates directly but should instead use the CPThemeState function.
|
||||||
@@ -769,7 +837,7 @@ var ParentAttributeForCoder = nil;
|
|||||||
if ([aCoder containsValueForKey:@"state"])
|
if ([aCoder containsValueForKey:@"state"])
|
||||||
state = [aCoder decodeObjectForKey:@"state"];
|
state = [aCoder decodeObjectForKey:@"state"];
|
||||||
else
|
else
|
||||||
state = CPThemeStateNormalString
|
state = CPThemeStateNormalString;
|
||||||
|
|
||||||
[_values setObject:[aCoder decodeObjectForKey:"value"] forKey:state];
|
[_values setObject:[aCoder decodeObjectForKey:"value"] forKey:state];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,6 +95,17 @@
|
|||||||
[unarchiver finishDecoding];
|
[unarchiver finishDecoding];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CSS Theming
|
||||||
|
|
||||||
|
for (var i = 0, nb = [_themes count], allThemes = [self themeNames], aThemeName, aTheme; i < nb; i++)
|
||||||
|
{
|
||||||
|
aThemeName = allThemes[i];
|
||||||
|
aTheme = [CPTheme themeNamed:aThemeName];
|
||||||
|
|
||||||
|
if ([aTheme isCSSBased])
|
||||||
|
[aTheme setCSSResourcesPath:[aBundle resourcePath]];
|
||||||
|
}
|
||||||
|
|
||||||
[_loadDelegate blendDidFinishLoading:self];
|
[_loadDelegate blendDidFinishLoading:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -523,17 +523,25 @@ CPTokenFieldDeleteButtonType = 1;
|
|||||||
var element = [self _inputElement];
|
var element = [self _inputElement];
|
||||||
|
|
||||||
CPTokenFieldInputResigning = YES;
|
CPTokenFieldInputResigning = YES;
|
||||||
element.blur();
|
|
||||||
|
if (CPTokenFieldInputIsActive)
|
||||||
|
element.blur();
|
||||||
|
|
||||||
if (!CPTokenFieldInputDidBlur)
|
if (!CPTokenFieldInputDidBlur)
|
||||||
CPTokenFieldBlurHandler();
|
CPTokenFieldBlurHandler();
|
||||||
|
|
||||||
CPTokenFieldInputDidBlur = NO;
|
|
||||||
CPTokenFieldInputResigning = NO;
|
|
||||||
|
|
||||||
if (element.parentNode == [_tokenScrollView documentView]._DOMElement)
|
if (element.parentNode == [_tokenScrollView documentView]._DOMElement)
|
||||||
element.parentNode.removeChild(element);
|
element.parentNode.removeChild(element);
|
||||||
|
|
||||||
|
// Previosly, we unflagged CPTokenFieldInputDidBlur and CPTokenFieldInputResigning before
|
||||||
|
// the call to removeChild. This may result in DOM exceptions in Chrome under certain conditions.
|
||||||
|
// See https://stackoverflow.com/questions/21926083/failed-to-execute-removechild-on-node
|
||||||
|
// for why we need to unflag CPTokenFieldInputDidBlur and CPTokenFieldInputResigning
|
||||||
|
// only after removing the element.
|
||||||
|
|
||||||
|
CPTokenFieldInputDidBlur = NO;
|
||||||
|
CPTokenFieldInputResigning = NO;
|
||||||
|
|
||||||
CPTokenFieldInputIsActive = NO;
|
CPTokenFieldInputIsActive = NO;
|
||||||
|
|
||||||
if (document.attachEvent)
|
if (document.attachEvent)
|
||||||
@@ -541,7 +549,7 @@ CPTokenFieldDeleteButtonType = 1;
|
|||||||
CPTokenFieldCachedSelectStartFunction = nil;
|
CPTokenFieldCachedSelectStartFunction = nil;
|
||||||
CPTokenFieldCachedDragFunction = nil;
|
CPTokenFieldCachedDragFunction = nil;
|
||||||
|
|
||||||
document.body.ondrag = CPTokenFieldCachedDragFunction
|
document.body.ondrag = CPTokenFieldCachedDragFunction;
|
||||||
document.body.onselectstart = CPTokenFieldCachedSelectStartFunction
|
document.body.onselectstart = CPTokenFieldCachedSelectStartFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1239,7 +1247,7 @@ CPTokenFieldDeleteButtonType = 1;
|
|||||||
var scrollToToken = _shouldScrollTo;
|
var scrollToToken = _shouldScrollTo;
|
||||||
|
|
||||||
if (scrollToToken === CPScrollDestinationLeft)
|
if (scrollToToken === CPScrollDestinationLeft)
|
||||||
scrollToToken = tokens[_selectedRange.location]
|
scrollToToken = tokens[_selectedRange.location];
|
||||||
else if (scrollToToken === CPScrollDestinationRight)
|
else if (scrollToToken === CPScrollDestinationRight)
|
||||||
scrollToToken = tokens[MAX(0, CPMaxRange(_selectedRange) - 1)];
|
scrollToToken = tokens[MAX(0, CPMaxRange(_selectedRange) - 1)];
|
||||||
[self _scrollTokenViewToVisible:scrollToToken];
|
[self _scrollTokenViewToVisible:scrollToToken];
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ var CPToolbarsByIdentifier = nil,
|
|||||||
|
|
||||||
if (!toolbarsSharingIdentifier)
|
if (!toolbarsSharingIdentifier)
|
||||||
{
|
{
|
||||||
toolbarsSharingIdentifier = []
|
toolbarsSharingIdentifier = [];
|
||||||
[CPToolbarsByIdentifier setObject:toolbarsSharingIdentifier forKey:identifier];
|
[CPToolbarsByIdentifier setObject:toolbarsSharingIdentifier forKey:identifier];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -588,7 +588,7 @@ var CPToolbarIdentifierKey = @"CPToolbarIdentifierKey",
|
|||||||
[aCoder encodeBool:_showsBaselineSeparator forKey:CPToolbarShowsBaselineSeparatorKey];
|
[aCoder encodeBool:_showsBaselineSeparator forKey:CPToolbarShowsBaselineSeparatorKey];
|
||||||
[aCoder encodeBool:_allowsUserCustomization forKey:CPToolbarAllowsUserCustomizationKey];
|
[aCoder encodeBool:_allowsUserCustomization forKey:CPToolbarAllowsUserCustomizationKey];
|
||||||
[aCoder encodeBool:_isVisible forKey:CPToolbarIsVisibleKey];
|
[aCoder encodeBool:_isVisible forKey:CPToolbarIsVisibleKey];
|
||||||
[aCoder encodeInt:_sizeMode forKey:CPToolbarSizeModeKey]
|
[aCoder encodeInt:_sizeMode forKey:CPToolbarSizeModeKey];
|
||||||
|
|
||||||
[aCoder encodeObject:_identifiedItems forKey:CPToolbarIdentifiedItemsKey];
|
[aCoder encodeObject:_identifiedItems forKey:CPToolbarIdentifiedItemsKey];
|
||||||
[aCoder encodeObject:_defaultItems forKey:CPToolbarDefaultItemsKey];
|
[aCoder encodeObject:_defaultItems forKey:CPToolbarDefaultItemsKey];
|
||||||
|
|||||||
@@ -129,7 +129,8 @@ var DOMElementPrototype = nil,
|
|||||||
BackgroundVerticalThreePartImage = 1,
|
BackgroundVerticalThreePartImage = 1,
|
||||||
BackgroundHorizontalThreePartImage = 2,
|
BackgroundHorizontalThreePartImage = 2,
|
||||||
BackgroundNinePartImage = 3,
|
BackgroundNinePartImage = 3,
|
||||||
BackgroundTransparentColor = 4;
|
BackgroundTransparentColor = 4,
|
||||||
|
BackgroundCSSStyling = 5;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var CPViewFlags = { },
|
var CPViewFlags = { },
|
||||||
@@ -195,6 +196,10 @@ var CPViewHighDPIDrawingEnabled = YES;
|
|||||||
CPArray _DOMImageSizes;
|
CPArray _DOMImageSizes;
|
||||||
|
|
||||||
unsigned _backgroundType;
|
unsigned _backgroundType;
|
||||||
|
|
||||||
|
// CSS styling
|
||||||
|
CPArray _cssStylePreviousState;
|
||||||
|
DOMElement _cssStyleNode;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CGRect _dirtyRect;
|
CGRect _dirtyRect;
|
||||||
@@ -320,6 +325,18 @@ var CPViewHighDPIDrawingEnabled = YES;
|
|||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (CPString)defaultThemeClass
|
||||||
|
{
|
||||||
|
return @"view";
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (CPDictionary)themeAttributes
|
||||||
|
{
|
||||||
|
return @{
|
||||||
|
@"css-based": NO
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
- (void)_setupViewFlags
|
- (void)_setupViewFlags
|
||||||
{
|
{
|
||||||
var theClass = [self class],
|
var theClass = [self class],
|
||||||
@@ -399,6 +416,8 @@ var CPViewHighDPIDrawingEnabled = YES;
|
|||||||
|
|
||||||
_DOMImageParts = [];
|
_DOMImageParts = [];
|
||||||
_DOMImageSizes = [];
|
_DOMImageSizes = [];
|
||||||
|
|
||||||
|
_cssStylePreviousState = @[];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_animator = nil;
|
_animator = nil;
|
||||||
@@ -409,7 +428,12 @@ var CPViewHighDPIDrawingEnabled = YES;
|
|||||||
|
|
||||||
_inhibitDOMUpdates = NO;
|
_inhibitDOMUpdates = NO;
|
||||||
_forceUpdates = NO;
|
_forceUpdates = NO;
|
||||||
}
|
|
||||||
|
// We force here an updateTrackingAreas in order to let the view install its own tracking areas
|
||||||
|
// in the case where an externally owned tracking area is installed on this view before putting
|
||||||
|
// it in the view hierarchy.
|
||||||
|
[self updateTrackingAreas];
|
||||||
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@@ -449,7 +473,7 @@ var CPViewHighDPIDrawingEnabled = YES;
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (!_toolTipFunctionIn)
|
if (!_toolTipFunctionIn)
|
||||||
_toolTipFunctionIn = function(e) { [_CPToolTip scheduleToolTipForView:self]; }
|
_toolTipFunctionIn = function(e) { [_CPToolTip scheduleToolTipForView:self]; };
|
||||||
|
|
||||||
if (!_toolTipFunctionOut)
|
if (!_toolTipFunctionOut)
|
||||||
_toolTipFunctionOut = function(e) { [_CPToolTip invalidateCurrentToolTipIfNeeded]; };
|
_toolTipFunctionOut = function(e) { [_CPToolTip invalidateCurrentToolTipIfNeeded]; };
|
||||||
@@ -1954,15 +1978,25 @@ var CPViewHighDPIDrawingEnabled = YES;
|
|||||||
_backgroundColor = aColor;
|
_backgroundColor = aColor;
|
||||||
|
|
||||||
#if PLATFORM(DOM)
|
#if PLATFORM(DOM)
|
||||||
|
if (_backgroundType === BackgroundCSSStyling)
|
||||||
|
[_backgroundColor restorePreviousCSSState:@ref(_cssStylePreviousState) forDOMElement:_DOMElement];
|
||||||
|
|
||||||
var patternImage = [_backgroundColor patternImage],
|
var patternImage = [_backgroundColor patternImage],
|
||||||
colorExists = _backgroundColor && ([_backgroundColor patternImage] || [_backgroundColor alphaComponent] > 0.0),
|
colorExists = _backgroundColor && ([_backgroundColor patternImage] || [_backgroundColor alphaComponent] > 0.0),
|
||||||
colorHasAlpha = colorExists && [_backgroundColor alphaComponent] < 1.0,
|
colorHasAlpha = colorExists && [_backgroundColor alphaComponent] < 1.0,
|
||||||
supportsRGBA = CPFeatureIsCompatible(CPCSSRGBAFeature),
|
supportsRGBA = CPFeatureIsCompatible(CPCSSRGBAFeature),
|
||||||
colorNeedsDOMElement = colorHasAlpha && !supportsRGBA,
|
colorNeedsDOMElement = colorHasAlpha && !supportsRGBA,
|
||||||
amount = 0,
|
amount = 0,
|
||||||
slices;
|
slices,
|
||||||
|
// For CSS theming
|
||||||
|
isCSSBasedColor = [_backgroundColor isCSSBased];
|
||||||
|
|
||||||
if ([patternImage isThreePartImage])
|
if (isCSSBasedColor)
|
||||||
|
{
|
||||||
|
_backgroundType = BackgroundCSSStyling;
|
||||||
|
amount = -_DOMImageParts.length;
|
||||||
|
}
|
||||||
|
else if ([patternImage isThreePartImage])
|
||||||
{
|
{
|
||||||
_backgroundType = [patternImage isVertical] ? BackgroundVerticalThreePartImage : BackgroundHorizontalThreePartImage;
|
_backgroundType = [patternImage isVertical] ? BackgroundVerticalThreePartImage : BackgroundHorizontalThreePartImage;
|
||||||
amount = 3;
|
amount = 3;
|
||||||
@@ -2025,7 +2059,14 @@ var CPViewHighDPIDrawingEnabled = YES;
|
|||||||
_DOMElement.removeChild(_DOMImageParts.pop());
|
_DOMElement.removeChild(_DOMImageParts.pop());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_backgroundType === BackgroundTrivialColor || _backgroundType === BackgroundTransparentColor)
|
if (_backgroundType === BackgroundCSSStyling)
|
||||||
|
{
|
||||||
|
_cssStyleNode = [_backgroundColor applyCSSColorForView:self
|
||||||
|
onDOMElement:_DOMElement
|
||||||
|
styleNode:_cssStyleNode
|
||||||
|
previousState:@ref(_cssStylePreviousState)];
|
||||||
|
}
|
||||||
|
else if (_backgroundType === BackgroundTrivialColor || _backgroundType === BackgroundTransparentColor)
|
||||||
{
|
{
|
||||||
var colorCSS = colorExists ? [_backgroundColor cssString] : "";
|
var colorCSS = colorExists ? [_backgroundColor cssString] : "";
|
||||||
|
|
||||||
@@ -2983,7 +3024,7 @@ setBoundsOrigin:
|
|||||||
*/
|
*/
|
||||||
- (BOOL)inLiveResize
|
- (BOOL)inLiveResize
|
||||||
{
|
{
|
||||||
return _inLiveResize;
|
return [self window] && [[self window] _inLiveResize];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -3434,6 +3475,17 @@ setBoundsOrigin:
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@implementation CPView (CSSTheming)
|
||||||
|
|
||||||
|
- (void)setDOMClassName:(CPString)aClassName
|
||||||
|
{
|
||||||
|
#if PLATFORM(DOM)
|
||||||
|
_DOMElement.className = aClassName;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
@implementation CPView (Appearance)
|
@implementation CPView (Appearance)
|
||||||
|
|
||||||
@@ -3553,11 +3605,12 @@ setBoundsOrigin:
|
|||||||
/*!
|
/*!
|
||||||
Invoked automatically when the view’s geometry changes such that its tracking areas need to be recalculated.
|
Invoked automatically when the view’s geometry changes such that its tracking areas need to be recalculated.
|
||||||
|
|
||||||
You should override this method to remove out of date tracking areas and add recomputed tracking areas;
|
You should override this method to remove out of date tracking areas, add recomputed tracking areas and then call super;
|
||||||
|
|
||||||
Cocoa calls this on every view, whereas they have tracking area(s) or not.
|
Cocoa calls this on every view, whereas they have tracking area(s) or not.
|
||||||
Cappuccino behaves differently :
|
Cappuccino behaves differently :
|
||||||
- updateTrackingAreas is called when placing a view in the view hierarchy (that is in a window)
|
- updateTrackingAreas is called during initWithFrame
|
||||||
|
- updateTrackingAreas is also called when placing a view in the view hierarchy (that is in a window)
|
||||||
- if you have only CPTrackingInVisibleRect tracking areas attached to a view, it will not be called again (until you move the view in the hierarchy)
|
- if you have only CPTrackingInVisibleRect tracking areas attached to a view, it will not be called again (until you move the view in the hierarchy)
|
||||||
- if you have at least one non-CPTrackingInVisibleRect tracking area attached, it will be called every time the view geometry could be modified
|
- if you have at least one non-CPTrackingInVisibleRect tracking area attached, it will be called every time the view geometry could be modified
|
||||||
You don't have to touch to CPTrackingInVisibleRect tracking areas, they will be automatically updated
|
You don't have to touch to CPTrackingInVisibleRect tracking areas, they will be automatically updated
|
||||||
@@ -3571,25 +3624,6 @@ setBoundsOrigin:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
This utility method is intended for CPView subclasses overriding updateTrackingAreas
|
|
||||||
|
|
||||||
Typical use would be :
|
|
||||||
|
|
||||||
- (void)updateTrackingAreas
|
|
||||||
{
|
|
||||||
[self removeAllTrackingAreas];
|
|
||||||
|
|
||||||
... add your specific updated tracking areas ...
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
- (void)removeAllTrackingAreas
|
|
||||||
{
|
|
||||||
while (_trackingAreas.length > 0)
|
|
||||||
[self _removeTrackingArea:_trackingAreas[0]];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Internal methods
|
// Internal methods
|
||||||
|
|
||||||
- (void)_removeTrackingArea:(CPTrackingArea)trackingArea
|
- (void)_removeTrackingArea:(CPTrackingArea)trackingArea
|
||||||
@@ -3749,6 +3783,8 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
|
|||||||
|
|
||||||
// DOM SETUP
|
// DOM SETUP
|
||||||
#if PLATFORM(DOM)
|
#if PLATFORM(DOM)
|
||||||
|
_cssStylePreviousState = @[];
|
||||||
|
|
||||||
_DOMImageParts = [];
|
_DOMImageParts = [];
|
||||||
_DOMImageSizes = [];
|
_DOMImageSizes = [];
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,7 @@
|
|||||||
@class CPToolbar
|
@class CPToolbar
|
||||||
@class CPWindowController
|
@class CPWindowController
|
||||||
@class _CPWindowFrameAnimation
|
@class _CPWindowFrameAnimation
|
||||||
|
@class _CPWindowFrameAnimationDelegate
|
||||||
|
|
||||||
@global CPApp
|
@global CPApp
|
||||||
@global _CPPlatformWindowWillCloseNotification
|
@global _CPPlatformWindowWillCloseNotification
|
||||||
@@ -178,7 +179,7 @@ var CPWindowActionMessageKeys = [
|
|||||||
BOOL _isVisible;
|
BOOL _isVisible;
|
||||||
BOOL _hasBeenOrderedIn @accessors;
|
BOOL _hasBeenOrderedIn @accessors;
|
||||||
BOOL _isMiniaturized;
|
BOOL _isMiniaturized;
|
||||||
BOOL _isAnimating;
|
BOOL _isAnimating @accessors(setter=_setAnimating:);
|
||||||
BOOL _hasShadow;
|
BOOL _hasShadow;
|
||||||
BOOL _isMovableByWindowBackground;
|
BOOL _isMovableByWindowBackground;
|
||||||
BOOL _isMovable;
|
BOOL _isMovable;
|
||||||
@@ -261,6 +262,7 @@ var CPWindowActionMessageKeys = [
|
|||||||
CPWindow _parentView;
|
CPWindow _parentView;
|
||||||
BOOL _isSheet;
|
BOOL _isSheet;
|
||||||
_CPWindowFrameAnimation _frameAnimation;
|
_CPWindowFrameAnimation _frameAnimation;
|
||||||
|
_CPWindowFrameAnimationDelegate _frameAnimationDelegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (Class)_binderClassForBinding:(CPString)aBinding
|
+ (Class)_binderClassForBinding:(CPString)aBinding
|
||||||
@@ -336,6 +338,8 @@ CPTexturedBackgroundWindowMask
|
|||||||
_isSheet = NO;
|
_isSheet = NO;
|
||||||
_sheetContext = nil;
|
_sheetContext = nil;
|
||||||
_parentView = nil;
|
_parentView = nil;
|
||||||
|
_frameAnimation = nil;
|
||||||
|
_frameAnimationDelegate = nil;
|
||||||
|
|
||||||
// Set up our window number.
|
// Set up our window number.
|
||||||
_windowNumber = [CPApp._windows count];
|
_windowNumber = [CPApp._windows count];
|
||||||
@@ -742,7 +746,7 @@ CPTexturedBackgroundWindowMask
|
|||||||
{
|
{
|
||||||
[_frameAnimation stopAnimation];
|
[_frameAnimation stopAnimation];
|
||||||
_frameAnimation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:frame];
|
_frameAnimation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:frame];
|
||||||
|
[_frameAnimation setDelegate:[self _frameAnimationDelegate]];
|
||||||
[_frameAnimation startAnimation];
|
[_frameAnimation startAnimation];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -802,6 +806,13 @@ CPTexturedBackgroundWindowMask
|
|||||||
[_platformWindow setContentRect:aFrame];
|
[_platformWindow setContentRect:aFrame];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (id)_frameAnimationDelegate
|
||||||
|
{
|
||||||
|
if (_frameAnimationDelegate == nil)
|
||||||
|
_frameAnimationDelegate = [[_CPWindowFrameAnimationDelegate alloc] initWithWindow:self];
|
||||||
|
|
||||||
|
return _frameAnimationDelegate;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
Constrain a frame so that the window remains at least partially visible on screen,
|
Constrain a frame so that the window remains at least partially visible on screen,
|
||||||
moving or resizing the frame as necessary.
|
moving or resizing the frame as necessary.
|
||||||
@@ -1840,16 +1851,12 @@ CPTexturedBackgroundWindowMask
|
|||||||
// CPLeftMouseDown is needed for window moving and resizing to work.
|
// CPLeftMouseDown is needed for window moving and resizing to work.
|
||||||
// CPMouseMoved is needed for rollover effects on title bar buttons.
|
// CPMouseMoved is needed for rollover effects on title bar buttons.
|
||||||
|
|
||||||
if (sheet)
|
if (sheet && _sheetContext["isAttached"])
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case CPLeftMouseDown:
|
case CPLeftMouseDown:
|
||||||
|
|
||||||
// This is needed when a doubleClick occurs when the sheet is closing or opening
|
|
||||||
if (!_parentWindow)
|
|
||||||
return;
|
|
||||||
|
|
||||||
[_windowView mouseDown:anEvent];
|
[_windowView mouseDown:anEvent];
|
||||||
|
|
||||||
// -dw- if the window is clicked, the sheet should come to front, and become key,
|
// -dw- if the window is clicked, the sheet should come to front, and become key,
|
||||||
@@ -1892,7 +1899,7 @@ CPTexturedBackgroundWindowMask
|
|||||||
// Make sure the browser doesn't try to do its own tab handling.
|
// Make sure the browser doesn't try to do its own tab handling.
|
||||||
// This is important or the browser might blur the shared text field or token field input field,
|
// This is important or the browser might blur the shared text field or token field input field,
|
||||||
// even that we just moved it to a new first responder.
|
// even that we just moved it to a new first responder.
|
||||||
[[[anEvent window] platformWindow] _propagateCurrentDOMEvent:NO]
|
[[[anEvent window] platformWindow] _propagateCurrentDOMEvent:NO];
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1906,7 +1913,7 @@ CPTexturedBackgroundWindowMask
|
|||||||
// Make sure the browser doesn't try to do its own tab handling.
|
// Make sure the browser doesn't try to do its own tab handling.
|
||||||
// This is important or the browser might blur the shared text field or token field input field,
|
// This is important or the browser might blur the shared text field or token field input field,
|
||||||
// even that we just moved it to a new first responder.
|
// even that we just moved it to a new first responder.
|
||||||
[[[anEvent window] platformWindow] _propagateCurrentDOMEvent:NO]
|
[[[anEvent window] platformWindow] _propagateCurrentDOMEvent:NO];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1998,13 +2005,13 @@ CPTexturedBackgroundWindowMask
|
|||||||
|
|
||||||
if (type == CPRightMouseDragged)
|
if (type == CPRightMouseDragged)
|
||||||
{
|
{
|
||||||
selector = @selector(rightMouseDragged:)
|
selector = @selector(rightMouseDragged:);
|
||||||
if (![_leftMouseDownView respondsToSelector:selector])
|
if (![_leftMouseDownView respondsToSelector:selector])
|
||||||
selector = nil;
|
selector = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!selector)
|
if (!selector)
|
||||||
selector = @selector(mouseDragged:)
|
selector = @selector(mouseDragged:);
|
||||||
|
|
||||||
return [_leftMouseDownView performSelector:selector withObject:anEvent];
|
return [_leftMouseDownView performSelector:selector withObject:anEvent];
|
||||||
|
|
||||||
@@ -2018,6 +2025,25 @@ CPTexturedBackgroundWindowMask
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)_startLiveResize
|
||||||
|
{
|
||||||
|
[[CPNotificationCenter defaultCenter]
|
||||||
|
postNotificationName:CPWindowWillStartLiveResizeNotification
|
||||||
|
object:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)_endLiveResize
|
||||||
|
{
|
||||||
|
[[CPNotificationCenter defaultCenter]
|
||||||
|
postNotificationName:CPWindowDidEndLiveResizeNotification
|
||||||
|
object:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)_inLiveResize
|
||||||
|
{
|
||||||
|
return [_windowView _isTracking];
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns the window's number in the desktop's screen list
|
Returns the window's number in the desktop's screen list
|
||||||
*/
|
*/
|
||||||
@@ -3768,13 +3794,6 @@ var interpolate = function(fromValue, toValue, progress)
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)startAnimation
|
|
||||||
{
|
|
||||||
[super startAnimation];
|
|
||||||
|
|
||||||
_window._isAnimating = YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)setCurrentProgress:(float)aProgress
|
- (void)setCurrentProgress:(float)aProgress
|
||||||
{
|
{
|
||||||
[super setCurrentProgress:aProgress];
|
[super setCurrentProgress:aProgress];
|
||||||
@@ -3782,7 +3801,7 @@ var interpolate = function(fromValue, toValue, progress)
|
|||||||
var value = [self currentValue];
|
var value = [self currentValue];
|
||||||
|
|
||||||
if (value == 1.0)
|
if (value == 1.0)
|
||||||
_window._isAnimating = NO;
|
[_window _setAnimating:NO];
|
||||||
|
|
||||||
var newFrame = CGRectMake(
|
var newFrame = CGRectMake(
|
||||||
interpolate(CGRectGetMinX(_startFrame), CGRectGetMinX(_targetFrame), value),
|
interpolate(CGRectGetMinX(_startFrame), CGRectGetMinX(_targetFrame), value),
|
||||||
@@ -3795,6 +3814,41 @@ var interpolate = function(fromValue, toValue, progress)
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@implementation _CPWindowFrameAnimationDelegate : CPObject
|
||||||
|
{
|
||||||
|
CPWindow _window;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)initWithWindow:(CPWindow)aWindow
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
|
||||||
|
_window = aWindow;
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)animationShouldStart:(CPAnimation)animation
|
||||||
|
{
|
||||||
|
[_window _setAnimating:YES];
|
||||||
|
[_window _startLiveResize];
|
||||||
|
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)animationDidStop:(CPAnimation)animation
|
||||||
|
{
|
||||||
|
[_window _setAnimating:NO];
|
||||||
|
[_window _endLiveResize];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)animationDidEnd:(CPAnimation)animation
|
||||||
|
{
|
||||||
|
[_window _setAnimating:NO];
|
||||||
|
[_window _endLiveResize];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
@implementation CPWindow (CPDraggingAdditions)
|
@implementation CPWindow (CPDraggingAdditions)
|
||||||
|
|
||||||
|
|||||||
@@ -176,6 +176,8 @@ CPWindowDidEndSheetNotification = @"CPWindowDidEndSheetNotificat
|
|||||||
CPWindowDidMiniaturizeNotification = @"CPWindowDidMiniaturizeNotification";
|
CPWindowDidMiniaturizeNotification = @"CPWindowDidMiniaturizeNotification";
|
||||||
CPWindowWillMiniaturizeNotification = @"CPWindowWillMiniaturizeNotification";
|
CPWindowWillMiniaturizeNotification = @"CPWindowWillMiniaturizeNotification";
|
||||||
CPWindowDidDeminiaturizeNotification = @"CPWindowDidDeminiaturizeNotification";
|
CPWindowDidDeminiaturizeNotification = @"CPWindowDidDeminiaturizeNotification";
|
||||||
|
CPWindowWillStartLiveResizeNotification = @"CPWindowWillStartLiveResizeNotification";
|
||||||
|
CPWindowDidEndLiveResizeNotification = @"CPWindowDidEndLiveResizeNotification";
|
||||||
|
|
||||||
_CPWindowDidChangeFirstResponderNotification = @"_CPWindowDidChangeFirstResponderNotification";
|
_CPWindowDidChangeFirstResponderNotification = @"_CPWindowDidChangeFirstResponderNotification";
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
+ (CPString)defaultThemeClass
|
+ (CPString)defaultThemeClass
|
||||||
{
|
{
|
||||||
return @"bordeless-bridge-window-view";
|
return @"borderless-bridge-window-view";
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (CPDictionary)themeAttributes
|
+ (CPDictionary)themeAttributes
|
||||||
|
|||||||
@@ -183,7 +183,7 @@
|
|||||||
if (_styleMask & CPClosableWindowMask)
|
if (_styleMask & CPClosableWindowMask)
|
||||||
{
|
{
|
||||||
[_closeButton setFrameOrigin:[self valueForThemeAttribute:@"close-image-origin"]];
|
[_closeButton setFrameOrigin:[self valueForThemeAttribute:@"close-image-origin"]];
|
||||||
[_closeButton setFrameSize:[self valueForThemeAttribute:@"close-image-size"]]
|
[_closeButton setFrameSize:[self valueForThemeAttribute:@"close-image-size"]];
|
||||||
[_closeButton setImage:[self valueForThemeAttribute:@"close-image"]];
|
[_closeButton setImage:[self valueForThemeAttribute:@"close-image"]];
|
||||||
[_closeButton setAlternateImage:[self valueForThemeAttribute:@"close-active-image"]];
|
[_closeButton setAlternateImage:[self valueForThemeAttribute:@"close-active-image"]];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ _CPWindowViewResizeSlop = 3;
|
|||||||
CGRect _cachedScreenFrame;
|
CGRect _cachedScreenFrame;
|
||||||
|
|
||||||
CPView _sheetShadowView;
|
CPView _sheetShadowView;
|
||||||
|
|
||||||
|
BOOL _isTracking @accessors(getter=_isTracking);
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
|
+ (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
|
||||||
@@ -148,6 +150,7 @@ _CPWindowViewResizeSlop = 3;
|
|||||||
_styleMask = aStyleMask;
|
_styleMask = aStyleMask;
|
||||||
_resizeIndicatorOffset = CGSizeMakeZero();
|
_resizeIndicatorOffset = CGSizeMakeZero();
|
||||||
_toolbarOffset = CGSizeMakeZero();
|
_toolbarOffset = CGSizeMakeZero();
|
||||||
|
_isTracking = NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
@@ -458,6 +461,8 @@ _CPWindowViewResizeSlop = 3;
|
|||||||
if (type === CPLeftMouseUp)
|
if (type === CPLeftMouseUp)
|
||||||
{
|
{
|
||||||
_cachedScreenFrame = nil;
|
_cachedScreenFrame = nil;
|
||||||
|
_isTracking = NO;
|
||||||
|
[_window _endLiveResize];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -474,6 +479,12 @@ _CPWindowViewResizeSlop = 3;
|
|||||||
}
|
}
|
||||||
else if (type === CPLeftMouseDragged)
|
else if (type === CPLeftMouseDragged)
|
||||||
{
|
{
|
||||||
|
if (!_isTracking)
|
||||||
|
{
|
||||||
|
_isTracking = YES;
|
||||||
|
[_window _startLiveResize];
|
||||||
|
}
|
||||||
|
|
||||||
var deltaX = globalLocation.x - _mouseDraggedPoint.x,
|
var deltaX = globalLocation.x - _mouseDraggedPoint.x,
|
||||||
deltaY = globalLocation.y - _mouseDraggedPoint.y,
|
deltaY = globalLocation.y - _mouseDraggedPoint.y,
|
||||||
startX = CGRectGetMinX(_cachedFrame),
|
startX = CGRectGetMinX(_cachedFrame),
|
||||||
@@ -973,16 +984,22 @@ _CPWindowViewResizeSlop = 3;
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation _CPWindowView (TrackingAreaAdditions)
|
@implementation _CPWindowView (TrackingAreaAdditions)
|
||||||
|
{
|
||||||
|
CPTrackingArea _windowViewTrackingArea;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)updateTrackingAreas
|
- (void)updateTrackingAreas
|
||||||
{
|
{
|
||||||
[self removeAllTrackingAreas];
|
if (_windowViewTrackingArea)
|
||||||
|
[self removeTrackingArea:_windowViewTrackingArea];
|
||||||
|
|
||||||
[self addTrackingArea:[[CPTrackingArea alloc] initWithRect:[self contentRectForFrameRect:[self frame]]
|
_windowViewTrackingArea = [[CPTrackingArea alloc] initWithRect:[self contentRectForFrameRect:[self frame]]
|
||||||
options:CPTrackingCursorUpdate | CPTrackingActiveInActiveApp
|
options:CPTrackingCursorUpdate | CPTrackingActiveInActiveApp
|
||||||
owner:self
|
owner:self
|
||||||
userInfo:nil]];
|
userInfo:nil];
|
||||||
|
|
||||||
|
[self addTrackingArea:_windowViewTrackingArea];
|
||||||
|
[super updateTrackingAreas];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -364,7 +364,7 @@
|
|||||||
{
|
{
|
||||||
[viewControllerView removeFromSuperview];
|
[viewControllerView removeFromSuperview];
|
||||||
[viewControllerView setFrame:[contentView frame]];
|
[viewControllerView setFrame:[contentView frame]];
|
||||||
[viewControllerView setAutoresizingMask:[contentView autoresizingMask]]
|
[viewControllerView setAutoresizingMask:[contentView autoresizingMask]];
|
||||||
[[self window] setContentView:viewControllerView];
|
[[self window] setContentView:viewControllerView];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -222,3 +222,28 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
|
|||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@implementation _CPCibCustomResource (CSSTheming)
|
||||||
|
|
||||||
|
- (BOOL)isCSSBased
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)hasCSSDictionary
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)hasCSSBeforeDictionary
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)hasCSSAfterDictionary
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ var _CPCibObjectDataNamesKeysKey = @"_CPCibObjectDataNamesKeysKey
|
|||||||
|
|
||||||
if ([object respondsToSelector:@selector(_cibInstantiate)])
|
if ([object respondsToSelector:@selector(_cibInstantiate)])
|
||||||
{
|
{
|
||||||
var instantiatedObject = [object _cibInstantiate];
|
instantiatedObject = [object _cibInstantiate];
|
||||||
|
|
||||||
if (instantiatedObject !== object)
|
if (instantiatedObject !== object)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -522,7 +522,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
|||||||
if (USE_BUFFER)
|
if (USE_BUFFER)
|
||||||
{
|
{
|
||||||
if (_delegateRespondsToDisplayLayerSelector)
|
if (_delegateRespondsToDisplayLayerSelector)
|
||||||
return [_delegate displayInLayer:self];
|
return [_delegate displayLayer:self];
|
||||||
|
|
||||||
if (CGRectGetWidth(_backingStoreFrame) == 0.0 || CGRectGetHeight(_backingStoreFrame) == 0.0)
|
if (CGRectGetWidth(_backingStoreFrame) == 0.0 || CGRectGetHeight(_backingStoreFrame) == 0.0)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -66,16 +66,6 @@ var _CPAnimationContextStack = nil,
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)copy
|
|
||||||
{
|
|
||||||
var context = [[CPAnimationContext alloc] init];
|
|
||||||
[context setDuration:[self duration]];
|
|
||||||
[context setTimingFunction:[self timingFunction]];
|
|
||||||
[context setCompletionHandler:[self completionHandler]];
|
|
||||||
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (void)_scheduleAnimationContextStackFlush
|
+ (void)_scheduleAnimationContextStackFlush
|
||||||
{
|
{
|
||||||
if (!_animationFlushingObserver)
|
if (!_animationFlushingObserver)
|
||||||
@@ -90,16 +80,13 @@ var _CPAnimationContextStack = nil,
|
|||||||
|
|
||||||
+ (void)beginGrouping
|
+ (void)beginGrouping
|
||||||
{
|
{
|
||||||
var newContext;
|
var newContext = [[CPAnimationContext alloc] init];
|
||||||
|
|
||||||
if ([_CPAnimationContextStack count])
|
if ([_CPAnimationContextStack count])
|
||||||
{
|
{
|
||||||
var currentContext = [_CPAnimationContextStack lastObject];
|
var currentContext = [_CPAnimationContextStack lastObject];
|
||||||
newContext = [currentContext copy];
|
[newContext setDuration:[currentContext duration]];
|
||||||
}
|
[newContext setTimingFunction:[currentContext timingFunction]];
|
||||||
else
|
|
||||||
{
|
|
||||||
newContext = [[CPAnimationContext alloc] init];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[_CPAnimationContextStack addObject:newContext];
|
[_CPAnimationContextStack addObject:newContext];
|
||||||
@@ -155,9 +142,6 @@ var _CPAnimationContextStack = nil,
|
|||||||
duration = [animation duration] || [self duration];
|
duration = [animation duration] || [self duration];
|
||||||
needsPeriodicFrameUpdates = [[anObject animator] needsPeriodicFrameUpdatesForKeyPath:aKeyPath];
|
needsPeriodicFrameUpdates = [[anObject animator] needsPeriodicFrameUpdatesForKeyPath:aKeyPath];
|
||||||
|
|
||||||
if (_completionHandlerAgent)
|
|
||||||
_completionHandlerAgent.increment();
|
|
||||||
|
|
||||||
var animatorClass = [[anObject class] animatorClass];
|
var animatorClass = [[anObject class] animatorClass];
|
||||||
|
|
||||||
var completionFunction = function()
|
var completionFunction = function()
|
||||||
@@ -221,7 +205,12 @@ var _CPAnimationContextStack = nil,
|
|||||||
if (_animationsByObject.size == 0)
|
if (_animationsByObject.size == 0)
|
||||||
{
|
{
|
||||||
if (_completionHandlerAgent)
|
if (_completionHandlerAgent)
|
||||||
|
{
|
||||||
|
#if (DEBUG)
|
||||||
|
CPLog.debug("No animations are scheduled. Firing completion handler");
|
||||||
|
#endif
|
||||||
_completionHandlerAgent.fire();
|
_completionHandlerAgent.fire();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
[self _startAnimations];
|
[self _startAnimations];
|
||||||
@@ -242,8 +231,23 @@ var _CPAnimationContextStack = nil,
|
|||||||
|
|
||||||
_animationsByObject.clear();
|
_animationsByObject.clear();
|
||||||
|
|
||||||
|
var k = timers.length,
|
||||||
|
n = cssAnimations.length;
|
||||||
|
|
||||||
|
if (_completionHandlerAgent)
|
||||||
|
{
|
||||||
|
if (n == 0)
|
||||||
|
{
|
||||||
|
#if (DEBUG)
|
||||||
|
CPLog.debug("Animations are not needed. Firing completion handler");
|
||||||
|
#endif
|
||||||
|
_completionHandlerAgent.fire();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_completionHandlerAgent.increment(n);
|
||||||
|
}
|
||||||
|
|
||||||
// start timers
|
// start timers
|
||||||
var k = timers.length;
|
|
||||||
while(k--)
|
while(k--)
|
||||||
{
|
{
|
||||||
#if (DEBUG)
|
#if (DEBUG)
|
||||||
@@ -253,7 +257,6 @@ var _CPAnimationContextStack = nil,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// start css animations
|
// start css animations
|
||||||
var n = cssAnimations.length;
|
|
||||||
while(n--)
|
while(n--)
|
||||||
{
|
{
|
||||||
#if (DEBUG)
|
#if (DEBUG)
|
||||||
@@ -360,9 +363,24 @@ var _CPAnimationContextStack = nil,
|
|||||||
- (void)setCompletionHandler:(Function)aCompletionHandler
|
- (void)setCompletionHandler:(Function)aCompletionHandler
|
||||||
{
|
{
|
||||||
if (_completionHandlerAgent)
|
if (_completionHandlerAgent)
|
||||||
_completionHandlerAgent.invalidate();
|
{
|
||||||
|
if (aCompletionHandler === _completionHandlerAgent._completionHandler)
|
||||||
|
return;
|
||||||
|
|
||||||
_completionHandlerAgent = aCompletionHandler ? (new CompletionHandlerAgent(aCompletionHandler)) : nil;
|
_completionHandlerAgent.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aCompletionHandler)
|
||||||
|
{
|
||||||
|
_completionHandlerAgent = new CompletionHandlerAgent(aCompletionHandler);
|
||||||
|
#if (DEBUG)
|
||||||
|
CPLog.debug("created a new completion Agent with id " + _completionHandlerAgent.id);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_completionHandlerAgent = nil;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)completionHandler
|
- (void)completionHandler
|
||||||
@@ -465,11 +483,14 @@ var _CPAnimationContextStack = nil,
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
var COMPLETION_AGENT_ID = 0;
|
||||||
|
|
||||||
var CompletionHandlerAgent = function(aCompletionHandler)
|
var CompletionHandlerAgent = function(aCompletionHandler)
|
||||||
{
|
{
|
||||||
this._completionHandler = aCompletionHandler;
|
this._completionHandler = aCompletionHandler;
|
||||||
this.total = 0;
|
this.total = 0;
|
||||||
this.valid = true;
|
this.valid = true;
|
||||||
|
this.id = COMPLETION_AGENT_ID++;
|
||||||
};
|
};
|
||||||
|
|
||||||
CompletionHandlerAgent.prototype.completionHandler = function()
|
CompletionHandlerAgent.prototype.completionHandler = function()
|
||||||
@@ -479,12 +500,17 @@ CompletionHandlerAgent.prototype.completionHandler = function()
|
|||||||
|
|
||||||
CompletionHandlerAgent.prototype.fire = function()
|
CompletionHandlerAgent.prototype.fire = function()
|
||||||
{
|
{
|
||||||
this._completionHandler();
|
if (this.valid)
|
||||||
|
{
|
||||||
|
this._completionHandler();
|
||||||
|
this.valid = false;
|
||||||
|
this.total = 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
CompletionHandlerAgent.prototype.increment = function()
|
CompletionHandlerAgent.prototype.increment = function(inc)
|
||||||
{
|
{
|
||||||
this.total++;
|
this.total += inc;
|
||||||
};
|
};
|
||||||
|
|
||||||
CompletionHandlerAgent.prototype.decrement = function()
|
CompletionHandlerAgent.prototype.decrement = function()
|
||||||
@@ -503,6 +529,8 @@ CompletionHandlerAgent.prototype.decrement = function()
|
|||||||
CompletionHandlerAgent.prototype.invalidate = function()
|
CompletionHandlerAgent.prototype.invalidate = function()
|
||||||
{
|
{
|
||||||
this.valid = false;
|
this.valid = false;
|
||||||
|
this.total = 0;
|
||||||
|
this._completionHandler = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
var _animationFlushingObserverCallback = function()
|
var _animationFlushingObserverCallback = function()
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ var transformSizeToHeight = function(start, current)
|
|||||||
|
|
||||||
var CSSStringFromCGAffineTransform = function(anAffineTransform)
|
var CSSStringFromCGAffineTransform = function(anAffineTransform)
|
||||||
{
|
{
|
||||||
return "matrix(" + anAffineTransform.a + ", " + anAffineTransform.b + ", " + anAffineTransform.c + ", " + anAffineTransform.d + ", " + anAffineTransform.tx + (CPBrowserIsEngine(CPGeckoBrowserEngine) ? "px, " : ", ") + anAffineTransform.ty + (CPBrowserIsEngine(CPGeckoBrowserEngine) ? "px)" : ")");
|
return [CPString stringWithFormat:@"matrix(%d,%d,%d,%d,%d,%d)", anAffineTransform.a, anAffineTransform.b, anAffineTransform.c, anAffineTransform.d, anAffineTransform.tx, anAffineTransform.ty];
|
||||||
};
|
};
|
||||||
|
|
||||||
var frameOriginToCSSTransformMatrix = function(start, current)
|
var frameOriginToCSSTransformMatrix = function(start, current)
|
||||||
@@ -408,20 +408,25 @@ var createUpdateFrame = function(aView, aKeyPath)
|
|||||||
{
|
{
|
||||||
[aView _setInhibitDOMUpdates:YES];
|
[aView _setInhibitDOMUpdates:YES];
|
||||||
|
|
||||||
var matrix = style[transformProperty].split('(')[1].split(')')[0].split(','),
|
var matrix_value = style[transformProperty];
|
||||||
x = ROUND(initialOrigin.x + parseFloat(matrix[4])),
|
|
||||||
y = ROUND(initialOrigin.y + parseFloat(matrix[5]));
|
|
||||||
|
|
||||||
if (aKeyPath === "frame")
|
if (matrix_value && matrix_value !== 'none')
|
||||||
{
|
{
|
||||||
var width = getCSSPropertyValue("width"),
|
var matrix_array = matrix_value.split('(')[1].split(')')[0].split(','),
|
||||||
height = getCSSPropertyValue("height");
|
x = ROUND(initialOrigin.x + parseFloat(matrix_array[4])),
|
||||||
|
y = ROUND(initialOrigin.y + parseFloat(matrix_array[5]));
|
||||||
|
|
||||||
[aView setFrame:CGRectMake(x, y, width, height)];
|
if (aKeyPath === "frame")
|
||||||
}
|
{
|
||||||
else
|
var width = getCSSPropertyValue("width"),
|
||||||
{
|
height = getCSSPropertyValue("height");
|
||||||
[aView setFrameOrigin:CGPointMake(x, y)];
|
|
||||||
|
[aView setFrame:CGRectMake(x, y, width, height)];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[aView setFrameOrigin:CGPointMake(x, y)];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[aView _setInhibitDOMUpdates:NO];
|
[aView _setInhibitDOMUpdates:NO];
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ var _supportsCSSAnimations = null;
|
|||||||
id <CPAnimatablePropertyContainer> _target;
|
id <CPAnimatablePropertyContainer> _target;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (BOOL)initialize
|
+ (void)initialize
|
||||||
{
|
{
|
||||||
if ([self class] !== [_CPObjectAnimator class])
|
if ([self class] !== [_CPObjectAnimator class])
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -557,14 +557,14 @@ CGContextConcatCTM = function(aContext, anAffineTransform)
|
|||||||
b = VT.b;
|
b = VT.b;
|
||||||
c = VT.c;
|
c = VT.c;
|
||||||
d = VT.d;
|
d = VT.d;
|
||||||
scale_rotate(a, b, c, d)
|
scale_rotate(a, b, c, d);
|
||||||
S.a *= sx;
|
S.a *= sx;
|
||||||
S.d *= sy;
|
S.d *= sy;
|
||||||
a = U.a;
|
a = U.a;
|
||||||
b = U.b;
|
b = U.b;
|
||||||
c = U.c;
|
c = U.c;
|
||||||
d = U.d;
|
d = U.d;
|
||||||
rotate_scale(a, b, c, d)
|
rotate_scale(a, b, c, d);
|
||||||
sx = S.a * sx;
|
sx = S.a * sx;
|
||||||
sy = S.d * sy;
|
sy = S.d * sy;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ function CGContextDrawPath(aContext, aMode)
|
|||||||
vml.push("\">");
|
vml.push("\">");
|
||||||
|
|
||||||
if (gState.gradient)
|
if (gState.gradient)
|
||||||
vml.push(gState.gradient)
|
vml.push(gState.gradient);
|
||||||
|
|
||||||
else if (fill)
|
else if (fill)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -132,9 +132,6 @@ function CGPathAddArc(aPath, aTransform, x, y, aRadius, aStartAngle, anEndAngle,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var arcStartX = x + aRadius * COS(aStartAngle),
|
|
||||||
arcStartY = y + aRadius * SIN(aStartAngle);
|
|
||||||
|
|
||||||
aPath.start = CGPointMake(arcStartX, arcStartY);
|
aPath.start = CGPointMake(arcStartX, arcStartY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,7 +271,7 @@ function CGPathAddQuadCurveToPoint(aPath, aTransform, cpx, cpy, x, y)
|
|||||||
end = CGPointApplyAffineTransform(end, aTransform);
|
end = CGPointApplyAffineTransform(end, aTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
aPath.elements[aPath.count++] = { type:kCGPathElementAddQuadCurveToPoint, cpx:cp.x, cpy:cp.y, x:end.x, y:end.y }
|
aPath.elements[aPath.count++] = { type:kCGPathElementAddQuadCurveToPoint, cpx:cp.x, cpy:cp.y, x:end.x, y:end.y };
|
||||||
aPath.current = end;
|
aPath.current = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ appKitTask = framework ("AppKit", function(appKitTask)
|
|||||||
appKitTask.setCompilerFlags("-O2 " + INCLUDES);
|
appKitTask.setCompilerFlags("-O2 " + INCLUDES);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
appKitTask.setCompilerFlags("-DDEBUG -g " + INCLUDES);
|
appKitTask.setCompilerFlags("-DDEBUG -g -S --inline-msg-send " + INCLUDES);
|
||||||
});
|
});
|
||||||
|
|
||||||
$BUILD_CJS_CAPPUCCINO_APPKIT = FILE.join($BUILD_CJS_CAPPUCCINO_FRAMEWORKS, "AppKit");
|
$BUILD_CJS_CAPPUCCINO_APPKIT = FILE.join($BUILD_CJS_CAPPUCCINO_FRAMEWORKS, "AppKit");
|
||||||
|
|||||||
@@ -224,18 +224,10 @@ var PrimaryPlatformWindow = NULL;
|
|||||||
|
|
||||||
- (void)deminiaturize:(id)sender
|
- (void)deminiaturize:(id)sender
|
||||||
{
|
{
|
||||||
#if PLATFORM(DOM)
|
|
||||||
if (_DOMWindow && typeof _DOMWindow["cpDeminiaturize"] === "function")
|
|
||||||
_DOMWindow.cpDeminiaturize();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)miniaturize:(id)sender
|
- (void)miniaturize:(id)sender
|
||||||
{
|
{
|
||||||
#if PLATFORM(DOM)
|
|
||||||
if (_DOMWindow && typeof _DOMWindow["cpMiniaturize"] === "function")
|
|
||||||
_DOMWindow.cpMiniaturize();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)moveWindow:(CPWindow)aWindow fromLevel:(int)fromLevel toLevel:(int)toLevel
|
- (void)moveWindow:(CPWindow)aWindow fromLevel:(int)fromLevel toLevel:(int)toLevel
|
||||||
@@ -255,31 +247,16 @@ var PrimaryPlatformWindow = NULL;
|
|||||||
- (void)setLevel:(CPInteger)aLevel
|
- (void)setLevel:(CPInteger)aLevel
|
||||||
{
|
{
|
||||||
_level = aLevel;
|
_level = aLevel;
|
||||||
|
|
||||||
#if PLATFORM(DOM)
|
|
||||||
if (_DOMWindow && _DOMWindow.cpSetLevel)
|
|
||||||
_DOMWindow.cpSetLevel(aLevel);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setHasShadow:(BOOL)shouldHaveShadow
|
- (void)setHasShadow:(BOOL)shouldHaveShadow
|
||||||
{
|
{
|
||||||
_hasShadow = shouldHaveShadow;
|
_hasShadow = shouldHaveShadow;
|
||||||
|
|
||||||
#if PLATFORM(DOM)
|
|
||||||
if (_DOMWindow && _DOMWindow.cpSetHasShadow)
|
|
||||||
_DOMWindow.cpSetHasShadow(shouldHaveShadow);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setShadowStyle:(int)aStyle
|
- (void)setShadowStyle:(int)aStyle
|
||||||
{
|
{
|
||||||
_shadowStyle = aStyle;
|
_shadowStyle = aStyle;
|
||||||
|
|
||||||
#if PLATFORM(DOM)
|
|
||||||
if (_DOMWindow && _DOMWindow.cpSetShadowStyle)
|
|
||||||
_shadowStyle.cpSetShadowStyle(aStyle);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)supportsFullPlatformWindows
|
- (BOOL)supportsFullPlatformWindows
|
||||||
|
|||||||
@@ -469,7 +469,7 @@ Return true if the event may be a copy and paste event, but the target is not an
|
|||||||
// By default we'll stop the native handling of the event since we're handling it ourselves. However, we need to
|
// By default we'll stop the native handling of the event since we're handling it ourselves. However, we need to
|
||||||
// stop it before we send the event so that the event can overrule our choice. CPTextField for instance wants the
|
// stop it before we send the event so that the event can overrule our choice. CPTextField for instance wants the
|
||||||
// default handling when focused (which is to insert into the field).
|
// default handling when focused (which is to insert into the field).
|
||||||
[platformWindow _propagateCurrentDOMEvent:NO]
|
[platformWindow _propagateCurrentDOMEvent:NO];
|
||||||
|
|
||||||
[CPApp sendEvent:anEvent];
|
[CPApp sendEvent:anEvent];
|
||||||
|
|
||||||
@@ -492,7 +492,7 @@ Return true if the event may be a copy and paste event, but the target is not an
|
|||||||
|
|
||||||
SUPPRESS_CAPPUCCINO_CUT_FOR_EVENT(anEvent);
|
SUPPRESS_CAPPUCCINO_CUT_FOR_EVENT(anEvent);
|
||||||
|
|
||||||
[platformWindow _propagateCurrentDOMEvent:NO]
|
[platformWindow _propagateCurrentDOMEvent:NO];
|
||||||
|
|
||||||
// Let the app react through copy: and cut: actions.
|
// Let the app react through copy: and cut: actions.
|
||||||
[CPApp sendEvent:anEvent];
|
[CPApp sendEvent:anEvent];
|
||||||
|
|||||||
@@ -205,6 +205,9 @@ var resizeTimer = nil;
|
|||||||
var PreventScroll = true;
|
var PreventScroll = true;
|
||||||
var blurTimer = nil;
|
var blurTimer = nil;
|
||||||
|
|
||||||
|
var touchStartingPointX,
|
||||||
|
touchStartingPointY;
|
||||||
|
|
||||||
_CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotification";
|
_CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotification";
|
||||||
|
|
||||||
|
|
||||||
@@ -244,9 +247,6 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
|||||||
if (!_DOMWindow)
|
if (!_DOMWindow)
|
||||||
return [self contentRect];
|
return [self contentRect];
|
||||||
|
|
||||||
if (_DOMWindow.cpFrame)
|
|
||||||
return _DOMWindow.cpFrame();
|
|
||||||
|
|
||||||
var contentRect = CGRectMakeZero();
|
var contentRect = CGRectMakeZero();
|
||||||
|
|
||||||
if (window.screenTop)
|
if (window.screenTop)
|
||||||
@@ -275,9 +275,6 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
|||||||
if (!_DOMWindow)
|
if (!_DOMWindow)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (typeof _DOMWindow["cpSetFrame"] === "function")
|
|
||||||
return _DOMWindow.cpSetFrame([self contentRect]);
|
|
||||||
|
|
||||||
var origin = [self contentRect].origin,
|
var origin = [self contentRect].origin,
|
||||||
nativeOrigin = [self nativeContentRect].origin;
|
nativeOrigin = [self nativeContentRect].origin;
|
||||||
|
|
||||||
@@ -573,22 +570,12 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
|||||||
|
|
||||||
[PlatformWindows addObject:self];
|
[PlatformWindows addObject:self];
|
||||||
|
|
||||||
// FIXME: cpSetFrame?
|
|
||||||
_DOMWindow.document.write('<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"></head><body style="background-color:transparent; overflow:hidden"></body></html>');
|
_DOMWindow.document.write('<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"></head><body style="background-color:transparent; overflow:hidden"></body></html>');
|
||||||
_DOMWindow.document.close();
|
_DOMWindow.document.close();
|
||||||
|
|
||||||
if (self != [CPPlatformWindow primaryPlatformWindow])
|
if (self != [CPPlatformWindow primaryPlatformWindow])
|
||||||
_DOMWindow.document.title = _title;
|
_DOMWindow.document.title = _title;
|
||||||
|
|
||||||
if (![CPPlatform isBrowser])
|
|
||||||
{
|
|
||||||
_DOMWindow.cpWindowNumber = [self._only windowNumber];
|
|
||||||
_DOMWindow.cpSetFrame(_contentRect);
|
|
||||||
_DOMWindow.cpSetLevel(_level);
|
|
||||||
_DOMWindow.cpSetHasShadow(_hasShadow);
|
|
||||||
_DOMWindow.cpSetShadowStyle(_shadowStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
[self registerDOMWindow];
|
[self registerDOMWindow];
|
||||||
|
|
||||||
_DOMBodyElement.style.cursor = [[CPCursor currentCursor] _cssString];
|
_DOMBodyElement.style.cursor = [[CPCursor currentCursor] _cssString];
|
||||||
@@ -666,7 +653,8 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
|||||||
}
|
}
|
||||||
else if (type === "dragend")
|
else if (type === "dragend")
|
||||||
{
|
{
|
||||||
var dropEffect = aDOMEvent.dataTransfer.dropEffect;
|
var dropEffect = aDOMEvent.dataTransfer.dropEffect,
|
||||||
|
dragOperation;
|
||||||
|
|
||||||
if (dropEffect === "move")
|
if (dropEffect === "move")
|
||||||
dragOperation = CPDragOperationMove;
|
dragOperation = CPDragOperationMove;
|
||||||
@@ -944,8 +932,7 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
|||||||
if (!theWindow)
|
if (!theWindow)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var windowNumber = [theWindow windowNumber];
|
windowNumber = [theWindow windowNumber];
|
||||||
|
|
||||||
location = [theWindow convertBridgeToBase:location];
|
location = [theWindow convertBridgeToBase:location];
|
||||||
|
|
||||||
var event = [CPEvent mouseEventWithType:CPScrollWheel location:location modifierFlags:modifierFlags
|
var event = [CPEvent mouseEventWithType:CPScrollWheel location:location modifierFlags:modifierFlags
|
||||||
@@ -1152,10 +1139,26 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
|||||||
|
|
||||||
- (void)touchEvent:(DOMEvent)aDOMEvent
|
- (void)touchEvent:(DOMEvent)aDOMEvent
|
||||||
{
|
{
|
||||||
|
var newEvent = {},
|
||||||
|
touch = aDOMEvent.touches.length ? aDOMEvent.touches[0] : aDOMEvent.changedTouches[0];
|
||||||
|
|
||||||
|
newEvent.timestamp = [CPEvent currentTimestamp];
|
||||||
|
newEvent.target = aDOMEvent.target;
|
||||||
|
newEvent.shiftKey = newEvent.ctrlKey = newEvent.altKey = newEvent.metaKey = false;
|
||||||
|
|
||||||
|
newEvent.clientX = touch.clientX;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Normally the document can't scroll in Cappuccino: our body element has top:0 and bottom:0 with absolute positioning. So it should always be exactly the height of the viewport. The below handles a special case. iOS scrolls the document when the virtual keyboard is present and it needs to move a text input upwards visually to avoid covering the input with the keyboard. For most purposes we can ignore this, except here. In theory I think we could always apply this (scrollTop should always be 0 on every other device and situation) but let's be defensive and only apply it for touch events to minimise the risk of surprises.
|
||||||
|
*/
|
||||||
|
newEvent.clientY = _DOMWindow.document.body.scrollTop + touch.clientY;
|
||||||
|
|
||||||
|
newEvent.preventDefault = function() { if (aDOMEvent.preventDefault) aDOMEvent.preventDefault() };
|
||||||
|
newEvent.stopPropagation = function() { if (aDOMEvent.stopPropagation) aDOMEvent.stopPropagation() };
|
||||||
|
|
||||||
|
// single finger event-> simulate a simple mouse-click
|
||||||
if (aDOMEvent.touches && (aDOMEvent.touches.length == 1 || (aDOMEvent.touches.length == 0 && aDOMEvent.changedTouches.length == 1)))
|
if (aDOMEvent.touches && (aDOMEvent.touches.length == 1 || (aDOMEvent.touches.length == 0 && aDOMEvent.changedTouches.length == 1)))
|
||||||
{
|
{
|
||||||
var newEvent = {};
|
|
||||||
|
|
||||||
switch (aDOMEvent.type)
|
switch (aDOMEvent.type)
|
||||||
{
|
{
|
||||||
case CPDOMEventTouchStart: newEvent.type = CPDOMEventMouseDown;
|
case CPDOMEventTouchStart: newEvent.type = CPDOMEventMouseDown;
|
||||||
@@ -1168,36 +1171,42 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var touch = aDOMEvent.touches.length ? aDOMEvent.touches[0] : aDOMEvent.changedTouches[0];
|
|
||||||
|
|
||||||
newEvent.clientX = touch.clientX;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Normally the document can't scroll in Cappuccino: our body element has top:0 and bottom:0 with absolute positioning. So it should always be exactly the height of the viewport. The below handles a special case. iOS scrolls the document when the virtual keyboard is present and it needs to move a text input upwards visually to avoid covering the input with the keyboard. For most purposes we can ignore this, except here. In theory I think we could always apply this (scrollTop should always be 0 on every other device and situation) but let's be defensive and only apply it for touch events to minimise the risk of surprises.
|
|
||||||
*/
|
|
||||||
newEvent.clientY = _DOMWindow.document.body.scrollTop + touch.clientY;
|
|
||||||
|
|
||||||
newEvent.timestamp = [CPEvent currentTimestamp];
|
|
||||||
newEvent.target = aDOMEvent.target;
|
|
||||||
|
|
||||||
newEvent.shiftKey = newEvent.ctrlKey = newEvent.altKey = newEvent.metaKey = false;
|
|
||||||
|
|
||||||
newEvent.preventDefault = function() { if (aDOMEvent.preventDefault) aDOMEvent.preventDefault() };
|
|
||||||
newEvent.stopPropagation = function() { if (aDOMEvent.stopPropagation) aDOMEvent.stopPropagation() };
|
|
||||||
|
|
||||||
[self mouseEvent:newEvent];
|
[self mouseEvent:newEvent];
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// two fingers->simulate scrolling events
|
||||||
|
if (aDOMEvent.touches && aDOMEvent.touches.length == 2)
|
||||||
|
{
|
||||||
|
switch (aDOMEvent.type)
|
||||||
|
{
|
||||||
|
case CPDOMEventTouchStart:
|
||||||
|
touchStartingPointX = touch.pageX;
|
||||||
|
touchStartingPointY = touch.pageY;
|
||||||
|
break;
|
||||||
|
case CPDOMEventTouchMove:
|
||||||
|
newEvent._hasPreciseScrollingDeltas = YES;
|
||||||
|
newEvent.deltaX = touchStartingPointX - touch.pageX;
|
||||||
|
newEvent.deltaY = touchStartingPointY - touch.pageY;
|
||||||
|
newEvent.type = CPDOMEventScrollWheel;
|
||||||
|
|
||||||
|
[self scrollEvent:newEvent];
|
||||||
|
|
||||||
|
touchStartingPointX = touch.pageX;
|
||||||
|
touchStartingPointY = touch.pageY;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// handle other touch cases specifically
|
||||||
|
|
||||||
if (aDOMEvent.preventDefault)
|
if (aDOMEvent.preventDefault)
|
||||||
aDOMEvent.preventDefault();
|
aDOMEvent.preventDefault();
|
||||||
|
|
||||||
if (aDOMEvent.stopPropagation)
|
if (aDOMEvent.stopPropagation)
|
||||||
aDOMEvent.stopPropagation();
|
aDOMEvent.stopPropagation();
|
||||||
}
|
}
|
||||||
// handle touch cases specifically
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)mouseEvent:(DOMEvent)aDOMEvent
|
- (void)mouseEvent:(DOMEvent)aDOMEvent
|
||||||
@@ -1422,7 +1431,7 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
|||||||
var insertionIndex = 0;
|
var insertionIndex = 0;
|
||||||
|
|
||||||
if (middle !== undefined)
|
if (middle !== undefined)
|
||||||
insertionIndex = _windowLevels[middle] > aLevel ? middle : middle + 1
|
insertionIndex = _windowLevels[middle] > aLevel ? middle : middle + 1;
|
||||||
|
|
||||||
[_windowLevels insertObject:aLevel atIndex:insertionIndex];
|
[_windowLevels insertObject:aLevel atIndex:insertionIndex];
|
||||||
layer._DOMElement.style.zIndex = aLevel + 1; // adding one avoids negative zIndices. These have been causing issues in Chrome
|
layer._DOMElement.style.zIndex = aLevel + 1; // adding one avoids negative zIndices. These have been causing issues in Chrome
|
||||||
@@ -1821,7 +1830,7 @@ var _CPEventFromNativeMouseEvent = function(aNativeEvent, anEventType, aPoint, m
|
|||||||
var CLICK_SPACE_DELTA = 5.0,
|
var CLICK_SPACE_DELTA = 5.0,
|
||||||
CLICK_TIME_DELTA = (typeof document != "undefined" && document.addEventListener) ? 0.55 : 1.0;
|
CLICK_TIME_DELTA = (typeof document != "undefined" && document.addEventListener) ? 0.55 : 1.0;
|
||||||
|
|
||||||
var CPDOMEventGetClickCount = function(aComparisonEvent, aTimestamp, aLocation)
|
CPDOMEventGetClickCount = function(aComparisonEvent, aTimestamp, aLocation)
|
||||||
{
|
{
|
||||||
if (!aComparisonEvent)
|
if (!aComparisonEvent)
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 317 B |
|
Before Width: | Height: | Size: 422 B |
|
Before Width: | Height: | Size: 409 B |
|
Before Width: | Height: | Size: 333 B |
|
Before Width: | Height: | Size: 432 B |
|
Before Width: | Height: | Size: 418 B |
|
Before Width: | Height: | Size: 76 B |
|
Before Width: | Height: | Size: 102 B |
|
Before Width: | Height: | Size: 102 B |
|
Before Width: | Height: | Size: 84 B After Width: | Height: | Size: 92 B |
|
Before Width: | Height: | Size: 171 B |
|
Before Width: | Height: | Size: 168 B |
|
Before Width: | Height: | Size: 95 B |
|
Before Width: | Height: | Size: 75 B |
|
Before Width: | Height: | Size: 96 B |
|
Before Width: | Height: | Size: 167 B |
|
Before Width: | Height: | Size: 77 B After Width: | Height: | Size: 85 B |
|
Before Width: | Height: | Size: 161 B |
|
Before Width: | Height: | Size: 349 B |
|
Before Width: | Height: | Size: 426 B |
|
Before Width: | Height: | Size: 396 B |
|
Before Width: | Height: | Size: 313 B |
|
Before Width: | Height: | Size: 433 B |
|
Before Width: | Height: | Size: 388 B |
|
Before Width: | Height: | Size: 78 B After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 81 B After Width: | Height: | Size: 3.6 KiB |
@@ -508,9 +508,7 @@ var themedButtonValues = nil,
|
|||||||
orientation: PatternIsVertical
|
orientation: PatternIsVertical
|
||||||
}),
|
}),
|
||||||
|
|
||||||
trackColorLegacy = PatternColor("scroller-legacy-vertical-track-center.png", 14.0, 1.0),
|
trackColorLegacy = PatternColor("scroller-legacy-vertical-track-center.png", 14.0, 1.0),
|
||||||
incrementColorLegacy = PatternColor("scroller-legacy-vertical-track-bottom.png", 14.0, 11.0),
|
|
||||||
decrementColorLegacy = PatternColor("scroller-legacy-vertical-track-top.png", 14.0, 11.0),
|
|
||||||
|
|
||||||
knobColor = PatternColor(
|
knobColor = PatternColor(
|
||||||
"scroller-vertical-knob{style}{position}.png",
|
"scroller-vertical-knob{style}{position}.png",
|
||||||
@@ -535,8 +533,8 @@ var themedButtonValues = nil,
|
|||||||
[@"minimum-knob-length", 21.0, CPThemeStateVertical],
|
[@"minimum-knob-length", 21.0, CPThemeStateVertical],
|
||||||
|
|
||||||
// Overlay
|
// Overlay
|
||||||
[@"scroller-width", 9.0, CPThemeStateVertical],
|
[@"scroller-width", 14.0, CPThemeStateVertical],
|
||||||
[@"knob-inset", CGInsetMake(2.0, 0.0, 0.0, 0.0), CPThemeStateVertical],
|
[@"knob-inset", CGInsetMake(0.0, 0.0, 0.0, 0.0), CPThemeStateVertical],
|
||||||
[@"track-inset", CGInsetMake(2.0, 0.0, 2.0, 0.0), CPThemeStateVertical],
|
[@"track-inset", CGInsetMake(2.0, 0.0, 2.0, 0.0), CPThemeStateVertical],
|
||||||
[@"track-border-overlay", 12.0, CPThemeStateVertical],
|
[@"track-border-overlay", 12.0, CPThemeStateVertical],
|
||||||
[@"knob-slot-color", [CPNull null], CPThemeStateVertical],
|
[@"knob-slot-color", [CPNull null], CPThemeStateVertical],
|
||||||
@@ -553,7 +551,7 @@ var themedButtonValues = nil,
|
|||||||
|
|
||||||
// Legacy
|
// Legacy
|
||||||
[@"scroller-width", 14.0, [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
[@"scroller-width", 14.0, [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
||||||
[@"knob-inset", CGInsetMake(0.0, 0.0, 0.0, 0.0), [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
[@"knob-inset", CGInsetMake(0.0, 2.0, 0.0, 2.0), [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
||||||
[@"track-inset", CGInsetMake(0.0, 0.0, 0.0, 0.0), [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
[@"track-inset", CGInsetMake(0.0, 0.0, 0.0, 0.0), [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
||||||
[@"track-border-overlay", 0.0, [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
[@"track-border-overlay", 0.0, [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
||||||
[@"knob-slot-color", trackColorLegacy, [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
[@"knob-slot-color", trackColorLegacy, [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
||||||
@@ -562,13 +560,11 @@ var themedButtonValues = nil,
|
|||||||
[@"knob-slot-color", trackColorLegacy, [CPThemeStateVertical, CPThemeStateScrollViewLegacy, CPThemeStateSelected, CPThemeStateScrollerKnobDark]],
|
[@"knob-slot-color", trackColorLegacy, [CPThemeStateVertical, CPThemeStateScrollViewLegacy, CPThemeStateSelected, CPThemeStateScrollerKnobDark]],
|
||||||
[@"knob-slot-color", trackColorLegacy, [CPThemeStateVertical, CPThemeStateScrollViewLegacy, CPThemeStateScrollerKnobDark]],
|
[@"knob-slot-color", trackColorLegacy, [CPThemeStateVertical, CPThemeStateScrollViewLegacy, CPThemeStateScrollerKnobDark]],
|
||||||
[@"knob-slot-color", trackColorLegacy, [CPThemeStateVertical, CPThemeStateScrollViewLegacy, CPThemeStateScrollerKnobLight]],
|
[@"knob-slot-color", trackColorLegacy, [CPThemeStateVertical, CPThemeStateScrollViewLegacy, CPThemeStateScrollerKnobLight]],
|
||||||
[@"knob-color", knobColorLegacy, [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
[@"knob-color", knobColor["dark"], [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
||||||
[@"knob-color", knobColorLegacy, [CPThemeStateVertical, CPThemeStateScrollViewLegacy, CPThemeStateScrollerKnobLight]],
|
[@"increment-line-color", [CPNull null], [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
||||||
[@"knob-color", knobColorLegacy, [CPThemeStateVertical, CPThemeStateScrollViewLegacy, CPThemeStateScrollerKnobDark]],
|
[@"decrement-line-color", [CPNull null], [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
||||||
[@"increment-line-color", incrementColorLegacy, [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
[@"decrement-line-size", CGSizeMakeZero(), [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
||||||
[@"decrement-line-color", decrementColorLegacy, [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
[@"increment-line-size", CGSizeMakeZero(), [CPThemeStateVertical, CPThemeStateScrollViewLegacy]]
|
||||||
[@"decrement-line-size", CGSizeMake(14.0, 11.0), [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
|
||||||
[@"increment-line-size", CGSizeMake(14.0, 11.0), [CPThemeStateVertical, CPThemeStateScrollViewLegacy]]
|
|
||||||
];
|
];
|
||||||
|
|
||||||
[self registerThemeValues:themedVerticalScrollerValues forView:scroller];
|
[self registerThemeValues:themedVerticalScrollerValues forView:scroller];
|
||||||
@@ -588,9 +584,7 @@ var themedButtonValues = nil,
|
|||||||
orientation: PatternIsHorizontal
|
orientation: PatternIsHorizontal
|
||||||
}),
|
}),
|
||||||
|
|
||||||
trackColorLegacy = PatternColor("scroller-legacy-horizontal-track-center.png", 1.0, 14.0),
|
trackColorLegacy = PatternColor("scroller-legacy-horizontal-track-center.png", 1.0, 14.0),
|
||||||
incrementColorLegacy = PatternColor("scroller-legacy-horizontal-track-right.png", 11.0, 14.0),
|
|
||||||
decrementColorLegacy = PatternColor("scroller-legacy-horizontal-track-left.png", 11.0, 14.0),
|
|
||||||
|
|
||||||
knobColor = PatternColor(
|
knobColor = PatternColor(
|
||||||
"scroller-horizontal-knob{style}{position}.png",
|
"scroller-horizontal-knob{style}{position}.png",
|
||||||
@@ -616,7 +610,7 @@ var themedButtonValues = nil,
|
|||||||
|
|
||||||
// Overlay
|
// Overlay
|
||||||
[@"scroller-width", 9.0],
|
[@"scroller-width", 9.0],
|
||||||
[@"knob-inset", CGInsetMake(0.0, 0.0, 0.0, 2.0)],
|
[@"knob-inset", CGInsetMake(0.0, 0.0, 0.0, 0.0)],
|
||||||
[@"track-inset", CGInsetMake(0.0, 2.0, 0.0, 2.0)],
|
[@"track-inset", CGInsetMake(0.0, 2.0, 0.0, 2.0)],
|
||||||
[@"track-border-overlay", 12.0],
|
[@"track-border-overlay", 12.0],
|
||||||
[@"knob-slot-color", [CPNull null]],
|
[@"knob-slot-color", [CPNull null]],
|
||||||
@@ -631,20 +625,18 @@ var themedButtonValues = nil,
|
|||||||
|
|
||||||
// Legacy
|
// Legacy
|
||||||
[@"scroller-width", 14.0, CPThemeStateScrollViewLegacy],
|
[@"scroller-width", 14.0, CPThemeStateScrollViewLegacy],
|
||||||
[@"knob-inset", CGInsetMake(0.0, 0.0, 0.0, 0.0), CPThemeStateScrollViewLegacy],
|
[@"knob-inset", CGInsetMake(2.0, 0.0, 2.0, 0.0), CPThemeStateScrollViewLegacy],
|
||||||
[@"track-inset", CGInsetMake(0.0, 0.0, 0.0, 0.0), CPThemeStateScrollViewLegacy],
|
[@"track-inset", CGInsetMake(0.0, 0.0, 0.0, 0.0), CPThemeStateScrollViewLegacy],
|
||||||
[@"track-border-overlay", 0.0, CPThemeStateScrollViewLegacy],
|
[@"track-border-overlay", 0.0, CPThemeStateScrollViewLegacy],
|
||||||
[@"knob-slot-color", trackColorLegacy, CPThemeStateScrollViewLegacy],
|
[@"knob-slot-color", trackColorLegacy, CPThemeStateScrollViewLegacy],
|
||||||
[@"knob-slot-color", trackColorLegacy, [CPThemeStateScrollViewLegacy, CPThemeStateSelected]],
|
[@"knob-slot-color", trackColorLegacy, [CPThemeStateScrollViewLegacy, CPThemeStateSelected]],
|
||||||
[@"knob-slot-color", trackColorLegacy, [CPThemeStateScrollViewLegacy, CPThemeStateScrollerKnobLight]],
|
[@"knob-slot-color", trackColorLegacy, [CPThemeStateScrollViewLegacy, CPThemeStateScrollerKnobLight]],
|
||||||
[@"knob-slot-color", trackColorLegacy, [CPThemeStateScrollViewLegacy, CPThemeStateScrollerKnobDark]],
|
[@"knob-slot-color", trackColorLegacy, [CPThemeStateScrollViewLegacy, CPThemeStateScrollerKnobDark]],
|
||||||
[@"knob-color", knobColorLegacy, CPThemeStateScrollViewLegacy],
|
[@"knob-color", knobColor["@"], CPThemeStateScrollViewLegacy],
|
||||||
[@"knob-color", knobColorLegacy, [CPThemeStateScrollViewLegacy, CPThemeStateScrollerKnobLight]],
|
[@"knob-color", knobColor["light"], [CPThemeStateScrollViewLegacy, CPThemeStateScrollerKnobLight]],
|
||||||
[@"knob-color", knobColorLegacy, [CPThemeStateScrollViewLegacy, CPThemeStateScrollerKnobDark]],
|
[@"knob-color", knobColor["dark"], [CPThemeStateScrollViewLegacy, CPThemeStateScrollerKnobDark]],
|
||||||
[@"increment-line-color", incrementColorLegacy, CPThemeStateScrollViewLegacy],
|
[@"decrement-line-size", CGSizeMakeZero(), CPThemeStateScrollViewLegacy],
|
||||||
[@"decrement-line-color", decrementColorLegacy, CPThemeStateScrollViewLegacy],
|
[@"increment-line-size", CGSizeMakeZero(), CPThemeStateScrollViewLegacy]
|
||||||
[@"decrement-line-size", CGSizeMake(11.0, 14.0), CPThemeStateScrollViewLegacy],
|
|
||||||
[@"increment-line-size", CGSizeMake(11.0, 14.0), CPThemeStateScrollViewLegacy]
|
|
||||||
];
|
];
|
||||||
|
|
||||||
[self registerThemeValues:themedHorizontalScrollerValues forView:scroller];
|
[self registerThemeValues:themedHorizontalScrollerValues forView:scroller];
|
||||||
@@ -2877,7 +2869,7 @@ var themedButtonValues = nil,
|
|||||||
|
|
||||||
+ (_CPBorderlessBridgeWindowView)themedBorderlessBridgeWindowView
|
+ (_CPBorderlessBridgeWindowView)themedBorderlessBridgeWindowView
|
||||||
{
|
{
|
||||||
var bordelessBridgeWindowView = [[_CPBorderlessBridgeWindowView alloc] initWithFrame:CGRectMake(0,0,0,0)],
|
var borderlessBridgeWindowView = [[_CPBorderlessBridgeWindowView alloc] initWithFrame:CGRectMake(0,0,0,0)],
|
||||||
|
|
||||||
toolbarBackgroundColor = PatternColor(
|
toolbarBackgroundColor = PatternColor(
|
||||||
[
|
[
|
||||||
@@ -2891,9 +2883,9 @@ var themedButtonValues = nil,
|
|||||||
[@"toolbar-background-color", toolbarBackgroundColor]
|
[@"toolbar-background-color", toolbarBackgroundColor]
|
||||||
];
|
];
|
||||||
|
|
||||||
[self registerThemeValues:themeValues forView:bordelessBridgeWindowView inherit:themedWindowViewValues];
|
[self registerThemeValues:themeValues forView:borderlessBridgeWindowView inherit:themedWindowViewValues];
|
||||||
|
|
||||||
return bordelessBridgeWindowView;
|
return borderlessBridgeWindowView;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (_CPToolbarView)themedToolbarView
|
+ (_CPToolbarView)themedToolbarView
|
||||||
|
|||||||
@@ -331,9 +331,9 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0,
|
|||||||
{
|
{
|
||||||
var textStyle = _DOMTextElement.style;
|
var textStyle = _DOMTextElement.style;
|
||||||
|
|
||||||
textFrame.origin.y = parseInt(textStyle.top.substr(0, textStyle.top.length - 2), 10),
|
textFrame.origin.y = parseInt(textStyle.top.substr(0, textStyle.top.length - 2), 10);
|
||||||
textFrame.origin.x = parseInt(textStyle.left.substr(0, textStyle.left.length - 2), 10),
|
textFrame.origin.x = parseInt(textStyle.left.substr(0, textStyle.left.length - 2), 10);
|
||||||
textFrame.size.width = parseInt(textStyle.width.substr(0, textStyle.width.length - 2), 10),
|
textFrame.size.width = parseInt(textStyle.width.substr(0, textStyle.width.length - 2), 10);
|
||||||
textFrame.size.height = parseInt(textStyle.height.substr(0, textStyle.height.length - 2), 10);
|
textFrame.size.height = parseInt(textStyle.height.substr(0, textStyle.height.length - 2), 10);
|
||||||
|
|
||||||
textFrame.size.width += _textShadowOffset.width;
|
textFrame.size.width += _textShadowOffset.width;
|
||||||
@@ -437,55 +437,67 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0,
|
|||||||
|
|
||||||
var textStyle = hasDOMTextElement ? _DOMTextElement.style : nil;
|
var textStyle = hasDOMTextElement ? _DOMTextElement.style : nil;
|
||||||
|
|
||||||
// Create or destroy the DOM Text Shadow element as necessary.
|
// If theme is CSS based and if shadow color is a CSS dictionary, we don't need a separate DOM element,
|
||||||
// If _textShadowColor's alphaComponent is 0, don't bother drawing anything (issue #1412).
|
// we simply put shadow styling on the regular text element
|
||||||
// This improves performance as we get rid of an invisible element, and makes IE <9.0 capable
|
if (hasDOMTextElement && [[self actualTheme] isCSSBased] && [_textShadowColor cssDictionary])
|
||||||
// of correctly 'rendering' shadows with [CPColor clearColor].
|
|
||||||
var needsDOMTextShadowElement = hasDOMTextElement && [_textShadowColor alphaComponent] > 0.0,
|
|
||||||
hasDOMTextShadowElement = !!_DOMTextShadowElement;
|
|
||||||
|
|
||||||
if (needsDOMTextShadowElement !== hasDOMTextShadowElement)
|
|
||||||
{
|
{
|
||||||
if (hasDOMTextShadowElement)
|
[[_textShadowColor cssDictionary] enumerateKeysAndObjectsUsingBlock:function(aKey, anObject, stop)
|
||||||
|
{
|
||||||
|
_DOMTextElement.style[aKey] = anObject;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Create or destroy the DOM Text Shadow element as necessary.
|
||||||
|
// If _textShadowColor's alphaComponent is 0, don't bother drawing anything (issue #1412).
|
||||||
|
// This improves performance as we get rid of an invisible element, and makes IE <9.0 capable
|
||||||
|
// of correctly 'rendering' shadows with [CPColor clearColor].
|
||||||
|
var needsDOMTextShadowElement = hasDOMTextElement && [_textShadowColor alphaComponent] > 0.0,
|
||||||
|
hasDOMTextShadowElement = !!_DOMTextShadowElement;
|
||||||
|
|
||||||
|
if (needsDOMTextShadowElement !== hasDOMTextShadowElement)
|
||||||
{
|
{
|
||||||
_DOMElement.removeChild(_DOMTextShadowElement);
|
if (hasDOMTextShadowElement)
|
||||||
|
|
||||||
_DOMTextShadowElement = nil;
|
|
||||||
|
|
||||||
hasDOMTextShadowElement = NO;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_DOMTextShadowElement = document.createElement("div");
|
|
||||||
|
|
||||||
var shadowStyle = _DOMTextShadowElement.style,
|
|
||||||
font = (_font || [CPFont systemFontOfSize:CPFontCurrentSystemSize]);
|
|
||||||
|
|
||||||
shadowStyle.font = [font cssString];
|
|
||||||
shadowStyle.position = "absolute";
|
|
||||||
shadowStyle.whiteSpace = textStyle.whiteSpace;
|
|
||||||
shadowStyle.wordWrap = textStyle.wordWrap;
|
|
||||||
shadowStyle.color = [_textShadowColor cssString];
|
|
||||||
shadowStyle.lineHeight = [font defaultLineHeightForFont] + "px";
|
|
||||||
|
|
||||||
shadowStyle.zIndex = 150;
|
|
||||||
shadowStyle.textOverflow = textStyle.textOverflow;
|
|
||||||
|
|
||||||
if (document.attachEvent)
|
|
||||||
{
|
{
|
||||||
shadowStyle.overflow = textStyle.overflow;
|
_DOMElement.removeChild(_DOMTextShadowElement);
|
||||||
|
|
||||||
|
_DOMTextShadowElement = nil;
|
||||||
|
|
||||||
|
hasDOMTextShadowElement = NO;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
shadowStyle.overflowX = textStyle.overflowX;
|
_DOMTextShadowElement = document.createElement("div");
|
||||||
shadowStyle.overflowY = textStyle.overflowY;
|
|
||||||
|
var shadowStyle = _DOMTextShadowElement.style,
|
||||||
|
font = (_font || [CPFont systemFontOfSize:CPFontCurrentSystemSize]);
|
||||||
|
|
||||||
|
shadowStyle.font = [font cssString];
|
||||||
|
shadowStyle.position = "absolute";
|
||||||
|
shadowStyle.whiteSpace = textStyle.whiteSpace;
|
||||||
|
shadowStyle.wordWrap = textStyle.wordWrap;
|
||||||
|
shadowStyle.color = [_textShadowColor cssString];
|
||||||
|
shadowStyle.lineHeight = [font defaultLineHeightForFont] + "px";
|
||||||
|
|
||||||
|
shadowStyle.zIndex = 150;
|
||||||
|
shadowStyle.textOverflow = textStyle.textOverflow;
|
||||||
|
|
||||||
|
if (document.attachEvent)
|
||||||
|
{
|
||||||
|
shadowStyle.overflow = textStyle.overflow;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shadowStyle.overflowX = textStyle.overflowX;
|
||||||
|
shadowStyle.overflowY = textStyle.overflowY;
|
||||||
|
}
|
||||||
|
|
||||||
|
_DOMElement.appendChild(_DOMTextShadowElement);
|
||||||
|
|
||||||
|
hasDOMTextShadowElement = YES;
|
||||||
|
|
||||||
|
_flags |= _CPImageAndTextViewTextChangedFlag; //sigh...
|
||||||
}
|
}
|
||||||
|
|
||||||
_DOMElement.appendChild(_DOMTextShadowElement);
|
|
||||||
|
|
||||||
hasDOMTextShadowElement = YES;
|
|
||||||
|
|
||||||
_flags |= _CPImageAndTextViewTextChangedFlag; //sigh...
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -591,41 +603,55 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0,
|
|||||||
}
|
}
|
||||||
|
|
||||||
var needsDOMImageElement = _image !== nil && _imagePosition !== CPNoImage,
|
var needsDOMImageElement = _image !== nil && _imagePosition !== CPNoImage,
|
||||||
hasDOMImageElement = !!_DOMImageElement;
|
hasDOMImageElement = !!_DOMImageElement,
|
||||||
|
// For CSS theming
|
||||||
|
isCSSBasedImage = [_image isCSSBased],
|
||||||
|
isIMGImageElement = hasDOMImageElement && (_DOMImageElement.nodeName == "IMG");
|
||||||
|
|
||||||
// Create or destroy DOM Image element
|
// First, check if we need to destroy a current DOM image element. This is the case if :
|
||||||
if (needsDOMImageElement !== hasDOMImageElement)
|
// - we have one but don't need it anymore
|
||||||
|
// - we have one but not the right one (that is a DIV but needing an IMG, and vice versa)
|
||||||
|
|
||||||
|
if (hasDOMImageElement)
|
||||||
{
|
{
|
||||||
if (hasDOMImageElement)
|
if (!needsDOMImageElement || (isIMGImageElement && isCSSBasedImage) || (!isIMGImageElement && !isCSSBasedImage))
|
||||||
{
|
{
|
||||||
|
// OK, destroy it
|
||||||
|
|
||||||
_DOMElement.removeChild(_DOMImageElement);
|
_DOMElement.removeChild(_DOMImageElement);
|
||||||
|
|
||||||
_DOMImageElement = nil;
|
_DOMImageElement = nil;
|
||||||
|
|
||||||
hasDOMImageElement = NO;
|
hasDOMImageElement = NO;
|
||||||
}
|
|
||||||
|
|
||||||
else
|
// CSS styling cleaning
|
||||||
|
_cssStylePreviousState = @[];
|
||||||
|
_cssStyleNode = nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now, if we need a DOM image element and if we don't have one, create a new one
|
||||||
|
|
||||||
|
if (needsDOMImageElement && !hasDOMImageElement)
|
||||||
|
{
|
||||||
|
_DOMImageElement = document.createElement(isCSSBasedImage ? "div" : "img");
|
||||||
|
|
||||||
|
if ([CPPlatform supportsDragAndDrop])
|
||||||
{
|
{
|
||||||
_DOMImageElement = document.createElement("img");
|
_DOMImageElement.setAttribute("draggable", "true");
|
||||||
|
_DOMImageElement.style["-khtml-user-drag"] = "element";
|
||||||
if ([CPPlatform supportsDragAndDrop])
|
|
||||||
{
|
|
||||||
_DOMImageElement.setAttribute("draggable", "true");
|
|
||||||
_DOMImageElement.style["-khtml-user-drag"] = "element";
|
|
||||||
}
|
|
||||||
|
|
||||||
var imageStyle = _DOMImageElement.style;
|
|
||||||
|
|
||||||
imageStyle.top = "0px";
|
|
||||||
imageStyle.left = "0px";
|
|
||||||
imageStyle.position = "absolute";
|
|
||||||
imageStyle.zIndex = 100;
|
|
||||||
|
|
||||||
_DOMElement.appendChild(_DOMImageElement);
|
|
||||||
|
|
||||||
hasDOMImageElement = YES;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var imageStyle = _DOMImageElement.style;
|
||||||
|
|
||||||
|
imageStyle.top = "0px";
|
||||||
|
imageStyle.left = "0px";
|
||||||
|
imageStyle.position = "absolute";
|
||||||
|
imageStyle.zIndex = 100;
|
||||||
|
|
||||||
|
_DOMElement.appendChild(_DOMImageElement);
|
||||||
|
|
||||||
|
hasDOMImageElement = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
var size = [self bounds].size,
|
var size = [self bounds].size,
|
||||||
@@ -637,7 +663,15 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0,
|
|||||||
var imageStyle = _DOMImageElement.style;
|
var imageStyle = _DOMImageElement.style;
|
||||||
|
|
||||||
if (_flags & _CPImageAndTextViewImageChangedFlag)
|
if (_flags & _CPImageAndTextViewImageChangedFlag)
|
||||||
_DOMImageElement.src = [_image filename];
|
{
|
||||||
|
if (isCSSBasedImage)
|
||||||
|
_cssStyleNode = [_image applyCSSImageForView:self
|
||||||
|
onDOMElement:_DOMImageElement
|
||||||
|
styleNode:_cssStyleNode
|
||||||
|
previousState:@ref(_cssStylePreviousState)];
|
||||||
|
else
|
||||||
|
_DOMImageElement.src = [_image filename];
|
||||||
|
}
|
||||||
|
|
||||||
var centerX = size.width / 2.0,
|
var centerX = size.width / 2.0,
|
||||||
centerY = size.height / 2.0,
|
centerY = size.height / 2.0,
|
||||||
@@ -836,7 +870,8 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0,
|
|||||||
- (void)setSelectedRange:(CPRange)aRange
|
- (void)setSelectedRange:(CPRange)aRange
|
||||||
{
|
{
|
||||||
#if PLATFORM(DOM)
|
#if PLATFORM(DOM)
|
||||||
[[[self window] platformWindow] setSelectedRange:aRange inElement:_DOMTextElement];
|
if (_DOMTextElement)
|
||||||
|
[[[self window] platformWindow] setSelectedRange:aRange inElement:_DOMTextElement];
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
@import <Foundation/Foundation.j>
|
@import <Foundation/Foundation.j>
|
||||||
|
@import "CPResponder.j"
|
||||||
|
|
||||||
@import "CPTheme.j"
|
@import "CPTheme.j"
|
||||||
|
|
||||||
@@ -477,4 +478,29 @@ var NULL_THEME = {};
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
#pragma mark -
|
||||||
|
#pragma mark CSS styling additions
|
||||||
|
|
||||||
|
- (CPTheme)actualTheme
|
||||||
|
{
|
||||||
|
return _theme ? _theme : [CPTheme defaultTheme];
|
||||||
|
}
|
||||||
|
|
||||||
|
// These methods implement inherited theme attributes thru class hierarchy.
|
||||||
|
- (id)actualValueForThemeAttribute:(CPString)aName
|
||||||
|
{
|
||||||
|
return [self actualValueForThemeAttribute:aName inState:CPThemeStateNormal];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)actualValueForThemeAttribute:(CPString)aName inState:(ThemeState)aState
|
||||||
|
{
|
||||||
|
for (var currentClass = [self class], foundAttribute = nil, currentTheme = [self actualTheme]; (currentClass && (currentClass !== CPResponder) && !foundAttribute); currentClass = [currentClass superclass])
|
||||||
|
|
||||||
|
foundAttribute = [currentTheme attributeWithName:aName forClass:currentClass];
|
||||||
|
|
||||||
|
return (foundAttribute ? [foundAttribute valueForState:aState] : nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@end
|
||||||
|
|||||||
@@ -574,7 +574,7 @@ var _CPPopoverWindow_shouldClose_ = 1 << 4,
|
|||||||
_isOpening = NO;
|
_isOpening = NO;
|
||||||
|
|
||||||
[_delegate _popoverWindowDidShow];
|
[_delegate _popoverWindowDidShow];
|
||||||
}
|
};
|
||||||
|
|
||||||
#if PLATFORM(DOM)
|
#if PLATFORM(DOM)
|
||||||
_DOMElement.addEventListener(CPBrowserStyleProperty('transitionend'), _transitionCompleteFunction, YES);
|
_DOMElement.addEventListener(CPBrowserStyleProperty('transitionend'), _transitionCompleteFunction, YES);
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ var _CPToolTipHeight = 24.0,
|
|||||||
textFrameSize.height += 4;
|
textFrameSize.height += 4;
|
||||||
|
|
||||||
_content = [CPTextField labelWithTitle:aString];
|
_content = [CPTextField labelWithTitle:aString];
|
||||||
[_content setFont:[CPFont systemFontOfSize:_CPToolTipFontSize]]
|
[_content setFont:[CPFont systemFontOfSize:_CPToolTipFontSize]];
|
||||||
[_content setLineBreakMode:CPLineBreakByCharWrapping];
|
[_content setLineBreakMode:CPLineBreakByCharWrapping];
|
||||||
[_content setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
|
[_content setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
|
||||||
[_content setFrameOrigin:CGPointMake(0.0, 0.0)];
|
[_content setFrameOrigin:CGPointMake(0.0, 0.0)];
|
||||||
|
|||||||
@@ -393,7 +393,7 @@
|
|||||||
|
|
||||||
while (index !== CPNotFound)
|
while (index !== CPNotFound)
|
||||||
{
|
{
|
||||||
_remove(_proxyObject, _removeSEL, index)
|
_remove(_proxyObject, _removeSEL, index);
|
||||||
index = [theIndexes indexLessThanIndex:index];
|
index = [theIndexes indexLessThanIndex:index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||