Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
675f32b10f | ||
|
|
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-workspace
|
||||
*.tm_properties
|
||||
*.idea
|
||||
@@ -216,7 +216,7 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
|
||||
}
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(applicationShouldTerminate:)])
|
||||
_implementedDelegateMethods |= CPApplicationDelegate_applicationShouldTerminate_
|
||||
_implementedDelegateMethods |= CPApplicationDelegate_applicationShouldTerminate_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(applicationShouldTerminateMessage:)])
|
||||
_implementedDelegateMethods |= CPApplicationDelegate_applicationShouldTerminateMessage_
|
||||
|
||||
@@ -563,7 +563,7 @@
|
||||
*/
|
||||
- (BOOL)setSelectionIndexes:(CPIndexSet)indexes
|
||||
{
|
||||
[self _selectionWillChange]
|
||||
[self _selectionWillChange];
|
||||
var r = [self __setSelectionIndexes:indexes avoidEmpty:NO];
|
||||
[self _selectionDidChange];
|
||||
return r;
|
||||
|
||||
@@ -378,7 +378,7 @@ CPButtonImageOffset = 3.0;
|
||||
|
||||
- (void)setImage:(CPImage)anImage
|
||||
{
|
||||
[self setValue:anImage forThemeAttribute:@"image"];
|
||||
[self setValue:anImage forThemeAttribute:@"image" inState:CPThemeStateNormal];
|
||||
}
|
||||
|
||||
- (CPImage)image
|
||||
|
||||
@@ -56,7 +56,7 @@ var CPCollectionViewDelegate_collectionView_acceptDrop_index_dropOperation_
|
||||
- (CPData)collectionView:(CPCollectionView)collectionView dataForItemsAtIndexes:(CPIndexSet)indices forType:(CPString)aType;
|
||||
- (CPDragOperation)collectionView:(CPCollectionView)collectionView validateDrop:(id)draggingInfo proposedIndex:(CPInteger)proposedDropIndex dropOperation:(CPCollectionViewDropOperation)proposedDropOperation;
|
||||
- (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;
|
||||
|
||||
@end
|
||||
|
||||
@@ -103,7 +103,8 @@ var cachedBlackColor,
|
||||
@"alternate-selected-control-color": [CPNull null],
|
||||
@"secondary-selected-control-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
|
||||
|
||||
#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
|
||||
var CPColorComponentsKey = @"CPColorComponentsKey",
|
||||
CPColorPatternImageKey = @"CPColorPatternImageKey";
|
||||
var CPColorComponentsKey = @"CPColorComponentsKey",
|
||||
CPColorPatternImageKey = @"CPColorPatternImageKey",
|
||||
CPColorCssDictionaryKey = @"CPColorCssDictionaryKey",
|
||||
CPColorCssBeforeDictionaryKey = @"CPColorCssBeforeDictionaryKey",
|
||||
CPColorCssAfterDictionaryKey = @"CPColorCssAfterDictionaryKey";
|
||||
/// @endcond
|
||||
|
||||
@implementation CPColor (CPCoding)
|
||||
@@ -891,6 +1104,10 @@ var CPColorComponentsKey = @"CPColorComponentsKey",
|
||||
{
|
||||
if ([aCoder containsValueForKey: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
|
||||
self = [self _initWithRGBA:[aCoder decodeObjectForKey:CPColorComponentsKey]];
|
||||
|
||||
@@ -907,6 +1124,12 @@ var CPColorComponentsKey = @"CPColorComponentsKey",
|
||||
{
|
||||
if (_patternImage)
|
||||
[aCoder encodeObject:_patternImage forKey:CPColorPatternImageKey];
|
||||
else if (_cssDictionary)
|
||||
{
|
||||
[aCoder encodeObject:_cssDictionary forKey:CPColorCssDictionaryKey];
|
||||
[aCoder encodeObject:_cssBeforeDictionary forKey:CPColorCssBeforeDictionaryKey];
|
||||
[aCoder encodeObject:_cssAfterDictionary forKey:CPColorCssAfterDictionaryKey];
|
||||
}
|
||||
else
|
||||
[aCoder encodeObject:_components forKey:CPColorComponentsKey];
|
||||
|
||||
@@ -1247,7 +1470,8 @@ var patternColorsFromPattern = function(pattern, attributes, imageFactory)
|
||||
bottomHeight,
|
||||
centerWidthHeight,
|
||||
centerIsNil,
|
||||
numParts;
|
||||
numParts,
|
||||
isVertical;
|
||||
|
||||
// positions are mandatory
|
||||
if (pattern.indexOf("{position}") < 0)
|
||||
|
||||
@@ -247,7 +247,7 @@
|
||||
_blackWheelImage = new Image();
|
||||
_blackWheelImage.src = path;
|
||||
_blackWheelImage.style.opacity = "0";
|
||||
_blackWheelImage.style.filter = "alpha(opacity=0)"
|
||||
_blackWheelImage.style.filter = "alpha(opacity=0)";
|
||||
_blackWheelImage.style.position = "absolute";
|
||||
|
||||
_DOMElement.appendChild(_wheelImage);
|
||||
|
||||
@@ -1057,14 +1057,21 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
@end
|
||||
|
||||
@implementation CPControl (CPTrackingArea)
|
||||
{
|
||||
CPTrackingArea _controlTrackingArea;
|
||||
}
|
||||
|
||||
- (void)updateTrackingAreas
|
||||
{
|
||||
[self removeAllTrackingAreas];
|
||||
[self addTrackingArea:[[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingMouseEnteredAndExited | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
|
||||
owner:self
|
||||
userInfo:nil]];
|
||||
if (_controlTrackingArea)
|
||||
[self removeTrackingArea:_controlTrackingArea];
|
||||
|
||||
_controlTrackingArea = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
|
||||
options:CPTrackingMouseEnteredAndExited | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
|
||||
owner:self
|
||||
userInfo:nil];
|
||||
[self addTrackingArea:_controlTrackingArea];
|
||||
[super updateTrackingAreas];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -352,8 +352,8 @@ CPEraDatePickerElementFlag = 0x0100;
|
||||
if (_implementedCDatePickerDelegateMethods & CPDatePicker_validateProposedDateValue_timeInterval)
|
||||
{
|
||||
// constrain timeInterval also
|
||||
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 aStartDateRef = function(x){if (typeof x == 'undefined') return aDateValue; aDateValue = x;};
|
||||
var aTimeIntervalRef = function(x){if (typeof x == 'undefined') return aTimeInterval; aTimeInterval = x;};
|
||||
|
||||
[_delegate datePicker:self validateProposedDateValue:aStartDateRef timeInterval:aTimeIntervalRef];
|
||||
}
|
||||
@@ -694,7 +694,7 @@ var CPDatePickerModeKey = @"CPDatePickerModeKey",
|
||||
[aCoder encodeInt:_datePickerStyle forKey:CPDatePickerStyleKey];
|
||||
[aCoder encodeInt:_datePickerElements forKey:CPDatePickerElementsKey];
|
||||
[aCoder encodeObject:_minDate forKey:CPMinDateKey];
|
||||
[aCoder encodeObject:_maxDate forKey:CPMaxDateKey]
|
||||
[aCoder encodeObject:_maxDate forKey:CPMaxDateKey];
|
||||
[aCoder encodeObject:_dateValue forKey:CPDateValueKey];;
|
||||
[aCoder encodeObject:_textFont forKey:CPTextFontKey];
|
||||
[aCoder encodeObject:_locale forKey:CPLocaleKey];
|
||||
|
||||
@@ -85,7 +85,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
{
|
||||
if (self = [super initWithFrame:aFrame])
|
||||
{
|
||||
_datePicker = aDatePicker
|
||||
_datePicker = aDatePicker;
|
||||
[self _init];
|
||||
}
|
||||
|
||||
@@ -435,7 +435,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
break;
|
||||
|
||||
default:
|
||||
return CPShortWeekDayNameArrayEn
|
||||
return CPShortWeekDayNameArrayEn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -464,7 +464,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
break;
|
||||
|
||||
default:
|
||||
return CPShortMonthNameArrayEn
|
||||
return CPShortMonthNameArrayEn;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -526,11 +526,11 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
var dayLabel = _dayLabels[i];
|
||||
|
||||
[dayLabel setStringValue:dayNames[i]];
|
||||
[dayLabel sizeToFit]
|
||||
[dayLabel sizeToFit];
|
||||
[dayLabel setFrameOrigin:CGPointMake(sizeTileWidth * (i + 1) - sizeTileWidth / 2 - [dayLabel frameSize].width / 2, 23)];
|
||||
|
||||
if (i == 0)
|
||||
firstDayTileX = sizeTileWidth * (i + 1) - sizeTileWidth / 2 - [dayLabel frameSize].width / 2
|
||||
firstDayTileX = sizeTileWidth * (i + 1) - sizeTileWidth / 2 - [dayLabel frameSize].width / 2;
|
||||
}
|
||||
|
||||
// Title
|
||||
@@ -769,7 +769,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
tileDate = [[tile date] copy],
|
||||
selected = NO;
|
||||
|
||||
[tileDate _resetToMidnight]
|
||||
[tileDate _resetToMidnight];
|
||||
|
||||
if (aStartDate)
|
||||
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
|
||||
if (!isBorderPair)
|
||||
y += 0.5
|
||||
y += 0.5;
|
||||
|
||||
CGContextMoveToPoint(context, 0, 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
|
||||
if (!isBorderPair)
|
||||
x += 0.5
|
||||
x += 0.5;
|
||||
|
||||
CGContextMoveToPoint(context, x, 0);
|
||||
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
|
||||
if (!isBorderPair)
|
||||
y += 0.5
|
||||
y += 0.5;
|
||||
|
||||
CGContextMoveToPoint(context, 0, y);
|
||||
CGContextAddLineToPoint(context, [self bounds].size.width, y);
|
||||
@@ -897,7 +897,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
_clickDate = [dateTile copy];
|
||||
_dragDate = nil;
|
||||
_indexDayTile = -1;
|
||||
_eventDragged = nil
|
||||
_eventDragged = nil;
|
||||
|
||||
_datePicker._invokedByUserEvent = YES;
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ var RADIANS = Math.PI / 180;
|
||||
if ([_datePicker _isAmericanFormat])
|
||||
{
|
||||
if (dateValue.getHours() > 11)
|
||||
[_PMAMTextField setStringValue:@"PM"]
|
||||
[_PMAMTextField setStringValue:@"PM"];
|
||||
else
|
||||
[_PMAMTextField setStringValue:@"AM"];
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ var CPZeroKeyCode = 48,
|
||||
{
|
||||
if (self = [super initWithFrame:aFrame])
|
||||
{
|
||||
_datePicker = aDatePicker
|
||||
_datePicker = aDatePicker;
|
||||
[self _init];
|
||||
}
|
||||
return self;
|
||||
|
||||
@@ -66,7 +66,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
CPWindow _window;
|
||||
Number _windowNumber;
|
||||
CPString _characters;
|
||||
CPString _charactersIgnoringModifiers
|
||||
CPString _charactersIgnoringModifiers;
|
||||
BOOL _isARepeat;
|
||||
unsigned _keyCode;
|
||||
DOMEvent _DOMEvent;
|
||||
@@ -642,7 +642,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
- (CPTrackingArea)trackingArea
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ following:
|
||||
if (normalizedFaces === _CPFontSystemFontFace)
|
||||
return;
|
||||
|
||||
[self _invalidateSystemFontCache]
|
||||
[self _invalidateSystemFontCache];
|
||||
_CPFontSystemFontFace = aFace;
|
||||
}
|
||||
|
||||
|
||||
@@ -246,7 +246,7 @@ function CPAppKitImage(aFilename, aSize)
|
||||
var canvas = document.createElement("canvas"),
|
||||
ctx = canvas.getContext("2d");
|
||||
|
||||
canvas.width = _image.width,
|
||||
canvas.width = _image.width;
|
||||
canvas.height = _image.height;
|
||||
|
||||
ctx.drawImage(_image, 0, 0);
|
||||
@@ -509,6 +509,212 @@ function CPAppKitImage(aFilename, aSize)
|
||||
|
||||
@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)
|
||||
|
||||
/*!
|
||||
@@ -518,7 +724,10 @@ function CPAppKitImage(aFilename, aSize)
|
||||
*/
|
||||
- (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 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
|
||||
|
||||
@@ -98,10 +98,32 @@ var CPImageViewEmptyPlaceholderImage = nil;
|
||||
- (void)_createDOMImageElement
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
if (_DOMImageElement)
|
||||
return;
|
||||
var image = [self objectValue],
|
||||
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.left = "0px";
|
||||
_DOMImageElement.style.top = "0px";
|
||||
@@ -150,10 +172,15 @@ var CPImageViewEmptyPlaceholderImage = nil;
|
||||
var newImage = [self objectValue];
|
||||
|
||||
#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
|
||||
|
||||
var size = [newImage size];
|
||||
|
||||
@@ -857,7 +857,7 @@ var CPBindingOperationAnd = 0,
|
||||
- (id)initWithName:(CPString)aName
|
||||
{
|
||||
if (self = [super init])
|
||||
_name = aName
|
||||
_name = aName;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -292,7 +292,7 @@ CPRatingLevelIndicatorStyle = 3;
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)setWarningValue:(double)warningValue;
|
||||
- (void)setWarningValue:(double)warningValue
|
||||
{
|
||||
if (_warningValue === warningValue)
|
||||
return;
|
||||
@@ -301,7 +301,7 @@ CPRatingLevelIndicatorStyle = 3;
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)setCriticalValue:(double)criticalValue;
|
||||
- (void)setCriticalValue:(double)criticalValue
|
||||
{
|
||||
if (_criticalValue === criticalValue)
|
||||
return;
|
||||
|
||||
@@ -505,7 +505,7 @@ CPOffState
|
||||
if (_submenu)
|
||||
{
|
||||
[_submenu setSupermenu:_menu];
|
||||
[_submenu setTitle:[self title]]
|
||||
[_submenu setTitle:[self title]];
|
||||
|
||||
[self setTarget:_menu];
|
||||
[self setAction:@selector(submenuAction:)];
|
||||
@@ -843,7 +843,7 @@ CPControlKeyMask
|
||||
[item setTarget:_target];
|
||||
[item setAction:_action];
|
||||
[item setEnabled:_isEnabled];
|
||||
[item setHidden:_isHidden]
|
||||
[item setHidden:_isHidden];
|
||||
[item setTag:_tag];
|
||||
[item setState:_state];
|
||||
[item setImage:_image];
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
@"menu-item-selection-color": [CPNull null],
|
||||
@"menu-item-text-shadow-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-highlighted-image": [CPNull null],
|
||||
@"menu-item-default-on-state-image": [CPNull null],
|
||||
@@ -124,7 +125,7 @@
|
||||
- (CPColor)textColor
|
||||
{
|
||||
if (![_menuItem isEnabled])
|
||||
return [CPColor lightGrayColor];
|
||||
return [self valueForThemeAttribute:@"menu-item-disabled-text-color"];
|
||||
|
||||
if (_highlighted)
|
||||
return [CPColor whiteColor];
|
||||
|
||||
@@ -1923,7 +1923,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
|
||||
|
||||
while (index !== CPNotFound)
|
||||
{
|
||||
[items addObject:[_outlineView itemAtRow:index]]
|
||||
[items addObject:[_outlineView itemAtRow:index]];
|
||||
index = [theIndexes indexGreaterThanIndex:index];
|
||||
}
|
||||
|
||||
@@ -1957,7 +1957,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
|
||||
- (void)_parentItemForDropOperation:(CPTableViewDropOperation)theDropOperation row:(CPInteger)theRow offset:(CGPoint)theOffset
|
||||
{
|
||||
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];
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ CPURLPboardType = @"CPURLPboardType";
|
||||
CPImagesPboardType = @"CPImagesPboardType";
|
||||
CPVideosPboardType = @"CPVideosPboardType";
|
||||
CPRTFPboardType = @"CPRTFPboardType";
|
||||
_CPSmartPboardType = @"_CPSmartPboardType";
|
||||
|
||||
UTF8PboardType = @"public.utf8-plain-text";
|
||||
|
||||
|
||||
@@ -463,13 +463,13 @@ var CPProgressIndicatorSpinningStyleColors = [];
|
||||
var midX = CGRectGetMidX(rect),
|
||||
midY = CGRectGetMidY(rect),
|
||||
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);
|
||||
CGContextSetLineWidth(context, borderSize);
|
||||
CGContextSetFillColor(context, [self currentValueForThemeAttribute:@"circular-color"])
|
||||
CGContextSetFillColor(context, [self currentValueForThemeAttribute:@"circular-color"]);
|
||||
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);
|
||||
CGContextClosePath(context);
|
||||
CGContextFillPath(context);
|
||||
@@ -478,7 +478,7 @@ var CPProgressIndicatorSpinningStyleColors = [];
|
||||
else if ([self doubleValue] == [self maxValue])
|
||||
{
|
||||
CGContextBeginPath(context);
|
||||
CGContextSetFillColor(context, [self currentValueForThemeAttribute:@"circular-color"])
|
||||
CGContextSetFillColor(context, [self currentValueForThemeAttribute:@"circular-color"]);
|
||||
CGContextAddEllipseInRect(context, rect);
|
||||
CGContextClosePath(context);
|
||||
CGContextFillPath(context);
|
||||
|
||||
@@ -209,8 +209,7 @@
|
||||
|
||||
- (void)_reconfigureSubviews
|
||||
{
|
||||
var ruleItems,
|
||||
criteria,
|
||||
var criteria,
|
||||
repObject,
|
||||
menuItem,
|
||||
ruleView,
|
||||
|
||||
@@ -35,6 +35,11 @@
|
||||
CPArray _allowedFileTypes @accessors(property=allowedFileTypes);
|
||||
}
|
||||
|
||||
+ (CPURL)proposedFileURLWithDocumentName:(CPString)aDocumentName
|
||||
{
|
||||
return [CPURL URLWithString:aDocumentName];
|
||||
}
|
||||
|
||||
+ (id)savePanel
|
||||
{
|
||||
return [[CPSavePanel alloc] init];
|
||||
|
||||
@@ -1253,7 +1253,7 @@ Notifies the delegate when the scroll view has finished scrolling.
|
||||
}
|
||||
|
||||
if (_timerScrollersHide)
|
||||
[_timerScrollersHide invalidate]
|
||||
[_timerScrollersHide invalidate];
|
||||
|
||||
_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,
|
||||
slotSize = height - effectiveDecrementLineHeight - effectiveIncrementLineHeight,
|
||||
minimumKnobLength = [self currentValueForThemeAttribute:"minimum-knob-length"],
|
||||
knobVerticalInset = knobInset.top + knobInset.bottom,
|
||||
knobWidth = width - knobInset.left - knobInset.right,
|
||||
knobHeight = MAX(minimumKnobLength, (slotSize * _knobProportion)),
|
||||
knobLocation = effectiveDecrementLineHeight + (slotSize - knobHeight) * [self floatValue];
|
||||
knobHeight = MAX(minimumKnobLength, ((slotSize - knobVerticalInset) * _knobProportion)),
|
||||
knobLocation = effectiveDecrementLineHeight + (slotSize - knobHeight - knobVerticalInset) * [self floatValue] + knobInset.top;
|
||||
|
||||
_partRects[CPScrollerDecrementPage] = CGRectMake(0.0, effectiveDecrementLineHeight, width, knobLocation - effectiveDecrementLineHeight);
|
||||
_partRects[CPScrollerKnob] = CGRectMake(knobInset.left, knobLocation, knobWidth, knobHeight);
|
||||
@@ -409,9 +410,10 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
|
||||
effectiveIncrementLineWidth = incrementLineSize.width + trackInset.right,
|
||||
slotSize = width - effectiveDecrementLineWidth - effectiveIncrementLineWidth,
|
||||
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,
|
||||
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[CPScrollerKnob] = CGRectMake(knobLocation, knobInset.top, knobWidth, knobHeight);
|
||||
@@ -460,9 +462,6 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
|
||||
*/
|
||||
- (void)fadeOut
|
||||
{
|
||||
if ([self hasThemeState:CPThemeStateScrollViewLegacy])
|
||||
return;
|
||||
|
||||
[_animationScroller startAnimation];
|
||||
}
|
||||
|
||||
@@ -765,7 +764,10 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
|
||||
if (_timerFadeOut)
|
||||
[_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-pressed": [CPNull null],
|
||||
@"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
|
||||
{
|
||||
if (self = [super initWithFrame:frame])
|
||||
@@ -87,10 +96,6 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
|
||||
_recentsAutosaveName = nil;
|
||||
|
||||
[self _init];
|
||||
#if PLATFORM(DOM)
|
||||
_cancelButton._DOMElement.style.cursor = "default";
|
||||
_searchButton._DOMElement.style.cursor = "default";
|
||||
#endif
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -177,7 +182,7 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
|
||||
- (void)resetSearchButton
|
||||
{
|
||||
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 setImageScaling:CPImageScaleAxesIndependently];
|
||||
@@ -246,8 +251,9 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
|
||||
|
||||
if (_searchButton)
|
||||
{
|
||||
var searchBounds = [self searchButtonRectForBounds:bounds];
|
||||
leftOffset = CGRectGetMaxX(searchBounds) + 2;
|
||||
var searchBounds = [self searchButtonRectForBounds:bounds],
|
||||
rightMargin = [self currentValueForThemeAttribute:@"search-right-margin"];
|
||||
leftOffset = CGRectGetMaxX(searchBounds) + rightMargin;
|
||||
}
|
||||
|
||||
if (_cancelButton)
|
||||
@@ -386,9 +392,9 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
|
||||
*/
|
||||
- (void)setRecentSearches:(CPArray)searches
|
||||
{
|
||||
var max = MIN([self maximumRecents], [searches count]),
|
||||
searches = [searches subarrayWithRange:CPMakeRange(0, max)];
|
||||
var max = MIN([self maximumRecents], [searches count]);
|
||||
|
||||
searches = [searches subarrayWithRange:CPMakeRange(0, max)];
|
||||
_recentSearches = searches;
|
||||
[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,
|
||||
displays a single disabled item:
|
||||
|
||||
No Recent Searches
|
||||
Provides the common case items for a recent searches menu.
|
||||
|
||||
If there are 1 more recent searches, it displays:
|
||||
|
||||
Recent Searches
|
||||
recent search 1
|
||||
recent search 2
|
||||
etc.
|
||||
Clear
|
||||
---------------------
|
||||
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
|
||||
before, a separator will automatically be placed before the default template item.
|
||||
@@ -568,6 +571,13 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
|
||||
var template = [[CPMenu alloc] init],
|
||||
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"
|
||||
action:nil
|
||||
keyEquivalent:@""];
|
||||
@@ -582,20 +592,6 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
|
||||
[item setTarget:self];
|
||||
[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;
|
||||
}
|
||||
|
||||
@@ -608,6 +604,8 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
|
||||
countOfRecents = [_recentSearches count],
|
||||
numberOfItems = [_searchMenuTemplate numberOfItems];
|
||||
|
||||
[menu setAutoenablesItems:NO];
|
||||
|
||||
for (var i = 0; i < numberOfItems; i++)
|
||||
{
|
||||
var item = [[_searchMenuTemplate itemAtIndex:i] copy];
|
||||
@@ -631,7 +629,6 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
|
||||
var recentItem = [[CPMenuItem alloc] initWithTitle:[_recentSearches objectAtIndex:recentIndex]
|
||||
action:itemAction
|
||||
keyEquivalent:[item keyEquivalent]];
|
||||
[recentItem setIndentationLevel:1];
|
||||
[item setTarget:self];
|
||||
[menu addItem:recentItem];
|
||||
}
|
||||
@@ -689,7 +686,7 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
|
||||
|
||||
- (void)_showMenu
|
||||
{
|
||||
if (_searchMenu === nil || [_searchMenu numberOfItems] === 0 || ![self isEnabled])
|
||||
if (_searchMenu === nil || [_searchMenu numberOfItems] === 0 || ![self isEnabled] || ([_recentSearches count] === 0))
|
||||
return;
|
||||
|
||||
var aFrame = [[self superview] convertRect:[self frame] toView:nil],
|
||||
@@ -771,8 +768,75 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
|
||||
_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
|
||||
|
||||
#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",
|
||||
CPSendsWholeSearchStringKey = @"CPSendsWholeSearchStringKey",
|
||||
CPSendsSearchStringImmediatelyKey = @"CPSendsSearchStringImmediatelyKey",
|
||||
@@ -825,3 +889,44 @@ var CPRecentsAutosaveNameKey = @"CPRecentsAutosaveNameKey",
|
||||
}
|
||||
|
||||
@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],
|
||||
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;
|
||||
|
||||
if (_trackingSegment === [self testSegment:location])
|
||||
{
|
||||
if (_trackingMode == CPSegmentSwitchTrackingSelectAny)
|
||||
case CPLeftMouseDown:
|
||||
|
||||
var trackingSegment = [self testSegment:location];
|
||||
if (trackingSegment > CPNotFound && [self isEnabledForSegment:trackingSegment])
|
||||
{
|
||||
[self setSelected:![self isSelectedForSegment:_trackingSegment] forSegment:_trackingSegment];
|
||||
|
||||
// With ANY, _selectedSegment means last pressed.
|
||||
_selectedSegment = _trackingSegment;
|
||||
_trackingHighlighted = YES;
|
||||
_trackingSegment = trackingSegment;
|
||||
[self drawSegmentBezel:_trackingSegment highlight:YES];
|
||||
}
|
||||
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];
|
||||
|
||||
_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];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
[CPApp setTarget:self selector:@selector(trackSegment:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
|
||||
|
||||
@@ -117,6 +117,7 @@ var ShouldSuppressResizeNotifications = 1,
|
||||
CPArray _DOMDividerElements;
|
||||
CPString _dividerImagePath;
|
||||
int _drawingDivider;
|
||||
BOOL _isTracking;
|
||||
|
||||
CPString _autosaveName;
|
||||
BOOL _shouldAutosave;
|
||||
@@ -158,6 +159,7 @@ var ShouldSuppressResizeNotifications = 1,
|
||||
_buttonBars = [];
|
||||
|
||||
_shouldAutosave = YES;
|
||||
_isTracking = NO;
|
||||
|
||||
[self _setVertical:YES];
|
||||
}
|
||||
@@ -213,6 +215,9 @@ var ShouldSuppressResizeNotifications = 1,
|
||||
[_subviews[index] setFrame:CGRectMake(0, ROUND((eachSize + dividerThickness) * index), frame.size.width, eachSize)];
|
||||
}
|
||||
|
||||
if (_DOMDividerElements[_drawingDivider])
|
||||
[self _setupDOMDivider];
|
||||
|
||||
[self setNeedsDisplay:YES];
|
||||
[self _postNotificationDidResize];
|
||||
|
||||
@@ -363,9 +368,9 @@ var ShouldSuppressResizeNotifications = 1,
|
||||
_DOMDividerElements[_drawingDivider].style.backgroundRepeat = "repeat";
|
||||
|
||||
CPDOMDisplayServerAppendChild(_DOMElement, _DOMDividerElements[_drawingDivider]);
|
||||
[self _setupDOMDivider];
|
||||
}
|
||||
|
||||
[self _setupDOMDivider];
|
||||
CPDOMDisplayServerSetStyleLeftTop(_DOMDividerElements[_drawingDivider], NULL, CGRectGetMinX(aRect), CGRectGetMinY(aRect));
|
||||
CPDOMDisplayServerSetStyleSize(_DOMDividerElements[_drawingDivider], CGRectGetWidth(aRect), CGRectGetHeight(aRect));
|
||||
#endif
|
||||
@@ -452,17 +457,26 @@ var ShouldSuppressResizeNotifications = 1,
|
||||
return nil;
|
||||
|
||||
var point = [self convertPoint:aPoint fromView:[self superview]],
|
||||
count = [_subviews count] - 1;
|
||||
dividerIndex = [self _dividerAtPoint:point];
|
||||
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
if ([self cursorAtPoint:point hitDividerAtIndex:i])
|
||||
return self;
|
||||
}
|
||||
if (dividerIndex !== CPNotFound)
|
||||
return self;
|
||||
|
||||
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.
|
||||
@param anEvent the input event
|
||||
@@ -473,12 +487,13 @@ var ShouldSuppressResizeNotifications = 1,
|
||||
|
||||
if (type == CPLeftMouseUp)
|
||||
{
|
||||
// We disabled autosaving during tracking.
|
||||
_shouldAutosave = YES;
|
||||
|
||||
if (_currentDivider != CPNotFound)
|
||||
if ([anEvent clickCount] == 2 || (_isTracking && _currentDivider != CPNotFound))
|
||||
{
|
||||
// We disabled autosaving during tracking.
|
||||
_shouldAutosave = YES;
|
||||
_currentDivider = CPNotFound;
|
||||
_isTracking = NO;
|
||||
|
||||
[self _autosave];
|
||||
[self _updateResizeCursor:anEvent];
|
||||
}
|
||||
@@ -488,59 +503,55 @@ var ShouldSuppressResizeNotifications = 1,
|
||||
|
||||
if (type == CPLeftMouseDown)
|
||||
{
|
||||
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil],
|
||||
count = [_subviews count] - 1;
|
||||
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
||||
_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],
|
||||
startPosition = frame.origin[_originComponent] + frame.size[_sizeComponent];
|
||||
var minPosition = [self minPossiblePositionOfDividerAtIndex:_currentDivider],
|
||||
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 &&
|
||||
[self _delegateRespondsToSplitViewCanCollapseSubview] &&
|
||||
[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];
|
||||
}
|
||||
}
|
||||
if ([self isSubviewCollapsed:_subviews[_currentDivider]])
|
||||
[self setPosition:preCollapsePosition ? preCollapsePosition : (minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:_currentDivider];
|
||||
else
|
||||
{
|
||||
_currentDivider = i;
|
||||
_initialOffset = startPosition - point[_originComponent];
|
||||
|
||||
// Don't autosave during a resize. We'll wait until it's done.
|
||||
_shouldAutosave = NO;
|
||||
[self _postNotificationWillResize];
|
||||
}
|
||||
[self setPosition:minPosition ofDividerAtIndex:_currentDivider];
|
||||
}
|
||||
else if ([self _sendDelegateSplitViewCanCollapseSubview:_subviews[_currentDivider + 1]] && [self _sendDelegateSplitViewShouldCollapseSubview:_subviews[_currentDivider + 1] forDoubleClickOnDividerAtIndex:_currentDivider])
|
||||
{
|
||||
if ([self isSubviewCollapsed:_subviews[_currentDivider + 1]])
|
||||
[self setPosition:preCollapsePosition ? preCollapsePosition : (minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:_currentDivider];
|
||||
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)
|
||||
{
|
||||
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];
|
||||
|
||||
[self setPosition:(point[_originComponent] + _initialOffset) ofDividerAtIndex:_currentDivider];
|
||||
@@ -553,8 +564,11 @@ var ShouldSuppressResizeNotifications = 1,
|
||||
|
||||
- (void)mouseDown:(CPEvent)anEvent
|
||||
{
|
||||
// FIXME: This should not trap events if not on a divider!
|
||||
[self trackDivider:anEvent];
|
||||
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil],
|
||||
dividerIndex = [self _dividerAtPoint:point];
|
||||
|
||||
if (dividerIndex !== CPNotFound)
|
||||
[self trackDivider:anEvent];
|
||||
}
|
||||
|
||||
- (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
|
||||
|
||||
@implementation CPSplitView (CPTrackingArea)
|
||||
{
|
||||
CPMutableArray _splitViewTrackingAreas;
|
||||
}
|
||||
|
||||
- (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;
|
||||
|
||||
|
||||
_splitViewTrackingAreas = @[];
|
||||
|
||||
for (var i = 0; i < _subviews.length - 1; i++)
|
||||
[self addTrackingArea:[[CPTrackingArea alloc] initWithRect:[self effectiveRectOfDividerAtIndex:i]
|
||||
options:options
|
||||
owner:self
|
||||
userInfo:nil]];
|
||||
{
|
||||
[_splitViewTrackingAreas addObject:[[CPTrackingArea alloc] initWithRect:[self effectiveRectOfDividerAtIndex:i]
|
||||
options:options
|
||||
owner:self
|
||||
userInfo:nil]];
|
||||
|
||||
[self addTrackingArea:_splitViewTrackingAreas[i]];
|
||||
}
|
||||
|
||||
[super updateTrackingAreas];
|
||||
}
|
||||
|
||||
- (void)cursorUpdate:(CPEvent)anEvent
|
||||
@@ -1438,6 +1469,7 @@ var CPSplitViewDelegateKey = "CPSplitViewDelegateKey",
|
||||
|
||||
_currentDivider = CPNotFound;
|
||||
_shouldAutosave = YES;
|
||||
_isTracking = NO;
|
||||
|
||||
_DOMDividerElements = [];
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ CPNoTabsLineBorder = 5; //Has no tabs and displays a line border.
|
||||
CPNoTabsNoBorder = 6; //Displays no tabs and no border.
|
||||
|
||||
@class _CPTabViewBox
|
||||
@class _CPSegmentedControl
|
||||
|
||||
var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
|
||||
CPTabViewShouldSelectTabViewItemSelector = 1 << 2,
|
||||
@@ -65,9 +66,9 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
|
||||
{
|
||||
CPArray _items;
|
||||
|
||||
CPSegmentedControl _tabs;
|
||||
_CPSegmentedControl _tabs;
|
||||
_CPTabViewBox _box;
|
||||
CPView _placeHolderView;
|
||||
CPView _placeholderView @accessors;
|
||||
|
||||
CPTabViewItem _selectedTabViewItem;
|
||||
|
||||
@@ -92,8 +93,8 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
|
||||
|
||||
- (void)_init
|
||||
{
|
||||
_tabs = [[CPSegmentedControl alloc] initWithFrame:CGRectMakeZero()];
|
||||
[_tabs setHitTests:NO];
|
||||
_tabs = [[_CPSegmentedControl alloc] initWithFrame:CGRectMakeZero()];
|
||||
[_tabs setTabView:self];
|
||||
[_tabs setSegments:[CPArray array]];
|
||||
|
||||
var height = [_tabs valueForThemeAttribute:@"min-size"].height;
|
||||
@@ -106,7 +107,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
|
||||
[self addSubview:_box];
|
||||
[self addSubview:_tabs];
|
||||
|
||||
_placeHolderView = nil;
|
||||
_placeholderView = nil;
|
||||
}
|
||||
|
||||
- (CPArray)items
|
||||
@@ -525,14 +526,6 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
|
||||
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
|
||||
{
|
||||
var horizontalCenterOfSelf = CGRectGetWidth([self bounds]) / 2,
|
||||
@@ -617,7 +610,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
|
||||
|
||||
- (CPBinder)binderForBinding:(CPString)aBinding
|
||||
{
|
||||
var cls = [[self class] _binderClassForBinding:aBinding]
|
||||
var cls = [[self class] _binderClassForBinding:aBinding];
|
||||
return [cls getBinding:aBinding forObject:self];
|
||||
}
|
||||
|
||||
@@ -652,17 +645,17 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
|
||||
|
||||
- (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()];
|
||||
[textField setTag:1000];
|
||||
[textField setTextColor:[CPColor whiteColor]];
|
||||
[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 sizeToFit];
|
||||
|
||||
@@ -672,7 +665,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
|
||||
|
||||
[textField setFrameOrigin:origin];
|
||||
|
||||
[self _displayItemView:_placeHolderView];
|
||||
[self _displayItemView:_placeholderView];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
@@ -887,3 +880,77 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
|
||||
}
|
||||
|
||||
@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])
|
||||
[self setMinWidth:width];
|
||||
else if (width > [self maxWidth])
|
||||
[self setMaxWidth:width]
|
||||
[self setMaxWidth:width];
|
||||
|
||||
if (_width !== width)
|
||||
[self setWidth:width];
|
||||
@@ -499,7 +499,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
*/
|
||||
- (void)setHidden:(BOOL)shouldBeHidden
|
||||
{
|
||||
shouldBeHidden = !!shouldBeHidden
|
||||
shouldBeHidden = !!shouldBeHidden;
|
||||
|
||||
if (_isHidden === shouldBeHidden)
|
||||
return;
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
var inset = [self currentValueForThemeAttribute:@"text-inset"],
|
||||
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 setFont:[self currentValueForThemeAttribute:@"font"]];
|
||||
[_textField setTextShadowColor:[self currentValueForThemeAttribute:@"text-shadow-color"]];
|
||||
@@ -461,21 +461,38 @@ var CPTableHeaderViewResizeZone = 3.0,
|
||||
@end
|
||||
|
||||
@implementation CPTableHeaderView (CPTrackingArea)
|
||||
{
|
||||
CPMutableArray _tableHeaderViewTrackingAreas;
|
||||
}
|
||||
|
||||
- (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;
|
||||
|
||||
if (!_tableView)
|
||||
return;
|
||||
|
||||
_tableHeaderViewTrackingAreas = @[];
|
||||
|
||||
for (var i = 0; i < _tableView._tableColumns.length; i++)
|
||||
[self addTrackingArea:[[CPTrackingArea alloc] initWithRect:[self _cursorRectForColumn:i]
|
||||
options:options
|
||||
owner:self
|
||||
userInfo:nil]];
|
||||
{
|
||||
[_tableHeaderViewTrackingAreas addObject:[[CPTrackingArea alloc] initWithRect:[self _cursorRectForColumn:i]
|
||||
options:options
|
||||
owner:self
|
||||
userInfo:nil]];
|
||||
|
||||
[self addTrackingArea:_tableHeaderViewTrackingAreas[i]];
|
||||
}
|
||||
|
||||
[super updateTrackingAreas];
|
||||
}
|
||||
|
||||
- (void)cursorUpdate:(CPEvent)anEvent
|
||||
|
||||
@@ -346,8 +346,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
+ (CPDictionary)themeAttributes
|
||||
{
|
||||
return @{
|
||||
@"alternating-row-colors": [CPNull null],
|
||||
@"grid-color": [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": [CPColor colorWithHexString:@"dce0e2"],
|
||||
@"grid-line-thickness": 1.0,
|
||||
@"highlighted-grid-color": [CPNull null],
|
||||
@"selection-color": [CPNull null],
|
||||
@@ -368,7 +368,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
@"dropview-above-border-color": [CPNull null],
|
||||
@"dropview-above-border-width": [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;
|
||||
|
||||
[self setUsesAlternatingRowBackgroundColors:NO];
|
||||
[self setAlternatingRowBackgroundColors:
|
||||
[[CPColor whiteColor], [CPColor colorWithRed:245.0 / 255.0 green:249.0 / 255.0 blue:252.0 / 255.0 alpha:1.0]]];
|
||||
[self setAlternatingRowBackgroundColors:[self valueForThemeAttribute:@"alternating-row-colors"]];
|
||||
|
||||
_tableColumns = [];
|
||||
_tableColumnRanges = [];
|
||||
@@ -401,10 +401,10 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
_intercellSpacing = CGSizeMake(3.0, 2.0);
|
||||
_rowHeight = [self valueForThemeAttribute:@"default-row-height"];
|
||||
|
||||
[self setGridColor:[CPColor colorWithHexString:@"dce0e2"]];
|
||||
[self setGridColor:[self valueForThemeAttribute:@"grid-color"]];
|
||||
[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]))]];
|
||||
|
||||
_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
|
||||
{
|
||||
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 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
|
||||
// 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)
|
||||
{
|
||||
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];
|
||||
}];
|
||||
@@ -3751,7 +3760,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
||||
{
|
||||
if (!dataViewsForRow)
|
||||
{
|
||||
dataViewsForRow = {}
|
||||
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],
|
||||
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];
|
||||
_startTrackingPoint = nil;
|
||||
|
||||
@@ -4896,7 +4907,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
||||
row = _retargetedDropRow;
|
||||
|
||||
if (row === nil)
|
||||
var row = [self _proposedRowAtPoint:location];
|
||||
row = [self _proposedRowAtPoint:location];
|
||||
|
||||
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];
|
||||
|
||||
[self _stopObservingFirstResponderForWindow:aWindow];
|
||||
[self _stopObservingFirstResponderForWindow:[self window]];
|
||||
|
||||
if (aWindow)
|
||||
[self _startObservingFirstResponderForWindow:aWindow];
|
||||
@@ -6107,7 +6118,6 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey",
|
||||
CPTableViewGridStyleMaskKey = @"CPTableViewGridStyleMaskKey",
|
||||
CPTableViewUsesAlternatingBackgroundKey = @"CPTableViewUsesAlternatingBackgroundKey",
|
||||
CPTableViewAlternatingRowColorsKey = @"CPTableViewAlternatingRowColorsKey",
|
||||
CPTableViewHeaderViewKey = @"CPTableViewHeaderViewKey",
|
||||
CPTableViewCornerViewKey = @"CPTableViewCornerViewKey",
|
||||
CPTableViewAutosaveNameKey = @"CPTableViewAutosaveNameKey",
|
||||
CPTableViewArchivedReusableViewsKey = @"CPTableViewArchivedReusableViewsKey";
|
||||
|
||||
@@ -33,11 +33,14 @@
|
||||
@import "CPView.j"
|
||||
|
||||
@global CPStringPboardType
|
||||
@global _CPSmartPboardType
|
||||
|
||||
@class CPAttributedString
|
||||
@class _CPRTFParser
|
||||
|
||||
@protocol CPTextDelegate <CPObject>
|
||||
|
||||
@optional
|
||||
- (BOOL)textShouldBeginEditing:(CPText)aTextObject;
|
||||
- (BOOL)textShouldEndEditing:(CPText)aTextObject;
|
||||
- (void)textDidBeginEditing:(CPNotification)aNotification;
|
||||
@@ -175,6 +178,11 @@ CPKernAttributeName = @"CPKernAttributeName";
|
||||
return stringForPasting;
|
||||
}
|
||||
|
||||
- (BOOL)_shouldUseSmartPasting
|
||||
{
|
||||
return parseInt([[CPPasteboard generalPasteboard] stringForType:_CPSmartPboardType], 10) > 0 || NO;
|
||||
}
|
||||
|
||||
- (void)paste:(id)sender
|
||||
{
|
||||
var stringForPasting = [self _stringForPasting];
|
||||
|
||||
@@ -331,7 +331,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
[CPTextFieldInputOwner keyUp:cappEvent];
|
||||
|
||||
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
||||
}
|
||||
};
|
||||
|
||||
CPTextFieldDOMPasswordInputElement.oninput = CPTextFieldInputFunction;
|
||||
CPTextFieldDOMPasswordInputElement.onblur = CPTextFieldBlurHandler;
|
||||
@@ -873,12 +873,18 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
if (!CPTextFieldInputDidBlur)
|
||||
CPTextFieldBlurHandler();
|
||||
|
||||
CPTextFieldInputDidBlur = NO;
|
||||
CPTextFieldInputResigning = NO;
|
||||
|
||||
if (element.parentNode == _DOMElement)
|
||||
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;
|
||||
|
||||
if (document.attachEvent)
|
||||
@@ -1034,7 +1040,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
[[self window] platformWindow]._DOMBodyElement.ondrag = CPTextFieldCachedDragFunction;
|
||||
[[self window] platformWindow]._DOMBodyElement.onselectstart = CPTextFieldCachedSelectStartFunction;
|
||||
|
||||
CPTextFieldCachedSelectStartFunction = nil
|
||||
CPTextFieldCachedSelectStartFunction = nil;
|
||||
CPTextFieldCachedDragFunction = nil;
|
||||
}
|
||||
|
||||
@@ -1237,7 +1243,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
return;
|
||||
|
||||
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];
|
||||
}
|
||||
@@ -1784,7 +1790,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
_implementedDelegateMethods = 0;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(control:didFailToFormatString:errorDescription:)])
|
||||
_implementedDelegateMethods |= CPTextFieldDelegate_control_didFailToFormatString_errorDescription_
|
||||
_implementedDelegateMethods |= CPTextFieldDelegate_control_didFailToFormatString_errorDescription_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(controlTextDidBeginEditing:)])
|
||||
_implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidBeginEditing_;
|
||||
@@ -2177,21 +2183,32 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
|
||||
@end
|
||||
|
||||
@implementation CPTextField (CPTrackingArea)
|
||||
{
|
||||
CPTrackingArea _textFieldTrackingArea;
|
||||
}
|
||||
|
||||
- (void)updateTrackingAreas
|
||||
{
|
||||
[self removeAllTrackingAreas];
|
||||
if (_textFieldTrackingArea)
|
||||
{
|
||||
[self removeTrackingArea:_textFieldTrackingArea];
|
||||
_textFieldTrackingArea = nil;
|
||||
}
|
||||
|
||||
if ([self isEnabled] && (_isEditable || _isSelectable))
|
||||
{
|
||||
var myBounds = CGRectMakeCopy([self bounds]),
|
||||
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)
|
||||
options:CPTrackingMouseEnteredAndExited | CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow
|
||||
owner:self
|
||||
userInfo:nil]];
|
||||
[self addTrackingArea:_textFieldTrackingArea];
|
||||
}
|
||||
|
||||
[super updateTrackingAreas];
|
||||
}
|
||||
|
||||
- (void)cursorUpdate:(CPEvent)anEvent
|
||||
|
||||
@@ -412,7 +412,7 @@ var _availableTraits= [@"Normal", @"Italic", @"Bold", @"Bold Italic"],
|
||||
return [_availableFonts count];
|
||||
|
||||
if (aBrowser === _traitBrowser)
|
||||
return [_availableTraits count]
|
||||
return [_availableTraits count];
|
||||
|
||||
return [_availableSizes count]
|
||||
}
|
||||
|
||||
@@ -1179,7 +1179,7 @@ var _objectsInRange = function(aList, aRange)
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
_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;
|
||||
origin.x += someAdvancements[i].width;
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ CPLineMovesUp = 4;
|
||||
@implementation CPTextContainer : CPObject
|
||||
{
|
||||
float _lineFragmentPadding @accessors(property=lineFragmentPadding);
|
||||
CGSize _size @accessors(property=containerSize)
|
||||
CGSize _size @accessors(property=containerSize);
|
||||
CPLayoutManager _layoutManager @accessors(property=layoutManager);
|
||||
CPTextView _textView @accessors(property=textView);
|
||||
BOOL _inResizing;
|
||||
@@ -168,10 +168,7 @@ CPLineMovesUp = 4;
|
||||
- (void)setTextView:(CPTextView)aTextView
|
||||
{
|
||||
if (_textView)
|
||||
{
|
||||
[self _removeAllLines];
|
||||
[_textView setTextContainer:nil];
|
||||
}
|
||||
|
||||
_textView = aTextView;
|
||||
|
||||
@@ -252,4 +249,4 @@ var CPTextContainerSizeKey = @"CPTextContainerSizeKey",
|
||||
[aCoder encodeObject:_layoutManager forKey:CPTextContainerLayoutManagerKey];
|
||||
}
|
||||
|
||||
@end
|
||||
@end
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
|
||||
@protocol CPTextViewDelegate <CPTextDelegate>
|
||||
|
||||
@optional
|
||||
- (BOOL)textView:(CPTextView)aTextView doCommandBySelector:(SEL)aSelector;
|
||||
- (BOOL)textView:(CPTextView)aTextView shouldChangeTextInRange:(CPRange)affectedCharRange replacementString:(CPString)replacementString;
|
||||
- (CPDictionary)textView:(CPTextView)textView shouldChangeTypingAttributes:(CPDictionary)oldTypingAttributes toAttributes:(CPDictionary)newTypingAttributes;
|
||||
@@ -94,13 +95,16 @@ CPSelectByWord = 1;
|
||||
CPSelectByParagraph = 2;
|
||||
|
||||
var kDelegateRespondsTo_textShouldBeginEditing = 1 << 0,
|
||||
kDelegateRespondsTo_textView_doCommandBySelector = 1 << 1,
|
||||
kDelegateRespondsTo_textView_willChangeSelectionFromCharacterRange_toCharacterRange = 1 << 2,
|
||||
kDelegateRespondsTo_textView_shouldChangeTextInRange_replacementString = 1 << 3,
|
||||
kDelegateRespondsTo_textView_shouldChangeTypingAttributes_toAttributes = 1 << 4,
|
||||
kDelegateRespondsTo_textView_textDidChange = 1 << 5,
|
||||
kDelegateRespondsTo_textView_didChangeSelection = 1 << 6,
|
||||
kDelegateRespondsTo_textView_didChangeTypingAttributes = 1 << 7;
|
||||
kDelegateRespondsTo_textShouldEndEditing = 1 << 1,
|
||||
kDelegateRespondsTo_textView_doCommandBySelector = 1 << 2,
|
||||
kDelegateRespondsTo_textView_willChangeSelectionFromCharacterRange_toCharacterRange = 1 << 3,
|
||||
kDelegateRespondsTo_textView_shouldChangeTextInRange_replacementString = 1 << 4,
|
||||
kDelegateRespondsTo_textView_shouldChangeTypingAttributes_toAttributes = 1 << 5,
|
||||
kDelegateRespondsTo_textView_textDidChange = 1 << 6,
|
||||
kDelegateRespondsTo_textView_didChangeSelection = 1 << 7,
|
||||
kDelegateRespondsTo_textView_didChangeTypingAttributes = 1 << 8,
|
||||
kDelegateRespondsTo_textView_textDidBeginEditing = 1 << 9,
|
||||
kDelegateRespondsTo_textView_textDidEndEditing = 1 << 10;
|
||||
|
||||
@class _CPCaret;
|
||||
|
||||
@@ -128,7 +132,6 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
CPSelectionGranularity _selectionGranularity @accessors(property=selectionGranularity);
|
||||
|
||||
CPSelectionGranularity _previousSelectionGranularity; // private
|
||||
CPSelectionGranularity _copySelectionGranularity; // private
|
||||
|
||||
CPTextContainer _textContainer @accessors(property=textContainer);
|
||||
CPTextStorage _textStorage @accessors(getter=textStorage);
|
||||
@@ -153,6 +156,10 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
CPTimer _scrollingTimer;
|
||||
|
||||
CPString _placeholderString;
|
||||
|
||||
BOOL _firstResponderButNotEditingYet;
|
||||
|
||||
CPRange _mouseDownOldSelection;
|
||||
}
|
||||
|
||||
+ (Class)_binderClassForBinding:(CPString)aBinding
|
||||
@@ -234,7 +241,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
_selectedTextAttributes = [CPMutableDictionary new];
|
||||
|
||||
_caret = [[_CPCaret alloc] initWithTextView:self];
|
||||
[_caret setRect:CGRectMake(0, 0, 1, 11)]
|
||||
[_caret setRect:CGRectMake(0, 0, 1, 11)];
|
||||
|
||||
var pboardTypes = [CPStringPboardType, CPColorDragType];
|
||||
|
||||
@@ -265,6 +272,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
|
||||
[super _removeObservers];
|
||||
[self _setObserveWindowKeyNotifications:NO];
|
||||
[self _removeDelegateObservers];
|
||||
}
|
||||
|
||||
- (void)_addObservers
|
||||
@@ -275,7 +283,53 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
[super _addObservers];
|
||||
[self _setObserveWindowKeyNotifications:YES];
|
||||
[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
|
||||
{
|
||||
if (!_observedClipView)
|
||||
@@ -359,7 +413,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
- (void)_windowDidResignKey:(CPNotification)aNotification
|
||||
{
|
||||
if (![[self window] isKeyWindow])
|
||||
[self resignFirstResponder];
|
||||
[self _resignFirstResponder];
|
||||
}
|
||||
|
||||
- (void)_windowDidBecomeKey:(CPNotification)aNotification
|
||||
@@ -373,7 +427,6 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
|
||||
- (void)copy:(id)sender
|
||||
{
|
||||
_copySelectionGranularity = _previousSelectionGranularity;
|
||||
[super copy:sender];
|
||||
|
||||
if (![self isRichText])
|
||||
@@ -387,6 +440,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
[pasteboard declareTypes:[CPStringPboardType, CPRTFPboardType] owner:nil];
|
||||
[pasteboard setString:stringForPasting._string forType:CPStringPboardType];
|
||||
[pasteboard setString:richData forType:CPRTFPboardType];
|
||||
[pasteboard setString:_previousSelectionGranularity + '' forType:_CPSmartPboardType];
|
||||
}
|
||||
|
||||
- (void)_pasteString:(id)stringForPasting
|
||||
@@ -394,7 +448,9 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
if (!stringForPasting)
|
||||
return;
|
||||
|
||||
if (_copySelectionGranularity > 0 && _selectionRange.location > 0)
|
||||
var shouldUseSmartPasting = [self _shouldUseSmartPasting];
|
||||
|
||||
if (shouldUseSmartPasting && _selectionRange.location > 0)
|
||||
{
|
||||
if (!_isWhitespaceCharacter([[_textStorage string] characterAtIndex:_selectionRange.location - 1]) &&
|
||||
_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];
|
||||
|
||||
if (_copySelectionGranularity > 0)
|
||||
if (shouldUseSmartPasting)
|
||||
{
|
||||
if (!_isWhitespaceCharacter([[_textStorage string] characterAtIndex:CPMaxRange(_selectionRange)]) &&
|
||||
!_isNewlineCharacter([[_textStorage string] characterAtIndex:MAX(0, _selectionRange.location - 1)]) &&
|
||||
@@ -471,17 +507,33 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
- (BOOL)becomeFirstResponder
|
||||
{
|
||||
[super becomeFirstResponder];
|
||||
_firstResponderButNotEditingYet = YES;
|
||||
[self _becomeFirstResponder];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)resignFirstResponder
|
||||
- (void)_resignFirstResponder
|
||||
{
|
||||
[self _reverseSetBinding];
|
||||
[_caret stopBlinking];
|
||||
[self setNeedsDisplay:YES];
|
||||
[_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;
|
||||
}
|
||||
@@ -498,6 +550,8 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
if (aDelegate === _delegate)
|
||||
return;
|
||||
|
||||
[self _removeDelegateObservers];
|
||||
|
||||
_delegateRespondsToSelectorMask = 0;
|
||||
_delegate = aDelegate;
|
||||
|
||||
@@ -512,12 +566,21 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
if ([_delegate respondsToSelector:@selector(textViewDidChangeTypingAttributes:)])
|
||||
_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:)])
|
||||
_delegateRespondsToSelectorMask |= kDelegateRespondsTo_textView_doCommandBySelector;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(textShouldBeginEditing:)])
|
||||
_delegateRespondsToSelectorMask |= kDelegateRespondsTo_textShouldBeginEditing;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(textShouldEndEditing:)])
|
||||
_delegateRespondsToSelectorMask |= kDelegateRespondsTo_textShouldEndEditing;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(textView:willChangeSelectionFromCharacterRange:toCharacterRange:)])
|
||||
_delegateRespondsToSelectorMask |= kDelegateRespondsTo_textView_willChangeSelectionFromCharacterRange_toCharacterRange;
|
||||
|
||||
@@ -526,6 +589,9 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(textView:shouldChangeTypingAttributes:toAttributes:)])
|
||||
_delegateRespondsToSelectorMask |= kDelegateRespondsTo_textView_shouldChangeTypingAttributes_toAttributes;
|
||||
|
||||
if (_superview)
|
||||
[self _addDelegateObservers];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -662,9 +728,21 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
- (void)didChangeText
|
||||
{
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPTextDidChangeNotification object:self];
|
||||
}
|
||||
|
||||
if (_delegateRespondsToSelectorMask & kDelegateRespondsTo_textView_textDidChange)
|
||||
[_delegate textDidChange:[[CPNotification alloc] initWithName:CPTextDidChangeNotification object:self userInfo:nil]];
|
||||
- (BOOL)_didBeginEditing
|
||||
{
|
||||
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
|
||||
@@ -672,7 +750,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
if (![self isEditable])
|
||||
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],
|
||||
string = isAttributed ? [aString string]:aString;
|
||||
|
||||
if (![self shouldChangeTextInRange:CPMakeRangeCopy(_selectionRange) replacementString:string])
|
||||
if (![self _didBeginEditing] || ![self shouldChangeTextInRange:CPMakeRangeCopy(_selectionRange) replacementString:string])
|
||||
return;
|
||||
|
||||
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
|
||||
{
|
||||
[_CPNativeInputManager cancelCurrentInputSessionIfNeeded];
|
||||
[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
|
||||
{
|
||||
[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
|
||||
{
|
||||
var maxRange = CPMakeRange(0, [_layoutManager numberOfCharacters]);
|
||||
var maxRange = CPMakeRange(0, [_layoutManager numberOfCharacters]),
|
||||
newSelectionRange;
|
||||
|
||||
range = CPIntersectionRange(maxRange, range);
|
||||
|
||||
if (!selecting && [self _delegateRespondsToWillChangeSelectionFromCharacterRangeToCharacterRange])
|
||||
{
|
||||
_selectionRange = [self _sendDelegateWillChangeSelectionFromCharacterRange:_selectionRange toCharacterRange:range];
|
||||
newSelectionRange = [self _sendDelegateWillChangeSelectionFromCharacterRange:_selectionRange toCharacterRange:range];
|
||||
}
|
||||
else
|
||||
{
|
||||
_selectionRange = CPMakeRangeCopy(range);
|
||||
_selectionRange = [self selectionRangeForProposedRange:_selectionRange granularity:[self selectionGranularity]];
|
||||
newSelectionRange = [self selectionRangeForProposedRange:range granularity:[self selectionGranularity]];
|
||||
}
|
||||
|
||||
if (_selectionRange.length)
|
||||
[_layoutManager invalidateDisplayForGlyphRange:_selectionRange];
|
||||
var isNewSelection = !CPEqualRanges(newSelectionRange, _selectionRange);
|
||||
|
||||
if (isNewSelection)
|
||||
_selectionRange = newSelectionRange;
|
||||
|
||||
if (newSelectionRange.length)
|
||||
{
|
||||
if (isNewSelection)
|
||||
[_layoutManager invalidateDisplayForGlyphRange:newSelectionRange];
|
||||
}
|
||||
else
|
||||
[self setNeedsDisplay:YES];
|
||||
|
||||
if (!selecting)
|
||||
{
|
||||
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]];
|
||||
|
||||
[[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];
|
||||
}
|
||||
|
||||
@@ -936,18 +1041,18 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
{
|
||||
var fraction = [],
|
||||
point = [self convertPoint:point fromView:nil];
|
||||
|
||||
|
||||
// convert to container coordinate
|
||||
point.x -= _textContainerOrigin.x;
|
||||
point.y -= _textContainerOrigin.y;
|
||||
|
||||
|
||||
var index = [_layoutManager glyphIndexForPoint:point inTextContainer:_textContainer fractionOfDistanceThroughGlyph:fraction];
|
||||
|
||||
|
||||
if (index === CPNotFound)
|
||||
index = [_layoutManager numberOfCharacters];
|
||||
else if (fraction[0] > 0.5)
|
||||
index++;
|
||||
|
||||
|
||||
return index;
|
||||
}
|
||||
- (CGPoint)_characterIndexFromEvent:(CPEvent)event
|
||||
@@ -970,9 +1075,9 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
|
||||
[_CPNativeInputManager cancelCurrentInputSessionIfNeeded];
|
||||
[_caret setVisibility:NO];
|
||||
|
||||
|
||||
_startTrackingLocation = [self _characterIndexFromEvent:event];
|
||||
|
||||
|
||||
var granularities = [CPNotFound, CPSelectByCharacter, CPSelectByWord, CPSelectByParagraph];
|
||||
[self setSelectionGranularity:granularities[[event clickCount]]];
|
||||
|
||||
@@ -985,20 +1090,20 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
placeholderFrame = CGRectIntersection([_layoutManager boundingRectForGlyphRange:placeholderRange inTextContainer:_textContainer], _frame),
|
||||
rangeToHide = CPMakeRange(0, _selectionRange.location - lineBeginningIndex),
|
||||
dragPlaceholder;
|
||||
|
||||
|
||||
// hide the left part of the first line of the selection that is not included
|
||||
[placeholderString addAttribute:CPForegroundColorAttributeName
|
||||
value:[CPColor colorWithRed:1 green:1 blue:1 alpha:0]
|
||||
range:rangeToHide];
|
||||
|
||||
|
||||
_movingSelection = CPMakeRange(_startTrackingLocation, 0);
|
||||
|
||||
|
||||
dragPlaceholder = [[CPTextView alloc] initWithFrame:placeholderFrame];
|
||||
[dragPlaceholder._textStorage replaceCharactersInRange:CPMakeRange(0, 0) withAttributedString:placeholderString];
|
||||
|
||||
[dragPlaceholder setBackgroundColor:[CPColor colorWithRed:1 green:1 blue:1 alpha:0]];
|
||||
[dragPlaceholder setAlphaValue:0.5];
|
||||
|
||||
|
||||
var stringForPasting = [_textStorage attributedSubstringFromRange:CPMakeRangeCopy(_selectionRange)],
|
||||
richData = [_CPRTFProducer produceRTF:stringForPasting documentAttributes:@{}],
|
||||
draggingPasteboard = [CPPasteboard pasteboardWithName:CPDragPboard];
|
||||
@@ -1013,17 +1118,19 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
pasteboard:draggingPasteboard
|
||||
source:self
|
||||
slideBack:YES];
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var setRange = CPMakeRange(_startTrackingLocation, 0);
|
||||
|
||||
|
||||
if ([event modifierFlags] & CPShiftKeyMask)
|
||||
setRange = _MakeRangeFromAbs(_startTrackingLocation < _MidRange(_selectionRange) ? CPMaxRange(_selectionRange) : _selectionRange.location, _startTrackingLocation);
|
||||
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
|
||||
|
||||
// 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];
|
||||
}
|
||||
|
||||
@@ -1039,7 +1146,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
|
||||
if (_movingSelection)
|
||||
return;
|
||||
|
||||
|
||||
var oldRange = [self selectedRange],
|
||||
index = [self _characterIndexFromEvent:event];
|
||||
|
||||
@@ -1066,6 +1173,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
_previousSelectionGranularity = [self selectionGranularity];
|
||||
[self setSelectionGranularity:CPSelectByCharacter];
|
||||
[self setSelectedRange:[self selectedRange] affinity:0 stillSelecting:NO];
|
||||
_mouseDownOldSelection = nil;
|
||||
|
||||
var point = [_layoutManager locationForGlyphAtIndex:[self selectedRange].location];
|
||||
_stickyXLocation = point.x;
|
||||
@@ -1478,7 +1586,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
- (void)moveWordLeft:(id)sender
|
||||
{
|
||||
if ([self isSelectable])
|
||||
[self _moveSelectionIntoDirection:-1 granularity:CPSelectByWord]
|
||||
[self _moveSelectionIntoDirection:-1 granularity:CPSelectByWord];
|
||||
}
|
||||
|
||||
- (void)moveRight:(id)sender
|
||||
@@ -1489,7 +1597,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
|
||||
- (void)_deleteForRange:(CPRange)changedRange
|
||||
{
|
||||
if (![self shouldChangeTextInRange:changedRange replacementString:@""])
|
||||
if (![self _didBeginEditing] || ![self shouldChangeTextInRange:changedRange replacementString:@""])
|
||||
return;
|
||||
|
||||
changedRange = CPIntersectionRange(CPMakeRange(0, [_layoutManager numberOfCharacters]), changedRange);
|
||||
@@ -1506,6 +1614,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
[self didChangeText];
|
||||
[_layoutManager _validateLayoutAndGlyphs];
|
||||
[self sizeToFit];
|
||||
[self scrollRangeToVisible:CPMakeRange(changedRange.location, 0)];
|
||||
_stickyXLocation = _caret._rect.origin.x;
|
||||
}
|
||||
|
||||
@@ -1514,7 +1623,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
[_CPNativeInputManager cancelCurrentInputSessionIfNeeded]; // handle ESC during native input
|
||||
}
|
||||
|
||||
- (void)deleteBackward:(id)sender ignoreSmart:(BOOL)ignoreFlag
|
||||
- (void)deleteBackward:(id)sender handleSmart:(BOOL)handleSmart
|
||||
{
|
||||
var changedRange;
|
||||
|
||||
@@ -1524,7 +1633,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
changedRange = _selectionRange;
|
||||
|
||||
// smart delete
|
||||
if (!ignoreFlag && _copySelectionGranularity > 0 &&
|
||||
if (handleSmart &&
|
||||
changedRange.location > 0 && _isWhitespaceCharacter([[_textStorage string] characterAtIndex:_selectionRange.location - 1]) &&
|
||||
changedRange.location < [[self string] length] && _isWhitespaceCharacter([[_textStorage string] characterAtIndex:CPMaxRange(changedRange)]))
|
||||
changedRange.length++;
|
||||
@@ -1535,8 +1644,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
|
||||
- (void)deleteBackward:(id)sender
|
||||
{
|
||||
_copySelectionGranularity = _previousSelectionGranularity; // smart delete
|
||||
[self deleteBackward:self ignoreSmart:_selectionRange.length > 0? NO:YES];
|
||||
[self deleteBackward:self handleSmart:[self _shouldUseSmartPasting] && _selectionRange.length > 0];
|
||||
}
|
||||
|
||||
- (void)deleteForward:(id)sender
|
||||
@@ -1559,7 +1667,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
return;
|
||||
|
||||
[self copy:sender];
|
||||
[self deleteBackward:sender ignoreSmart:NO];
|
||||
[self deleteBackward:sender handleSmart:_previousSelectionGranularity];
|
||||
}
|
||||
|
||||
- (void)insertLineBreak:(id)sender
|
||||
@@ -1612,11 +1720,11 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
[self _enrichEssentialTypingAttributes:_typingAttributes];
|
||||
}
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPTextViewDidChangeTypingAttributesNotification
|
||||
object:self];
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPTextViewDidChangeTypingAttributesNotification object:self];
|
||||
|
||||
if (_delegateRespondsToSelectorMask & kDelegateRespondsTo_textView_didChangeTypingAttributes)
|
||||
[_delegate textViewDidChangeTypingAttributes:[[CPNotification alloc] initWithName:CPTextViewDidChangeTypingAttributesNotification object:self userInfo:nil]];
|
||||
// We always clear the saved selection range from the last mouse down event here.
|
||||
// This is normally done in mouseUp: but this is if that event was never sent.
|
||||
_mouseDownOldSelection = nil;
|
||||
}
|
||||
|
||||
- (CPDictionary)_attributesForFontPanel
|
||||
@@ -1759,7 +1867,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
|
||||
- (void)underline:(id)sender
|
||||
{
|
||||
if (![self shouldChangeTextInRange:_selectionRange replacementString:nil])
|
||||
if (![self _didBeginEditing] || ![self shouldChangeTextInRange:_selectionRange replacementString:nil])
|
||||
return;
|
||||
|
||||
if (!CPEmptyRange(_selectionRange))
|
||||
@@ -1999,7 +2107,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
|
||||
- (BOOL)shouldDrawInsertionPoint
|
||||
{
|
||||
return (_selectionRange.length === 0 && [self _isFocused]);
|
||||
return (_selectionRange.length === 0 && [self _isFocused] && !_placeholderString);
|
||||
}
|
||||
|
||||
- (void)updateInsertionPointStateAndRestartTimer:(BOOL)flag
|
||||
@@ -2060,7 +2168,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
{
|
||||
var point = [info draggingLocation],
|
||||
location = [self _characterIndexFromRawPoint:CGPointCreateCopy(point)];
|
||||
|
||||
|
||||
_movingSelection = CPMakeRange(location, 0);
|
||||
[_caret _drawCaretAtLocation:_movingSelection.location];
|
||||
[_caret setVisibility:YES];
|
||||
@@ -2073,11 +2181,11 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
{
|
||||
var location = [self convertPoint:[aSender draggingLocation] fromView:nil],
|
||||
pasteboard = [aSender draggingPasteboard];
|
||||
|
||||
|
||||
if ([pasteboard availableTypeFromArray:[CPRTFPboardType, CPStringPboardType]])
|
||||
{
|
||||
[_caret setVisibility:NO];
|
||||
|
||||
|
||||
if (CPLocationInRange(_movingSelection.location, _selectionRange))
|
||||
{
|
||||
[self setSelectedRange:_movingSelection];
|
||||
@@ -2102,7 +2210,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
[self insertText:dataForPasting];
|
||||
}, 0);
|
||||
}
|
||||
|
||||
|
||||
if ([pasteboard availableTypeFromArray:[CPColorDragType]])
|
||||
[self setTextColor:[CPKeyedUnarchiver unarchiveObjectWithData:[pasteboard dataForType:CPColorDragType]] range:_selectionRange];
|
||||
}
|
||||
@@ -2142,7 +2250,8 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
[[self class] _binderClassForBinding:CPValueBinding],
|
||||
theBinding = [binderClass getBinding:CPAttributedStringBinding forObject:self] || [binderClass getBinding:CPValueBinding forObject:self];
|
||||
|
||||
[theBinding reverseSetValueFor:@"objectValue"];
|
||||
if (theBinding && [self isEditable])
|
||||
[theBinding reverseSetValueFor:@"objectValue"];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -2176,6 +2285,14 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
return [_delegate textShouldBeginEditing:self];
|
||||
}
|
||||
|
||||
- (BOOL)_sendDelegateTextShouldEndEditing
|
||||
{
|
||||
if (!(_delegateRespondsToSelectorMask & kDelegateRespondsTo_textShouldEndEditing))
|
||||
return YES;
|
||||
|
||||
return [_delegate textShouldEndEditing:self];
|
||||
}
|
||||
|
||||
- (BOOL)_sendDelegateShouldChangeTextInRange:(CPRange)aRange replacementString:(CPString)aString
|
||||
{
|
||||
if (!(_delegateRespondsToSelectorMask & kDelegateRespondsTo_textView_shouldChangeTextInRange_replacementString))
|
||||
@@ -2186,7 +2303,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
|
||||
- (CPDictionary)_sendDelegateShouldChangeTypingAttributes:(CPDictionary)typingAttributes toAttributes:(CPDictionary)attributes
|
||||
{
|
||||
if (!(_delegateRespondsToSelectorMask & kDelegateRespondsTo_textView_doCommandBySelector))
|
||||
if (!(_delegateRespondsToSelectorMask & kDelegateRespondsTo_textView_shouldChangeTypingAttributes_toAttributes))
|
||||
return [CPDictionary dictionary];
|
||||
|
||||
return [_delegate textView:self shouldChangeTypingAttributes:typingAttributes toAttributes:attributes];
|
||||
@@ -2275,7 +2392,7 @@ var CPTextViewAllowsUndoKey = @"CPTextViewAllowsUndoKey",
|
||||
{
|
||||
DOMElement _selectionBoxDOM;
|
||||
CGRect _rect;
|
||||
CPColor _color
|
||||
CPColor _color;
|
||||
CPTextView _textView;
|
||||
}
|
||||
|
||||
@@ -2419,13 +2536,13 @@ var CPTextViewAllowsUndoKey = @"CPTextViewAllowsUndoKey",
|
||||
_caretTimer = nil;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void)_drawCaretAtLocation:(int)aLoc
|
||||
{
|
||||
var rect = [_textView._layoutManager boundingRectForGlyphRange:CPMakeRange(aLoc, 1) inTextContainer:_textView._textContainer];
|
||||
|
||||
if (aLoc >= [_textView._layoutManager numberOfCharacters])
|
||||
rect.origin.x = CGRectGetMaxX(rect)
|
||||
rect.origin.x = CGRectGetMaxX(rect);
|
||||
|
||||
[self setRect:rect];
|
||||
}
|
||||
@@ -2606,7 +2723,7 @@ var _CPCopyPlaceholder = '-';
|
||||
isPlain = YES;
|
||||
|
||||
// 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();
|
||||
|
||||
@@ -2634,7 +2751,7 @@ var _CPCopyPlaceholder = '-';
|
||||
}, 20);
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
if (CPBrowserIsEngine(CPGeckoBrowserEngine))
|
||||
{
|
||||
@@ -2650,7 +2767,7 @@ var _CPCopyPlaceholder = '-';
|
||||
e.clipboardData.setData('text/plain', stringForPasting);
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
_CPNativeInputField.oncut = function(e)
|
||||
{
|
||||
@@ -2752,6 +2869,3 @@ var _CPCopyPlaceholder = '-';
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ var CPSystemTypesetterFactory,
|
||||
rect = CGRectMake(lineOrigin.x, lineOrigin.y, _lineWidth, _lineHeight),
|
||||
containerSize = aContainer._size;
|
||||
|
||||
[_layoutManager _appendNewLineFragmentInTextContainer:_currentTextContainer forGlyphRange:lineRange]
|
||||
[_layoutManager _appendNewLineFragmentInTextContainer:_currentTextContainer forGlyphRange:lineRange];
|
||||
|
||||
var fragment = [_layoutManager._lineFragments lastObject];
|
||||
fragment._isLast = !sameLine;
|
||||
@@ -293,8 +293,8 @@ var CPSystemTypesetterFactory,
|
||||
if (!currentFont)
|
||||
currentFont = [_textStorage font] || [CPFont systemFontOfSize:12.0];
|
||||
|
||||
ascent = [currentFont ascender]
|
||||
descent = [currentFont descender]
|
||||
ascent = [currentFont ascender];
|
||||
descent = [currentFont descender];
|
||||
leading = (ascent - descent) * 0.2; // FAKE leading
|
||||
|
||||
currentFontLineHeight = ascent - descent + leading;
|
||||
|
||||
@@ -113,13 +113,13 @@ var hexTable = [];
|
||||
|
||||
- (CPNumber)script
|
||||
{
|
||||
return [CPNumber numberWithInt: script];
|
||||
return [CPNumber numberWithInt:script];
|
||||
}
|
||||
|
||||
- (CPNumber)underline
|
||||
{
|
||||
if (underline != 0)
|
||||
return [CPNumber numberWithInteger: underline];
|
||||
return [CPNumber numberWithInt:underline];
|
||||
else
|
||||
return nil;
|
||||
}
|
||||
@@ -127,7 +127,7 @@ var hexTable = [];
|
||||
- (CPNumber)strikethrough
|
||||
{
|
||||
if (strikethrough != 0)
|
||||
return [CPNumber numberWithInteger: strikethrough];
|
||||
return [CPNumber numberWithInt:strikethrough];
|
||||
else
|
||||
return nil;
|
||||
}
|
||||
@@ -657,7 +657,7 @@ var kRgsymRtf = {
|
||||
}
|
||||
- (CPAttributedString)parseRTF:(CPString)rtf
|
||||
{
|
||||
rtf = rtf.replace(/\\\n/g, "\\par\n")
|
||||
rtf = rtf.replace(/\\\n/g, "\\par\n");
|
||||
|
||||
if (rtf.length == 0)
|
||||
return '';
|
||||
@@ -718,7 +718,7 @@ var kRgsymRtf = {
|
||||
_freename = "";
|
||||
}
|
||||
|
||||
[self _flushCurrentRun]
|
||||
[self _flushCurrentRun];
|
||||
break;
|
||||
|
||||
case "\\":
|
||||
@@ -751,7 +751,7 @@ var kRgsymRtf = {
|
||||
if (hexTable && hexTable[hex.toUpperCase()] !== undefined)
|
||||
temp = parseInt(hexTable[hex.toUpperCase()], 16);
|
||||
|
||||
[self _appendPlainString: String.fromCharCode(temp)]
|
||||
[self _appendPlainString: String.fromCharCode(temp)];
|
||||
hex = '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
RTFProducer.j
|
||||
_CPRTFProducer.j
|
||||
|
||||
Serialize CPAttributedString to a RTF String
|
||||
|
||||
@@ -189,11 +189,9 @@ function _points2twips(a) { return (a) * 20.0; }
|
||||
|
||||
if (val)
|
||||
{
|
||||
var size = [val sizeValue];
|
||||
|
||||
detail = [CPString stringWithFormat:@"\\paperw%d \\paperh%d",
|
||||
_points2twips(size.width),
|
||||
_points2twips(size.height)];
|
||||
_points2twips(val.width),
|
||||
_points2twips(val.height)];
|
||||
|
||||
result += detail;
|
||||
}
|
||||
@@ -612,4 +610,4 @@ function _points2twips(a) { return (a) * 20.0; }
|
||||
output += trailerString;
|
||||
return output;
|
||||
}
|
||||
@end
|
||||
@end
|
||||
|
||||
@@ -24,9 +24,12 @@
|
||||
@import <Foundation/CPMutableArray.j>
|
||||
@import <Foundation/CPString.j>
|
||||
@import <Foundation/CPKeyedUnarchiver.j>
|
||||
@import <Foundation/CPBundle.j>
|
||||
|
||||
@class CPView
|
||||
@class _CPThemeAttribute
|
||||
@class CPImage
|
||||
@class CPColor
|
||||
|
||||
var CPThemesByName = { },
|
||||
CPThemeDefaultTheme = nil,
|
||||
@@ -313,6 +316,71 @@ var CPThemeNameKey = @"CPThemeNameKey",
|
||||
|
||||
@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 directly but should instead use the CPThemeState function.
|
||||
@@ -769,7 +837,7 @@ var ParentAttributeForCoder = nil;
|
||||
if ([aCoder containsValueForKey:@"state"])
|
||||
state = [aCoder decodeObjectForKey:@"state"];
|
||||
else
|
||||
state = CPThemeStateNormalString
|
||||
state = CPThemeStateNormalString;
|
||||
|
||||
[_values setObject:[aCoder decodeObjectForKey:"value"] forKey:state];
|
||||
}
|
||||
|
||||
@@ -95,6 +95,17 @@
|
||||
[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];
|
||||
}
|
||||
|
||||
|
||||
@@ -523,17 +523,25 @@ CPTokenFieldDeleteButtonType = 1;
|
||||
var element = [self _inputElement];
|
||||
|
||||
CPTokenFieldInputResigning = YES;
|
||||
element.blur();
|
||||
|
||||
if (CPTokenFieldInputIsActive)
|
||||
element.blur();
|
||||
|
||||
if (!CPTokenFieldInputDidBlur)
|
||||
CPTokenFieldBlurHandler();
|
||||
|
||||
CPTokenFieldInputDidBlur = NO;
|
||||
CPTokenFieldInputResigning = NO;
|
||||
|
||||
if (element.parentNode == [_tokenScrollView documentView]._DOMElement)
|
||||
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;
|
||||
|
||||
if (document.attachEvent)
|
||||
@@ -541,7 +549,7 @@ CPTokenFieldDeleteButtonType = 1;
|
||||
CPTokenFieldCachedSelectStartFunction = nil;
|
||||
CPTokenFieldCachedDragFunction = nil;
|
||||
|
||||
document.body.ondrag = CPTokenFieldCachedDragFunction
|
||||
document.body.ondrag = CPTokenFieldCachedDragFunction;
|
||||
document.body.onselectstart = CPTokenFieldCachedSelectStartFunction
|
||||
}
|
||||
|
||||
@@ -1239,7 +1247,7 @@ CPTokenFieldDeleteButtonType = 1;
|
||||
var scrollToToken = _shouldScrollTo;
|
||||
|
||||
if (scrollToToken === CPScrollDestinationLeft)
|
||||
scrollToToken = tokens[_selectedRange.location]
|
||||
scrollToToken = tokens[_selectedRange.location];
|
||||
else if (scrollToToken === CPScrollDestinationRight)
|
||||
scrollToToken = tokens[MAX(0, CPMaxRange(_selectedRange) - 1)];
|
||||
[self _scrollTokenViewToVisible:scrollToToken];
|
||||
|
||||
@@ -153,7 +153,7 @@ var CPToolbarsByIdentifier = nil,
|
||||
|
||||
if (!toolbarsSharingIdentifier)
|
||||
{
|
||||
toolbarsSharingIdentifier = []
|
||||
toolbarsSharingIdentifier = [];
|
||||
[CPToolbarsByIdentifier setObject:toolbarsSharingIdentifier forKey:identifier];
|
||||
}
|
||||
|
||||
@@ -588,7 +588,7 @@ var CPToolbarIdentifierKey = @"CPToolbarIdentifierKey",
|
||||
[aCoder encodeBool:_showsBaselineSeparator forKey:CPToolbarShowsBaselineSeparatorKey];
|
||||
[aCoder encodeBool:_allowsUserCustomization forKey:CPToolbarAllowsUserCustomizationKey];
|
||||
[aCoder encodeBool:_isVisible forKey:CPToolbarIsVisibleKey];
|
||||
[aCoder encodeInt:_sizeMode forKey:CPToolbarSizeModeKey]
|
||||
[aCoder encodeInt:_sizeMode forKey:CPToolbarSizeModeKey];
|
||||
|
||||
[aCoder encodeObject:_identifiedItems forKey:CPToolbarIdentifiedItemsKey];
|
||||
[aCoder encodeObject:_defaultItems forKey:CPToolbarDefaultItemsKey];
|
||||
|
||||
@@ -129,7 +129,8 @@ var DOMElementPrototype = nil,
|
||||
BackgroundVerticalThreePartImage = 1,
|
||||
BackgroundHorizontalThreePartImage = 2,
|
||||
BackgroundNinePartImage = 3,
|
||||
BackgroundTransparentColor = 4;
|
||||
BackgroundTransparentColor = 4,
|
||||
BackgroundCSSStyling = 5;
|
||||
#endif
|
||||
|
||||
var CPViewFlags = { },
|
||||
@@ -195,6 +196,10 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
CPArray _DOMImageSizes;
|
||||
|
||||
unsigned _backgroundType;
|
||||
|
||||
// CSS styling
|
||||
CPArray _cssStylePreviousState;
|
||||
DOMElement _cssStyleNode;
|
||||
#endif
|
||||
|
||||
CGRect _dirtyRect;
|
||||
@@ -320,6 +325,18 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (CPString)defaultThemeClass
|
||||
{
|
||||
return @"view";
|
||||
}
|
||||
|
||||
+ (CPDictionary)themeAttributes
|
||||
{
|
||||
return @{
|
||||
@"css-based": NO
|
||||
};
|
||||
}
|
||||
|
||||
- (void)_setupViewFlags
|
||||
{
|
||||
var theClass = [self class],
|
||||
@@ -399,6 +416,8 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
|
||||
_DOMImageParts = [];
|
||||
_DOMImageSizes = [];
|
||||
|
||||
_cssStylePreviousState = @[];
|
||||
#endif
|
||||
|
||||
_animator = nil;
|
||||
@@ -409,7 +428,12 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
|
||||
_inhibitDOMUpdates = 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;
|
||||
}
|
||||
@@ -449,7 +473,7 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
return;
|
||||
|
||||
if (!_toolTipFunctionIn)
|
||||
_toolTipFunctionIn = function(e) { [_CPToolTip scheduleToolTipForView:self]; }
|
||||
_toolTipFunctionIn = function(e) { [_CPToolTip scheduleToolTipForView:self]; };
|
||||
|
||||
if (!_toolTipFunctionOut)
|
||||
_toolTipFunctionOut = function(e) { [_CPToolTip invalidateCurrentToolTipIfNeeded]; };
|
||||
@@ -1954,15 +1978,25 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
_backgroundColor = aColor;
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
if (_backgroundType === BackgroundCSSStyling)
|
||||
[_backgroundColor restorePreviousCSSState:@ref(_cssStylePreviousState) forDOMElement:_DOMElement];
|
||||
|
||||
var patternImage = [_backgroundColor patternImage],
|
||||
colorExists = _backgroundColor && ([_backgroundColor patternImage] || [_backgroundColor alphaComponent] > 0.0),
|
||||
colorHasAlpha = colorExists && [_backgroundColor alphaComponent] < 1.0,
|
||||
supportsRGBA = CPFeatureIsCompatible(CPCSSRGBAFeature),
|
||||
colorNeedsDOMElement = colorHasAlpha && !supportsRGBA,
|
||||
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;
|
||||
amount = 3;
|
||||
@@ -2025,7 +2059,14 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
_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] : "";
|
||||
|
||||
@@ -2983,7 +3024,7 @@ setBoundsOrigin:
|
||||
*/
|
||||
- (BOOL)inLiveResize
|
||||
{
|
||||
return _inLiveResize;
|
||||
return [self window] && [[self window] _inLiveResize];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -3434,6 +3475,17 @@ setBoundsOrigin:
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPView (CSSTheming)
|
||||
|
||||
- (void)setDOMClassName:(CPString)aClassName
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
_DOMElement.className = aClassName;
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@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.
|
||||
|
||||
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.
|
||||
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 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
|
||||
@@ -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
|
||||
|
||||
- (void)_removeTrackingArea:(CPTrackingArea)trackingArea
|
||||
@@ -3749,6 +3783,8 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
|
||||
|
||||
// DOM SETUP
|
||||
#if PLATFORM(DOM)
|
||||
_cssStylePreviousState = @[];
|
||||
|
||||
_DOMImageParts = [];
|
||||
_DOMImageSizes = [];
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
@class CPToolbar
|
||||
@class CPWindowController
|
||||
@class _CPWindowFrameAnimation
|
||||
@class _CPWindowFrameAnimationDelegate
|
||||
|
||||
@global CPApp
|
||||
@global _CPPlatformWindowWillCloseNotification
|
||||
@@ -178,7 +179,7 @@ var CPWindowActionMessageKeys = [
|
||||
BOOL _isVisible;
|
||||
BOOL _hasBeenOrderedIn @accessors;
|
||||
BOOL _isMiniaturized;
|
||||
BOOL _isAnimating;
|
||||
BOOL _isAnimating @accessors(setter=_setAnimating:);
|
||||
BOOL _hasShadow;
|
||||
BOOL _isMovableByWindowBackground;
|
||||
BOOL _isMovable;
|
||||
@@ -261,6 +262,7 @@ var CPWindowActionMessageKeys = [
|
||||
CPWindow _parentView;
|
||||
BOOL _isSheet;
|
||||
_CPWindowFrameAnimation _frameAnimation;
|
||||
_CPWindowFrameAnimationDelegate _frameAnimationDelegate;
|
||||
}
|
||||
|
||||
+ (Class)_binderClassForBinding:(CPString)aBinding
|
||||
@@ -336,6 +338,8 @@ CPTexturedBackgroundWindowMask
|
||||
_isSheet = NO;
|
||||
_sheetContext = nil;
|
||||
_parentView = nil;
|
||||
_frameAnimation = nil;
|
||||
_frameAnimationDelegate = nil;
|
||||
|
||||
// Set up our window number.
|
||||
_windowNumber = [CPApp._windows count];
|
||||
@@ -742,7 +746,7 @@ CPTexturedBackgroundWindowMask
|
||||
{
|
||||
[_frameAnimation stopAnimation];
|
||||
_frameAnimation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:frame];
|
||||
|
||||
[_frameAnimation setDelegate:[self _frameAnimationDelegate]];
|
||||
[_frameAnimation startAnimation];
|
||||
}
|
||||
else
|
||||
@@ -802,6 +806,13 @@ CPTexturedBackgroundWindowMask
|
||||
[_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,
|
||||
moving or resizing the frame as necessary.
|
||||
@@ -1840,16 +1851,12 @@ CPTexturedBackgroundWindowMask
|
||||
// CPLeftMouseDown is needed for window moving and resizing to work.
|
||||
// CPMouseMoved is needed for rollover effects on title bar buttons.
|
||||
|
||||
if (sheet)
|
||||
if (sheet && _sheetContext["isAttached"])
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case CPLeftMouseDown:
|
||||
|
||||
// This is needed when a doubleClick occurs when the sheet is closing or opening
|
||||
if (!_parentWindow)
|
||||
return;
|
||||
|
||||
[_windowView mouseDown:anEvent];
|
||||
|
||||
// -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.
|
||||
// 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.
|
||||
[[[anEvent window] platformWindow] _propagateCurrentDOMEvent:NO]
|
||||
[[[anEvent window] platformWindow] _propagateCurrentDOMEvent:NO];
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
@@ -1906,7 +1913,7 @@ CPTexturedBackgroundWindowMask
|
||||
// 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,
|
||||
// even that we just moved it to a new first responder.
|
||||
[[[anEvent window] platformWindow] _propagateCurrentDOMEvent:NO]
|
||||
[[[anEvent window] platformWindow] _propagateCurrentDOMEvent:NO];
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -1998,13 +2005,13 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
if (type == CPRightMouseDragged)
|
||||
{
|
||||
selector = @selector(rightMouseDragged:)
|
||||
selector = @selector(rightMouseDragged:);
|
||||
if (![_leftMouseDownView respondsToSelector:selector])
|
||||
selector = nil;
|
||||
}
|
||||
|
||||
if (!selector)
|
||||
selector = @selector(mouseDragged:)
|
||||
selector = @selector(mouseDragged:);
|
||||
|
||||
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
|
||||
*/
|
||||
@@ -3768,13 +3794,6 @@ var interpolate = function(fromValue, toValue, progress)
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)startAnimation
|
||||
{
|
||||
[super startAnimation];
|
||||
|
||||
_window._isAnimating = YES;
|
||||
}
|
||||
|
||||
- (void)setCurrentProgress:(float)aProgress
|
||||
{
|
||||
[super setCurrentProgress:aProgress];
|
||||
@@ -3782,7 +3801,7 @@ var interpolate = function(fromValue, toValue, progress)
|
||||
var value = [self currentValue];
|
||||
|
||||
if (value == 1.0)
|
||||
_window._isAnimating = NO;
|
||||
[_window _setAnimating:NO];
|
||||
|
||||
var newFrame = CGRectMake(
|
||||
interpolate(CGRectGetMinX(_startFrame), CGRectGetMinX(_targetFrame), value),
|
||||
@@ -3795,6 +3814,41 @@ var interpolate = function(fromValue, toValue, progress)
|
||||
|
||||
@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)
|
||||
|
||||
|
||||
@@ -176,6 +176,8 @@ CPWindowDidEndSheetNotification = @"CPWindowDidEndSheetNotificat
|
||||
CPWindowDidMiniaturizeNotification = @"CPWindowDidMiniaturizeNotification";
|
||||
CPWindowWillMiniaturizeNotification = @"CPWindowWillMiniaturizeNotification";
|
||||
CPWindowDidDeminiaturizeNotification = @"CPWindowDidDeminiaturizeNotification";
|
||||
CPWindowWillStartLiveResizeNotification = @"CPWindowWillStartLiveResizeNotification";
|
||||
CPWindowDidEndLiveResizeNotification = @"CPWindowDidEndLiveResizeNotification";
|
||||
|
||||
_CPWindowDidChangeFirstResponderNotification = @"_CPWindowDidChangeFirstResponderNotification";
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
+ (CPString)defaultThemeClass
|
||||
{
|
||||
return @"bordeless-bridge-window-view";
|
||||
return @"borderless-bridge-window-view";
|
||||
}
|
||||
|
||||
+ (CPDictionary)themeAttributes
|
||||
|
||||
@@ -183,7 +183,7 @@
|
||||
if (_styleMask & CPClosableWindowMask)
|
||||
{
|
||||
[_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 setAlternateImage:[self valueForThemeAttribute:@"close-active-image"]];
|
||||
}
|
||||
|
||||
@@ -64,6 +64,8 @@ _CPWindowViewResizeSlop = 3;
|
||||
CGRect _cachedScreenFrame;
|
||||
|
||||
CPView _sheetShadowView;
|
||||
|
||||
BOOL _isTracking @accessors(getter=_isTracking);
|
||||
}
|
||||
|
||||
+ (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
|
||||
@@ -148,6 +150,7 @@ _CPWindowViewResizeSlop = 3;
|
||||
_styleMask = aStyleMask;
|
||||
_resizeIndicatorOffset = CGSizeMakeZero();
|
||||
_toolbarOffset = CGSizeMakeZero();
|
||||
_isTracking = NO;
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -458,6 +461,8 @@ _CPWindowViewResizeSlop = 3;
|
||||
if (type === CPLeftMouseUp)
|
||||
{
|
||||
_cachedScreenFrame = nil;
|
||||
_isTracking = NO;
|
||||
[_window _endLiveResize];
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -474,6 +479,12 @@ _CPWindowViewResizeSlop = 3;
|
||||
}
|
||||
else if (type === CPLeftMouseDragged)
|
||||
{
|
||||
if (!_isTracking)
|
||||
{
|
||||
_isTracking = YES;
|
||||
[_window _startLiveResize];
|
||||
}
|
||||
|
||||
var deltaX = globalLocation.x - _mouseDraggedPoint.x,
|
||||
deltaY = globalLocation.y - _mouseDraggedPoint.y,
|
||||
startX = CGRectGetMinX(_cachedFrame),
|
||||
@@ -973,16 +984,22 @@ _CPWindowViewResizeSlop = 3;
|
||||
@end
|
||||
|
||||
@implementation _CPWindowView (TrackingAreaAdditions)
|
||||
{
|
||||
CPTrackingArea _windowViewTrackingArea;
|
||||
}
|
||||
|
||||
- (void)updateTrackingAreas
|
||||
{
|
||||
[self removeAllTrackingAreas];
|
||||
if (_windowViewTrackingArea)
|
||||
[self removeTrackingArea:_windowViewTrackingArea];
|
||||
|
||||
[self addTrackingArea:[[CPTrackingArea alloc] initWithRect:[self contentRectForFrameRect:[self frame]]
|
||||
options:CPTrackingCursorUpdate | CPTrackingActiveInActiveApp
|
||||
owner:self
|
||||
userInfo:nil]];
|
||||
_windowViewTrackingArea = [[CPTrackingArea alloc] initWithRect:[self contentRectForFrameRect:[self frame]]
|
||||
options:CPTrackingCursorUpdate | CPTrackingActiveInActiveApp
|
||||
owner:self
|
||||
userInfo:nil];
|
||||
|
||||
[self addTrackingArea:_windowViewTrackingArea];
|
||||
[super updateTrackingAreas];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -364,7 +364,7 @@
|
||||
{
|
||||
[viewControllerView removeFromSuperview];
|
||||
[viewControllerView setFrame:[contentView frame]];
|
||||
[viewControllerView setAutoresizingMask:[contentView autoresizingMask]]
|
||||
[viewControllerView setAutoresizingMask:[contentView autoresizingMask]];
|
||||
[[self window] setContentView:viewControllerView];
|
||||
}
|
||||
else
|
||||
|
||||
@@ -222,3 +222,28 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
|
||||
}
|
||||
|
||||
@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)])
|
||||
{
|
||||
var instantiatedObject = [object _cibInstantiate];
|
||||
instantiatedObject = [object _cibInstantiate];
|
||||
|
||||
if (instantiatedObject !== object)
|
||||
{
|
||||
|
||||
@@ -522,7 +522,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
if (USE_BUFFER)
|
||||
{
|
||||
if (_delegateRespondsToDisplayLayerSelector)
|
||||
return [_delegate displayInLayer:self];
|
||||
return [_delegate displayLayer:self];
|
||||
|
||||
if (CGRectGetWidth(_backingStoreFrame) == 0.0 || CGRectGetHeight(_backingStoreFrame) == 0.0)
|
||||
return;
|
||||
|
||||
@@ -66,16 +66,6 @@ var _CPAnimationContextStack = nil,
|
||||
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
|
||||
{
|
||||
if (!_animationFlushingObserver)
|
||||
@@ -90,16 +80,13 @@ var _CPAnimationContextStack = nil,
|
||||
|
||||
+ (void)beginGrouping
|
||||
{
|
||||
var newContext;
|
||||
var newContext = [[CPAnimationContext alloc] init];
|
||||
|
||||
if ([_CPAnimationContextStack count])
|
||||
{
|
||||
var currentContext = [_CPAnimationContextStack lastObject];
|
||||
newContext = [currentContext copy];
|
||||
}
|
||||
else
|
||||
{
|
||||
newContext = [[CPAnimationContext alloc] init];
|
||||
[newContext setDuration:[currentContext duration]];
|
||||
[newContext setTimingFunction:[currentContext timingFunction]];
|
||||
}
|
||||
|
||||
[_CPAnimationContextStack addObject:newContext];
|
||||
@@ -155,9 +142,6 @@ var _CPAnimationContextStack = nil,
|
||||
duration = [animation duration] || [self duration];
|
||||
needsPeriodicFrameUpdates = [[anObject animator] needsPeriodicFrameUpdatesForKeyPath:aKeyPath];
|
||||
|
||||
if (_completionHandlerAgent)
|
||||
_completionHandlerAgent.increment();
|
||||
|
||||
var animatorClass = [[anObject class] animatorClass];
|
||||
|
||||
var completionFunction = function()
|
||||
@@ -221,7 +205,12 @@ var _CPAnimationContextStack = nil,
|
||||
if (_animationsByObject.size == 0)
|
||||
{
|
||||
if (_completionHandlerAgent)
|
||||
{
|
||||
#if (DEBUG)
|
||||
CPLog.debug("No animations are scheduled. Firing completion handler");
|
||||
#endif
|
||||
_completionHandlerAgent.fire();
|
||||
}
|
||||
}
|
||||
else
|
||||
[self _startAnimations];
|
||||
@@ -242,8 +231,23 @@ var _CPAnimationContextStack = nil,
|
||||
|
||||
_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
|
||||
var k = timers.length;
|
||||
while(k--)
|
||||
{
|
||||
#if (DEBUG)
|
||||
@@ -253,7 +257,6 @@ var _CPAnimationContextStack = nil,
|
||||
}
|
||||
|
||||
// start css animations
|
||||
var n = cssAnimations.length;
|
||||
while(n--)
|
||||
{
|
||||
#if (DEBUG)
|
||||
@@ -360,9 +363,24 @@ var _CPAnimationContextStack = nil,
|
||||
- (void)setCompletionHandler:(Function)aCompletionHandler
|
||||
{
|
||||
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
|
||||
@@ -465,11 +483,14 @@ var _CPAnimationContextStack = nil,
|
||||
|
||||
@end
|
||||
|
||||
var COMPLETION_AGENT_ID = 0;
|
||||
|
||||
var CompletionHandlerAgent = function(aCompletionHandler)
|
||||
{
|
||||
this._completionHandler = aCompletionHandler;
|
||||
this.total = 0;
|
||||
this.valid = true;
|
||||
this.id = COMPLETION_AGENT_ID++;
|
||||
};
|
||||
|
||||
CompletionHandlerAgent.prototype.completionHandler = function()
|
||||
@@ -479,12 +500,17 @@ CompletionHandlerAgent.prototype.completionHandler = 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()
|
||||
@@ -503,6 +529,8 @@ CompletionHandlerAgent.prototype.decrement = function()
|
||||
CompletionHandlerAgent.prototype.invalidate = function()
|
||||
{
|
||||
this.valid = false;
|
||||
this.total = 0;
|
||||
this._completionHandler = null;
|
||||
};
|
||||
|
||||
var _animationFlushingObserverCallback = function()
|
||||
|
||||
@@ -214,7 +214,7 @@ var transformSizeToHeight = function(start, current)
|
||||
|
||||
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)
|
||||
@@ -408,20 +408,25 @@ var createUpdateFrame = function(aView, aKeyPath)
|
||||
{
|
||||
[aView _setInhibitDOMUpdates:YES];
|
||||
|
||||
var matrix = style[transformProperty].split('(')[1].split(')')[0].split(','),
|
||||
x = ROUND(initialOrigin.x + parseFloat(matrix[4])),
|
||||
y = ROUND(initialOrigin.y + parseFloat(matrix[5]));
|
||||
var matrix_value = style[transformProperty];
|
||||
|
||||
if (aKeyPath === "frame")
|
||||
if (matrix_value && matrix_value !== 'none')
|
||||
{
|
||||
var width = getCSSPropertyValue("width"),
|
||||
height = getCSSPropertyValue("height");
|
||||
var matrix_array = matrix_value.split('(')[1].split(')')[0].split(','),
|
||||
x = ROUND(initialOrigin.x + parseFloat(matrix_array[4])),
|
||||
y = ROUND(initialOrigin.y + parseFloat(matrix_array[5]));
|
||||
|
||||
[aView setFrame:CGRectMake(x, y, width, height)];
|
||||
}
|
||||
else
|
||||
{
|
||||
[aView setFrameOrigin:CGPointMake(x, y)];
|
||||
if (aKeyPath === "frame")
|
||||
{
|
||||
var width = getCSSPropertyValue("width"),
|
||||
height = getCSSPropertyValue("height");
|
||||
|
||||
[aView setFrame:CGRectMake(x, y, width, height)];
|
||||
}
|
||||
else
|
||||
{
|
||||
[aView setFrameOrigin:CGPointMake(x, y)];
|
||||
}
|
||||
}
|
||||
|
||||
[aView _setInhibitDOMUpdates:NO];
|
||||
|
||||
@@ -20,7 +20,7 @@ var _supportsCSSAnimations = null;
|
||||
id <CPAnimatablePropertyContainer> _target;
|
||||
}
|
||||
|
||||
+ (BOOL)initialize
|
||||
+ (void)initialize
|
||||
{
|
||||
if ([self class] !== [_CPObjectAnimator class])
|
||||
return;
|
||||
|
||||
@@ -557,14 +557,14 @@ CGContextConcatCTM = function(aContext, anAffineTransform)
|
||||
b = VT.b;
|
||||
c = VT.c;
|
||||
d = VT.d;
|
||||
scale_rotate(a, b, c, d)
|
||||
scale_rotate(a, b, c, d);
|
||||
S.a *= sx;
|
||||
S.d *= sy;
|
||||
a = U.a;
|
||||
b = U.b;
|
||||
c = U.c;
|
||||
d = U.d;
|
||||
rotate_scale(a, b, c, d)
|
||||
rotate_scale(a, b, c, d);
|
||||
sx = S.a * sx;
|
||||
sy = S.d * sy;
|
||||
}
|
||||
|
||||
@@ -242,7 +242,7 @@ function CGContextDrawPath(aContext, aMode)
|
||||
vml.push("\">");
|
||||
|
||||
if (gState.gradient)
|
||||
vml.push(gState.gradient)
|
||||
vml.push(gState.gradient);
|
||||
|
||||
else if (fill)
|
||||
{
|
||||
|
||||
@@ -132,9 +132,6 @@ function CGPathAddArc(aPath, aTransform, x, y, aRadius, aStartAngle, anEndAngle,
|
||||
}
|
||||
else
|
||||
{
|
||||
var arcStartX = x + aRadius * COS(aStartAngle),
|
||||
arcStartY = y + aRadius * SIN(aStartAngle);
|
||||
|
||||
aPath.start = CGPointMake(arcStartX, arcStartY);
|
||||
}
|
||||
|
||||
@@ -274,7 +271,7 @@ function CGPathAddQuadCurveToPoint(aPath, aTransform, cpx, cpy, x, y)
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ appKitTask = framework ("AppKit", function(appKitTask)
|
||||
appKitTask.setCompilerFlags("-O2 " + INCLUDES);
|
||||
}
|
||||
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");
|
||||
|
||||
@@ -224,18 +224,10 @@ var PrimaryPlatformWindow = NULL;
|
||||
|
||||
- (void)deminiaturize:(id)sender
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
if (_DOMWindow && typeof _DOMWindow["cpDeminiaturize"] === "function")
|
||||
_DOMWindow.cpDeminiaturize();
|
||||
#endif
|
||||
}
|
||||
|
||||
- (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
|
||||
@@ -255,31 +247,16 @@ var PrimaryPlatformWindow = NULL;
|
||||
- (void)setLevel:(CPInteger)aLevel
|
||||
{
|
||||
_level = aLevel;
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
if (_DOMWindow && _DOMWindow.cpSetLevel)
|
||||
_DOMWindow.cpSetLevel(aLevel);
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)setHasShadow:(BOOL)shouldHaveShadow
|
||||
{
|
||||
_hasShadow = shouldHaveShadow;
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
if (_DOMWindow && _DOMWindow.cpSetHasShadow)
|
||||
_DOMWindow.cpSetHasShadow(shouldHaveShadow);
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)setShadowStyle:(int)aStyle
|
||||
{
|
||||
_shadowStyle = aStyle;
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
if (_DOMWindow && _DOMWindow.cpSetShadowStyle)
|
||||
_shadowStyle.cpSetShadowStyle(aStyle);
|
||||
#endif
|
||||
}
|
||||
|
||||
- (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
|
||||
// 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).
|
||||
[platformWindow _propagateCurrentDOMEvent:NO]
|
||||
[platformWindow _propagateCurrentDOMEvent:NO];
|
||||
|
||||
[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);
|
||||
|
||||
[platformWindow _propagateCurrentDOMEvent:NO]
|
||||
[platformWindow _propagateCurrentDOMEvent:NO];
|
||||
|
||||
// Let the app react through copy: and cut: actions.
|
||||
[CPApp sendEvent:anEvent];
|
||||
|
||||
@@ -205,6 +205,9 @@ var resizeTimer = nil;
|
||||
var PreventScroll = true;
|
||||
var blurTimer = nil;
|
||||
|
||||
var touchStartingPointX,
|
||||
touchStartingPointY;
|
||||
|
||||
_CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotification";
|
||||
|
||||
|
||||
@@ -244,9 +247,6 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
||||
if (!_DOMWindow)
|
||||
return [self contentRect];
|
||||
|
||||
if (_DOMWindow.cpFrame)
|
||||
return _DOMWindow.cpFrame();
|
||||
|
||||
var contentRect = CGRectMakeZero();
|
||||
|
||||
if (window.screenTop)
|
||||
@@ -275,9 +275,6 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
||||
if (!_DOMWindow)
|
||||
return;
|
||||
|
||||
if (typeof _DOMWindow["cpSetFrame"] === "function")
|
||||
return _DOMWindow.cpSetFrame([self contentRect]);
|
||||
|
||||
var origin = [self contentRect].origin,
|
||||
nativeOrigin = [self nativeContentRect].origin;
|
||||
|
||||
@@ -573,22 +570,12 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
||||
|
||||
[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.close();
|
||||
|
||||
if (self != [CPPlatformWindow primaryPlatformWindow])
|
||||
_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];
|
||||
|
||||
_DOMBodyElement.style.cursor = [[CPCursor currentCursor] _cssString];
|
||||
@@ -666,7 +653,8 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
||||
}
|
||||
else if (type === "dragend")
|
||||
{
|
||||
var dropEffect = aDOMEvent.dataTransfer.dropEffect;
|
||||
var dropEffect = aDOMEvent.dataTransfer.dropEffect,
|
||||
dragOperation;
|
||||
|
||||
if (dropEffect === "move")
|
||||
dragOperation = CPDragOperationMove;
|
||||
@@ -944,8 +932,7 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
||||
if (!theWindow)
|
||||
return;
|
||||
|
||||
var windowNumber = [theWindow windowNumber];
|
||||
|
||||
windowNumber = [theWindow windowNumber];
|
||||
location = [theWindow convertBridgeToBase:location];
|
||||
|
||||
var event = [CPEvent mouseEventWithType:CPScrollWheel location:location modifierFlags:modifierFlags
|
||||
@@ -1152,10 +1139,26 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
||||
|
||||
- (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)))
|
||||
{
|
||||
var newEvent = {};
|
||||
|
||||
switch (aDOMEvent.type)
|
||||
{
|
||||
case CPDOMEventTouchStart: newEvent.type = CPDOMEventMouseDown;
|
||||
@@ -1168,36 +1171,42 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
||||
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];
|
||||
|
||||
return;
|
||||
}
|
||||
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)
|
||||
aDOMEvent.preventDefault();
|
||||
|
||||
if (aDOMEvent.stopPropagation)
|
||||
aDOMEvent.stopPropagation();
|
||||
}
|
||||
// handle touch cases specifically
|
||||
}
|
||||
|
||||
- (void)mouseEvent:(DOMEvent)aDOMEvent
|
||||
@@ -1422,7 +1431,7 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio
|
||||
var insertionIndex = 0;
|
||||
|
||||
if (middle !== undefined)
|
||||
insertionIndex = _windowLevels[middle] > aLevel ? middle : middle + 1
|
||||
insertionIndex = _windowLevels[middle] > aLevel ? middle : middle + 1;
|
||||
|
||||
[_windowLevels insertObject:aLevel atIndex:insertionIndex];
|
||||
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,
|
||||
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)
|
||||
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
|
||||
}),
|
||||
|
||||
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),
|
||||
trackColorLegacy = PatternColor("scroller-legacy-vertical-track-center.png", 14.0, 1.0),
|
||||
|
||||
knobColor = PatternColor(
|
||||
"scroller-vertical-knob{style}{position}.png",
|
||||
@@ -535,8 +533,8 @@ var themedButtonValues = nil,
|
||||
[@"minimum-knob-length", 21.0, CPThemeStateVertical],
|
||||
|
||||
// Overlay
|
||||
[@"scroller-width", 9.0, CPThemeStateVertical],
|
||||
[@"knob-inset", CGInsetMake(2.0, 0.0, 0.0, 0.0), CPThemeStateVertical],
|
||||
[@"scroller-width", 14.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-border-overlay", 12.0, CPThemeStateVertical],
|
||||
[@"knob-slot-color", [CPNull null], CPThemeStateVertical],
|
||||
@@ -553,7 +551,7 @@ var themedButtonValues = nil,
|
||||
|
||||
// Legacy
|
||||
[@"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-border-overlay", 0.0, [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, CPThemeStateScrollerKnobDark]],
|
||||
[@"knob-slot-color", trackColorLegacy, [CPThemeStateVertical, CPThemeStateScrollViewLegacy, CPThemeStateScrollerKnobLight]],
|
||||
[@"knob-color", knobColorLegacy, [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
||||
[@"knob-color", knobColorLegacy, [CPThemeStateVertical, CPThemeStateScrollViewLegacy, CPThemeStateScrollerKnobLight]],
|
||||
[@"knob-color", knobColorLegacy, [CPThemeStateVertical, CPThemeStateScrollViewLegacy, CPThemeStateScrollerKnobDark]],
|
||||
[@"increment-line-color", incrementColorLegacy, [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
||||
[@"decrement-line-color", decrementColorLegacy, [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
||||
[@"decrement-line-size", CGSizeMake(14.0, 11.0), [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
||||
[@"increment-line-size", CGSizeMake(14.0, 11.0), [CPThemeStateVertical, CPThemeStateScrollViewLegacy]]
|
||||
[@"knob-color", knobColor["dark"], [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
||||
[@"increment-line-color", [CPNull null], [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
||||
[@"decrement-line-color", [CPNull null], [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
||||
[@"decrement-line-size", CGSizeMakeZero(), [CPThemeStateVertical, CPThemeStateScrollViewLegacy]],
|
||||
[@"increment-line-size", CGSizeMakeZero(), [CPThemeStateVertical, CPThemeStateScrollViewLegacy]]
|
||||
];
|
||||
|
||||
[self registerThemeValues:themedVerticalScrollerValues forView:scroller];
|
||||
@@ -588,9 +584,7 @@ var themedButtonValues = nil,
|
||||
orientation: PatternIsHorizontal
|
||||
}),
|
||||
|
||||
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),
|
||||
trackColorLegacy = PatternColor("scroller-legacy-horizontal-track-center.png", 1.0, 14.0),
|
||||
|
||||
knobColor = PatternColor(
|
||||
"scroller-horizontal-knob{style}{position}.png",
|
||||
@@ -616,7 +610,7 @@ var themedButtonValues = nil,
|
||||
|
||||
// Overlay
|
||||
[@"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-border-overlay", 12.0],
|
||||
[@"knob-slot-color", [CPNull null]],
|
||||
@@ -631,20 +625,18 @@ var themedButtonValues = nil,
|
||||
|
||||
// Legacy
|
||||
[@"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-border-overlay", 0.0, CPThemeStateScrollViewLegacy],
|
||||
[@"knob-slot-color", trackColorLegacy, CPThemeStateScrollViewLegacy],
|
||||
[@"knob-slot-color", trackColorLegacy, [CPThemeStateScrollViewLegacy, CPThemeStateSelected]],
|
||||
[@"knob-slot-color", trackColorLegacy, [CPThemeStateScrollViewLegacy, CPThemeStateScrollerKnobLight]],
|
||||
[@"knob-slot-color", trackColorLegacy, [CPThemeStateScrollViewLegacy, CPThemeStateScrollerKnobDark]],
|
||||
[@"knob-color", knobColorLegacy, CPThemeStateScrollViewLegacy],
|
||||
[@"knob-color", knobColorLegacy, [CPThemeStateScrollViewLegacy, CPThemeStateScrollerKnobLight]],
|
||||
[@"knob-color", knobColorLegacy, [CPThemeStateScrollViewLegacy, CPThemeStateScrollerKnobDark]],
|
||||
[@"increment-line-color", incrementColorLegacy, CPThemeStateScrollViewLegacy],
|
||||
[@"decrement-line-color", decrementColorLegacy, CPThemeStateScrollViewLegacy],
|
||||
[@"decrement-line-size", CGSizeMake(11.0, 14.0), CPThemeStateScrollViewLegacy],
|
||||
[@"increment-line-size", CGSizeMake(11.0, 14.0), CPThemeStateScrollViewLegacy]
|
||||
[@"knob-color", knobColor["@"], CPThemeStateScrollViewLegacy],
|
||||
[@"knob-color", knobColor["light"], [CPThemeStateScrollViewLegacy, CPThemeStateScrollerKnobLight]],
|
||||
[@"knob-color", knobColor["dark"], [CPThemeStateScrollViewLegacy, CPThemeStateScrollerKnobDark]],
|
||||
[@"decrement-line-size", CGSizeMakeZero(), CPThemeStateScrollViewLegacy],
|
||||
[@"increment-line-size", CGSizeMakeZero(), CPThemeStateScrollViewLegacy]
|
||||
];
|
||||
|
||||
[self registerThemeValues:themedHorizontalScrollerValues forView:scroller];
|
||||
@@ -2877,7 +2869,7 @@ var themedButtonValues = nil,
|
||||
|
||||
+ (_CPBorderlessBridgeWindowView)themedBorderlessBridgeWindowView
|
||||
{
|
||||
var bordelessBridgeWindowView = [[_CPBorderlessBridgeWindowView alloc] initWithFrame:CGRectMake(0,0,0,0)],
|
||||
var borderlessBridgeWindowView = [[_CPBorderlessBridgeWindowView alloc] initWithFrame:CGRectMake(0,0,0,0)],
|
||||
|
||||
toolbarBackgroundColor = PatternColor(
|
||||
[
|
||||
@@ -2891,9 +2883,9 @@ var themedButtonValues = nil,
|
||||
[@"toolbar-background-color", toolbarBackgroundColor]
|
||||
];
|
||||
|
||||
[self registerThemeValues:themeValues forView:bordelessBridgeWindowView inherit:themedWindowViewValues];
|
||||
[self registerThemeValues:themeValues forView:borderlessBridgeWindowView inherit:themedWindowViewValues];
|
||||
|
||||
return bordelessBridgeWindowView;
|
||||
return borderlessBridgeWindowView;
|
||||
}
|
||||
|
||||
+ (_CPToolbarView)themedToolbarView
|
||||
|
||||
@@ -331,9 +331,9 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0,
|
||||
{
|
||||
var textStyle = _DOMTextElement.style;
|
||||
|
||||
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.size.width = parseInt(textStyle.width.substr(0, textStyle.width.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.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.width += _textShadowOffset.width;
|
||||
@@ -437,55 +437,67 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0,
|
||||
|
||||
var textStyle = hasDOMTextElement ? _DOMTextElement.style : nil;
|
||||
|
||||
// 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)
|
||||
// If theme is CSS based and if shadow color is a CSS dictionary, we don't need a separate DOM element,
|
||||
// we simply put shadow styling on the regular text element
|
||||
if (hasDOMTextElement && [[self actualTheme] isCSSBased] && [_textShadowColor cssDictionary])
|
||||
{
|
||||
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);
|
||||
|
||||
_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)
|
||||
if (hasDOMTextShadowElement)
|
||||
{
|
||||
shadowStyle.overflow = textStyle.overflow;
|
||||
_DOMElement.removeChild(_DOMTextShadowElement);
|
||||
|
||||
_DOMTextShadowElement = nil;
|
||||
|
||||
hasDOMTextShadowElement = NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
shadowStyle.overflowX = textStyle.overflowX;
|
||||
shadowStyle.overflowY = textStyle.overflowY;
|
||||
_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;
|
||||
}
|
||||
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,
|
||||
hasDOMImageElement = !!_DOMImageElement;
|
||||
hasDOMImageElement = !!_DOMImageElement,
|
||||
// For CSS theming
|
||||
isCSSBasedImage = [_image isCSSBased],
|
||||
isIMGImageElement = hasDOMImageElement && (_DOMImageElement.nodeName == "IMG");
|
||||
|
||||
// Create or destroy DOM Image element
|
||||
if (needsDOMImageElement !== hasDOMImageElement)
|
||||
// First, check if we need to destroy a current DOM image element. This is the case if :
|
||||
// - 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);
|
||||
|
||||
_DOMImageElement = nil;
|
||||
|
||||
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");
|
||||
|
||||
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;
|
||||
_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 size = [self bounds].size,
|
||||
@@ -637,7 +663,15 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0,
|
||||
var imageStyle = _DOMImageElement.style;
|
||||
|
||||
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,
|
||||
centerY = size.height / 2.0,
|
||||
@@ -836,7 +870,8 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0,
|
||||
- (void)setSelectedRange:(CPRange)aRange
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
[[[self window] platformWindow] setSelectedRange:aRange inElement:_DOMTextElement];
|
||||
if (_DOMTextElement)
|
||||
[[[self window] platformWindow] setSelectedRange:aRange inElement:_DOMTextElement];
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
@import <Foundation/Foundation.j>
|
||||
@import "CPResponder.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;
|
||||
|
||||
[_delegate _popoverWindowDidShow];
|
||||
}
|
||||
};
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
_DOMElement.addEventListener(CPBrowserStyleProperty('transitionend'), _transitionCompleteFunction, YES);
|
||||
|
||||
@@ -181,7 +181,7 @@ var _CPToolTipHeight = 24.0,
|
||||
textFrameSize.height += 4;
|
||||
|
||||
_content = [CPTextField labelWithTitle:aString];
|
||||
[_content setFont:[CPFont systemFontOfSize:_CPToolTipFontSize]]
|
||||
[_content setFont:[CPFont systemFontOfSize:_CPToolTipFontSize]];
|
||||
[_content setLineBreakMode:CPLineBreakByCharWrapping];
|
||||
[_content setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
|
||||
[_content setFrameOrigin:CGPointMake(0.0, 0.0)];
|
||||
|
||||
@@ -393,7 +393,7 @@
|
||||
|
||||
while (index !== CPNotFound)
|
||||
{
|
||||
_remove(_proxyObject, _removeSEL, index)
|
||||
_remove(_proxyObject, _removeSEL, index);
|
||||
index = [theIndexes indexLessThanIndex:index];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,8 +82,7 @@
|
||||
*/
|
||||
- (void)encodePoint:(CGPoint)aPoint
|
||||
{
|
||||
[self encodeNumber:aPoint.x];
|
||||
[self encodeNumber:aPoint.y];
|
||||
_CPRaiseInvalidAbstractInvocation(self, _cmd);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -92,8 +91,7 @@
|
||||
*/
|
||||
- (void)encodeRect:(CGRect)aRect
|
||||
{
|
||||
[self encodePoint:aRect.origin];
|
||||
[self encodeSize:aRect.size];
|
||||
_CPRaiseInvalidAbstractInvocation(self, _cmd);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -102,8 +100,7 @@
|
||||
*/
|
||||
- (void)encodeSize:(CGSize)aSize
|
||||
{
|
||||
[self encodeNumber:aSize.width];
|
||||
[self encodeNumber:aSize.height];
|
||||
_CPRaiseInvalidAbstractInvocation(self, _cmd);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||