Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0036f329f5 | ||
|
|
15af54efda | ||
|
|
07966bb7fe | ||
|
|
e7d9b0503b | ||
|
|
072b43d178 | ||
|
|
281d2295ae | ||
|
|
79cf4370b4 | ||
|
|
6217fc8459 | ||
|
|
f1fd3d170a | ||
|
|
4e410f8a81 | ||
|
|
7a1b273d8d | ||
|
|
820531342d | ||
|
|
353db3277a | ||
|
|
82f37549ae | ||
|
|
09e1bd6bf1 | ||
|
|
44f3abf262 | ||
|
|
8c09af5013 | ||
|
|
0781e932c6 | ||
|
|
3cee00323c | ||
|
|
b1f6f3ddfa | ||
|
|
7147266ddf | ||
|
|
357212bff7 | ||
|
|
ed4fc3b20f | ||
|
|
7e8b71dd52 | ||
|
|
267f00bfe1 | ||
|
|
8f90dbce99 | ||
|
|
00485dba89 | ||
|
|
8fd4f5e4b6 | ||
|
|
e7e69b3fd4 | ||
|
|
2463c1dc05 | ||
|
|
bc590286f2 | ||
|
|
8c83816ec8 | ||
|
|
699069ce8f | ||
|
|
ec0cd22c1d | ||
|
|
8da3a8866d | ||
|
|
21f6fdff48 | ||
|
|
ed82a1fc87 | ||
|
|
1fa143453d | ||
|
|
1240bab7ed | ||
|
|
4af29d83d7 | ||
|
|
6aed29af91 | ||
|
|
37f1f50000 | ||
|
|
a93654c66b | ||
|
|
0d2dd94c81 | ||
|
|
c2f97e9aa3 | ||
|
|
e04bf6de95 | ||
|
|
38499c006a | ||
|
|
80cac38682 | ||
|
|
2b16d36aa2 | ||
|
|
dc9d49a12c | ||
|
|
03c81dfa9c | ||
|
|
b096e5dd0a | ||
|
|
7ae519145f | ||
|
|
592c3c1652 | ||
|
|
e940f294a6 | ||
|
|
759de8f45f | ||
|
|
c92c6c37f7 | ||
|
|
f425601043 | ||
|
|
68ba089a26 | ||
|
|
5ff7169546 | ||
|
|
7365a95b4d | ||
|
|
788427ec09 | ||
|
|
01ed8ad583 | ||
|
|
f516ba7a7d | ||
|
|
ab5603bd5a | ||
|
|
5c560e82b3 | ||
|
|
263a94af18 | ||
|
|
9d1cf360b6 | ||
|
|
60f664a5c2 | ||
|
|
a1c7aa7790 | ||
|
|
a29096ca5c | ||
|
|
0ef64f4091 | ||
|
|
945deeba60 | ||
|
|
aa775675b5 | ||
|
|
db76044880 | ||
|
|
edc58e358b | ||
|
|
1133efb3f1 | ||
|
|
d524accc98 | ||
|
|
543f91dd6e | ||
|
|
9848dabfa8 | ||
|
|
bc59efc3ba | ||
|
|
9af63ca32f | ||
|
|
eb8a566ae8 | ||
|
|
38eb3e489e | ||
|
|
97f7eaf499 | ||
|
|
d3356eea5c | ||
|
|
7a57bd73c3 | ||
|
|
b517c93190 | ||
|
|
7a9fded2e4 | ||
|
|
8ed2096de7 | ||
|
|
791a1eb130 | ||
|
|
9dab10ce19 | ||
|
|
fd95c2ced6 | ||
|
|
c32fef0eb9 | ||
|
|
c77b35c07b | ||
|
|
4303ea3584 | ||
|
|
ddb6f63ea7 | ||
|
|
06985a5b6c | ||
|
|
4841f209b3 | ||
|
|
7e6ed01dd2 | ||
|
|
b7e41894af | ||
|
|
5dfcfc32e7 | ||
|
|
fb74541796 | ||
|
|
2f7b29593e | ||
|
|
7ce6b1cfda | ||
|
|
7ad1d14d15 | ||
|
|
444c30e389 | ||
|
|
06fc31c33b | ||
|
|
4c58077cee | ||
|
|
25253942a6 | ||
|
|
4d75b47713 | ||
|
|
63c500c444 | ||
|
|
208c3fea35 | ||
|
|
3201b5921c | ||
|
|
e92a7825bf | ||
|
|
65b1fb2bae | ||
|
|
98df7e1eb8 | ||
|
|
86079af3b1 | ||
|
|
eeab0cf1b2 | ||
|
|
ac16b7ad0b | ||
|
|
e9b87d7acc | ||
|
|
b37893d9bb | ||
|
|
6f4ecdfbd9 | ||
|
|
697921b486 | ||
|
|
3c01d4aa8b | ||
|
|
a1eafdfbd8 | ||
|
|
2cfb171b38 | ||
|
|
2742e3d77b | ||
|
|
5488d8f633 | ||
|
|
35c7155983 | ||
|
|
b90a8a58fd | ||
|
|
85fa2011b2 | ||
|
|
063b05d964 | ||
|
|
ac90a0c0fb | ||
|
|
3efe33d2fb | ||
|
|
3e5ea97768 | ||
|
|
a970657312 | ||
|
|
240615c71b | ||
|
|
d3f4e205af | ||
|
|
cc63c239f6 | ||
|
|
4b82cae638 | ||
|
|
68c8d15ed4 | ||
|
|
021f5bb030 | ||
|
|
fc5d9a413d | ||
|
|
e09acb9208 | ||
|
|
2f57404c9c | ||
|
|
a29bdf0cf4 | ||
|
|
c29597689c | ||
|
|
797fbca6d4 | ||
|
|
6ed4b289d8 | ||
|
|
7dd07b2f5b | ||
|
|
b371fda0a5 | ||
|
|
3bdb11d804 | ||
|
|
199b777dcc | ||
|
|
70ccec2e82 | ||
|
|
a195624549 | ||
|
|
e417eba6bd | ||
|
|
210bb3e5c9 | ||
|
|
140ae354a1 | ||
|
|
2451b08306 | ||
|
|
04d33e772f | ||
|
|
3592fd8dae | ||
|
|
889e8d3b6e | ||
|
|
908fc67f96 | ||
|
|
c9a645285a | ||
|
|
3655724810 | ||
|
|
866047c116 | ||
|
|
8912d31bec | ||
|
|
1e65342814 | ||
|
|
c7ca352205 | ||
|
|
4b1ce8bc0b | ||
|
|
422e940bc7 | ||
|
|
76e2a2b8ca | ||
|
|
e3565bdc7d | ||
|
|
86f01cfaec | ||
|
|
6e4007adc0 | ||
|
|
8c6913c399 | ||
|
|
efdfd0db10 | ||
|
|
d6412eec58 | ||
|
|
53a6d2de83 | ||
|
|
7fe990e9f6 | ||
|
|
7b7ad0715b | ||
|
|
1a57d032b9 | ||
|
|
77bb169680 | ||
|
|
b424c19eee | ||
|
|
4d597069cf | ||
|
|
5afbdf7f20 | ||
|
|
33f558b221 | ||
|
|
b05d0dd1ec | ||
|
|
b2b305cc4b | ||
|
|
c5a9ee544c | ||
|
|
368d66f76e | ||
|
|
5aaae61b46 | ||
|
|
29fe50c2d7 | ||
|
|
d0c59ee253 | ||
|
|
d2e39238f4 | ||
|
|
4aec3f7466 | ||
|
|
c8991e07b9 | ||
|
|
48157db973 | ||
|
|
d070e5fce5 | ||
|
|
a8fae51ea8 | ||
|
|
2815d462be | ||
|
|
85f8ca9241 | ||
|
|
b5fb9e8c23 | ||
|
|
1addc002d3 | ||
|
|
e99e2660e9 | ||
|
|
03d1bb8bce | ||
|
|
5b00f7f2e8 | ||
|
|
97b7f0901e | ||
|
|
67b2671dad | ||
|
|
7886d49e65 | ||
|
|
e5284e9b43 | ||
|
|
c6403baa04 | ||
|
|
662b1ec696 | ||
|
|
9570e541d9 | ||
|
|
043df71185 | ||
|
|
8dab47f4da | ||
|
|
90d069df2b | ||
|
|
dcbe3ee650 | ||
|
|
e32489aba1 | ||
|
|
b619c0b793 | ||
|
|
fab61d14fa | ||
|
|
b4edc084f8 | ||
|
|
c7518d0c49 | ||
|
|
a40345c14d | ||
|
|
909471a5d7 | ||
|
|
38f7ea00c2 | ||
|
|
9f459f053e | ||
|
|
4195f3b8c6 | ||
|
|
4926824482 | ||
|
|
cb2f539cf7 | ||
|
|
7f31be7cb1 | ||
|
|
78b9c5b576 | ||
|
|
01e35efdbb | ||
|
|
bef1687b1f | ||
|
|
afa691376e | ||
|
|
be10bcf27a | ||
|
|
89b23ef0d7 | ||
|
|
b958911c63 | ||
|
|
f7a7f06c67 | ||
|
|
860f0d5846 |
@@ -9,4 +9,4 @@ WebSite
|
||||
*.xcodeproj/*.perspectivev3
|
||||
xcuserdata/
|
||||
!*.xcodeproj/project.pbxproj
|
||||
target
|
||||
*.xCodeSupport/
|
||||
|
||||
@@ -37,14 +37,12 @@
|
||||
@import "CPCibControlConnector.j"
|
||||
@import "CPCibLoading.j"
|
||||
@import "CPCibOutletConnector.j"
|
||||
@import "CPCibRuntimeAttributesConnector.j"
|
||||
@import "CPClipView.j"
|
||||
@import "CPCollectionView.j"
|
||||
@import "CPCollectionViewItem.j"
|
||||
@import "CPColor.j"
|
||||
@import "CPColorPanel.j"
|
||||
@import "CPColorWell.j"
|
||||
@import "CPComboBox.j"
|
||||
@import "CPCompatibility.j"
|
||||
@import "CPControl.j"
|
||||
@import "CPCookie.j"
|
||||
|
||||
@@ -371,8 +371,8 @@ CPCriticalAlertStyle = 2;
|
||||
[_informativeLabel setAlignment:[self currentValueForThemeAttribute:@"informative-text-alignment"]];
|
||||
[_informativeLabel setLineBreakMode:CPLineBreakByWordWrapping];
|
||||
|
||||
informativeLabelWidth = CGRectGetWidth([[_window contentView] frame]) - inset.left - inset.right,
|
||||
informativeLabelOriginY = [_messageLabel frameOrigin].y + [_messageLabel frameSize].height + defaultElementsMargin,
|
||||
informativeLabelWidth = CGRectGetWidth([[_window contentView] frame]) - inset.left - inset.right;
|
||||
informativeLabelOriginY = [_messageLabel frameOrigin].y + [_messageLabel frameSize].height + defaultElementsMargin;
|
||||
informativeLabelTextSize = [[_informativeLabel stringValue] sizeWithFont:[_informativeLabel font] inWidth:informativeLabelWidth];
|
||||
|
||||
[_informativeLabel setFrame:CGRectMake(inset.left, informativeLabelOriginY, informativeLabelTextSize.width, informativeLabelTextSize.height + sizeWithFontCorrection)];
|
||||
|
||||
@@ -107,7 +107,7 @@ CPRunContinuesResponse = -1002;
|
||||
|
||||
CPPanel _aboutPanel;
|
||||
|
||||
CPArray _themeBlends @accessors(property=themeBlends);
|
||||
CPThemeBlend _themeBlend @accessors(property=themeBlend);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -141,8 +141,6 @@ CPRunContinuesResponse = -1002;
|
||||
_windows = [];
|
||||
|
||||
[_windows addObject:nil];
|
||||
|
||||
_themeBlends = [];
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -1158,16 +1156,6 @@ CPRunContinuesResponse = -1002;
|
||||
userInfo:nil];
|
||||
}
|
||||
|
||||
- (CPThemeBlend)themeBlend
|
||||
{
|
||||
return (_themeBlends.length > 0 ? _themeBlends[0] : nil);
|
||||
}
|
||||
|
||||
- (void)setThemeBlend:(CPThemeBlend)aThemeBlend
|
||||
{
|
||||
_themeBlends[0] = aThemeBlend;
|
||||
}
|
||||
|
||||
+ (CPString)defaultThemeName
|
||||
{
|
||||
return ([[CPBundle mainBundle] objectForInfoDictionaryKey:"CPDefaultTheme"] || @"Aristo");
|
||||
@@ -1230,14 +1218,15 @@ function CPApplicationMain(args, namedArgs)
|
||||
[_CPAppBootstrapper performActions];
|
||||
}
|
||||
|
||||
var _CPAppBootstrapperActions = nil,
|
||||
_CPAppThemeURLsToLoad = [];
|
||||
var _CPAppBootstrapperActions = nil;
|
||||
|
||||
@implementation _CPAppBootstrapper : CPObject
|
||||
{
|
||||
}
|
||||
|
||||
+ (CPArray)actions
|
||||
{
|
||||
return [@selector(bootstrapPlatform), @selector(loadThemes), @selector(loadMainCibFile)];
|
||||
return [@selector(bootstrapPlatform), @selector(loadDefaultTheme), @selector(loadMainCibFile)];
|
||||
}
|
||||
|
||||
+ (void)performActions
|
||||
@@ -1261,30 +1250,17 @@ var _CPAppBootstrapperActions = nil,
|
||||
return [CPPlatform bootstrap];
|
||||
}
|
||||
|
||||
+ (BOOL)loadThemes
|
||||
+ (BOOL)loadDefaultTheme
|
||||
{
|
||||
_CPAppThemeURLsToLoad.push([CPApplication defaultThemeName]);
|
||||
var defaultThemeName = [CPApplication defaultThemeName],
|
||||
themeURL = nil;
|
||||
|
||||
var auxiliaryThemes = ([[CPBundle mainBundle] objectForInfoDictionaryKey:@"CPAuxiliaryThemes"] || []);
|
||||
|
||||
_CPAppThemeURLsToLoad = _CPAppThemeURLsToLoad.concat(auxiliaryThemes);
|
||||
|
||||
[self loadNextTheme];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (BOOL)loadNextTheme
|
||||
{
|
||||
var themeName = _CPAppThemeURLsToLoad.shift();
|
||||
|
||||
if (themeName === @"Aristo")
|
||||
themeURL = [[CPBundle bundleForClass:[CPApplication class]] pathForResource:themeName + @".blend"];
|
||||
if (defaultThemeName === @"Aristo")
|
||||
themeURL = [[CPBundle bundleForClass:[CPApplication class]] pathForResource:defaultThemeName + @".blend"];
|
||||
else
|
||||
themeURL = [[CPBundle mainBundle] pathForResource:themeName + @".blend"];
|
||||
themeURL = [[CPBundle mainBundle] pathForResource:defaultThemeName + @".blend"];
|
||||
|
||||
var blend = [[CPThemeBlend alloc] initWithContentsOfURL:themeURL];
|
||||
|
||||
[blend loadWithDelegate:self];
|
||||
|
||||
return YES;
|
||||
@@ -1292,17 +1268,10 @@ var _CPAppBootstrapperActions = nil,
|
||||
|
||||
+ (void)blendDidFinishLoading:(CPThemeBlend)aThemeBlend
|
||||
{
|
||||
var themeBlends = [CPApp themeBlends];
|
||||
[[CPApplication sharedApplication] setThemeBlend:aThemeBlend];
|
||||
[CPTheme setDefaultTheme:[CPTheme themeNamed:[CPApplication defaultThemeName]]];
|
||||
|
||||
[themeBlends addObject:aThemeBlend];
|
||||
|
||||
if ([themeBlends count] === 1)
|
||||
[CPTheme setDefaultTheme:[CPTheme themeNamed:[CPApplication defaultThemeName]]];
|
||||
|
||||
if (_CPAppThemeURLsToLoad.length === 0)
|
||||
[self performActions];
|
||||
else
|
||||
[self loadNextTheme];
|
||||
[self performActions];
|
||||
}
|
||||
|
||||
+ (BOOL)loadMainCibFile
|
||||
@@ -1371,8 +1340,8 @@ var _CPAppBootstrapperActions = nil,
|
||||
[editMenu addItem:undoMenuItem];
|
||||
[editMenu addItem:redoMenuItem];
|
||||
|
||||
[editMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Cut" action:@selector(cut:) keyEquivalent:@"x"]],
|
||||
[editMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Copy" action:@selector(copy:) keyEquivalent:@"c"]],
|
||||
[editMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Cut" action:@selector(cut:) keyEquivalent:@"x"]];
|
||||
[editMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Copy" action:@selector(copy:) keyEquivalent:@"c"]];
|
||||
[editMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Paste" action:@selector(paste:) keyEquivalent:@"v"]];
|
||||
|
||||
[editMenuItem setSubmenu:editMenu];
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
@import "CPObjectController.j"
|
||||
@import "CPKeyValueBinding.j"
|
||||
|
||||
|
||||
/*!
|
||||
|
||||
@class CPArrayController
|
||||
@@ -285,7 +284,8 @@
|
||||
|
||||
if (value === nil)
|
||||
value = [];
|
||||
else if (![value isKindOfClass:[CPArray class]])
|
||||
|
||||
if (![value isKindOfClass:[CPArray class]])
|
||||
value = [value];
|
||||
|
||||
var oldSelectedObjects = nil,
|
||||
@@ -339,6 +339,14 @@
|
||||
[self setContent:anArray];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)_setContentSet:(id)aSet
|
||||
{
|
||||
[self setContent:[aSet allObjects]];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the content array of the controller.
|
||||
@return id the content array of the receiver
|
||||
@@ -348,14 +356,6 @@
|
||||
return [self content];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)_setContentSet:(id)aSet
|
||||
{
|
||||
[self setContent:[aSet allObjects]];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the content of the receiver as a CPSet.
|
||||
|
||||
@@ -564,13 +564,9 @@
|
||||
- (BOOL)setSelectionIndexes:(CPIndexSet)indexes
|
||||
{
|
||||
[self _selectionWillChange]
|
||||
|
||||
// When explicitly setting the selection, ignore avoidsEmptySelection
|
||||
var changed = [self __setSelectionIndexes:indexes obeyAvoidsEmptySelection:NO];
|
||||
|
||||
[self _selectionDidChangeNotify:NO];
|
||||
|
||||
return changed;
|
||||
var r = [self __setSelectionIndexes:indexes];
|
||||
[self _selectionDidChange];
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -579,7 +575,7 @@
|
||||
*/
|
||||
- (BOOL)__setSelectionIndex:(int)theIndex
|
||||
{
|
||||
return [self __setSelectionIndexes:[CPIndexSet indexSetWithIndex:theIndex] obeyAvoidsEmptySelection:YES];
|
||||
return [self __setSelectionIndexes:[CPIndexSet indexSetWithIndex:theIndex]];
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -588,37 +584,38 @@
|
||||
*/
|
||||
- (BOOL)__setSelectionIndexes:(CPIndexSet)indexes
|
||||
{
|
||||
[self __setSelectionIndexes:indexes obeyAvoidsEmptySelection:YES];
|
||||
}
|
||||
var newIndexes = indexes;
|
||||
|
||||
/*
|
||||
Like setSelectionIndexes but don't fire any change notifications.
|
||||
@ignore
|
||||
*/
|
||||
- (BOOL)__setSelectionIndexes:(CPIndexSet)indexes obeyAvoidsEmptySelection:(BOOL)obeyAvoidsEmptySelection
|
||||
{
|
||||
if (!indexes)
|
||||
indexes = [CPIndexSet indexSet];
|
||||
if (!newIndexes)
|
||||
newIndexes = [CPIndexSet indexSet];
|
||||
|
||||
if (![indexes count])
|
||||
if (![newIndexes count])
|
||||
{
|
||||
if (obeyAvoidsEmptySelection && _avoidsEmptySelection && [[self arrangedObjects] count])
|
||||
indexes = [CPIndexSet indexSetWithIndex:0];
|
||||
if (_avoidsEmptySelection && [[self arrangedObjects] count])
|
||||
newIndexes = [CPIndexSet indexSetWithIndex:0];
|
||||
}
|
||||
else
|
||||
{
|
||||
var objectsCount = [[self arrangedObjects] count];
|
||||
|
||||
// Don't trash the input - the caller might depend on it or we might have been
|
||||
// given _selectionIndexes as the input in which case the equality test below
|
||||
// would always succeed despite our change below.
|
||||
newIndexes = [newIndexes copy];
|
||||
|
||||
// Remove out of bounds indexes.
|
||||
[indexes removeIndexesInRange:CPMakeRange(objectsCount, [indexes lastIndex] + 1)];
|
||||
[newIndexes removeIndexesInRange:CPMakeRange(objectsCount, [newIndexes lastIndex] + 1)];
|
||||
// When avoiding empty selection and the deleted selection was at the bottom, select the last item.
|
||||
if (![indexes count] && _avoidsEmptySelection && objectsCount)
|
||||
indexes = [CPIndexSet indexSetWithIndex:objectsCount - 1];
|
||||
if (![newIndexes count] && _avoidsEmptySelection && objectsCount)
|
||||
newIndexes = [CPIndexSet indexSetWithIndex:objectsCount - 1];
|
||||
}
|
||||
|
||||
if ([_selectionIndexes isEqualToIndexSet:indexes])
|
||||
if ([_selectionIndexes isEqualToIndexSet:newIndexes])
|
||||
return NO;
|
||||
|
||||
_selectionIndexes = [indexes copy];
|
||||
// If we haven't already created our own index instance, make sure to copy it here so that
|
||||
// the copy the user sent in is decoupled from our internal copy.
|
||||
_selectionIndexes = indexes === newIndexes ? [indexes copy] : newIndexes;
|
||||
|
||||
// Push back the new selection to the model for selectionIndexes if we have one.
|
||||
// There won't be an infinite loop because of the equality check above.
|
||||
@@ -650,10 +647,11 @@
|
||||
[self willChangeValueForKey:@"selectionIndexes"];
|
||||
[self _selectionWillChange];
|
||||
|
||||
[self __setSelectedObjects:objects obeyAvoidsEmptySelection:NO];
|
||||
var r = [self __setSelectedObjects:objects];
|
||||
|
||||
[self didChangeValueForKey:@"selectionIndexes"];
|
||||
[self _selectionDidChangeNotify:NO];
|
||||
[self _selectionDidChange];
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -661,15 +659,6 @@
|
||||
@ignore
|
||||
*/
|
||||
- (BOOL)__setSelectedObjects:(CPArray)objects
|
||||
{
|
||||
[self __setSelectedObjects:objects obeyAvoidsEmptySelection:YES];
|
||||
}
|
||||
|
||||
/*
|
||||
Like setSelectedObjects but don't fire any change notifications.
|
||||
@ignore
|
||||
*/
|
||||
- (BOOL)__setSelectedObjects:(CPArray)objects obeyAvoidsEmptySelection:(BOOL)obeyAvoidsEmptySelection
|
||||
{
|
||||
var set = [CPIndexSet indexSet],
|
||||
count = [objects count],
|
||||
@@ -683,7 +672,7 @@
|
||||
[set addIndex:index];
|
||||
}
|
||||
|
||||
[self __setSelectionIndexes:set obeyAvoidsEmptySelection:obeyAvoidsEmptySelection];
|
||||
[self __setSelectionIndexes:set];
|
||||
return YES;
|
||||
}
|
||||
|
||||
@@ -752,13 +741,21 @@
|
||||
}
|
||||
|
||||
[self willChangeValueForKey:@"content"];
|
||||
[self _willModifyContent];
|
||||
|
||||
/*
|
||||
If the content array is bound then our addObject: message below will cause the observed
|
||||
array to change. The binding will call setContent:_contentObject on this array
|
||||
controller to let it know about the change. We want to ignore that message since we
|
||||
A) already have the right _contentObject and B) properly update _arrangedObjects
|
||||
by hand below.
|
||||
*/
|
||||
_disableSetContent = YES;
|
||||
[_contentObject addObject:object];
|
||||
|
||||
// Allow handlesContentAsCompoundValue reverse sets to trigger.
|
||||
[[CPBinder getBinding:@"contentArray" forObject:self] _contentArrayDidChange];
|
||||
|
||||
[self _didModifyContent];
|
||||
_disableSetContent = NO;
|
||||
|
||||
if (willClearPredicate)
|
||||
{
|
||||
@@ -779,15 +776,14 @@
|
||||
[_selectionIndexes shiftIndexesStartingAtIndex:pos by:1];
|
||||
}
|
||||
/*
|
||||
else if (_filterPredicate !== nil)
|
||||
...
|
||||
Implies _filterPredicate && ![_filterPredicate evaluateWithObject:object], so the new object does
|
||||
not appear in arrangedObjects and we do not have to update at all.
|
||||
else if (_filterPredicate !== nil)
|
||||
...
|
||||
// Implies _filterPredicate && ![_filterPredicate evaluateWithObject:object], so the new object does
|
||||
// not appear in arrangedObjects and we do not have to update at all.
|
||||
*/
|
||||
|
||||
// This will also send notificaitons for arrangedObjects.
|
||||
[self didChangeValueForKey:@"content"];
|
||||
|
||||
if (willClearPredicate)
|
||||
[self didChangeValueForKey:@"filterPredicate"];
|
||||
}
|
||||
@@ -813,7 +809,10 @@
|
||||
|
||||
[self willChangeValueForKey:@"content"];
|
||||
|
||||
[self _willModifyContent];
|
||||
/*
|
||||
See _disableSetContent explanation in addObject:.
|
||||
*/
|
||||
_disableSetContent = YES;
|
||||
|
||||
// The atArrangedObjectIndex: part of this method's name only refers to where the
|
||||
// object goes in arrangedObjects, not in the content array. So use addObject:,
|
||||
@@ -822,7 +821,7 @@
|
||||
// Allow handlesContentAsCompoundValue reverse sets to trigger.
|
||||
[[CPBinder getBinding:@"contentArray" forObject:self] _contentArrayDidChange];
|
||||
|
||||
[self _didModifyContent];
|
||||
_disableSetContent = NO;
|
||||
|
||||
if (willClearPredicate)
|
||||
[self __setFilterPredicate:nil];
|
||||
@@ -840,7 +839,6 @@
|
||||
[self __setSelectionIndexes:[CPIndexSet indexSetWithIndex:0]];
|
||||
|
||||
[self didChangeValueForKey:@"content"];
|
||||
|
||||
if (willClearPredicate)
|
||||
[self didChangeValueForKey:@"filterPredicate"];
|
||||
}
|
||||
@@ -853,13 +851,15 @@
|
||||
- (void)removeObject:(id)object
|
||||
{
|
||||
[self willChangeValueForKey:@"content"];
|
||||
[self _willModifyContent];
|
||||
|
||||
// See _disableSetContent explanation in addObject:.
|
||||
_disableSetContent = YES;
|
||||
|
||||
[_contentObject removeObject:object];
|
||||
// Allow handlesContentAsCompoundValue reverse sets to trigger.
|
||||
[[CPBinder getBinding:@"contentArray" forObject:self] _contentArrayDidChange];
|
||||
|
||||
[self _didModifyContent];
|
||||
_disableSetContent = NO;
|
||||
|
||||
if (_filterPredicate === nil || [_filterPredicate evaluateWithObject:object])
|
||||
{
|
||||
@@ -910,15 +910,6 @@
|
||||
[self removeObjectsAtArrangedObjectIndexes:_selectionIndexes];
|
||||
}
|
||||
|
||||
/*!
|
||||
Removes the object at the specified index in the controller's arranged objects from the content array.
|
||||
@param int index - index of the object to remove.
|
||||
*/
|
||||
- (void)removeObjectAtArrangedObjectIndex:(int)index
|
||||
{
|
||||
[self removeObjectsAtArrangedObjectIndexes:[CPIndexSet indexSetWithIndex:index]];
|
||||
}
|
||||
|
||||
/*!
|
||||
Removes the objects at the specified indexes in the controller's arranged objects from the content array.
|
||||
@param CPIndexSet indexes - indexes of the objects to remove.
|
||||
@@ -927,21 +918,20 @@
|
||||
{
|
||||
[self willChangeValueForKey:@"content"];
|
||||
|
||||
/*
|
||||
See _disableSetContent explanation in addObject:.
|
||||
*/
|
||||
_disableSetContent = YES;
|
||||
|
||||
var arrangedObjects = [self arrangedObjects],
|
||||
index = [anIndexSet lastIndex],
|
||||
position = CPNotFound,
|
||||
newSelectionIndexes = [_selectionIndexes copy],
|
||||
proxy = [_CPKVOProxy proxyForObject:self];
|
||||
newSelectionIndexes = [_selectionIndexes copy];
|
||||
|
||||
while (index !== CPNotFound)
|
||||
{
|
||||
var object = [arrangedObjects objectAtIndex:index];
|
||||
|
||||
// Make sure arrangedObjects does not notify because of content change
|
||||
[proxy suppressNotificationsForKeyPath:@"arrangedObjects"];
|
||||
|
||||
// First try the simple case which should work if there are no sort descriptors.
|
||||
if ([_contentObject objectAtIndex:index] === object)
|
||||
[_contentObject removeObjectAtIndex:index];
|
||||
@@ -955,9 +945,6 @@
|
||||
contentIndex = [_contentObject indexOfObjectIdenticalTo:object];
|
||||
[_contentObject removeObjectAtIndex:contentIndex];
|
||||
}
|
||||
|
||||
// Now arrangedObjects can notify
|
||||
[proxy unsuppressNotificationsForKeyPath:@"arrangedObjects"];
|
||||
[arrangedObjects removeObjectAtIndex:index];
|
||||
|
||||
// Deselect this row if it was selected, and either way shift all selection indexes
|
||||
@@ -967,7 +954,6 @@
|
||||
|
||||
index = [anIndexSet indexLessThanIndex:index];
|
||||
}
|
||||
|
||||
// Allow handlesContentAsCompoundValue reverse sets to trigger.
|
||||
[[CPBinder getBinding:@"contentArray" forObject:self] _contentArrayDidChange];
|
||||
_disableSetContent = NO;
|
||||
@@ -1014,13 +1000,15 @@
|
||||
- (void)_removeObjects:(CPArray)objects
|
||||
{
|
||||
[self willChangeValueForKey:@"content"];
|
||||
[self _willModifyContent];
|
||||
|
||||
// See _disableSetContent explanation in addObject:.
|
||||
_disableSetContent = YES;
|
||||
|
||||
[_contentObject removeObjectsInArray:objects];
|
||||
// Allow handlesContentAsCompoundValue reverse sets to trigger.
|
||||
[[CPBinder getBinding:@"contentArray" forObject:self] _contentArrayDidChange];
|
||||
|
||||
[self _didModifyContent];
|
||||
_disableSetContent = NO;
|
||||
|
||||
var arrangedObjects = [self arrangedObjects],
|
||||
position = [arrangedObjects indexOfObject:[objects objectAtIndex:0]];
|
||||
@@ -1057,39 +1045,13 @@
|
||||
return [self isEditable];
|
||||
}
|
||||
|
||||
// Internal
|
||||
- (void)_willModifyContent
|
||||
{
|
||||
/*
|
||||
If the content array is bound then our addObject: message below will cause the observed
|
||||
array to change. The binding will call setContent:_contentObject on this array
|
||||
controller to let it know about the change. We want to ignore that message since we
|
||||
A) already have the right _contentObject and B) properly update _arrangedObjects
|
||||
by hand below.
|
||||
*/
|
||||
_disableSetContent = YES;
|
||||
|
||||
/*
|
||||
When mutating arrangedObjects, we mutate the content first. But mutating the content
|
||||
will trigger a notification that the arrangedObjects have changed, which we want to
|
||||
suppress, since the arrangedObjects mutation will do the correct notification.
|
||||
*/
|
||||
[[_CPKVOProxy proxyForObject:self] suppressNotificationsForKeyPath:@"arrangedObjects"];
|
||||
}
|
||||
|
||||
- (void)_didModifyContent
|
||||
{
|
||||
_disableSetContent = NO;
|
||||
[[_CPKVOProxy proxyForObject:self] unsuppressNotificationsForKeyPath:@"arrangedObjects"];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPArrayController (CPBinder)
|
||||
|
||||
+ (Class)_binderClassForBinding:(CPString)theBinding
|
||||
{
|
||||
if (theBinding === @"content" || theBinding === @"contentArray")
|
||||
if (theBinding == @"contentArray")
|
||||
return [_CPArrayControllerContentBinder class];
|
||||
|
||||
return [super _binderClassForBinding:theBinding];
|
||||
@@ -1104,7 +1066,7 @@
|
||||
var destination = [_info objectForKey:CPObservedObjectKey],
|
||||
keyPath = [_info objectForKey:CPObservedKeyPathKey],
|
||||
options = [_info objectForKey:CPOptionsKey],
|
||||
isCompound = [self handlesContentAsCompoundValue] || keyPath.indexOf("@") !== -1;
|
||||
isCompound = [self handlesContentAsCompoundValue];
|
||||
|
||||
if (!isCompound)
|
||||
{
|
||||
|
||||
@@ -60,7 +60,7 @@ var cachedBlackColor,
|
||||
/*!
|
||||
Orientation to use with \c CPColorPattern for vertical patterns.
|
||||
*/
|
||||
CPColorPatternIsVertical = YES,
|
||||
CPColorPatternIsVertical = YES;
|
||||
|
||||
/*!
|
||||
Orientation to use with \c CPColorPattern for horizontal patterns.
|
||||
|
||||
@@ -51,7 +51,7 @@ CPWheelColorPickerMode = 1;
|
||||
*/
|
||||
CPSliderColorPickerMode = 2;
|
||||
|
||||
CPColorPickerViewWidth = 265,
|
||||
CPColorPickerViewWidth = 265;
|
||||
CPColorPickerViewHeight = 370;
|
||||
|
||||
/*!
|
||||
|
||||
@@ -526,7 +526,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
// Cocoa raises an invalid parameter assertion and returns if you pass nil.
|
||||
if (aString === nil || aString === undefined)
|
||||
{
|
||||
CPLog.warn("nil or undefined sent to CPControl -setStringValue");
|
||||
CPLog.warn("nil sent to CPControl -setStringValue");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -536,10 +536,10 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
{
|
||||
value = nil;
|
||||
|
||||
if (![_formatter getObjectValue:AT_REF(value) forString:aString errorDescription:nil])
|
||||
if ([_formatter getObjectValue:AT_REF(value) forString:aString errorDescription:nil] === NO)
|
||||
{
|
||||
// If the given string is non-empty and doesn't work, Cocoa tries an empty string.
|
||||
if (!aString || ![_formatter getObjectValue:AT_REF(value) forString:@"" errorDescription:nil])
|
||||
if (!aString || [_formatter getObjectValue:AT_REF(value) forString:@"" errorDescription:nil] === NO)
|
||||
value = undefined; // Means the value is invalid
|
||||
}
|
||||
}
|
||||
|
||||
@@ -571,10 +571,12 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
if (_modifierFlags & (CPCommandKeyMask | CPControlKeyMask))
|
||||
return YES;
|
||||
|
||||
// Cocoa does not consider space, backspace, or escape a key equivalent
|
||||
// if the first responder is a text field (presumably a subclass of NSText).
|
||||
// Cocoa allows almost any key as a key equivalent unless the first responder is a
|
||||
// text field (presumably a subclass of NSText.)
|
||||
var firstResponderIsText = [[_window firstResponder] isKindOfClass:[CPTextField class]];
|
||||
|
||||
// Some keys are accepted as key equivalents even if the first responder is a text
|
||||
// field.
|
||||
for (var i = 0; i < characterCount; i++)
|
||||
{
|
||||
var c = _characters.charAt(i);
|
||||
@@ -583,18 +585,13 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
c === CPEnterCharacter ||
|
||||
c === CPNewlineCharacter ||
|
||||
c === CPCarriageReturnCharacter ||
|
||||
c === CPEscapeFunctionKey ||
|
||||
(!firstResponderIsText &&
|
||||
(c === CPSpaceFunctionKey ||
|
||||
c === CPDeleteCharacter ||
|
||||
c === CPBackspaceCharacter)))
|
||||
c === CPEscapeFunctionKey)
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: More cases?
|
||||
return NO;
|
||||
return !firstResponderIsText;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -204,6 +204,7 @@ var CPBindingOperationAnd = 0,
|
||||
if (valueTransformer)
|
||||
aValue = [valueTransformer transformedValue:aValue];
|
||||
|
||||
|
||||
if (aValue === undefined || aValue === nil || aValue === [CPNull null])
|
||||
aValue = [options objectForKey:CPNullPlaceholderBindingOption] || nil;
|
||||
|
||||
@@ -313,7 +314,7 @@ var CPBindingOperationAnd = 0,
|
||||
return CPLog.error("Invalid object or path on " + self + " for " + aBinding);
|
||||
|
||||
//if (![[self exposedBindings] containsObject:aBinding])
|
||||
// CPLog.warn("No binding exposed on "+self+" for "+aBinding);
|
||||
// CPLog.warn("No binding exposed on " + self + " for " + aBinding);
|
||||
|
||||
var binderClass = [[self class] _binderClassForBinding:aBinding];
|
||||
|
||||
@@ -487,8 +488,6 @@ CPSelectedIndexBinding = @"selectedIndex";
|
||||
CPTextColorBinding = @"textColor";
|
||||
CPToolTipBinding = @"toolTip";
|
||||
CPValueBinding = @"value";
|
||||
CPContentBinding = @"content";
|
||||
CPContentValuesBinding = @"contentValues";
|
||||
|
||||
//Binding options constants
|
||||
CPAllowsEditingMultipleValuesSelectionBindingOption = @"CPAllowsEditingMultipleValuesSelection";
|
||||
|
||||
@@ -352,8 +352,12 @@ var _CPMenuBarVisible = NO,
|
||||
while (count--)
|
||||
[_items[count] setMenu:nil];
|
||||
|
||||
_items = [CPMutableArray array];
|
||||
_highlightedIndex = CPNotFound;
|
||||
|
||||
// Because we are changing _items directly, be sure to notify KVO
|
||||
[self willChangeValueForKey:@"items"];
|
||||
_items = [CPMutableArray array];
|
||||
[self didChangeValueForKey:@"items"];
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
@import <Foundation/CPObject.j>
|
||||
|
||||
|
||||
_CPMenuManagerScrollingStateUp = -1,
|
||||
_CPMenuManagerScrollingStateDown = 1,
|
||||
_CPMenuManagerScrollingStateUp = -1;
|
||||
_CPMenuManagerScrollingStateDown = 1;
|
||||
_CPMenuManagerScrollingStateNone = 0;
|
||||
|
||||
var STICKY_TIME_INTERVAL = 500,
|
||||
|
||||
@@ -131,8 +131,8 @@
|
||||
|
||||
_contentObject = aContent;
|
||||
|
||||
[self didChangeValueForKey:@"contentObject"];
|
||||
[self _selectionDidChange];
|
||||
[self didChangeValueForKey:@"contentObject"];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -323,22 +323,12 @@
|
||||
@ignore
|
||||
*/
|
||||
- (void)_selectionDidChange
|
||||
{
|
||||
[self _selectionDidChangeNotify:YES];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)_selectionDidChangeNotify:(BOOL)notify
|
||||
{
|
||||
if (_selection === undefined || _selection === nil)
|
||||
_selection = [[CPControllerSelectionProxy alloc] initWithController:self];
|
||||
|
||||
[_selection controllerDidChange];
|
||||
|
||||
if (notify)
|
||||
[self didChangeValueForKey:@"selection"];
|
||||
[self didChangeValueForKey:@"selection"];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -676,21 +666,21 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
|
||||
var count = [theValues count];
|
||||
|
||||
if (!count)
|
||||
return CPNoSelectionMarker;
|
||||
value = CPNoSelectionMarker;
|
||||
else if (count === 1)
|
||||
value = [theValues objectAtIndex:0];
|
||||
else
|
||||
{
|
||||
if ([_controller alwaysUsesMultipleValuesMarker])
|
||||
return CPMultipleValuesMarker;
|
||||
value = CPMultipleValuesMarker;
|
||||
else
|
||||
{
|
||||
value = [theValues objectAtIndex:0];
|
||||
|
||||
for (var i = 0, count = [theValues count]; i < count; i++)
|
||||
for (var i = 0, count= [theValues count]; i < count && value != CPMultipleValuesMarker; i++)
|
||||
{
|
||||
if (![value isEqual:[theValues objectAtIndex:i]])
|
||||
return CPMultipleValuesMarker;
|
||||
value = CPMultipleValuesMarker;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -703,21 +693,8 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
|
||||
|
||||
- (id)valueForKeyPath:(CPString)theKeyPath
|
||||
{
|
||||
// If valueForKeyPath fails because of an undefined key, return CPNotApplicableMarker
|
||||
var value;
|
||||
|
||||
try
|
||||
{
|
||||
var values = [[_controller selectedObjects] valueForKeyPath:theKeyPath];
|
||||
value = [self _controllerMarkerForValues:values];
|
||||
}
|
||||
catch (ex)
|
||||
{
|
||||
if ([ex name] === CPUndefinedKeyException)
|
||||
value = CPNotApplicableMarker;
|
||||
else
|
||||
throw ex;
|
||||
}
|
||||
var values = [[_controller selectedObjects] valueForKeyPath:theKeyPath];
|
||||
value = [self _controllerMarkerForValues:values];
|
||||
|
||||
[_cachedValues setObject:value forKey:theKeyPath];
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
|
||||
[self setPullsDown:shouldPullDown];
|
||||
|
||||
var options = CPKeyValueObservingOptionNew |CPKeyValueObservingOptionOld;/* |CPKeyValueObservingOptionInitial;*/
|
||||
var options = CPKeyValueObservingOptionNew | CPKeyValueObservingOptionOld; // | CPKeyValueObservingOptionInitial;
|
||||
[self addObserver:self forKeyPath:@"menu.items" options:options context:nil];
|
||||
[self addObserver:self forKeyPath:@"_firstItem.changeCount" options:options context:nil];
|
||||
[self addObserver:self forKeyPath:@"selectedItem.changeCount" options:options context:nil];
|
||||
@@ -193,6 +193,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
- (void)removeAllItems
|
||||
{
|
||||
[[self menu] removeAllItems];
|
||||
[self synchronizeTitleAndSelectedItem];
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -39,7 +39,7 @@ CPPopoverBehaviorSemitransient = 2;
|
||||
var CPPopoverDelegate_popover_willShow_ = 1 << 0,
|
||||
CPPopoverDelegate_popover_didShow_ = 1 << 1,
|
||||
CPPopoverDelegate_popover_shouldClose_ = 1 << 2,
|
||||
CPPopoverDelegate_popover_willClose_ = 1 << 3,
|
||||
CPPopoverDelegate_popover_willClose_ = 1 << 3,
|
||||
CPPopoverDelegate_popover_didClose_ = 1 << 4;
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark INitialization
|
||||
#pragma mark Initialization
|
||||
|
||||
/*!
|
||||
Initialize the CPPopover witn default values
|
||||
@@ -103,7 +103,7 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
|
||||
|
||||
@return CPRect represeting the frame of the popover
|
||||
*/
|
||||
- (CPRect)positionningRect
|
||||
- (CPRect)positioningRect
|
||||
{
|
||||
if (!_attachedWindow || ![_attachedWindow isVisible])
|
||||
return nil;
|
||||
@@ -113,7 +113,7 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
|
||||
/*! Sets the frame of the popover
|
||||
@param aRect the desired frame
|
||||
*/
|
||||
- (void)setPositionningRect:(CPRect)aRect
|
||||
- (void)setPositioningRect:(CPRect)aRect
|
||||
{
|
||||
if (!_attachedWindow || ![_attachedWindow isVisible])
|
||||
return;
|
||||
@@ -196,14 +196,14 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Positionning
|
||||
#pragma mark Positioning
|
||||
|
||||
/*!
|
||||
Show the popover
|
||||
|
||||
@param positioningRect if set, the popover will be positionned to a random rect relative to the window
|
||||
@param positioningView if set, the popover will be positioned relative to this view
|
||||
@param preferredEdge: CPRectEdge representing the prefered positionning.
|
||||
@param preferredEdge: CPRectEdge representing the preferred positioning.
|
||||
*/
|
||||
- (void)showRelativeToRect:(CPRect)positioningRect ofView:(CPView)positioningView preferredEdge:(CPRectEdge)preferredEdge
|
||||
{
|
||||
@@ -213,7 +213,7 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
|
||||
if (!_contentViewController)
|
||||
[CPException raise:CPInternalInconsistencyException reason:@"contentViewController must not be nil"];
|
||||
|
||||
if (_needsCompute)
|
||||
if (_needsCompute || !_attachedWindow)
|
||||
{
|
||||
var styleMask = (_behavior == CPPopoverBehaviorTransient) ? CPClosableOnBlurWindowMask : nil;
|
||||
_attachedWindow = [[_CPAttachedWindow alloc] initWithContentRect:CPRectMakeZero() styleMask:styleMask];
|
||||
@@ -221,6 +221,7 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
|
||||
|
||||
[_attachedWindow setAppearance:_appearance];
|
||||
[_attachedWindow setAnimates:_animates];
|
||||
[_attachedWindow setDelegate:self];
|
||||
[_attachedWindow setMovableByWindowBackground:NO];
|
||||
[_attachedWindow setFrame:[_attachedWindow frameRectForContentRect:[[_contentViewController view] frame]]];
|
||||
[_attachedWindow setContentView:[_contentViewController view]];
|
||||
@@ -230,7 +231,7 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
|
||||
else if (positioningView)
|
||||
[_attachedWindow positionRelativeToView:positioningView preferredEdge:preferredEdge];
|
||||
else
|
||||
[CPException raise:CPInvalidArgumentException reason:@"you must set positioningRect or positioningRect"];
|
||||
[CPException raise:CPInvalidArgumentException reason:@"a value must be passed for positioningRect or positioningView"];
|
||||
|
||||
if (_implementedDelegateMethods & CPPopoverDelegate_popover_didShow_)
|
||||
[_delegate popoverDidShow:self];
|
||||
@@ -268,8 +269,28 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
|
||||
[self close];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Delegates
|
||||
|
||||
/*! @ignore */
|
||||
- (BOOL)attachedWindowShouldClose:(_CPAttachedWindow)anAttachedWindow
|
||||
{
|
||||
[self close];
|
||||
|
||||
// we return NO, because we want the CPPopover to compute
|
||||
// if the attached can be close in order to send delegate messages
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var CPPopoverNeedsComputeKey = @"CPPopoverNeedsComputeKey",
|
||||
CPPopoverAppearanceKey = @"CPPopoverAppearanceKey",
|
||||
CPPopoverAnimatesKey = @"CPPopoverAnimatesKey",
|
||||
CPPopoverContentViewControllerKey = @"CPPopoverContentViewControllerKey",
|
||||
CPPopoverDelegateKey = @"CPPopoverDelegateKey",
|
||||
CPPopoverBehaviorKey = @"CPPopoverBehaviorKey";
|
||||
|
||||
@implementation CPPopover (CPCoding)
|
||||
|
||||
@@ -279,12 +300,12 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
|
||||
|
||||
if (self)
|
||||
{
|
||||
_needsCompute = [aCoder decodeIntForKey:@"_needsCompute"];
|
||||
_appearance = [aCoder decodeIntForKey:@"_appearance"];
|
||||
_animates = [aCoder decodeBoolForKey:@"_animates"];
|
||||
_contentViewController = [aCoder decodeObjectForKey:@"_contentViewController"];
|
||||
[self setDelegate:[aCoder decodeObjectForKey:@"_delegate"]];
|
||||
[self setBehaviour:[aCoder decodeIntForKey:@"_behavior"]];
|
||||
_needsCompute = [aCoder decodeIntForKey:CPPopoverNeedsComputeKey];
|
||||
_appearance = [aCoder decodeIntForKey:CPPopoverAppearanceKey];
|
||||
_animates = [aCoder decodeBoolForKey:CPPopoverAnimatesKey];
|
||||
_contentViewController = [aCoder decodeObjectForKey:CPPopoverContentViewControllerKey];
|
||||
[self setDelegate:[aCoder decodeObjectForKey:CPPopoverDelegateKey]];
|
||||
[self setBehaviour:[aCoder decodeIntForKey:CPPopoverBehaviorKey]];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -293,12 +314,12 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
|
||||
{
|
||||
[super encodeWithCoder:aCoder];
|
||||
|
||||
[aCoder encodeInt:_behavior forKey:@"_behavior"];
|
||||
[aCoder encodeInt:_appearance forKey:@"_appearance"];
|
||||
[aCoder encodeBool:_needsCompute forKey:@"_needsCompute"];
|
||||
[aCoder encodeObject:_contentViewController forKey:@"_contentViewController"];
|
||||
[aCoder encodeObject:_delegate forKey:@"_delegate"];
|
||||
[aCoder encodeObject:_animates forKey:@"_animates"];
|
||||
[aCoder encodeBool:_needsCompute forKey:CPPopoverNeedsComputeKey];
|
||||
[aCoder encodeInt:_appearance forKey:CPPopoverAppearanceKey];
|
||||
[aCoder encodeObject:_animates forKey:CPPopoverAnimatesKey];
|
||||
[aCoder encodeObject:_contentViewController forKey:CPPopoverContentViewControllerKey];
|
||||
[aCoder encodeObject:_delegate forKey:CPPopoverDelegateKey];
|
||||
[aCoder encodeInt:_behavior forKey:CPPopoverBehaviorKey];
|
||||
}
|
||||
|
||||
@end
|
||||
@end
|
||||
|
||||
@@ -150,6 +150,14 @@ CPRadioImageOffset = 4.0;
|
||||
[_radioGroup _setSelectedRadio:self];
|
||||
}
|
||||
|
||||
- (void)sendAction:(SEL)anAction to:(id)anObject
|
||||
{
|
||||
[super sendAction:anAction to:anObject];
|
||||
|
||||
if (_radioGroup)
|
||||
[CPApp sendAction:[_radioGroup action] to:[_radioGroup target] from:_radioGroup];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var CPRadioRadioGroupKey = @"CPRadioRadioGroupKey";
|
||||
@@ -220,8 +228,6 @@ var CPRadioRadioGroupKey = @"CPRadioRadioGroupKey";
|
||||
|
||||
[_selectedRadio setState:CPOffState];
|
||||
_selectedRadio = aRadio;
|
||||
|
||||
[CPApp sendAction:_action to:_target from:self];
|
||||
}
|
||||
|
||||
- (CPRadio)selectedRadio
|
||||
|
||||
@@ -200,7 +200,7 @@
|
||||
if (isPopup)
|
||||
{
|
||||
itemArray = [[templateView itemArray] valueForKey:@"title"];
|
||||
itemsCount = [itemArray count],
|
||||
itemsCount = [itemArray count];
|
||||
menuIndex = 0;
|
||||
}
|
||||
|
||||
@@ -501,4 +501,4 @@ var CPPredicateTemplatesKey = @"CPPredicateTemplates";
|
||||
|
||||
@end
|
||||
|
||||
/*! @endcond */
|
||||
/*! @endcond */
|
||||
|
||||
@@ -20,17 +20,17 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
CPUndefinedAttributeType = 0,
|
||||
CPInteger16AttributeType = 100,
|
||||
CPInteger32AttributeType = 200,
|
||||
CPInteger64AttributeType = 300,
|
||||
CPDecimalAttributeType = 400,
|
||||
CPDoubleAttributeType = 500,
|
||||
CPFloatAttributeType = 600,
|
||||
CPStringAttributeType = 700,
|
||||
CPBooleanAttributeType = 800,
|
||||
CPDateAttributeType = 900,
|
||||
CPBinaryDataAttributeType = 1000,
|
||||
CPUndefinedAttributeType = 0;
|
||||
CPInteger16AttributeType = 100;
|
||||
CPInteger32AttributeType = 200;
|
||||
CPInteger64AttributeType = 300;
|
||||
CPDecimalAttributeType = 400;
|
||||
CPDoubleAttributeType = 500;
|
||||
CPFloatAttributeType = 600;
|
||||
CPStringAttributeType = 700;
|
||||
CPBooleanAttributeType = 800;
|
||||
CPDateAttributeType = 900;
|
||||
CPBinaryDataAttributeType = 1000;
|
||||
CPTransformableAttributeType = 1800;
|
||||
|
||||
@implementation CPPredicateEditorRowTemplate : CPObject
|
||||
@@ -785,4 +785,4 @@ var CPPredicateTemplateTypeKey = @"CPPredicateTemplateType",
|
||||
}
|
||||
|
||||
@end
|
||||
/*! @endcond */
|
||||
/*! @endcond */
|
||||
|
||||
@@ -16,12 +16,12 @@ var GRADIENT_NORMAL,
|
||||
{
|
||||
if (CPBrowserIsEngine(CPWebKitBrowserEngine))
|
||||
{
|
||||
GRADIENT_NORMAL = "-webkit-gradient(linear, left top, left bottom, from(rgb(252, 252, 252)), to(rgb(223, 223, 223)))",
|
||||
GRADIENT_NORMAL = "-webkit-gradient(linear, left top, left bottom, from(rgb(252, 252, 252)), to(rgb(223, 223, 223)))";
|
||||
GRADIENT_HIGHLIGHTED = "-webkit-gradient(linear, left top, left bottom, from(rgb(223, 223, 223)), to(rgb(252, 252, 252)))";
|
||||
}
|
||||
else if (CPBrowserIsEngine(CPGeckoBrowserEngine))
|
||||
{
|
||||
GRADIENT_NORMAL = "-moz-linear-gradient(top, rgb(252, 252, 252), rgb(223, 223, 223))",
|
||||
GRADIENT_NORMAL = "-moz-linear-gradient(top, rgb(252, 252, 252), rgb(223, 223, 223))";
|
||||
GRADIENT_HIGHLIGHTED = "-moz-linear-gradient(top, rgb(223, 223, 223), rgb(252, 252, 252))";
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ var GRADIENT_NORMAL,
|
||||
style.border = "1px solid rgb(189, 189, 189)";
|
||||
style.filter = IE_FILTER;
|
||||
|
||||
[self setTextColor:[CPColor colorWithWhite:101/255 alpha:1]];
|
||||
[self setTextColor:[CPColor colorWithWhite:101 / 255 alpha:1]];
|
||||
[self setBordered:NO];
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
* Created by Francisco Tolmasky.
|
||||
* Copyright 2008, 280 North, Inc.
|
||||
*
|
||||
* Modified to match Lion style by Antoine Mercadal 2011
|
||||
* <antoine.mercadal@archipelproject.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
@@ -22,7 +25,6 @@
|
||||
|
||||
@import "CPControl.j"
|
||||
|
||||
|
||||
// CPScroller Constants
|
||||
CPScrollerNoPart = 0;
|
||||
CPScrollerDecrementPage = 1;
|
||||
@@ -54,6 +56,17 @@ NAMES_FOR_PARTS[CPScrollerKnobSlot] = @"knob-slot";
|
||||
NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
||||
|
||||
|
||||
CPScrollerStyleLegacy = 0;
|
||||
CPScrollerStyleOverlay = 1;
|
||||
|
||||
CPScrollerKnobStyleDefault = 0;
|
||||
CPScrollerKnobStyleDark = 1;
|
||||
CPScrollerKnobStyleLight = 2;
|
||||
|
||||
CPThemeStateScrollViewLegacy = CPThemeState("scroller-style-legacy");
|
||||
CPThemeStateScrollerKnobLight = CPThemeState("scroller-knob-light");
|
||||
CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
|
||||
|
||||
@implementation CPScroller : CPControl
|
||||
{
|
||||
CPControlSize _controlSize;
|
||||
@@ -68,8 +81,19 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
||||
CPScrollerPart _trackingPart;
|
||||
float _trackingFloatValue;
|
||||
CGPoint _trackingStartPoint;
|
||||
|
||||
CPViewAnimation _animationScroller;
|
||||
|
||||
BOOL _allowFadingOut @accessors(getter=allowFadingOut);
|
||||
int _style;
|
||||
CPTimer _timerFadeOut;
|
||||
BOOL _isMouseOver;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Class methods
|
||||
|
||||
+ (CPString)defaultThemeClass
|
||||
{
|
||||
return "scroller";
|
||||
@@ -78,49 +102,43 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
||||
+ (id)themeAttributes
|
||||
{
|
||||
return [CPDictionary dictionaryWithJSObject:{
|
||||
@"scroller-width": 15.0,
|
||||
@"knob-slot-color": [CPColor lightGrayColor],
|
||||
@"scroller-width": 7.0,
|
||||
@"knob-slot-color": [CPNull null],
|
||||
@"decrement-line-color": [CPNull null],
|
||||
@"increment-line-color": [CPNull null],
|
||||
@"knob-color": [CPColor grayColor],
|
||||
@"knob-color": [CPNull null],
|
||||
@"decrement-line-size":_CGSizeMakeZero(),
|
||||
@"increment-line-size":_CGSizeMakeZero(),
|
||||
@"track-inset":_CGInsetMakeZero(),
|
||||
@"knob-inset": _CGInsetMakeZero(),
|
||||
@"minimum-knob-length":21.0
|
||||
}]
|
||||
@"minimum-knob-length":21.0,
|
||||
@"track-border-overlay": 9.0
|
||||
}];
|
||||
}
|
||||
|
||||
|
||||
// Calculating Layout
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
+ (float)scrollerWidth
|
||||
{
|
||||
self = [super initWithFrame:aFrame];
|
||||
|
||||
if (self)
|
||||
{
|
||||
_controlSize = CPRegularControlSize;
|
||||
_partRects = [];
|
||||
|
||||
[self setFloatValue:0.0];
|
||||
[self setKnobProportion:1.0];
|
||||
|
||||
_hitPart = CPScrollerNoPart;
|
||||
|
||||
[self _calculateIsVertical];
|
||||
}
|
||||
|
||||
return self;
|
||||
return [self scrollerWidthInStyle:CPScrollerStyleLegacy];
|
||||
}
|
||||
|
||||
// Determining CPScroller Size
|
||||
/*!
|
||||
Returns the CPScroller's width for a CPRegularControlSize.
|
||||
*/
|
||||
+ (float)scrollerWidth
|
||||
+ (float)scrollerWidthInStyle:(int)aStyle
|
||||
{
|
||||
return [[[CPScroller alloc] init] currentValueForThemeAttribute:@"scroller-width"];
|
||||
var scroller = [[self alloc] init];
|
||||
|
||||
if (aStyle == CPScrollerStyleLegacy)
|
||||
return [scroller valueForThemeAttribute:@"scroller-width" inState:CPThemeStateScrollViewLegacy];
|
||||
return [scroller currentValueForThemeAttribute:@"scroller-width"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the CPScroller's overlay value.
|
||||
*/
|
||||
+ (float)scrollerOverlay
|
||||
{
|
||||
return [[[self alloc] init] currentValueForThemeAttribute:@"track-border-overlay"];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -132,6 +150,87 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
||||
return [self scrollerWidth];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
{
|
||||
if (self = [super initWithFrame:aFrame])
|
||||
{
|
||||
_controlSize = CPRegularControlSize;
|
||||
_partRects = [];
|
||||
|
||||
[self setFloatValue:0.0];
|
||||
[self setKnobProportion:1.0];
|
||||
|
||||
_hitPart = CPScrollerNoPart;
|
||||
_allowFadingOut = YES;
|
||||
_isMouseOver = NO;
|
||||
_style = CPScrollerStyleOverlay;
|
||||
var paramAnimFadeOut = [CPDictionary dictionaryWithObjects:[self, CPViewAnimationFadeOutEffect]
|
||||
forKeys:[CPViewAnimationTargetKey, CPViewAnimationEffectKey]];
|
||||
|
||||
_animationScroller = [[CPViewAnimation alloc] initWithDuration:0.2 animationCurve:CPAnimationEaseInOut];
|
||||
[_animationScroller setViewAnimations:[paramAnimFadeOut]];
|
||||
[_animationScroller setDelegate:self];
|
||||
[self setAlphaValue:0.0];
|
||||
[self _calculateIsVertical];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Getters / Setters
|
||||
|
||||
/*!
|
||||
Returns the scroller's style
|
||||
*/
|
||||
- (void)style
|
||||
{
|
||||
return _style;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the scroller's control size
|
||||
@param aStyle the scroller style: CPScrollerStyleLegacy or CPScrollerStyleOverlay
|
||||
*/
|
||||
- (void)setStyle:(id)aStyle
|
||||
{
|
||||
if (_style != nil && _style === aStyle)
|
||||
return;
|
||||
|
||||
_style = aStyle;
|
||||
|
||||
if (_style === CPScrollerStyleLegacy)
|
||||
{
|
||||
[self fadeIn];
|
||||
[self setThemeState:CPThemeStateScrollViewLegacy];
|
||||
}
|
||||
else
|
||||
{
|
||||
_allowFadingOut = YES;
|
||||
[self unsetThemeState:CPThemeStateScrollViewLegacy];
|
||||
}
|
||||
|
||||
[self _adjustScrollerSize];
|
||||
}
|
||||
|
||||
- (void)setObjectValue:(id)aValue
|
||||
{
|
||||
[super setObjectValue:MIN(1.0, MAX(0.0, +aValue))];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the scroller's control size
|
||||
*/
|
||||
- (CPControlSize)controlSize
|
||||
{
|
||||
return _controlSize;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the scroller's size.
|
||||
@param aControlSize the scroller's size
|
||||
@@ -148,18 +247,17 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the scroller's control size
|
||||
Return's the knob's proportion
|
||||
*/
|
||||
- (CPControlSize)controlSize
|
||||
- (float)knobProportion
|
||||
{
|
||||
return _controlSize;
|
||||
}
|
||||
|
||||
- (void)setObjectValue:(id)aValue
|
||||
{
|
||||
[super setObjectValue:MIN(1.0, MAX(0.0, +aValue))];
|
||||
return _knobProportion;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the knob's proportion
|
||||
@param aProportion the desired proportion
|
||||
*/
|
||||
- (void)setKnobProportion:(float)aProportion
|
||||
{
|
||||
_knobProportion = MIN(1.0, MAX(0.0001, aProportion));
|
||||
@@ -168,25 +266,35 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
/*!
|
||||
Return's the knob's proportion
|
||||
*/
|
||||
- (float)knobProportion
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Privates
|
||||
|
||||
/*! @ignore */
|
||||
- (void)_adjustScrollerSize
|
||||
{
|
||||
return _knobProportion;
|
||||
var frame = [self frame],
|
||||
scrollerWidth = [self currentValueForThemeAttribute:@"scroller-width"];
|
||||
|
||||
if ([self isVertical] && CGRectGetWidth(frame) !== scrollerWidth)
|
||||
frame.size.width = scrollerWidth;
|
||||
|
||||
if (![self isVertical] && CGRectGetHeight(frame) !== scrollerWidth)
|
||||
frame.size.height = scrollerWidth;
|
||||
|
||||
[self setFrame:frame];
|
||||
}
|
||||
|
||||
- (id)currentValueForThemeAttribute:(CPString)anAttributeName
|
||||
/*! @ignore */
|
||||
- (void)_performFadeOut:(CPTimer)aTimer
|
||||
{
|
||||
var themeState = _themeState;
|
||||
|
||||
if (NAMES_FOR_PARTS[_hitPart] + "-color" !== anAttributeName)
|
||||
themeState &= ~CPThemeStateHighlighted;
|
||||
|
||||
return [self valueForThemeAttribute:anAttributeName inState:themeState];
|
||||
[self fadeOut];
|
||||
_timerFadeOut = nil;
|
||||
}
|
||||
|
||||
// Calculating Layout
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Utilities
|
||||
|
||||
- (CGRect)rectForPart:(CPScrollerPart)aPart
|
||||
{
|
||||
@@ -208,6 +316,9 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
||||
// The ordering of these tests is important. We check the knob and
|
||||
// page rects first since they may overlap with the arrows.
|
||||
|
||||
if (![self hasThemeState:CPThemeStateSelected])
|
||||
return CPScrollerNoPart;
|
||||
|
||||
if (CGRectContainsPoint([self rectForPart:CPScrollerKnob], aPoint))
|
||||
return CPScrollerKnob;
|
||||
|
||||
@@ -330,7 +441,35 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
||||
return _usableParts;
|
||||
}
|
||||
|
||||
// Drawing the Parts
|
||||
/*!
|
||||
Display the scroller
|
||||
*/
|
||||
- (void)fadeIn
|
||||
{
|
||||
if (_isMouseOver && _knobProportion != 1.0)
|
||||
[self setThemeState:CPThemeStateSelected];
|
||||
|
||||
if (_timerFadeOut)
|
||||
[_timerFadeOut invalidate];
|
||||
|
||||
[self setAlphaValue:1.0];
|
||||
}
|
||||
|
||||
/*!
|
||||
Start the fade out anination
|
||||
*/
|
||||
- (void)fadeOut
|
||||
{
|
||||
if ([self hasThemeState:CPThemeStateScrollViewLegacy])
|
||||
return;
|
||||
|
||||
[_animationScroller startAnimation];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Drawing
|
||||
|
||||
/*!
|
||||
Draws the specified arrow and sets the highlight.
|
||||
@param anArrow the arrow to draw
|
||||
@@ -457,7 +596,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
||||
}
|
||||
|
||||
[CPApp setTarget:self selector:@selector(trackKnob:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
|
||||
|
||||
|
||||
if (type === CPLeftMouseDragged)
|
||||
[self sendAction:[self action] to:[self target]];
|
||||
}
|
||||
@@ -565,6 +704,20 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Overrides
|
||||
|
||||
- (id)currentValueForThemeAttribute:(CPString)anAttributeName
|
||||
{
|
||||
var themeState = _themeState;
|
||||
|
||||
if (NAMES_FOR_PARTS[_hitPart] + "-color" !== anAttributeName)
|
||||
themeState &= ~CPThemeStateHighlighted;
|
||||
|
||||
return [self valueForThemeAttribute:anAttributeName inState:themeState];
|
||||
}
|
||||
|
||||
- (void)mouseDown:(CPEvent)anEvent
|
||||
{
|
||||
if (![self isEnabled])
|
||||
@@ -583,10 +736,52 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
||||
}
|
||||
}
|
||||
|
||||
- (void)mouseEntered:(CPEvent)anEvent
|
||||
{
|
||||
[super mouseEntered:anEvent];
|
||||
|
||||
if (_timerFadeOut)
|
||||
[_timerFadeOut invalidate];
|
||||
|
||||
if (![self isEnabled])
|
||||
return;
|
||||
|
||||
_allowFadingOut = NO;
|
||||
_isMouseOver = YES;
|
||||
|
||||
if ([self alphaValue] > 0 && _knobProportion != 1.0)
|
||||
[self setThemeState:CPThemeStateSelected];
|
||||
}
|
||||
|
||||
- (void)mouseExited:(CPEvent)anEvent
|
||||
{
|
||||
[super mouseExited:anEvent];
|
||||
|
||||
if ([self isHidden] || ![self isEnabled] || !_isMouseOver)
|
||||
return;
|
||||
|
||||
_allowFadingOut = YES;
|
||||
_isMouseOver = NO;
|
||||
|
||||
if (_timerFadeOut)
|
||||
[_timerFadeOut invalidate];
|
||||
_timerFadeOut = [CPTimer scheduledTimerWithTimeInterval:1.2 target:self selector:@selector(_performFadeOut:) userInfo:nil repeats:NO];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Delegates
|
||||
|
||||
- (void)animationDidEnd:(CPAnimation)animation
|
||||
{
|
||||
[self unsetThemeState:CPThemeStateSelected];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var CPScrollerControlSizeKey = "CPScrollerControlSize",
|
||||
CPScrollerKnobProportionKey = "CPScrollerKnobProportion";
|
||||
var CPScrollerControlSizeKey = @"CPScrollerControlSize",
|
||||
CPScrollerKnobProportionKey = @"CPScrollerKnobProportion",
|
||||
CPScrollerStyleKey = @"CPScrollerStyleKey";
|
||||
|
||||
@implementation CPScroller (CPCoding)
|
||||
|
||||
@@ -606,20 +801,18 @@ var CPScrollerControlSizeKey = "CPScrollerControlSize",
|
||||
|
||||
_hitPart = CPScrollerNoPart;
|
||||
|
||||
_allowFadingOut = YES;
|
||||
_isMouseOver = NO;
|
||||
var paramAnimFadeOut = [CPDictionary dictionaryWithObjects:[self, CPViewAnimationFadeOutEffect]
|
||||
forKeys:[CPViewAnimationTargetKey, CPViewAnimationEffectKey]];
|
||||
_animationScroller = [[CPViewAnimation alloc] initWithDuration:0.2 animationCurve:CPAnimationEaseInOut];
|
||||
[_animationScroller setViewAnimations:[paramAnimFadeOut]];
|
||||
[_animationScroller setDelegate:self];
|
||||
[self setAlphaValue:0.0];
|
||||
|
||||
[self _calculateIsVertical];
|
||||
|
||||
// Adjust the size of the scroller if the size from cib
|
||||
// isn't equal to the scrollerWidth
|
||||
var frame = [self frame],
|
||||
scrollerWidth = [CPScroller scrollerWidth];
|
||||
|
||||
if ([self isVertical] && CGRectGetWidth(frame) !== scrollerWidth)
|
||||
frame.size.width = scrollerWidth;
|
||||
|
||||
if (![self isVertical] && CGRectGetHeight(frame) !== scrollerWidth)
|
||||
frame.size.height = scrollerWidth;
|
||||
|
||||
[self setFrame:frame];
|
||||
[self setStyle:[aCoder decodeIntForKey:CPScrollerStyleKey]];
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -631,6 +824,7 @@ var CPScrollerControlSizeKey = "CPScrollerControlSize",
|
||||
|
||||
[aCoder encodeInt:_controlSize forKey:CPScrollerControlSizeKey];
|
||||
[aCoder encodeFloat:_knobProportion forKey:CPScrollerKnobProportionKey];
|
||||
[aCoder encodeInt:_style forKey:CPScrollerStyleKey];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -20,16 +20,43 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "../Foundation/Foundation.h"
|
||||
|
||||
@import "CPButtonBar.j"
|
||||
@import "CPImage.j"
|
||||
@import "CPView.j"
|
||||
|
||||
#define SPLIT_VIEW_MAYBE_POST_WILL_RESIZE() \
|
||||
if ((_suppressResizeNotificationsMask & DidPostWillResizeNotification) === 0) \
|
||||
{ \
|
||||
[self _postNotificationWillResize]; \
|
||||
_suppressResizeNotificationsMask |= DidPostWillResizeNotification; \
|
||||
}
|
||||
|
||||
#define SPLIT_VIEW_MAYBE_POST_DID_RESIZE() \
|
||||
if ((_suppressResizeNotificationsMask & ShouldSuppressResizeNotifications) !== 0) \
|
||||
_suppressResizeNotificationsMask |= DidSuppressResizeNotification; \
|
||||
else \
|
||||
[self _postNotificationDidResize];
|
||||
|
||||
#define SPLIT_VIEW_DID_SUPPRESS_RESIZE_NOTIFICATION() \
|
||||
((_suppressResizeNotificationsMask & DidSuppressResizeNotification) !== 0)
|
||||
|
||||
#define SPLIT_VIEW_SUPPRESS_RESIZE_NOTIFICATIONS(shouldSuppress) \
|
||||
if (shouldSuppress) \
|
||||
_suppressResizeNotificationsMask |= ShouldSuppressResizeNotifications; \
|
||||
else \
|
||||
_suppressResizeNotificationsMask = 0;
|
||||
|
||||
CPSplitViewDidResizeSubviewsNotification = @"CPSplitViewDidResizeSubviewsNotification";
|
||||
CPSplitViewWillResizeSubviewsNotification = @"CPSplitViewWillResizeSubviewsNotification";
|
||||
|
||||
var CPSplitViewHorizontalImage = nil,
|
||||
CPSplitViewVerticalImage = nil;
|
||||
CPSplitViewVerticalImage = nil,
|
||||
|
||||
ShouldSuppressResizeNotifications = 1,
|
||||
DidPostWillResizeNotification = 1 << 1,
|
||||
DidSuppressResizeNotification = 1 << 2;
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@@ -45,24 +72,29 @@ var CPSplitViewHorizontalImage = nil,
|
||||
|
||||
@implementation CPSplitView : CPView
|
||||
{
|
||||
id _delegate;
|
||||
BOOL _isVertical;
|
||||
BOOL _isPaneSplitter;
|
||||
id _delegate;
|
||||
BOOL _isVertical;
|
||||
BOOL _isPaneSplitter;
|
||||
|
||||
int _currentDivider;
|
||||
float _initialOffset;
|
||||
float _preCollapsePosition;
|
||||
int _currentDivider;
|
||||
float _initialOffset;
|
||||
CPDictionary _preCollapsePositions;
|
||||
|
||||
CPString _originComponent;
|
||||
CPString _sizeComponent;
|
||||
CPString _originComponent;
|
||||
CPString _sizeComponent;
|
||||
|
||||
CPArray _DOMDividerElements;
|
||||
CPString _dividerImagePath;
|
||||
int _drawingDivider;
|
||||
CPArray _DOMDividerElements;
|
||||
CPString _dividerImagePath;
|
||||
int _drawingDivider;
|
||||
|
||||
BOOL _needsResizeSubviews;
|
||||
CPString _autosaveName;
|
||||
BOOL _shouldAutosave;
|
||||
BOOL _needsRestoreFromAutosave;
|
||||
|
||||
CPArray _buttonBars;
|
||||
BOOL _needsResizeSubviews;
|
||||
int _suppressResizeNotificationsMask;
|
||||
|
||||
CPArray _buttonBars;
|
||||
}
|
||||
|
||||
+ (CPString)defaultThemeClass
|
||||
@@ -93,11 +125,15 @@ var CPSplitViewHorizontalImage = nil,
|
||||
{
|
||||
if (self = [super initWithFrame:aFrame])
|
||||
{
|
||||
_suppressResizeNotificationsMask = 0;
|
||||
_preCollapsePositions = [CPMutableDictionary new];
|
||||
_currentDivider = CPNotFound;
|
||||
|
||||
_DOMDividerElements = [];
|
||||
_buttonBars = [];
|
||||
|
||||
_shouldAutosave = YES;
|
||||
|
||||
[self _setVertical:YES];
|
||||
}
|
||||
|
||||
@@ -412,7 +448,6 @@ var CPSplitViewHorizontalImage = nil,
|
||||
{
|
||||
_currentDivider = CPNotFound;
|
||||
[self _updateResizeCursor:anEvent];
|
||||
[self _postNotificationDidResize];
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -436,7 +471,8 @@ var CPSplitViewHorizontalImage = nil,
|
||||
[_delegate respondsToSelector:@selector(splitView:shouldCollapseSubview:forDoubleClickOnDividerAtIndex:)])
|
||||
{
|
||||
var minPosition = [self minPossiblePositionOfDividerAtIndex:i],
|
||||
maxPosition = [self maxPossiblePositionOfDividerAtIndex:i];
|
||||
maxPosition = [self maxPossiblePositionOfDividerAtIndex:i],
|
||||
_preCollapsePosition = [_preCollapsePositions objectForKey:"" + i] || 0;
|
||||
|
||||
if ([_delegate splitView:self canCollapseSubview:_subviews[i]] && [_delegate splitView:self shouldCollapseSubview:_subviews[i] forDoubleClickOnDividerAtIndex:i])
|
||||
{
|
||||
@@ -526,20 +562,34 @@ var CPSplitViewHorizontalImage = nil,
|
||||
// If we are currently tracking, keep the resize cursor active even outside of hit areas.
|
||||
if (_currentDivider === i || (_currentDivider == CPNotFound && [self cursorAtPoint:point hitDividerAtIndex:i]))
|
||||
{
|
||||
var frame = [_subviews[i] frame],
|
||||
size = frame.size[_sizeComponent],
|
||||
startPosition = frame.origin[_originComponent] + size,
|
||||
var frameA = [_subviews[i] frame],
|
||||
sizeA = frameA.size[_sizeComponent],
|
||||
startPosition = frameA.origin[_originComponent] + sizeA,
|
||||
frameB = [_subviews[i + 1] frame],
|
||||
sizeB = frameB.size[_sizeComponent],
|
||||
canShrink = [self _realPositionForPosition:startPosition - 1 ofDividerAtIndex:i] < startPosition,
|
||||
canGrow = [self _realPositionForPosition:startPosition + 1 ofDividerAtIndex:i] > startPosition,
|
||||
cursor = [CPCursor arrowCursor];
|
||||
|
||||
if (size === 0)
|
||||
if (sizeA === 0)
|
||||
canGrow = YES; // Subview is collapsed.
|
||||
else if (!canShrink &&
|
||||
[_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)] &&
|
||||
[_delegate splitView:self canCollapseSubview:_subviews[i]])
|
||||
canShrink = YES; // Subview is collapsible.
|
||||
|
||||
if (sizeB === 0)
|
||||
{
|
||||
// Right/lower subview is collapsed.
|
||||
canGrow = NO;
|
||||
// It's safe to assume it can always be uncollapsed.
|
||||
canShrink = YES;
|
||||
}
|
||||
else if (!canGrow &&
|
||||
[_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)] &&
|
||||
[_delegate splitView:self canCollapseSubview:_subviews[i + 1]])
|
||||
canGrow = YES; // Right/lower subview is collapsible.
|
||||
|
||||
if (_isVertical && canShrink && canGrow)
|
||||
cursor = [CPCursor resizeLeftRightCursor];
|
||||
else if (_isVertical && canShrink)
|
||||
@@ -597,7 +647,15 @@ var CPSplitViewHorizontalImage = nil,
|
||||
{
|
||||
// not sure where this should override other positions?
|
||||
if ([_delegate respondsToSelector:@selector(splitView:constrainSplitPosition:ofSubviewAt:)])
|
||||
position = [_delegate splitView:self constrainSplitPosition:position ofSubviewAt:dividerIndex];
|
||||
{
|
||||
var proposedPosition = [_delegate splitView:self constrainSplitPosition:position ofSubviewAt:dividerIndex];
|
||||
|
||||
// Silently ignore bad positions which could result from odd delegate responses. We don't want these
|
||||
// bad results to go into the system and cause havoc with frame sizes as the split view tries to resize
|
||||
// its subviews.
|
||||
if (_IS_NUMERIC(proposedPosition))
|
||||
position = proposedPosition;
|
||||
}
|
||||
|
||||
var proposedMax = [self maxPossiblePositionOfDividerAtIndex:dividerIndex],
|
||||
proposedMin = [self minPossiblePositionOfDividerAtIndex:dividerIndex],
|
||||
@@ -605,18 +663,33 @@ var CPSplitViewHorizontalImage = nil,
|
||||
actualMin = proposedMin;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitView:constrainMinCoordinate:ofSubviewAt:)])
|
||||
actualMin = [_delegate splitView:self constrainMinCoordinate:proposedMin ofSubviewAt:dividerIndex];
|
||||
{
|
||||
var proposedActualMin = [_delegate splitView:self constrainMinCoordinate:proposedMin ofSubviewAt:dividerIndex];
|
||||
if (_IS_NUMERIC(proposedActualMin))
|
||||
actualMin = proposedActualMin;
|
||||
}
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitView:constrainMaxCoordinate:ofSubviewAt:)])
|
||||
actualMax = [_delegate splitView:self constrainMaxCoordinate:proposedMax ofSubviewAt:dividerIndex];
|
||||
{
|
||||
var proposedActualMax = [_delegate splitView:self constrainMaxCoordinate:proposedMax ofSubviewAt:dividerIndex];
|
||||
if (_IS_NUMERIC(proposedActualMax))
|
||||
actualMax = proposedActualMax;
|
||||
}
|
||||
|
||||
var viewA = _subviews[dividerIndex],
|
||||
viewB = _subviews[dividerIndex + 1],
|
||||
realPosition = MAX(MIN(position, actualMax), actualMin);
|
||||
|
||||
if (position < proposedMin + (actualMin - proposedMin) / 2)
|
||||
// Is this position past the halfway point to collapse?
|
||||
if (position < proposedMin + (actualMin - proposedMin) / 2)
|
||||
if ([_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)])
|
||||
if ([_delegate splitView:self canCollapseSubview:viewA])
|
||||
realPosition = proposedMin;
|
||||
// We can also collapse to the right.
|
||||
if (position > proposedMax - (proposedMax - actualMax) / 2)
|
||||
if ([_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)])
|
||||
if ([_delegate splitView:self canCollapseSubview:viewB])
|
||||
realPosition = proposedMax;
|
||||
|
||||
return realPosition;
|
||||
}
|
||||
@@ -628,6 +701,7 @@ var CPSplitViewHorizontalImage = nil,
|
||||
*/
|
||||
- (void)setPosition:(float)position ofDividerAtIndex:(int)dividerIndex
|
||||
{
|
||||
SPLIT_VIEW_SUPPRESS_RESIZE_NOTIFICATIONS(YES);
|
||||
[self _adjustSubviewsWithCalculatedSize];
|
||||
|
||||
var realPosition = [self _realPositionForPosition:position ofDividerAtIndex:dividerIndex];
|
||||
@@ -635,32 +709,59 @@ var CPSplitViewHorizontalImage = nil,
|
||||
var viewA = _subviews[dividerIndex],
|
||||
frameA = [viewA frame],
|
||||
viewB = _subviews[dividerIndex + 1],
|
||||
frameB = [viewB frame];
|
||||
|
||||
_preCollapsePosition = 0;
|
||||
frameB = [viewB frame],
|
||||
_preCollapsePosition = 0;
|
||||
|
||||
var preSize = frameA.size[_sizeComponent];
|
||||
frameA.size[_sizeComponent] = realPosition - frameA.origin[_originComponent];
|
||||
if (preSize !== 0 && frameA.size[_sizeComponent] === 0)
|
||||
_preCollapsePosition = preSize;
|
||||
[_subviews[dividerIndex] setFrame:frameA];
|
||||
if (preSize !== frameA.size[_sizeComponent])
|
||||
{
|
||||
SPLIT_VIEW_MAYBE_POST_WILL_RESIZE();
|
||||
[_subviews[dividerIndex] setFrame:frameA];
|
||||
SPLIT_VIEW_MAYBE_POST_DID_RESIZE();
|
||||
}
|
||||
|
||||
preSize = frameB.size[_sizeComponent];
|
||||
var preOrigin = frameB.origin[_originComponent];
|
||||
frameB.size[_sizeComponent] = frameB.origin[_originComponent] + frameB.size[_sizeComponent] - realPosition - [self dividerThickness];
|
||||
if (preSize !== 0 && frameB.size[_sizeComponent] === 0)
|
||||
_preCollapsePosition = preSize;
|
||||
_preCollapsePosition = frameB.origin[_originComponent];
|
||||
frameB.origin[_originComponent] = realPosition + [self dividerThickness];
|
||||
[_subviews[dividerIndex + 1] setFrame:frameB];
|
||||
if (preSize !== frameB.size[_sizeComponent] || preOrigin !== frameB.origin[_originComponent])
|
||||
{
|
||||
SPLIT_VIEW_MAYBE_POST_WILL_RESIZE();
|
||||
[_subviews[dividerIndex + 1] setFrame:frameB];
|
||||
SPLIT_VIEW_MAYBE_POST_DID_RESIZE();
|
||||
}
|
||||
|
||||
if (_preCollapsePosition)
|
||||
[_preCollapsePositions setObject:_preCollapsePosition forKey:"" + dividerIndex];
|
||||
|
||||
[self setNeedsDisplay:YES];
|
||||
|
||||
if (SPLIT_VIEW_DID_SUPPRESS_RESIZE_NOTIFICATION())
|
||||
[self _postNotificationDidResize];
|
||||
SPLIT_VIEW_SUPPRESS_RESIZE_NOTIFICATIONS(NO);
|
||||
}
|
||||
|
||||
- (void)setFrameSize:(CGSize)aSize
|
||||
{
|
||||
[self _adjustSubviewsWithCalculatedSize];
|
||||
if (_needsRestoreFromAutosave)
|
||||
_shouldAutosave = NO;
|
||||
else
|
||||
[self _adjustSubviewsWithCalculatedSize];
|
||||
|
||||
[super setFrameSize:aSize];
|
||||
|
||||
if (_needsRestoreFromAutosave)
|
||||
{
|
||||
_needsRestoreFromAutosave = NO;
|
||||
[self _restoreFromAutosave];
|
||||
_shouldAutosave = YES;
|
||||
}
|
||||
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
@@ -672,6 +773,7 @@ var CPSplitViewHorizontalImage = nil,
|
||||
return;
|
||||
}
|
||||
|
||||
SPLIT_VIEW_MAYBE_POST_WILL_RESIZE();
|
||||
[self _postNotificationWillResize];
|
||||
|
||||
var index = 0,
|
||||
@@ -730,9 +832,10 @@ var CPSplitViewHorizontalImage = nil,
|
||||
bounds.origin[_originComponent] += viewFrame.size[_sizeComponent] + dividerThickness;
|
||||
|
||||
[view setFrame:viewFrame];
|
||||
|
||||
}
|
||||
|
||||
[self _postNotificationDidResize];
|
||||
SPLIT_VIEW_MAYBE_POST_DID_RESIZE();
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -831,6 +934,7 @@ The sum of the views and the sum of the dividers should be equal to the size of
|
||||
@param CPButtonBar - The supplied button bar.
|
||||
@param unsigned int - The divider index the button bar will be assigned to.
|
||||
*/
|
||||
// FIXME Should be renamed to setButtonBar:ofDividerAtIndex:.
|
||||
- (void)setButtonBar:(CPButtonBar)aButtonBar forDividerAtIndex:(unsigned)dividerIndex
|
||||
{
|
||||
if (!aButtonBar)
|
||||
@@ -867,15 +971,121 @@ The sum of the views and the sum of the dividers should be equal to the size of
|
||||
|
||||
- (void)_postNotificationDidResize
|
||||
{
|
||||
[self _autosave];
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPSplitViewDidResizeSubviewsNotification object:self];
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the name under which the split view divider positions is automatically saved to CPUserDefaults.
|
||||
|
||||
@param autosaveName the name to save under or nil to not save
|
||||
*/
|
||||
- (void)setAutosaveName:(CPString)autosaveName
|
||||
{
|
||||
if (_autosaveName == autosaveName)
|
||||
return;
|
||||
_autosaveName = autosaveName;
|
||||
}
|
||||
|
||||
/*!
|
||||
Get the name under which the split view divider position is automatically saved to CPUserDefaults.
|
||||
|
||||
@return the name to save under or nil if no auto save is active
|
||||
*/
|
||||
- (CPString)autosaveName
|
||||
{
|
||||
return _autosaveName;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)_autosave
|
||||
{
|
||||
if (!_shouldAutosave)
|
||||
return;
|
||||
|
||||
var userDefaults = [CPUserDefaults standardUserDefaults],
|
||||
autosaveName = [self _framesKeyForAutosaveName:[self autosaveName]],
|
||||
autosavePrecollapseName = [self _precollapseKeyForAutosaveName:[self autosaveName]],
|
||||
count = [_subviews count],
|
||||
positions = [CPMutableArray new],
|
||||
preCollapseArray = [CPMutableArray new];
|
||||
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var frame = [_subviews[i] frame];
|
||||
[positions addObject:CPStringFromRect(frame)];
|
||||
[preCollapseArray addObject:[_preCollapsePositions objectForKey:"" + i]];
|
||||
}
|
||||
|
||||
[userDefaults setObject:positions forKey:autosaveName];
|
||||
[userDefaults setObject:preCollapseArray forKey:autosavePrecollapseName];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)_restoreFromAutosave
|
||||
{
|
||||
if (!_autosaveName)
|
||||
return;
|
||||
|
||||
var autosaveName = [self _framesKeyForAutosaveName:[self autosaveName]],
|
||||
autosavePrecollapseName = [self _precollapseKeyForAutosaveName:[self autosaveName]],
|
||||
userDefaults = [CPUserDefaults standardUserDefaults],
|
||||
frames = [userDefaults objectForKey:autosaveName],
|
||||
preCollapseArray = [userDefaults objectForKey:autosavePrecollapseName];
|
||||
|
||||
if (frames)
|
||||
{
|
||||
var dividerThickness = [self dividerThickness],
|
||||
position = 0;
|
||||
|
||||
_shouldAutosave = NO;
|
||||
for (var i = 0, count = [frames count] - 1; i < count; i++)
|
||||
{
|
||||
var frame = CPRectFromString(frames[i]);
|
||||
position += frame.size[_sizeComponent];
|
||||
|
||||
[self setPosition:position ofDividerAtIndex:i];
|
||||
|
||||
position += dividerThickness;
|
||||
}
|
||||
_shouldAutosave = YES;
|
||||
}
|
||||
|
||||
if (preCollapseArray)
|
||||
{
|
||||
_preCollapsePositions = [CPMutableDictionary new];
|
||||
for (var i = 0, count = [preCollapseArray count]; i < count; i++)
|
||||
[_preCollapsePositions setObject:preCollapseArray[i] forKey:i + ""];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (CPString)_framesKeyForAutosaveName:(CPString)theAutosaveName
|
||||
{
|
||||
return @"CPSplitView Subview Frames " + theAutosaveName;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (CPString)_precollapseKeyForAutosaveName:(CPString)theAutosaveName
|
||||
{
|
||||
return @"CPSplitView Subview Precollapse Positions " + theAutosaveName;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var CPSplitViewDelegateKey = "CPSplitViewDelegateKey",
|
||||
CPSplitViewIsVerticalKey = "CPSplitViewIsVerticalKey",
|
||||
CPSplitViewIsPaneSplitterKey = "CPSplitViewIsPaneSplitterKey",
|
||||
CPSplitViewButtonBarsKey = "CPSplitViewButtonBarsKey";
|
||||
CPSplitViewButtonBarsKey = "CPSplitViewButtonBarsKey",
|
||||
CPSplitViewAutosaveNameKey = "CPSplitViewAutosaveNameKey";
|
||||
|
||||
@implementation CPSplitView (CPCoding)
|
||||
|
||||
@@ -889,7 +1099,11 @@ var CPSplitViewDelegateKey = "CPSplitViewDelegateKey",
|
||||
|
||||
if (self)
|
||||
{
|
||||
_suppressResizeNotificationsMask = 0;
|
||||
_preCollapsePositions = [CPMutableDictionary new];
|
||||
|
||||
_currentDivider = CPNotFound;
|
||||
_shouldAutosave = YES;
|
||||
|
||||
_DOMDividerElements = [];
|
||||
|
||||
@@ -899,6 +1113,13 @@ var CPSplitViewDelegateKey = "CPSplitViewDelegateKey",
|
||||
|
||||
_isPaneSplitter = [aCoder decodeBoolForKey:CPSplitViewIsPaneSplitterKey];
|
||||
[self _setVertical:[aCoder decodeBoolForKey:CPSplitViewIsVerticalKey]];
|
||||
|
||||
[self setAutosaveName:[aCoder decodeObjectForKey:CPSplitViewAutosaveNameKey]];
|
||||
|
||||
// We have to wait until we know our frame size before restoring, or the frame resize later will throw
|
||||
// away the restored size.
|
||||
if (_autosaveName)
|
||||
_needsRestoreFromAutosave = YES;
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -919,6 +1140,8 @@ var CPSplitViewDelegateKey = "CPSplitViewDelegateKey",
|
||||
|
||||
[aCoder encodeBool:_isVertical forKey:CPSplitViewIsVerticalKey];
|
||||
[aCoder encodeBool:_isPaneSplitter forKey:CPSplitViewIsPaneSplitterKey];
|
||||
|
||||
[aCoder encodeObject:_autosaveName forKey:CPSplitViewAutosaveNameKey];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -25,11 +25,11 @@
|
||||
@import <AppKit/CPTextField.j>
|
||||
|
||||
|
||||
var CPStepperButtonsSize = CPSizeMake(19, 13);
|
||||
|
||||
/*! CPStepper is an implementation of Cocoa NSStepper.
|
||||
/*!
|
||||
CPStepper is an implementation of Cocoa NSStepper.
|
||||
|
||||
This control display a two part button that can be used to increase or decrease a value with a given interval.
|
||||
This control displays a two part button that can be used to increase or decrease a value with a given interval.
|
||||
*/
|
||||
@implementation CPStepper: CPControl
|
||||
{
|
||||
@@ -45,7 +45,8 @@ var CPStepperButtonsSize = CPSizeMake(19, 13);
|
||||
#pragma mark -
|
||||
#pragma mark Initialization
|
||||
|
||||
/*! Initializes a CPStepper with given values
|
||||
/*!
|
||||
Initializes a CPStepper with given values.
|
||||
@param aValue the initial value of the CPStepper
|
||||
@param minValue the minimal acceptable value of the stepper
|
||||
@param maxValue the maximal acceptable value of the stepper
|
||||
@@ -53,7 +54,7 @@ var CPStepperButtonsSize = CPSizeMake(19, 13);
|
||||
*/
|
||||
+ (CPStepper)stepperWithInitialValue:(float)aValue minValue:(float)aMinValue maxValue:(float)aMaxValue
|
||||
{
|
||||
var stepper = [[CPStepper alloc] initWithFrame:CPRectMake(0, 0, 19, 25)];
|
||||
var stepper = [[CPStepper alloc] initWithFrame:_CGRectMake(0, 0, 19, 25)];
|
||||
[stepper setDoubleValue:aValue];
|
||||
[stepper setMinValue:aMinValue];
|
||||
[stepper setMaxValue:aMaxValue];
|
||||
@@ -61,10 +62,12 @@ var CPStepperButtonsSize = CPSizeMake(19, 13);
|
||||
return stepper;
|
||||
}
|
||||
|
||||
/*! Initializes a CPStepper with default values:
|
||||
/*!
|
||||
Initializes a CPStepper with default values:
|
||||
- minValue = 0.0
|
||||
- maxValue = 59.0
|
||||
- value = 0.0
|
||||
|
||||
@return Initialized CPStepper
|
||||
*/
|
||||
+ (CPStepper)stepper
|
||||
@@ -72,7 +75,8 @@ var CPStepperButtonsSize = CPSizeMake(19, 13);
|
||||
return [CPStepper stepperWithInitialValue:0.0 minValue:0.0 maxValue:59.0];
|
||||
}
|
||||
|
||||
/*! Initializes the CPStepper
|
||||
/*!
|
||||
Initializes a CPStepper.
|
||||
@param aFrame the frame of the control
|
||||
@return initialized CPStepper
|
||||
*/
|
||||
@@ -87,14 +91,14 @@ var CPStepperButtonsSize = CPSizeMake(19, 13);
|
||||
|
||||
[self setDoubleValue:0.0];
|
||||
|
||||
_buttonUp = [[CPButton alloc] initWithFrame:CPRectMake(aFrame.size.width - CPStepperButtonsSize.width, 0, CPStepperButtonsSize.width, CPStepperButtonsSize.height)];
|
||||
_buttonUp = [[CPButton alloc] initWithFrame:_CGRectMakeZero()];
|
||||
[_buttonUp setContinuous:YES];
|
||||
[_buttonUp setTarget:self];
|
||||
[_buttonUp setAction:@selector(_buttonDidClick:)];
|
||||
[_buttonUp setAutoresizingMask:CPViewNotSizable];
|
||||
[self addSubview:_buttonUp];
|
||||
|
||||
_buttonDown = [[CPButton alloc] initWithFrame:CPRectMake(aFrame.size.width - CPStepperButtonsSize.width, CPStepperButtonsSize.height, CPStepperButtonsSize.width, CPStepperButtonsSize.height - 1)];
|
||||
_buttonDown = [[CPButton alloc] initWithFrame:_CGRectMakeZero()];
|
||||
[_buttonDown setContinuous:YES];
|
||||
[_buttonDown setTarget:self];
|
||||
[_buttonDown setAction:@selector(_buttonDidClick:)];
|
||||
@@ -110,7 +114,8 @@ var CPStepperButtonsSize = CPSizeMake(19, 13);
|
||||
#pragma mark -
|
||||
#pragma mark Superclass overrides
|
||||
|
||||
/*! set if the CPStepper is enabled or not
|
||||
/*!
|
||||
Set if the CPStepper is enabled or not.
|
||||
@param shouldEnabled BOOL that define if stepper is enabled or not.
|
||||
*/
|
||||
- (void)setEnabled:(BOOL)shouldEnabled
|
||||
@@ -121,19 +126,30 @@ var CPStepperButtonsSize = CPSizeMake(19, 13);
|
||||
[_buttonDown setEnabled:shouldEnabled];
|
||||
}
|
||||
|
||||
/*! set the frame of the CPStepper and check if width is not smaller than theme min-size
|
||||
@param aFrame the frame
|
||||
*/
|
||||
|
||||
- (void)setFrame:(CGRect)aFrame
|
||||
{
|
||||
if (aFrame.size.width >= CGRectGetWidth(aFrame))
|
||||
[super setFrame:aFrame];
|
||||
var upSize = [self valueForThemeAttribute:@"up-button-size"],
|
||||
downSize = [self valueForThemeAttribute:@"down-button-size"],
|
||||
minSize = _CGSizeMake(upSize.width, upSize.height + downSize.height),
|
||||
frame = _CGRectMakeCopy(aFrame);
|
||||
|
||||
frame.size.width = Math.max(minSize.width, frame.size.width);
|
||||
frame.size.height = Math.max(minSize.height, frame.size.height);
|
||||
[super setFrame:frame];
|
||||
}
|
||||
|
||||
/*! @ignore
|
||||
*/
|
||||
/*! @ignore */
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
var aFrame = [self frame],
|
||||
upSize = [self valueForThemeAttribute:@"up-button-size"],
|
||||
downSize = [self valueForThemeAttribute:@"down-button-size"],
|
||||
upFrame = _CGRectMake(aFrame.size.width - upSize.width, 0, upSize.width, upSize.height),
|
||||
downFrame = _CGRectMake(aFrame.size.width - downSize.width, upSize.height, downSize.width, downSize.height);
|
||||
[_buttonUp setFrame:upFrame];
|
||||
[_buttonDown setFrame:downFrame];
|
||||
|
||||
[_buttonUp setValue:[self valueForThemeAttribute:@"bezel-color-up-button" inState:CPThemeStateBordered] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered];
|
||||
[_buttonUp setValue:[self valueForThemeAttribute:@"bezel-color-up-button" inState:CPThemeStateBordered | CPThemeStateDisabled] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered | CPThemeStateDisabled];
|
||||
[_buttonUp setValue:[self valueForThemeAttribute:@"bezel-color-up-button" inState:CPThemeStateBordered | CPThemeStateHighlighted] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered | CPThemeStateHighlighted];
|
||||
@@ -142,7 +158,8 @@ var CPStepperButtonsSize = CPSizeMake(19, 13);
|
||||
[_buttonDown setValue:[self valueForThemeAttribute:@"bezel-color-down-button" inState:CPThemeStateBordered | CPThemeStateHighlighted] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered | CPThemeStateHighlighted];
|
||||
}
|
||||
|
||||
/*! set if CPStepper should autorepeat
|
||||
/*!
|
||||
Set if CPStepper should autorepeat.
|
||||
@param shouldAutoRepeat if YES, the first mouse down does one increment (decrement) and, after each delay of 0.5 seconds
|
||||
*/
|
||||
- (void)setAutorepeat:(BOOL)shouldAutoRepeat
|
||||
@@ -151,7 +168,8 @@ var CPStepperButtonsSize = CPSizeMake(19, 13);
|
||||
[_buttonDown setContinuous:shouldAutoRepeat];
|
||||
}
|
||||
|
||||
/*! set the current value of the stepper
|
||||
/*!
|
||||
Set the current value of the stepper.
|
||||
@param aValue a float containing the value
|
||||
*/
|
||||
- (void)setDoubleValue:(float)aValue
|
||||
@@ -167,8 +185,7 @@ var CPStepperButtonsSize = CPSizeMake(19, 13);
|
||||
#pragma mark -
|
||||
#pragma mark Actions
|
||||
|
||||
/*! @ignore
|
||||
*/
|
||||
/*! @ignore */
|
||||
- (IBAction)_buttonDidClick:(id)aSender
|
||||
{
|
||||
if (![self isEnabled])
|
||||
@@ -183,7 +200,8 @@ var CPStepperButtonsSize = CPSizeMake(19, 13);
|
||||
[self sendAction:_action to:_target];
|
||||
}
|
||||
|
||||
/*! @perform a programatic click on up button
|
||||
/*!
|
||||
Perform a programatic click on up button.
|
||||
@param aSender sender of the action
|
||||
*/
|
||||
- (IBAction)performClickUp:(id)aSender
|
||||
@@ -191,7 +209,8 @@ var CPStepperButtonsSize = CPSizeMake(19, 13);
|
||||
[_buttonUp performClick:aSender];
|
||||
}
|
||||
|
||||
/*! @perform a programatic click on down button
|
||||
/*!
|
||||
Perform a programatic click on down button.
|
||||
@param aSender sender of the action
|
||||
*/
|
||||
- (IBAction)performClickDown:(id)aSender
|
||||
@@ -210,8 +229,8 @@ var CPStepperButtonsSize = CPSizeMake(19, 13);
|
||||
|
||||
+ (id)themeAttributes
|
||||
{
|
||||
return [CPDictionary dictionaryWithObjects:[[CPNull null], [CPNull null]]
|
||||
forKeys:[@"bezel-color-up-button", @"bezel-color-down-button"]];
|
||||
return [CPDictionary dictionaryWithObjects:[[CPNull null], [CPNull null], _CGSizeMakeZero(), _CGSizeMakeZero()]
|
||||
forKeys:[@"bezel-color-up-button", @"bezel-color-down-button", @"up-button-size", @"down-button-size"]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -132,7 +132,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
{
|
||||
var min = [self minWidth],
|
||||
max = [self maxWidth],
|
||||
newWidth = MIN(MAX(width, min), max);
|
||||
newWidth = ROUND(MIN(MAX(width, min), max));
|
||||
|
||||
[self setWidth:newWidth];
|
||||
|
||||
@@ -332,18 +332,18 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
individual cell that is shown. As a result, changes made after calling this method won't be reflected.
|
||||
|
||||
Example:
|
||||
@code
|
||||
[tableColumn setDataView:someView]; // snapshot taken
|
||||
[[tableColumn dataView] setSomething:x]; //won't work
|
||||
@endcode
|
||||
@code
|
||||
[tableColumn setDataView:someView]; // snapshot taken
|
||||
[[tableColumn dataView] setSomething:x]; //won't work
|
||||
@endcode
|
||||
|
||||
This doesn't work because the snapshot is taken before the new property is applied. Instead, do:
|
||||
@code
|
||||
[someView setSomething:x];
|
||||
[tableColumn setDataView:someView];
|
||||
@endcode
|
||||
@code
|
||||
[someView setSomething:x];
|
||||
[tableColumn setDataView:someView];
|
||||
@endcode
|
||||
|
||||
@note You should implement CPKeyedArchiving otherwise you might see unexpected results.
|
||||
@note you should implement CPKeyedArchiving otherwise you might see unexpected results.
|
||||
This is done by adding the following methods to your class:
|
||||
@endnote
|
||||
|
||||
@@ -380,7 +380,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@section Theming
|
||||
@section Themeing
|
||||
|
||||
When you set a dataview and it is added to the tableview the theme state will be set to \c CPThemeStateTableDataView
|
||||
When the dataview becomes selected the theme state will be set to \c CPThemeStateSelectedDataView.
|
||||
@@ -594,7 +594,22 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
[super bind:aBinding toObject:anObject withKeyPath:aKeyPath options:options];
|
||||
|
||||
if (![aBinding isEqual:@"someListOfExceptedBindings(notAcceptedBindings)"])
|
||||
[[self tableView] _establishBindingsIfUnbound:anObject];
|
||||
{
|
||||
// Bind the table to the array controller this column is bound to.
|
||||
// Note that anObject might not be the array controller. E.g. the keypath could be something like
|
||||
// somePathTo.anArrayController.arrangedObjects.aKey. Cocoa doesn't support this but it is consistent
|
||||
// and it makes sense.
|
||||
var acIndex = aKeyPath.lastIndexOf("arrangedObjects."),
|
||||
arrayController = anObject;
|
||||
|
||||
if (acIndex > 1)
|
||||
{
|
||||
var firstPart = aKeyPath.substring(0, acIndex - 1);
|
||||
arrayController = [anObject valueForKeyPath:firstPart];
|
||||
}
|
||||
|
||||
[[self tableView] _establishBindingsIfUnbound:arrayController];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -323,7 +323,6 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
{
|
||||
_tableViewFlags = 0;
|
||||
_lastSelectedRow = -1;
|
||||
_clickedRow = -1;
|
||||
|
||||
_selectedColumnIndexes = [CPIndexSet indexSet];
|
||||
_selectedRowIndexes = [CPIndexSet indexSet];
|
||||
@@ -510,6 +509,11 @@ NOT YET IMPLEMENTED
|
||||
_objectValues = { };
|
||||
_cachedRowHeights = [];
|
||||
|
||||
// Otherwise, if we have a row marked as group with a
|
||||
// index greater than the new number or rows
|
||||
// it keeps the the graphical group style.
|
||||
[_groupRows removeAllIndexes];
|
||||
|
||||
// This updates the size too.
|
||||
[self noteNumberOfRowsChanged];
|
||||
|
||||
@@ -1985,7 +1989,7 @@ NOT YET IMPLEMENTED
|
||||
// so we should size the last resized to fit
|
||||
|
||||
// find the last visisble column
|
||||
while (count-- && [_tableColumns[count] isHidden]) ;
|
||||
while (count-- && [_tableColumns[count] isHidden]);
|
||||
|
||||
// find the max x, but subtract a single pixel since the spacing isn't applicable here.
|
||||
var delta = superviewWidth - _CGRectGetMaxX([self rectOfColumn:count]) - ([self intercellSpacing].width || 1),
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/*
|
||||
* CPTextField.j
|
||||
* AppKit
|
||||
@@ -29,7 +28,7 @@
|
||||
@import "_CPImageAndTextView.j"
|
||||
|
||||
|
||||
CPTextFieldSquareBezel = 0; /*! A textfield bezel with a squared corners. */
|
||||
CPTextFieldSquareBezel = 0; /*! A textfield bezel with squared corners. */
|
||||
CPTextFieldRoundedBezel = 1; /*! A textfield bezel with rounded corners. */
|
||||
|
||||
CPTextFieldDidFocusNotification = @"CPTextFieldDidFocusNotification";
|
||||
@@ -169,8 +168,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
+ (id)themeAttributes
|
||||
{
|
||||
return [CPDictionary dictionaryWithObjects:[_CGInsetMakeZero(), _CGInsetMake(2.0, 2.0, 2.0, 2.0), _CGInsetMake(3.0, 3.0, 3.0, 3.0), [CPNull null]]
|
||||
forKeys:[@"bezel-inset", @"content-inset", @"border-inset", @"bezel-color"]];
|
||||
return [CPDictionary dictionaryWithObjects:[_CGInsetMakeZero(), _CGInsetMake(2.0, 2.0, 2.0, 2.0), [CPNull null]]
|
||||
forKeys:[@"bezel-inset", @"content-inset", @"bezel-color"]];
|
||||
}
|
||||
|
||||
/* @ignore */
|
||||
@@ -507,32 +506,31 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
}
|
||||
|
||||
var contentRect = [self contentRectForBounds:[self bounds]],
|
||||
verticalAlign = [self currentValueForThemeAttribute:"vertical-alignment"],
|
||||
lineHeight = [font defaultLineHeightForFont];
|
||||
verticalAlign = [self currentValueForThemeAttribute:"vertical-alignment"];
|
||||
|
||||
switch (verticalAlign)
|
||||
{
|
||||
case CPTopVerticalTextAlignment:
|
||||
var topPoint = _CGRectGetMinY(contentRect) + "px"; // for the same reason we have a -1 for the left, we also have a + 1 here
|
||||
var topPoint = (_CGRectGetMinY(contentRect) + 1) + "px"; // for the same reason we have a -1 for the left, we also have a + 1 here
|
||||
break;
|
||||
|
||||
case CPCenterVerticalTextAlignment:
|
||||
var topPoint = (_CGRectGetMidY(contentRect) - (lineHeight / 2)) + "px";
|
||||
var topPoint = (_CGRectGetMidY(contentRect) - (font._lineHeight / 2) + 1) + "px";
|
||||
break;
|
||||
|
||||
case CPBottomVerticalTextAlignment:
|
||||
var topPoint = (_CGRectGetMaxY(contentRect) - lineHeight) + "px";
|
||||
var topPoint = (_CGRectGetMaxY(contentRect) - font._lineHeight) + "px";
|
||||
break;
|
||||
|
||||
default:
|
||||
var topPoint = _CGRectGetMinY(contentRect) + "px";
|
||||
var topPoint = (_CGRectGetMinY(contentRect) + 1) + "px";
|
||||
break;
|
||||
}
|
||||
|
||||
element.style.top = topPoint;
|
||||
element.style.left = (_CGRectGetMinX(contentRect) - 1) + "px"; // why -1?
|
||||
element.style.width = _CGRectGetWidth(contentRect) + "px";
|
||||
element.style.height = lineHeight + "px";
|
||||
element.style.height = font._lineHeight + "px"; // private ivar for the line height of the DOM text at this particular size
|
||||
|
||||
_DOMElement.appendChild(element);
|
||||
|
||||
@@ -575,11 +573,17 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
#if PLATFORM(DOM)
|
||||
|
||||
var element = [self _inputElement],
|
||||
newValue = element.value,
|
||||
error = @"";
|
||||
|
||||
if (newValue !== _stringValue)
|
||||
{
|
||||
[self _setStringValue:newValue];
|
||||
}
|
||||
|
||||
// If there is a formatter, always give it a chance to reject the resignation,
|
||||
// even if the value has not changed.
|
||||
if ([self _valueIsValid:element.value] === NO)
|
||||
if ([self _valueIsValid:newValue] === NO)
|
||||
{
|
||||
[self setThemeState:CPThemeStateEditing];
|
||||
element.focus();
|
||||
@@ -626,11 +630,15 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
#endif
|
||||
|
||||
_isEditing = NO;
|
||||
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:nil]];
|
||||
// post CPControlTextDidEndEditingNotification
|
||||
if (_isEditing)
|
||||
{
|
||||
_isEditing = NO;
|
||||
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:nil]];
|
||||
|
||||
if ([self sendsActionOnEndEditing])
|
||||
[self sendAction:[self action] to:[self target]];
|
||||
if ([self sendsActionOnEndEditing])
|
||||
[self sendAction:[self action] to:[self target]];
|
||||
}
|
||||
|
||||
[self textDidBlur:[CPNotification notificationWithName:CPTextFieldDidBlurNotification object:self userInfo:nil]];
|
||||
|
||||
@@ -771,6 +779,13 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
- (void)insertNewline:(id)sender
|
||||
{
|
||||
var newValue = [self _inputElement].value;
|
||||
|
||||
if (newValue !== _stringValue)
|
||||
{
|
||||
[self _setStringValue:newValue];
|
||||
}
|
||||
|
||||
if ([self _valueIsValid:_stringValue])
|
||||
{
|
||||
// If _isEditing == YES then the target action can also be called via
|
||||
@@ -1007,7 +1022,6 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
However, since you don't know how tall it needs to be if you change the font, sizeToFit will still be
|
||||
useful for making the textfield an appropriate height.
|
||||
*/
|
||||
|
||||
- (void)sizeToFit
|
||||
{
|
||||
[self setFrameSize:[self _minimumFrameSize]];
|
||||
@@ -1021,7 +1035,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
maxSize = [self currentValueForThemeAttribute:@"max-size"],
|
||||
lineBreakMode = [self lineBreakMode],
|
||||
text = (_stringValue || @" "),
|
||||
textSize = CGSizeMakeCopy(frameSize),
|
||||
textSize = _CGSizeMakeCopy(frameSize),
|
||||
font = [self currentValueForThemeAttribute:@"font"];
|
||||
|
||||
textSize.width -= contentInset.left + contentInset.right;
|
||||
@@ -1291,8 +1305,10 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
- (CGRect)contentRectForBounds:(CGRect)bounds
|
||||
{
|
||||
var bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"],
|
||||
contentInset = [self currentValueForThemeAttribute:@"content-inset"];
|
||||
var contentInset = [self currentValueForThemeAttribute:@"content-inset"];
|
||||
|
||||
if (!contentInset)
|
||||
return bounds;
|
||||
|
||||
bounds.origin.x += contentInset.left;
|
||||
bounds.origin.y += contentInset.top;
|
||||
@@ -1317,14 +1333,6 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
return bounds;
|
||||
}
|
||||
|
||||
- (CGInset)borderInset
|
||||
{
|
||||
var bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"],
|
||||
borderInset = [self currentValueForThemeAttribute:@"border-inset"];
|
||||
|
||||
return CGInsetUnion(bezelInset, borderInset);
|
||||
}
|
||||
|
||||
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aName
|
||||
{
|
||||
if (aName === "bezel-view")
|
||||
|
||||
@@ -25,10 +25,9 @@
|
||||
@import <Foundation/CPKeyedUnarchiver.j>
|
||||
|
||||
|
||||
var CPThemesByName = { },
|
||||
CPThemeNamesByInheritance = [],
|
||||
CPThemeDefaultTheme = nil,
|
||||
CPThemeDefaultHudTheme = nil;
|
||||
var CPThemesByName = { },
|
||||
CPThemeDefaultTheme = nil,
|
||||
CPThemeDefaultHudTheme = nil;
|
||||
|
||||
|
||||
/*!
|
||||
@@ -77,52 +76,6 @@ var CPThemesByName = { },
|
||||
return CPThemesByName[aName];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns an array of names of all loaded themes, in the order they were loaded.
|
||||
*/
|
||||
+ (CPArray)allThemeNames
|
||||
{
|
||||
return [CPThemeNamesByInheritance copy];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the closest matching theme for a given view or view class.
|
||||
The matching proceeds as follows:
|
||||
|
||||
- The default theme class name for the class is retrieved.
|
||||
- Starting with the last loaded theme and proceeding towards the default theme,
|
||||
each theme is checked to see if it defines that theme class.
|
||||
- If the theme defines the class name, that theme is returned.
|
||||
- If no themes match, the default theme is returned.
|
||||
|
||||
@param aViewOrClass The view or view class to match with a theme
|
||||
@return The first matching theme
|
||||
*/
|
||||
+ (CPTheme)themeForView:(id)aViewOrClass
|
||||
{
|
||||
var themeClass = nil;
|
||||
|
||||
if (class_isMetaClass(aViewOrClass.isa))
|
||||
themeClass = [aViewOrClass defaultThemeClass];
|
||||
else
|
||||
themeClass = [aViewOrClass themeClass];
|
||||
|
||||
if (themeClass)
|
||||
{
|
||||
var count = CPThemeNamesByInheritance.length;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
var theme = CPThemesByName[CPThemeNamesByInheritance[count]];
|
||||
|
||||
if ([theme._attributes containsKey:themeClass])
|
||||
return theme;
|
||||
}
|
||||
}
|
||||
|
||||
return CPThemeDefaultTheme;
|
||||
}
|
||||
|
||||
- (id)initWithName:(CPString)aName
|
||||
{
|
||||
self = [super init];
|
||||
@@ -133,9 +86,6 @@ var CPThemesByName = { },
|
||||
_attributes = [CPDictionary dictionary];
|
||||
|
||||
CPThemesByName[_name] = self;
|
||||
|
||||
if (![CPThemeNamesByInheritance containsObject:_name])
|
||||
CPThemeNamesByInheritance.push(_name);
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -349,9 +299,6 @@ var CPThemeNameKey = @"CPThemeNameKey",
|
||||
_attributes = [aCoder decodeObjectForKey:CPThemeAttributesKey];
|
||||
|
||||
CPThemesByName[_name] = self;
|
||||
|
||||
if (![CPThemeNamesByInheritance containsObject:_name])
|
||||
CPThemeNamesByInheritance.push(_name);
|
||||
}
|
||||
|
||||
return self;
|
||||
|
||||
@@ -93,11 +93,10 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
return "tokenfield";
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame
|
||||
- (id)initWithFrame:(CPRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame])
|
||||
{
|
||||
_selectedRange = CPMakeRange(0, 0);
|
||||
_completionDelay = [CPTokenField defaultCompletionDelay];
|
||||
_tokenizingCharacterSet = [[self class] defaultTokenizingCharacterSet];
|
||||
[self setBezeled:YES];
|
||||
@@ -114,14 +113,16 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
|
||||
- (void)_init
|
||||
{
|
||||
_selectedRange = CPMakeRange(0, 0);
|
||||
|
||||
var frame = [self frame];
|
||||
|
||||
_tokenScrollView = [[CPScrollView alloc] initWithFrame:_CGRectMakeZero()];
|
||||
_tokenScrollView = [[CPScrollView alloc] initWithFrame:CGRectMakeZero()];
|
||||
[_tokenScrollView setHasHorizontalScroller:NO];
|
||||
[_tokenScrollView setHasVerticalScroller:NO];
|
||||
[_tokenScrollView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
|
||||
|
||||
var contentView = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
|
||||
var contentView = [[CPView alloc] initWithFrame:CGRectMakeZero()];
|
||||
[contentView setAutoresizingMask:CPViewWidthSizable];
|
||||
[_tokenScrollView setDocumentView:contentView];
|
||||
|
||||
@@ -129,15 +130,15 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
|
||||
_cachedCompletions = [];
|
||||
|
||||
_autocompleteContainer = [[CPView alloc] initWithFrame:_CGRectMake(0.0, 0.0, frame.size.width, 92.0)];
|
||||
_autocompleteContainer = [[CPView alloc] initWithFrame:CPRectMake(0.0, 0.0, frame.size.width, 92.0)];
|
||||
[_autocompleteContainer setBackgroundColor:[_CPMenuWindow backgroundColorForBackgroundStyle:_CPMenuWindowPopUpBackgroundStyle]];
|
||||
|
||||
_autocompleteScrollView = [[CPScrollView alloc] initWithFrame:_CGRectMake(1.0, 1.0, frame.size.width - 2.0, 90.0)];
|
||||
_autocompleteScrollView = [[CPScrollView alloc] initWithFrame:CPRectMake(1.0, 1.0, frame.size.width - 2.0, 90.0)];
|
||||
[_autocompleteScrollView setAutohidesScrollers:YES];
|
||||
[_autocompleteScrollView setHasHorizontalScroller:NO];
|
||||
[_autocompleteContainer addSubview:_autocompleteScrollView];
|
||||
|
||||
_autocompleteView = [[CPTableView alloc] initWithFrame:_CGRectMakeZero()];
|
||||
_autocompleteView = [[CPTableView alloc] initWithFrame:CPRectMakeZero()];
|
||||
|
||||
var tableColumn = [[CPTableColumn alloc] initWithIdentifier:CPTokenFieldTableColumnIdentifier];
|
||||
[tableColumn setResizingMask:CPTableColumnAutoresizingMask];
|
||||
@@ -163,31 +164,28 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
{
|
||||
var indexOfSelectedItem = 0;
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
_cachedCompletions = [self tokenField:self completionsForSubstring:[self _inputElement].value indexOfToken:0 indexOfSelectedItem:indexOfSelectedItem];
|
||||
#endif
|
||||
|
||||
[_autocompleteView selectRowIndexes:[CPIndexSet indexSetWithIndex:indexOfSelectedItem] byExtendingSelection:NO];
|
||||
[_autocompleteView reloadData];
|
||||
}
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
|
||||
- (void)_autocompleteWithDOMEvent:(JSObject)DOMEvent
|
||||
{
|
||||
if (!_cachedCompletions || ![self hasThemeState:CPThemeStateAutoCompleting])
|
||||
if (![self _inputElement].value && (!_cachedCompletions || ![self hasThemeState:CPThemeStateAutoCompleting]))
|
||||
return;
|
||||
|
||||
[self _hideCompletions];
|
||||
|
||||
var token = _cachedCompletions[[_autocompleteView selectedRow]],
|
||||
var token = _cachedCompletions ? _cachedCompletions[[_autocompleteView selectedRow]] : nil,
|
||||
shouldRemoveLastObject = token !== @"" && [self _inputElement].value !== @"";
|
||||
|
||||
if (!token)
|
||||
token = [self _inputElement].value;
|
||||
|
||||
// Make sure the user typed an actual token to prevent the previous token from being emptied
|
||||
// If the input area is empty, we want to fallback to the normal behavior, resigning first responder or select the next or previous key view
|
||||
// If the input area is empty, we want to fall back to the normal behavior, resigning first
|
||||
// responder or selecting the next or previous key view.
|
||||
if (!token || token === @"")
|
||||
{
|
||||
if (DOMEvent && DOMEvent.keyCode === CPTabKeyCode)
|
||||
@@ -202,7 +200,6 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var objectValue = [self objectValue];
|
||||
|
||||
// Remove the uncompleted token and add the token string.
|
||||
@@ -210,10 +207,25 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
if (shouldRemoveLastObject)
|
||||
[objectValue removeObjectAtIndex:_selectedRange.location];
|
||||
|
||||
[objectValue insertObject:token atIndex:_selectedRange.location];
|
||||
// Give the delegate a chance to confirm, replace or add to the list of tokens being added.
|
||||
var delegateApprovedObjects = [self tokenField:self shouldAddObjects:[CPArray arrayWithObject:token] atIndex:_selectedRange.location],
|
||||
delegateApprovedObjectsCount = [delegateApprovedObjects count];
|
||||
if (delegateApprovedObjects)
|
||||
{
|
||||
for (var i = 0; i < delegateApprovedObjectsCount; i++)
|
||||
{
|
||||
[objectValue insertObject:[delegateApprovedObjects objectAtIndex:i] atIndex:_selectedRange.location + i];
|
||||
}
|
||||
}
|
||||
|
||||
// Put the cursor after the last inserted token.
|
||||
var location = _selectedRange.location;
|
||||
|
||||
[self setObjectValue:objectValue];
|
||||
_selectedRange = CPMakeRange(location + 1, 0);
|
||||
|
||||
if (delegateApprovedObjectsCount)
|
||||
location += delegateApprovedObjectsCount;
|
||||
_selectedRange = CPMakeRange(location, 0);
|
||||
|
||||
[self _inputElement].value = @"";
|
||||
[self setNeedsLayout];
|
||||
@@ -226,8 +238,6 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
[self _autocompleteWithDOMEvent:nil];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
- (void)_selectToken:(_CPTokenFieldToken)token byExtendingSelection:(BOOL)extend
|
||||
{
|
||||
var indexOfToken = [[self _tokens] indexOfObject:token];
|
||||
@@ -260,8 +270,13 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
var indexOfToken = [[self _tokens] indexOfObject:token],
|
||||
objectValue = [self objectValue];
|
||||
|
||||
// If the token was selected, deselect it for selection preservation.
|
||||
[self _deselectToken:token];
|
||||
// If the selection was to the right of the deleted token, move it to the left. If the deleted token was
|
||||
// selected, deselect it.
|
||||
if (indexOfToken < _selectedRange.location)
|
||||
_selectedRange.location--;
|
||||
else
|
||||
[self _deselectToken:token];
|
||||
|
||||
// Preserve selection.
|
||||
var selection = CPCopyRange(_selectedRange);
|
||||
[objectValue removeObjectAtIndex:indexOfToken];
|
||||
@@ -301,6 +316,14 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
[self _controlTextDidChange];
|
||||
}
|
||||
|
||||
- (void)_updatePlaceholderState
|
||||
{
|
||||
if (([[self _tokens] count] === 0) && ![self hasThemeState:CPThemeStateEditing])
|
||||
[self setThemeState:CPTextFieldStatePlaceholder];
|
||||
else
|
||||
[self unsetThemeState:CPTextFieldStatePlaceholder];
|
||||
}
|
||||
|
||||
// =============
|
||||
// = RESPONDER =
|
||||
// =============
|
||||
@@ -378,10 +401,10 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
|
||||
[self unsetThemeState:CPThemeStateEditing];
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
|
||||
[self _autocomplete];
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
|
||||
var element = [self _inputElement];
|
||||
|
||||
CPTokenFieldInputResigning = YES;
|
||||
@@ -585,14 +608,16 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// ========
|
||||
// = VIEW =
|
||||
// ========
|
||||
- (void)viewDidMoveToWindow
|
||||
{
|
||||
[[[self window] contentView] addSubview:_autocompleteContainer];
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
_autocompleteContainer._DOMElement.style.zIndex = 1000; // Anything else doesn't seem to work
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)removeFromSuperview
|
||||
@@ -664,7 +689,7 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
rowRect = [autocompleteView rectOfRow:index],
|
||||
owner = CPTokenFieldInputOwner;
|
||||
|
||||
if (rowRect && !CGRectContainsRect([clipView bounds], rowRect))
|
||||
if (rowRect && !CPRectContainsRect([clipView bounds], rowRect))
|
||||
[clipView scrollToPoint:[autocompleteView rectOfRow:index].origin];
|
||||
|
||||
if (aDOMEvent.keyCode === CPReturnKeyCode || aDOMEvent.keyCode === CPTabKeyCode)
|
||||
@@ -754,7 +779,7 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
else if (aDOMEvent.keyCode === CPDeleteKeyCode)
|
||||
{
|
||||
// Highlight the previous token if backspace was pressed in an empty input element or re-show the completions view
|
||||
if (CPTokenFieldDOMInputElement.value.length === 0)
|
||||
if (CPTokenFieldDOMInputElement.value == @"")
|
||||
{
|
||||
[self _hideCompletions];
|
||||
|
||||
@@ -874,15 +899,6 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
}
|
||||
#endif
|
||||
|
||||
// In the context of a token field, it is empty when there are no tokens
|
||||
- (void)_updatePlaceholderState
|
||||
{
|
||||
if (([[self _tokens] count] === 0) && ![self hasThemeState:CPThemeStateEditing])
|
||||
[self setThemeState:CPTextFieldStatePlaceholder];
|
||||
else
|
||||
[self unsetThemeState:CPTextFieldStatePlaceholder];
|
||||
}
|
||||
|
||||
// - (void)setTokenStyle: (NSTokenStyle) style;
|
||||
// - (NSTokenStyle)tokenStyle;
|
||||
//
|
||||
@@ -965,9 +981,9 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
// Manually sizeToFit because CPTableView's sizeToFit doesn't work properly
|
||||
[_autocompleteContainer setHidden:NO];
|
||||
var frameOrigin = [self convertPoint:[self bounds].origin toView:[_autocompleteContainer superview]];
|
||||
[_autocompleteContainer setFrameOrigin:_CGPointMake(frameOrigin.x, frameOrigin.y + frame.size.height)];
|
||||
[_autocompleteContainer setFrameSize:_CGSizeMake(_CGRectGetWidth([self bounds]), 92.0)];
|
||||
[_autocompleteScrollView setFrameSize:_CGSizeMake([_autocompleteContainer frame].size.width - 2.0, 90.0)];
|
||||
[_autocompleteContainer setFrameOrigin:CPPointMake(frameOrigin.x, frameOrigin.y + frame.size.height)];
|
||||
[_autocompleteContainer setFrameSize:CPSizeMake(CPRectGetWidth([self bounds]), 92.0)];
|
||||
[_autocompleteScrollView setFrameSize:CPSizeMake([_autocompleteContainer frame].size.width - 2.0, 90.0)];
|
||||
}
|
||||
else
|
||||
[_autocompleteContainer setHidden:YES];
|
||||
@@ -977,11 +993,11 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
return;
|
||||
|
||||
// Move each token into the right position.
|
||||
var contentRect = _CGRectMakeCopy([contentView bounds]),
|
||||
var contentRect = CGRectMakeCopy([contentView bounds]),
|
||||
contentOrigin = contentRect.origin,
|
||||
contentSize = contentRect.size,
|
||||
offset = _CGPointMake(contentOrigin.x, contentOrigin.y),
|
||||
spaceBetweenTokens = _CGSizeMake(2.0, 2.0),
|
||||
offset = CPPointMake(contentOrigin.x, contentOrigin.y),
|
||||
spaceBetweenTokens = CPSizeMake(2.0, 2.0),
|
||||
isEditing = [[self window] firstResponder] == self,
|
||||
tokenToken = [_CPTokenFieldToken new];
|
||||
|
||||
@@ -992,7 +1008,7 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
|
||||
var fitAndFrame = function(width, height)
|
||||
{
|
||||
var r = _CGRectMake(0, 0, width, height);
|
||||
var r = CGRectMake(0, 0, width, height);
|
||||
|
||||
if (offset.x + width >= contentSize.width && offset.x > contentOrigin.x)
|
||||
{
|
||||
@@ -1005,7 +1021,7 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
|
||||
// Make sure the frame fits.
|
||||
if (CGRectGetHeight([contentView bounds]) < offset.y + height)
|
||||
[contentView setFrame:_CGRectMake(0, 0, CGRectGetWidth([_tokenScrollView bounds]), offset.y + height)];
|
||||
[contentView setFrame:CGRectMake(0, 0, CGRectGetWidth([_tokenScrollView bounds]), offset.y + height)];
|
||||
|
||||
offset.x += width + spaceBetweenTokens.width;
|
||||
|
||||
@@ -1014,7 +1030,6 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
|
||||
var placeEditor = function(useRemainingWidth)
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
var element = [self _inputElement],
|
||||
textWidth = 1;
|
||||
|
||||
@@ -1024,7 +1039,6 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
// without clipping. Since different fonts might have different sizes of "X" this
|
||||
// solution is not ideal, but it works.
|
||||
textWidth = [(element.value || @"") + "X" sizeWithFont:[self font]].width;
|
||||
|
||||
if (useRemainingWidth)
|
||||
textWidth = MAX(contentSize.width - offset.x - 1, textWidth);
|
||||
}
|
||||
@@ -1039,7 +1053,6 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
// When editing, always scroll to the cursor.
|
||||
if (_selectedRange.length == 0)
|
||||
[[_tokenScrollView documentView] scrollRectToVisible:inputFrame];
|
||||
#endif
|
||||
}
|
||||
|
||||
for (var i = 0, count = [tokens count]; i < count; i++)
|
||||
@@ -1066,7 +1079,6 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
if (isEditing && CPMaxRange(_selectedRange) >= [tokens count])
|
||||
placeEditor(true);
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
// Hide the editor if there are selected tokens, but still keep it active
|
||||
// so we can continue using our standard keyboard handling events.
|
||||
if (isEditing && _selectedRange.length)
|
||||
@@ -1074,27 +1086,24 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
[self _inputElement].style.left = "-10000px";
|
||||
[self _inputElement].focus();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Trim off any excess height downwards.
|
||||
if (CGRectGetHeight([contentView bounds]) > offset.y + tokenHeight)
|
||||
[contentView setFrame:_CGRectMake(0, 0, CGRectGetWidth([_tokenScrollView bounds]), offset.y + tokenHeight)];
|
||||
[contentView setFrame:CGRectMake(0, 0, CGRectGetWidth([_tokenScrollView bounds]), offset.y + tokenHeight)];
|
||||
|
||||
if (_shouldScrollTo !== CPScrollDestinationNone)
|
||||
{
|
||||
// Only carry out the scroll if the cursor isn't visible.
|
||||
if (!(isEditing && _selectedRange.length == 0))
|
||||
{
|
||||
var scrollToToken = _shouldScrollTo;
|
||||
|
||||
var scrollToToken = _shouldScrollTo;
|
||||
if (scrollToToken === CPScrollDestinationLeft)
|
||||
scrollToToken = tokens[_selectedRange.location]
|
||||
else if (scrollToToken === CPScrollDestinationRight)
|
||||
scrollToToken = tokens[MAX(0, CPMaxRange(_selectedRange) - 1)];
|
||||
|
||||
[self _scrollTokenViewToVisible:scrollToToken];
|
||||
}
|
||||
|
||||
_shouldScrollTo = CPScrollDestinationNone;
|
||||
}
|
||||
}
|
||||
@@ -1175,7 +1184,19 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
// // return an array of represented objects you want to add.
|
||||
// // If you want to reject the add, return an empty array.
|
||||
// // returning nil will cause an error.
|
||||
// - (NSArray *)tokenField:(NSTokenField *)tokenField shouldAddObjects:(NSArray *)tokens atIndex:(NSUInteger)index;
|
||||
- (CPArray)tokenField:(CPTokenField)tokenField shouldAddObjects:(CPArray)tokens atIndex:(int)index
|
||||
{
|
||||
var delegate = [self delegate];
|
||||
if ([delegate respondsToSelector:@selector(tokenField:shouldAddObjects:atIndex:)])
|
||||
{
|
||||
var approvedObjects = [delegate tokenField:tokenField shouldAddObjects:tokens atIndex:index];
|
||||
if (approvedObjects !== nil)
|
||||
return approvedObjects;
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
//
|
||||
// // If you return nil or don't implement these delegate methods, we will assume
|
||||
// // editing string = display string = represented object
|
||||
@@ -1210,11 +1231,11 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
return "tokenfield-token";
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame
|
||||
- (id)initWithFrame:(CPRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame])
|
||||
{
|
||||
_deleteButton = [[_CPTokenFieldTokenCloseButton alloc] initWithFrame:_CGRectMakeZero()];
|
||||
_deleteButton = [[_CPTokenFieldTokenCloseButton alloc] initWithFrame:CPRectMakeZero()];
|
||||
[self addSubview:_deleteButton];
|
||||
|
||||
[self setEditable:NO];
|
||||
@@ -1275,7 +1296,7 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
buttonOffset = [_deleteButton currentValueForThemeAttribute:@"offset"],
|
||||
buttonSize = [_deleteButton currentValueForThemeAttribute:@"min-size"];
|
||||
|
||||
[_deleteButton setFrame:_CGRectMake(_CGRectGetMaxX(frame) - buttonOffset.x, _CGRectGetMinY(frame) + buttonOffset.y, buttonSize.width, buttonSize.height)];
|
||||
[_deleteButton setFrame:CPRectMake(CPRectGetMaxX(frame) - buttonOffset.x, CPRectGetMinY(frame) + buttonOffset.y, buttonSize.width, buttonSize.height)];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -295,7 +295,7 @@ var CPViewFlags = { },
|
||||
_DOMImageSizes = [];
|
||||
#endif
|
||||
|
||||
_theme = [CPTheme themeForView:self];
|
||||
_theme = [CPTheme defaultTheme];
|
||||
_themeState = CPThemeStateNormal;
|
||||
|
||||
[self setupViewFlags];
|
||||
@@ -2543,32 +2543,6 @@ setBoundsOrigin:
|
||||
return (_themeAttributes && _themeAttributes[aName] !== undefined);
|
||||
}
|
||||
|
||||
- (void)registerThemeValues:(CPArray)themeValues
|
||||
{
|
||||
for (var i = 0; i < themeValues.length; ++i)
|
||||
{
|
||||
var attributeValueState = themeValues[i],
|
||||
attribute = attributeValueState[0],
|
||||
value = attributeValueState[1],
|
||||
state = attributeValueState[2];
|
||||
|
||||
if (state)
|
||||
[self setValue:value forThemeAttribute:attribute inState:state];
|
||||
else
|
||||
[self setValue:value forThemeAttribute:attribute];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)registerThemeValues:(CPArray)themeValues inherit:(CPArray)inheritedValues
|
||||
{
|
||||
// Register inherited values first, then override those with the subtheme values.
|
||||
if (inheritedValues)
|
||||
[self registerThemeValues:inheritedValues];
|
||||
|
||||
if (themeValues)
|
||||
[self registerThemeValues:themeValues];
|
||||
}
|
||||
|
||||
- (CPView)createEphemeralSubviewNamed:(CPString)aViewName
|
||||
{
|
||||
return nil;
|
||||
@@ -2721,7 +2695,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
|
||||
|
||||
[self setupViewFlags];
|
||||
|
||||
_theme = [CPTheme themeForView:self];
|
||||
_theme = [CPTheme defaultTheme];
|
||||
_themeClass = [aCoder decodeObjectForKey:CPViewThemeClassKey];
|
||||
_themeState = CPThemeState([aCoder decodeIntForKey:CPViewThemeStateKey]);
|
||||
_themeAttributes = {};
|
||||
|
||||
@@ -271,6 +271,7 @@ var CPWindowActionMessageKeys = [
|
||||
BOOL _isAnimating;
|
||||
BOOL _hasShadow;
|
||||
BOOL _isMovableByWindowBackground;
|
||||
BOOL _isMovable;
|
||||
unsigned _shadowStyle;
|
||||
BOOL _showsResizeIndicator;
|
||||
|
||||
@@ -404,6 +405,7 @@ CPTexturedBackgroundWindowMask
|
||||
_registeredDraggedTypesArray = [];
|
||||
_isSheet = NO;
|
||||
_acceptsMouseMovedEvents = YES;
|
||||
_isMovable = YES;
|
||||
|
||||
// Set up our window number.
|
||||
_windowNumber = [CPApp._windows count];
|
||||
@@ -426,6 +428,7 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
// Create a generic content view.
|
||||
[self setContentView:[[CPView alloc] initWithFrame:CGRectMakeZero()]];
|
||||
[self setInitialFirstResponder:[self contentView]];
|
||||
|
||||
_firstResponder = self;
|
||||
|
||||
@@ -480,7 +483,7 @@ CPTexturedBackgroundWindowMask
|
||||
[self close];
|
||||
|
||||
_platformWindow = aPlatformWindow;
|
||||
[_platformWindow setTitle:_title];
|
||||
[_platformWindow _setTitle:_title window:self];
|
||||
|
||||
if (wasVisible)
|
||||
[self orderFront:self];
|
||||
@@ -950,6 +953,12 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
var bounds = CGRectMake(0.0, 0.0, CGRectGetWidth(_frame), CGRectGetHeight(_frame));
|
||||
|
||||
// During init the initial first responder is set to the contentView
|
||||
// if it hasn't changed in the mean time we need to update that reference
|
||||
// to the new contentView
|
||||
if ([self initialFirstResponder] === _contentView)
|
||||
[self setInitialFirstResponder:aView];
|
||||
|
||||
_contentView = aView;
|
||||
[_contentView setFrame:[self contentRectForFrameRect:bounds]];
|
||||
|
||||
@@ -1274,17 +1283,17 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
- (BOOL)acceptsFirstResponder
|
||||
{
|
||||
return YES;
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (id)initialFirstResponder
|
||||
- (CPView)initialFirstResponder
|
||||
{
|
||||
return _initialFirstResponder;
|
||||
}
|
||||
|
||||
- (void)setInitialFirstResponder:(id)aResponder
|
||||
- (void)setInitialFirstResponder:(CPView)aView
|
||||
{
|
||||
_initialFirstResponder = aResponder;
|
||||
_initialFirstResponder = aView;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1360,7 +1369,7 @@ CPTexturedBackgroundWindowMask
|
||||
_title = aTitle;
|
||||
|
||||
[_windowView setTitle:aTitle];
|
||||
[_platformWindow setTitle:_title];
|
||||
[_platformWindow _setTitle:_title window:self];
|
||||
|
||||
[self _synchronizeMenuBarTitleWithWindowTitle];
|
||||
}
|
||||
@@ -1431,6 +1440,23 @@ CPTexturedBackgroundWindowMask
|
||||
return _isMovableByWindowBackground;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets whether the window can be moved.
|
||||
@param shouldBeMovable \c YES makes the window movable.
|
||||
*/
|
||||
- (void)setMovable:(BOOL)shouldBeMovable
|
||||
{
|
||||
_isMovable = shouldBeMovable;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c YES if the window can be moved.
|
||||
*/
|
||||
- (void)isMovable
|
||||
{
|
||||
return _isMovable;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the window location to be the center of the screen
|
||||
*/
|
||||
@@ -2487,30 +2513,70 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
- (void)selectNextKeyView:(id)sender
|
||||
{
|
||||
if (_keyViewLoopIsDirty && [self autorecalculatesKeyViewLoop])
|
||||
[self recalculateKeyViewLoop];
|
||||
|
||||
var nextValidKeyView = nil;
|
||||
|
||||
if ([_firstResponder isKindOfClass:[CPView class]])
|
||||
[self selectKeyViewFollowingView:_firstResponder];
|
||||
nextValidKeyView = [_firstResponder nextValidKeyView];
|
||||
|
||||
if (!nextValidKeyView)
|
||||
{
|
||||
var initialFirstResponder = [self initialFirstResponder];
|
||||
|
||||
if ([initialFirstResponder acceptsFirstResponder])
|
||||
nextValidKeyView = initialFirstResponder;
|
||||
else
|
||||
nextValidKeyView = [initialFirstResponder nextValidKeyView];
|
||||
}
|
||||
|
||||
[self makeFirstResponder:nextValidKeyView];
|
||||
}
|
||||
|
||||
- (void)selectPreviousKeyView:(id)sender
|
||||
{
|
||||
if (_keyViewLoopIsDirty && [self autorecalculatesKeyViewLoop])
|
||||
[self recalculateKeyViewLoop];
|
||||
|
||||
var previousValidKeyView = nil;
|
||||
|
||||
if ([_firstResponder isKindOfClass:[CPView class]])
|
||||
[self selectKeyViewPrecedingView:_firstResponder];
|
||||
previousValidKeyView = [_firstResponder previousValidKeyView];
|
||||
|
||||
if (!previousValidKeyView)
|
||||
{
|
||||
var initialFirstResponder = [self initialFirstResponder];
|
||||
|
||||
if ([initialFirstResponder acceptsFirstResponder])
|
||||
previousValidKeyView = initialFirstResponder;
|
||||
else
|
||||
previousValidKeyView = [initialFirstResponder previousValidKeyView];
|
||||
}
|
||||
|
||||
[self makeFirstResponder:previousValidKeyView];
|
||||
}
|
||||
|
||||
- (void)selectKeyViewFollowingView:(CPView)aView
|
||||
{
|
||||
if (_keyViewLoopIsDirty)
|
||||
if (_keyViewLoopIsDirty && [self autorecalculatesKeyViewLoop])
|
||||
[self recalculateKeyViewLoop];
|
||||
|
||||
[self makeFirstResponder:[aView nextValidKeyView]];
|
||||
var nextValidKeyView = [aView nextValidKeyView];
|
||||
|
||||
if ([nextValidKeyView isKindOfClass:[CPView class]])
|
||||
[self makeFirstResponder:nextValidKeyView];
|
||||
}
|
||||
|
||||
- (void)selectKeyViewPrecedingView:(CPView)aView
|
||||
{
|
||||
if (_keyViewLoopIsDirty)
|
||||
if (_keyViewLoopIsDirty && [self autorecalculatesKeyViewLoop])
|
||||
[self recalculateKeyViewLoop];
|
||||
|
||||
[self makeFirstResponder:[aView previousValidKeyView]];
|
||||
var previousValidKeyView = [aView previousValidKeyView];
|
||||
|
||||
if ([previousValidKeyView isKindOfClass:[CPView class]])
|
||||
[self makeFirstResponder:previousValidKeyView];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -2598,9 +2664,11 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
var allViews = function(aWindow)
|
||||
{
|
||||
var views = [[aWindow contentView] subviews],
|
||||
index = 0;
|
||||
var views = [CPArray arrayWithObject:[aWindow contentView]];
|
||||
|
||||
[views addObjectsFromArray:[[aWindow contentView] subviews]];
|
||||
|
||||
var index = 0;
|
||||
for (; index < views.length; ++index)
|
||||
views = views.concat([views[index] subviews]);
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ var _CPWindowViewResizeIndicatorImage = nil;
|
||||
return [self trackResizeWithEvent:anEvent];
|
||||
}
|
||||
|
||||
if ([theWindow isMovableByWindowBackground])
|
||||
if ([theWindow isMovable] && [theWindow isMovableByWindowBackground])
|
||||
[self trackMoveWithEvent:anEvent];
|
||||
|
||||
else
|
||||
@@ -174,6 +174,9 @@ var _CPWindowViewResizeIndicatorImage = nil;
|
||||
|
||||
- (void)trackMoveWithEvent:(CPEvent)anEvent
|
||||
{
|
||||
if (![[self window] isMovable])
|
||||
return;
|
||||
|
||||
var type = [anEvent type];
|
||||
|
||||
if (type === CPLeftMouseUp)
|
||||
|
||||
@@ -34,9 +34,9 @@
|
||||
@import "_CPCibWindowTemplate.j"
|
||||
|
||||
|
||||
CPCibOwner = @"CPCibOwner",
|
||||
CPCibTopLevelObjects = @"CPCibTopLevelObjects",
|
||||
CPCibReplacementClasses = @"CPCibReplacementClasses",
|
||||
CPCibOwner = @"CPCibOwner";
|
||||
CPCibTopLevelObjects = @"CPCibTopLevelObjects";
|
||||
CPCibReplacementClasses = @"CPCibReplacementClasses";
|
||||
CPCibExternalObjects = @"CPCibExternalObjects";
|
||||
|
||||
var CPCibObjectDataKey = @"CPCibObjectDataKey";
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* CPCibRuntimeAttributesConnector.j
|
||||
* AppKit
|
||||
*
|
||||
* Created by Aparajita Fishman.
|
||||
* Copyright 2011, 280 North, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
@import "CPCibConnector.j"
|
||||
|
||||
var CPCibRuntimeAttributesConnectorObjectKey = @"CPCibRuntimeAttributesConnectorObjectKey",
|
||||
CPCibRuntimeAttributesConnectorKeyPathsKey = @"CPCibRuntimeAttributesConnectorKeyPathsKey",
|
||||
CPCibRuntimeAttributesConnectorValuesKey = @"CPCibRuntimeAttributesConnectorValuesKey";
|
||||
|
||||
@implementation CPCibRuntimeAttributesConnector : CPCibConnector
|
||||
{
|
||||
id _keyPaths;
|
||||
id _values;
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
if (self = [super initWithCoder:aCoder])
|
||||
{
|
||||
_source = [aCoder decodeObjectForKey:CPCibRuntimeAttributesConnectorObjectKey];
|
||||
_keyPaths = [aCoder decodeObjectForKey:CPCibRuntimeAttributesConnectorKeyPathsKey];
|
||||
_values = [aCoder decodeObjectForKey:CPCibRuntimeAttributesConnectorValuesKey];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
[super encodeWithCoder:aCoder];
|
||||
|
||||
[aCoder encodeObject:_source forKey:CPCibRuntimeAttributesConnectorObjectKey];
|
||||
[aCoder encodeObject:_keyPaths forKey:CPCibRuntimeAttributesConnectorKeyPathsKey];
|
||||
[aCoder encodeObject:_values forKey:CPCibRuntimeAttributesConnectorValuesKey];
|
||||
}
|
||||
|
||||
- (void)establishConnection
|
||||
{
|
||||
var count = [_keyPaths count];
|
||||
|
||||
while (count--)
|
||||
[_source setValue:_values[count] forKeyPath:_keyPaths[count]];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -61,14 +61,14 @@ var _CPCibClassSwapperClassNameKey = @"_CPCibClassSwapperClassNameKey",
|
||||
|
||||
if (!object)
|
||||
{
|
||||
CPLog.error("Unable to find class " + theClassName + " referenced in cib file.");
|
||||
CPLog.error("Unable to find class " + theClassName + " in cib file.");
|
||||
|
||||
object = [self allocObjectWithCoder:aCoder className:[aCoder decodeObjectForKey:_CPCibClassSwapperOriginalClassNameKey]];
|
||||
}
|
||||
}
|
||||
|
||||
if (!object)
|
||||
[CPException raise:CPInvalidArgumentException reason:@"Unable to find class " + theClassName + " referenced in cib file."];
|
||||
[CPException raise:CPInvalidArgumentException reason:@"Unable to find class " + theClassName + " in cib file."];
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
@@ -43,11 +43,6 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
|
||||
return [[self alloc] initWithClassName:@"CPImage" resourceName:aResourceName properties:[CPDictionary dictionaryWithObject:aSize forKey:@"size"]];
|
||||
}
|
||||
|
||||
+ (id)imageResourceWithName:(CPString)aResourceName size:(CGSize)aSize bundleClass:(CPString)aBundleClass
|
||||
{
|
||||
return [[self alloc] initWithClassName:@"CPImage" resourceName:aResourceName properties:[CPDictionary dictionaryWithObjects:[aSize, aBundleClass] forKeys:[@"size", @"bundleClass"]]];
|
||||
}
|
||||
|
||||
- (id)initWithClassName:(CPString)aClassName resourceName:(CPString)aResourceName properties:(CPDictionary)properties
|
||||
{
|
||||
self = [super init];
|
||||
@@ -94,18 +89,7 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",
|
||||
else if (_resourceName == "CPRemoveTemplate")
|
||||
return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPButtonBar class]] pathForResource:@"minus_button.png"] size:CGSizeMake(11, 4)];
|
||||
|
||||
var bundleClass = _properties.valueForKey(@"bundleClass"),
|
||||
bundle = nil;
|
||||
|
||||
if (bundleClass)
|
||||
{
|
||||
bundleClass = CPClassFromString(bundleClass);
|
||||
|
||||
if (bundleClass)
|
||||
bundle = [CPBundle bundleForClass:bundleClass];
|
||||
}
|
||||
|
||||
return [[CPImage alloc] initWithContentsOfFile:[(bundle || [aCoder bundle]) pathForResource:_resourceName] size:_properties.valueForKey(@"size")];
|
||||
return [[CPImage alloc] initWithContentsOfFile:[[aCoder bundle] pathForResource:_resourceName] size:_properties.valueForKey(@"size")];
|
||||
}
|
||||
|
||||
return self;
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
@import "CPCibControlConnector.j"
|
||||
@import "CPCibOutletConnector.j"
|
||||
@import "CPCibBindingConnector.j"
|
||||
@import "CPCibRuntimeAttributesConnector.j"
|
||||
|
||||
|
||||
@implementation _CPCibObjectData : CPObject
|
||||
@@ -258,29 +257,11 @@ var _CPCibObjectDataNamesKeysKey = @"_CPCibObjectDataNamesKeysKey
|
||||
_replacementObjects[[_fileOwner UID]] = anOwner;
|
||||
|
||||
var index = 0,
|
||||
count = _connections.length,
|
||||
runtimeAttributeConnectors = [],
|
||||
connection = nil;
|
||||
count = _connections.length;
|
||||
|
||||
for (; index < count; ++index)
|
||||
{
|
||||
connection = _connections[index];
|
||||
|
||||
if ([connection isKindOfClass:[CPCibRuntimeAttributesConnector class]])
|
||||
// Defer runtime attribute connections until after all other connections are made
|
||||
runtimeAttributeConnectors.push(connection);
|
||||
else
|
||||
{
|
||||
[connection replaceObjects:_replacementObjects];
|
||||
[connection establishConnection];
|
||||
}
|
||||
}
|
||||
|
||||
count = runtimeAttributeConnectors.length;
|
||||
|
||||
for (index = 0; index < count; ++index)
|
||||
{
|
||||
connection = runtimeAttributeConnectors[index];
|
||||
var connection = _connections[index];
|
||||
|
||||
[connection replaceObjects:_replacementObjects];
|
||||
[connection establishConnection];
|
||||
|
||||
@@ -108,7 +108,7 @@ function CGColorCreateCopy(aColor)
|
||||
*/
|
||||
function CGColorCreateGenericGray(gray, alpha)
|
||||
{
|
||||
return CGColorCreate(CGColorSpaceCreateDeviceRGB(), [gray,gray,gray, alpha]);
|
||||
return CGColorCreate(CGColorSpaceCreateDeviceRGB(), [gray, gray, gray, alpha]);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -137,7 +137,7 @@ function CGColorCreateGenericRGB(red, green, blue, alpha)
|
||||
*/
|
||||
function CGColorCreateGenericCMYK(cyan, magenta, yellow, black, alpha)
|
||||
{
|
||||
return CGColorCreate(CGColorSpaceCreateDeviceCMYK(),
|
||||
return CGColorCreate(CGColorSpaceCreateDeviceCMYK(),
|
||||
[cyan, magenta, yellow, black, alpha]);
|
||||
}
|
||||
|
||||
@@ -150,7 +150,8 @@ function CGColorCreateGenericCMYK(cyan, magenta, yellow, black, alpha)
|
||||
*/
|
||||
function CGColorCreateCopyWithAlpha(aColor, anAlpha)
|
||||
{
|
||||
if ( !aColor ) return aColor; // Avoid error null pointer in next line
|
||||
if (!aColor)
|
||||
return aColor; // Avoid error null pointer in next line
|
||||
|
||||
var components = aColor.components.slice();
|
||||
|
||||
|
||||
@@ -267,32 +267,6 @@ function CGPointFromEvent(anEvent)
|
||||
return _CGPointMake(anEvent.clientX, anEvent.clientY);
|
||||
}
|
||||
|
||||
/*!
|
||||
Combines two insets by adding their individual elements and returns the result.
|
||||
|
||||
@group CGInset
|
||||
*/
|
||||
function CGInsetUnion(lhsInset, rhsInset)
|
||||
{
|
||||
return _CGInsetMake(lhsInset.top + rhsInset.top,
|
||||
lhsInset.right + rhsInset.right,
|
||||
lhsInset.bottom + rhsInset.bottom,
|
||||
lhsInset.left + rhsInset.left);
|
||||
}
|
||||
|
||||
/*!
|
||||
Subtract one inset from another by subtracting their individual elements and returns the result.
|
||||
|
||||
@group CGInset
|
||||
*/
|
||||
function CGInsetDifference(lhsInset, rhsInset)
|
||||
{
|
||||
return _CGInsetMake(lhsInset.top - rhsInset.top,
|
||||
lhsInset.right - rhsInset.right,
|
||||
lhsInset.bottom - rhsInset.bottom,
|
||||
lhsInset.left - rhsInset.left);
|
||||
}
|
||||
|
||||
function CGInsetFromString(aString)
|
||||
{
|
||||
var numbers = aString.substr(1, aString.length - 2).split(',');
|
||||
|
||||
@@ -259,12 +259,13 @@ var PrimaryPlatformWindow = NULL;
|
||||
return [CPPlatform isBrowser];
|
||||
}
|
||||
|
||||
- (void)setTitle:(CPString)aTitle
|
||||
- (void)_setTitle:(CPString)aTitle window:(CPWindow)aWindow
|
||||
{
|
||||
_title = aTitle;
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
if (_DOMWindow && _DOMWindow.document)
|
||||
if (_DOMWindow && _DOMWindow.document
|
||||
&& (aWindow === [CPApp mainWindow] || [aWindow platformWindow] !== [CPPlatformWindow primaryPlatformWindow]))
|
||||
_DOMWindow.document.title = _title;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -541,7 +541,8 @@ var ModifierKeyCodes = [
|
||||
// FIXME: cpSetFrame?
|
||||
_DOMWindow.document.write("<!DOCTYPE html><html lang='en'><head></head><body style='background-color:transparent;'></body></html>");
|
||||
_DOMWindow.document.close();
|
||||
_DOMWindow.document.title = _title;
|
||||
if (self != [CPPlatformWindow primaryPlatformWindow])
|
||||
_DOMWindow.document.title = _title;
|
||||
|
||||
if (![CPPlatform isBrowser])
|
||||
{
|
||||
@@ -707,7 +708,8 @@ var ModifierKeyCodes = [
|
||||
var characters;
|
||||
|
||||
// Handle key codes for which String.fromCharCode won't work.
|
||||
if (aDOMEvent.which === 0 || aDOMEvent.charCode === 0)
|
||||
// Refs #1036: In Internet Explorer, both 'which' and 'charCode' are undefined for special keys.
|
||||
if (aDOMEvent.which === 0 || aDOMEvent.charCode === 0 || (aDOMEvent.which === undefined && aDOMEvent.charCode === undefined))
|
||||
characters = KeyCodesToUnicodeMap[_keyCode];
|
||||
|
||||
if (!characters)
|
||||
|
||||
|
Before Width: | Height: | Size: 161 B |
|
Before Width: | Height: | Size: 146 B |
|
Before Width: | Height: | Size: 141 B |
|
Before Width: | Height: | Size: 219 B |
|
Before Width: | Height: | Size: 490 B |
|
Before Width: | Height: | Size: 160 B |
|
Before Width: | Height: | Size: 361 B |
|
Before Width: | Height: | Size: 694 B |
|
Before Width: | Height: | Size: 221 B |
|
Before Width: | Height: | Size: 146 B |
|
Before Width: | Height: | Size: 141 B |
|
Before Width: | Height: | Size: 219 B |
|
Before Width: | Height: | Size: 407 B |
|
Before Width: | Height: | Size: 160 B |
|
Before Width: | Height: | Size: 348 B |
|
Before Width: | Height: | Size: 622 B |
|
Before Width: | Height: | Size: 217 B |
|
Before Width: | Height: | Size: 422 B |
|
Before Width: | Height: | Size: 527 B |
|
Before Width: | Height: | Size: 146 B After Width: | Height: | Size: 123 B |
|
After Width: | Height: | Size: 120 B |
|
After Width: | Height: | Size: 162 B |
|
After Width: | Height: | Size: 155 B |
|
Before Width: | Height: | Size: 154 B |
|
Before Width: | Height: | Size: 436 B |
|
Before Width: | Height: | Size: 452 B |
|
Before Width: | Height: | Size: 444 B After Width: | Height: | Size: 205 B |
|
After Width: | Height: | Size: 122 B |
|
After Width: | Height: | Size: 158 B |
|
After Width: | Height: | Size: 157 B |
|
Before Width: | Height: | Size: 460 B After Width: | Height: | Size: 208 B |
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 185 B |
|
After Width: | Height: | Size: 179 B |
|
Before Width: | Height: | Size: 145 B |
|
After Width: | Height: | Size: 220 B |
|
After Width: | Height: | Size: 122 B |
|
After Width: | Height: | Size: 158 B |
|
After Width: | Height: | Size: 152 B |
|
After Width: | Height: | Size: 218 B |
|
Before Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 123 B |
|
After Width: | Height: | Size: 158 B |
|
After Width: | Height: | Size: 157 B |
|
After Width: | Height: | Size: 145 B |
|
After Width: | Height: | Size: 285 B |
|
After Width: | Height: | Size: 301 B |
|
After Width: | Height: | Size: 153 B |
|
After Width: | Height: | Size: 123 B |
|
After Width: | Height: | Size: 157 B |
|
After Width: | Height: | Size: 310 B |
|
After Width: | Height: | Size: 139 B |
|
After Width: | Height: | Size: 302 B |
|
Before Width: | Height: | Size: 423 B After Width: | Height: | Size: 189 B |
|
Before Width: | Height: | Size: 136 B After Width: | Height: | Size: 119 B |
|
After Width: | Height: | Size: 160 B |
|
After Width: | Height: | Size: 119 B |