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 | ||
|
|
608cb86a4a | ||
|
|
88780ff0a9 | ||
|
|
a5e241afd7 | ||
|
|
28772d3254 | ||
|
|
d1f5c1eebc | ||
|
|
c77a282aaf | ||
|
|
7a1cd5c545 | ||
|
|
29ff54054e | ||
|
|
8e1bbe0132 | ||
|
|
a2b6585c0d | ||
|
|
aa452952a8 | ||
|
|
6ea4aa0a66 | ||
|
|
2462cd7b1d | ||
|
|
331e338c06 | ||
|
|
2b68f40872 | ||
|
|
2f7b3c306d | ||
|
|
eba5dbe654 | ||
|
|
9ae1f548bf | ||
|
|
d191255a84 | ||
|
|
9bf8824109 | ||
|
|
f773bd217c | ||
|
|
a5f0f0e3db | ||
|
|
6f6bfc667b | ||
|
|
0789f49b94 | ||
|
|
92c94eab8f | ||
|
|
9f06ed725e | ||
|
|
c45039fd70 | ||
|
|
8e203ec78e | ||
|
|
e32515e5cc | ||
|
|
2b77da821c | ||
|
|
f8404c7a97 | ||
|
|
156610ee07 | ||
|
|
fcaf672bf8 | ||
|
|
dd5d8fcdce | ||
|
|
e0c4f6455d | ||
|
|
dd5d7e9979 | ||
|
|
408baac91e | ||
|
|
f241142216 | ||
|
|
f0561844d8 | ||
|
|
bd6294b806 | ||
|
|
70f8e3a832 | ||
|
|
59b302acde | ||
|
|
f54f8dfec9 | ||
|
|
93135e7e81 | ||
|
|
b8026e19ba | ||
|
|
147d9282fb | ||
|
|
7c18b8bc5f | ||
|
|
2ccbf5d4e5 | ||
|
|
da6d8c86d1 | ||
|
|
78d997b404 | ||
|
|
89b23ef0d7 | ||
|
|
b958911c63 | ||
|
|
c6e5219f2e | ||
|
|
3bb450adbf | ||
|
|
a0f5257258 | ||
|
|
6520615bb0 | ||
|
|
4593212698 | ||
|
|
5363deb122 | ||
|
|
d5a651fc43 | ||
|
|
4740acbcc6 | ||
|
|
bfb2134329 | ||
|
|
ec83977fe1 | ||
|
|
98d08ff05d | ||
|
|
1eb6319b49 | ||
|
|
8f7e06f9d6 | ||
|
|
81e3abe10c | ||
|
|
edcee8934d | ||
|
|
d115d2ef47 | ||
|
|
d1dd725848 | ||
|
|
ebdba33082 | ||
|
|
918f6fbb8f | ||
|
|
28733ec592 | ||
|
|
916b9a399b | ||
|
|
3d62791477 | ||
|
|
64e6764015 | ||
|
|
cbed5c9cb1 | ||
|
|
0246d501e2 | ||
|
|
3d5b30ab9e | ||
|
|
4719578f10 | ||
|
|
fe370c7066 | ||
|
|
63d208bf20 | ||
|
|
5158540208 | ||
|
|
a69f7dc81a | ||
|
|
e848e161d4 | ||
|
|
3db61216e1 | ||
|
|
63b00186f4 | ||
|
|
110d4c478d | ||
|
|
49c29ded92 | ||
|
|
06670f2214 | ||
|
|
134bfec615 | ||
|
|
279326ffe1 | ||
|
|
ecb04e983e | ||
|
|
73b4c33f05 | ||
|
|
ad30f4dcbb | ||
|
|
0318587f80 | ||
|
|
2b6fddf26c | ||
|
|
da61da392b | ||
|
|
984b46ba07 | ||
|
|
1abce77b3a | ||
|
|
420606d8e8 | ||
|
|
80c8fd9794 | ||
|
|
1f479c3f20 | ||
|
|
0af89853d4 | ||
|
|
b5bb9c8ec3 | ||
|
|
ff13de9f75 | ||
|
|
47f40eb04b | ||
|
|
1ffc7ed6fb | ||
|
|
63710d5fae | ||
|
|
a2ef701d18 | ||
|
|
55e07536d9 | ||
|
|
af0a479f88 | ||
|
|
86a28d8cc1 | ||
|
|
3dd178a69d | ||
|
|
417334419a | ||
|
|
c03b3c2d34 | ||
|
|
e97d4a8e72 | ||
|
|
24d0af3104 | ||
|
|
5790e99359 | ||
|
|
0d6c2c9890 | ||
|
|
42220e057b | ||
|
|
c5df9c973f | ||
|
|
91509e7d36 | ||
|
|
b89aa9af0d | ||
|
|
4421b55613 | ||
|
|
75d9929483 | ||
|
|
7c78c2ef5d | ||
|
|
3758c86d20 | ||
|
|
ada547a79d | ||
|
|
445adcb47f | ||
|
|
4e9b975ca8 | ||
|
|
5d26066e02 | ||
|
|
de73d86684 | ||
|
|
d6244f090e | ||
|
|
1c44dc1052 | ||
|
|
4f7fbdc344 | ||
|
|
c5f37e665b | ||
|
|
99180ba001 | ||
|
|
9377cf9128 | ||
|
|
e17d8ca302 | ||
|
|
acbaa1eec4 | ||
|
|
65b6ff6ecc | ||
|
|
df7aa30267 | ||
|
|
0f4aab926e | ||
|
|
7f3512d22c | ||
|
|
a6b5ed22b0 | ||
|
|
e843b31287 | ||
|
|
06a5aa45ba | ||
|
|
45a5eed62f | ||
|
|
188e27e931 | ||
|
|
f7a7f06c67 | ||
|
|
ed560ed489 | ||
|
|
186eb66f52 | ||
|
|
860f0d5846 | ||
|
|
8b566f06f0 | ||
|
|
28d174d9d8 | ||
|
|
dd892f746d | ||
|
|
95b1b8b19d | ||
|
|
298b73ddfc | ||
|
|
4b9695ff50 | ||
|
|
a02b721944 | ||
|
|
f60a92d2c4 |
@@ -9,3 +9,4 @@ WebSite
|
||||
*.xcodeproj/*.perspectivev3
|
||||
xcuserdata/
|
||||
!*.xcodeproj/project.pbxproj
|
||||
*.xCodeSupport/
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
@import "CPOutlineView.j"
|
||||
@import "CPPanel.j"
|
||||
@import "CPPasteboard.j"
|
||||
@import "CPPopover.j"
|
||||
@import "CPPopUpButton.j"
|
||||
@import "CPPredicateEditor.j"
|
||||
@import "CPPredicateEditorRowTemplate.j"
|
||||
|
||||
@@ -117,7 +117,7 @@ CPCriticalAlertStyle = 2;
|
||||
*/
|
||||
+ (CPAlert)alertWithMessageText:(CPString)aMessage defaultButton:(CPString)defaultButtonTitle alternateButton:(CPString)alternateButtonTitle otherButton:(CPString)otherButtonTitle informativeTextWithFormat:(CPString)informativeText
|
||||
{
|
||||
var alert = [[CPAlert alloc] init];
|
||||
var alert = [[self alloc] init];
|
||||
|
||||
[alert setMessageText:aMessage];
|
||||
[alert addButtonWithTitle:defaultButtonTitle];
|
||||
@@ -142,7 +142,7 @@ CPCriticalAlertStyle = 2;
|
||||
*/
|
||||
+ (CPAlert)alertWithError:(CPString)anErrorMessage
|
||||
{
|
||||
var alert = [[CPAlert alloc] init];
|
||||
var alert = [[self alloc] init];
|
||||
|
||||
[alert setMessageText:anErrorMessage];
|
||||
[alert setAlertStyle:CPCriticalAlertStyle];
|
||||
@@ -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)];
|
||||
|
||||
@@ -306,6 +306,9 @@ ACTUAL_FRAME_RATE = 0;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(animation:valueForProgress:)])
|
||||
return [_delegate animation:self valueForProgress:t];
|
||||
|
||||
if (_animationCurve == CPAnimationLinear)
|
||||
return t;
|
||||
|
||||
var c1 = [],
|
||||
c2 = [];
|
||||
|
||||
@@ -338,7 +338,7 @@ CPRunContinuesResponse = -1002;
|
||||
Copyright - Human readable copyright information.
|
||||
</pre>
|
||||
|
||||
If you choose not the include any of the above keys, they will default
|
||||
If you choose not the include any of the above keys, they will default
|
||||
to the following respective keys in your info.plist file.
|
||||
|
||||
<pre>
|
||||
@@ -1003,7 +1003,7 @@ CPRunContinuesResponse = -1002;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the arguments of your application.
|
||||
Sets the arguments of your application.
|
||||
That is, set the slash seperated values of an array as the window location hash.
|
||||
|
||||
For example if you pass an array:
|
||||
@@ -1340,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];
|
||||
|
||||
@@ -564,8 +564,9 @@
|
||||
- (BOOL)setSelectionIndexes:(CPIndexSet)indexes
|
||||
{
|
||||
[self _selectionWillChange]
|
||||
[self __setSelectionIndexes:indexes];
|
||||
var r = [self __setSelectionIndexes:indexes];
|
||||
[self _selectionDidChange];
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -574,7 +575,7 @@
|
||||
*/
|
||||
- (BOOL)__setSelectionIndex:(int)theIndex
|
||||
{
|
||||
[self __setSelectionIndexes:[CPIndexSet indexSetWithIndex:theIndex]];
|
||||
return [self __setSelectionIndexes:[CPIndexSet indexSetWithIndex:theIndex]];
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -583,28 +584,38 @@
|
||||
*/
|
||||
- (BOOL)__setSelectionIndexes:(CPIndexSet)indexes
|
||||
{
|
||||
if (!indexes)
|
||||
indexes = [CPIndexSet indexSet];
|
||||
var newIndexes = indexes;
|
||||
|
||||
if (![indexes count])
|
||||
if (!newIndexes)
|
||||
newIndexes = [CPIndexSet indexSet];
|
||||
|
||||
if (![newIndexes count])
|
||||
{
|
||||
if (_avoidsEmptySelection && [[self arrangedObjects] count])
|
||||
indexes = [CPIndexSet indexSetWithIndex:0];
|
||||
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.
|
||||
@@ -636,10 +647,11 @@
|
||||
[self willChangeValueForKey:@"selectionIndexes"];
|
||||
[self _selectionWillChange];
|
||||
|
||||
[self __setSelectedObjects:objects];
|
||||
var r = [self __setSelectedObjects:objects];
|
||||
|
||||
[self didChangeValueForKey:@"selectionIndexes"];
|
||||
[self _selectionDidChange];
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -61,6 +61,7 @@ CPGrooveBorder = 3;
|
||||
var box = [[self alloc] initWithFrame:CGRectMakeZero()],
|
||||
enclosingView = [aView superview];
|
||||
|
||||
[box setAutoresizingMask:[aView autoresizingMask]];
|
||||
[box setFrameFromContentFrame:[aView frame]];
|
||||
|
||||
[enclosingView replaceSubview:aView with:box];
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
@import "CPCompatibility.j"
|
||||
@import "CPImage.j"
|
||||
|
||||
/// @cond IGNORE
|
||||
|
||||
var _redComponent = 0,
|
||||
_greenComponent = 1,
|
||||
@@ -54,6 +55,66 @@ var cachedBlackColor,
|
||||
cachedShadowColor,
|
||||
cachedClearColor;
|
||||
|
||||
/// @endcond
|
||||
|
||||
/*!
|
||||
Orientation to use with \c CPColorPattern for vertical patterns.
|
||||
*/
|
||||
CPColorPatternIsVertical = YES;
|
||||
|
||||
/*!
|
||||
Orientation to use with \c CPColorPattern for horizontal patterns.
|
||||
*/
|
||||
CPColorPatternIsHorizontal = NO;
|
||||
|
||||
/*!
|
||||
To create a simple color with a pattern image:
|
||||
|
||||
<code>CPColorWithImages(name, width, height{, bundle})</code>
|
||||
|
||||
To create a color with a three part pattern image:
|
||||
|
||||
<code>CPColorWithImages(slices{, orientation})</code>
|
||||
|
||||
where slices is an array of three [name, width, height{, bundle}] arrays,
|
||||
and orientation is \c CPColorPatternIsVertical or \ref CPColorPatternIsHorizontal.
|
||||
If orientatation is not passed, it defaults to \ref CPColorPatternIsHorizontal.
|
||||
|
||||
To create a color with a nine part pattern image:
|
||||
|
||||
<code>CPColorWithImages(slices);</code>
|
||||
|
||||
where slices is an array of nine [name, width, height{, bundle}] arrays.
|
||||
*/
|
||||
function CPColorWithImages()
|
||||
{
|
||||
if (arguments.length < 3)
|
||||
{
|
||||
var slices = arguments[0],
|
||||
imageSlices = [];
|
||||
|
||||
for (var i = 0; i < slices.length; ++i)
|
||||
{
|
||||
var slice = slices[i];
|
||||
|
||||
imageSlices.push(slice ? CPImageInBundle(slice[0], CGSizeMake(slice[1], slice[2]), slice[3]) : nil);
|
||||
}
|
||||
|
||||
if (imageSlices.length === 3)
|
||||
return [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:imageSlices isVertical:arguments[1] || CPColorPatternIsHorizontal]];
|
||||
else
|
||||
return [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices:imageSlices]];
|
||||
}
|
||||
else if (arguments.length === 3 || arguments.length === 4)
|
||||
{
|
||||
return [CPColor colorWithPatternImage:CPImageInBundle(arguments[0], CGSizeMake(arguments[1], arguments[2]), arguments[3])];
|
||||
}
|
||||
else
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
|
||||
@@ -633,7 +694,36 @@ url("data:image/png;base64,BASE64ENCODEDDATA") // if there is a pattern image
|
||||
|
||||
- (CPString)description
|
||||
{
|
||||
return [super description]+" "+[self cssString];
|
||||
var description = [super description],
|
||||
patternImage = [self patternImage];
|
||||
|
||||
if (!patternImage)
|
||||
return description + " " + [self cssString];
|
||||
|
||||
description += " {\n";
|
||||
|
||||
if ([patternImage isThreePartImage] || [patternImage isNinePartImage])
|
||||
{
|
||||
var slices = [patternImage imageSlices];
|
||||
|
||||
if ([patternImage isThreePartImage])
|
||||
description += " orientation: " + ([patternImage isVertical] ? "vertical" : "horizontal") + ",\n";
|
||||
|
||||
description += " patternImage (" + slices.length + " part): [\n";
|
||||
|
||||
for (var i = 0; i < slices.length; ++i)
|
||||
{
|
||||
var imgDescription = [slices[i] description];
|
||||
|
||||
description += imgDescription.replace(/^/mg, " ") + ",\n";
|
||||
}
|
||||
|
||||
description = description.substr(0, description.length - 2) + "\n ]\n}";
|
||||
}
|
||||
else
|
||||
description += [patternImage description].replace(/^/mg, " ") + "\n}";
|
||||
|
||||
return description;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -678,8 +768,10 @@ url("data:image/png;base64,BASE64ENCODEDDATA") // if there is a pattern image
|
||||
|
||||
@end
|
||||
|
||||
/// @cond IGNORE
|
||||
var CPColorComponentsKey = @"CPColorComponentsKey",
|
||||
CPColorPatternImageKey = @"CPColorPatternImageKey";
|
||||
/// @endcond
|
||||
|
||||
@implementation CPColor (CPCoding)
|
||||
|
||||
@@ -710,13 +802,12 @@ var CPColorComponentsKey = @"CPColorComponentsKey",
|
||||
@end
|
||||
|
||||
|
||||
/// @cond IGNORE
|
||||
var hexCharacters = "0123456789ABCDEF";
|
||||
|
||||
/*!
|
||||
Used for the CPColor \c +colorWithHexString: implementation
|
||||
@ignore
|
||||
@class CPColor
|
||||
@return an array of rgb components
|
||||
/*
|
||||
Used for the CPColor +colorWithHexString: implementation.
|
||||
Returns an array of rgb components.
|
||||
*/
|
||||
var hexToRGB = function(hex)
|
||||
{
|
||||
@@ -754,3 +845,5 @@ var byteToHex = function(n)
|
||||
return hexCharacters.charAt((n - n % 16) / 16) +
|
||||
hexCharacters.charAt(n % 16);
|
||||
};
|
||||
|
||||
/// @endcond
|
||||
|
||||
@@ -51,7 +51,7 @@ CPWheelColorPickerMode = 1;
|
||||
*/
|
||||
CPSliderColorPickerMode = 2;
|
||||
|
||||
CPColorPickerViewWidth = 265,
|
||||
CPColorPickerViewWidth = 265;
|
||||
CPColorPickerViewHeight = 370;
|
||||
|
||||
/*!
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#import "../Foundation/Ref.h"
|
||||
|
||||
@import "../Foundation/CPFormatter.j"
|
||||
@import "CPFont.j"
|
||||
@import "CPShadow.j"
|
||||
@import "CPView.j"
|
||||
@@ -82,6 +85,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
@implementation CPControl : CPView
|
||||
{
|
||||
id _value;
|
||||
CPFormatter _formatter @accessors(property=formatter);
|
||||
|
||||
// Target-Action Support
|
||||
id _target;
|
||||
@@ -221,10 +225,11 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
@param anAction the action to send
|
||||
@param anObject the object to which the action will be sent
|
||||
*/
|
||||
- (void)sendAction:(SEL)anAction to:(id)anObject
|
||||
- (BOOL)sendAction:(SEL)anAction to:(id)anObject
|
||||
{
|
||||
[self _reverseSetBinding];
|
||||
[CPApp sendAction:anAction to:anObject from:self];
|
||||
|
||||
return [CPApp sendAction:anAction to:anObject from:self];
|
||||
}
|
||||
|
||||
- (int)sendActionOn:(int)mask
|
||||
@@ -502,15 +507,46 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
*/
|
||||
- (CPString)stringValue
|
||||
{
|
||||
if (_formatter && _value !== undefined && _value !== nil)
|
||||
{
|
||||
var formattedValue = [self hasThemeState:CPThemeStateEditing] ? [_formatter editingStringForObjectValue:_value] : [_formatter stringForObjectValue:_value];
|
||||
|
||||
if (formattedValue !== nil && formattedValue !== undefined)
|
||||
return formattedValue;
|
||||
}
|
||||
|
||||
return (_value === undefined || _value === nil) ? "" : String(_value);
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the receiver's string value.
|
||||
*/
|
||||
- (void)setStringValue:(CPString)anObject
|
||||
- (void)setStringValue:(CPString)aString
|
||||
{
|
||||
[self setObjectValue:anObject];
|
||||
// Cocoa raises an invalid parameter assertion and returns if you pass nil.
|
||||
if (aString === nil || aString === undefined)
|
||||
{
|
||||
CPLog.warn("nil sent to CPControl -setStringValue");
|
||||
return;
|
||||
}
|
||||
|
||||
var value;
|
||||
|
||||
if (_formatter)
|
||||
{
|
||||
value = 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] === NO)
|
||||
value = undefined; // Means the value is invalid
|
||||
}
|
||||
}
|
||||
else
|
||||
value = aString;
|
||||
|
||||
[self setObjectValue:value];
|
||||
}
|
||||
|
||||
- (void)takeDoubleValueFrom:(id)sender
|
||||
@@ -526,21 +562,18 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
[self setFloatValue:[sender floatValue]];
|
||||
}
|
||||
|
||||
|
||||
- (void)takeIntegerValueFrom:(id)sender
|
||||
{
|
||||
if ([sender respondsToSelector:@selector(integerValue)])
|
||||
[self setIntegerValue:[sender integerValue]];
|
||||
}
|
||||
|
||||
|
||||
- (void)takeIntValueFrom:(id)sender
|
||||
{
|
||||
if ([sender respondsToSelector:@selector(intValue)])
|
||||
[self setIntValue:[sender intValue]];
|
||||
}
|
||||
|
||||
|
||||
- (void)takeObjectValueFrom:(id)sender
|
||||
{
|
||||
if ([sender respondsToSelector:@selector(objectValue)])
|
||||
@@ -882,7 +915,7 @@ var __Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
|
||||
if (_target !== nil)
|
||||
[aCoder encodeConditionalObject:_target forKey:CPControlTargetKey];
|
||||
|
||||
if (_action !== NULL)
|
||||
if (_action !== nil)
|
||||
[aCoder encodeObject:_action forKey:CPControlActionKey];
|
||||
|
||||
[aCoder encodeInt:_sendActionOn forKey:CPControlSendActionOnKey];
|
||||
|
||||
@@ -571,31 +571,27 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
if (_modifierFlags & (CPCommandKeyMask | CPControlKeyMask))
|
||||
return YES;
|
||||
|
||||
// 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++)
|
||||
{
|
||||
switch (_characters.charAt(i))
|
||||
var c = _characters.charAt(i);
|
||||
|
||||
if ((c >= CPUpArrowFunctionKey && c <= CPModeSwitchFunctionKey) ||
|
||||
c === CPEnterCharacter ||
|
||||
c === CPNewlineCharacter ||
|
||||
c === CPCarriageReturnCharacter ||
|
||||
c === CPEscapeFunctionKey)
|
||||
{
|
||||
case CPBackspaceCharacter:
|
||||
case CPDeleteCharacter:
|
||||
case CPDeleteFunctionKey:
|
||||
case CPTabCharacter:
|
||||
case CPCarriageReturnCharacter:
|
||||
case CPNewlineCharacter:
|
||||
case CPSpaceFunctionKey:
|
||||
case CPEscapeFunctionKey:
|
||||
case CPPageUpFunctionKey:
|
||||
case CPPageDownFunctionKey:
|
||||
case CPLeftArrowFunctionKey:
|
||||
case CPUpArrowFunctionKey:
|
||||
case CPRightArrowFunctionKey:
|
||||
case CPDownArrowFunctionKey:
|
||||
case CPEndFunctionKey:
|
||||
case CPHomeFunctionKey:
|
||||
return YES;
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
// FIXME: More cases?
|
||||
return NO;
|
||||
|
||||
return !firstResponderIsText;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -651,4 +647,3 @@ function _CPEventFromNativeMouseEvent(aNativeEvent, anEventType, aPoint, modifie
|
||||
|
||||
return aNativeEvent;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,8 @@ CPImageNameColorPanel = @"CPImageNameColorPanel";
|
||||
CPImageNameColorPanelHighlighted = @"CPImageNameColorPanelHighlighted";
|
||||
|
||||
var imagesForNames = { },
|
||||
AppKitImageForNames = { };
|
||||
AppKitImageForNames = { },
|
||||
ImageDescriptionFormat = "%s {\n filename: \"%s\",\n size: { width:%f, height:%f }\n}";
|
||||
|
||||
AppKitImageForNames[CPImageNameColorPanel] = CGSizeMake(26.0, 29.0);
|
||||
AppKitImageForNames[CPImageNameColorPanelHighlighted] = CGSizeMake(26.0, 29.0);
|
||||
@@ -324,6 +325,24 @@ function CPAppKitImage(aFilename, aSize)
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (CPString)description
|
||||
{
|
||||
var filename = [self filename],
|
||||
size = [self size];
|
||||
|
||||
if (filename.indexOf("data:") === 0)
|
||||
{
|
||||
var index = filename.indexOf(",");
|
||||
|
||||
if (index > 0)
|
||||
filename = [CPString stringWithFormat:@"%s,%s...%s", filename.substr(0, index), filename.substr(index + 1, 10), filename.substr(filename.length - 10)];
|
||||
else
|
||||
filename = "data:<unknown type>";
|
||||
}
|
||||
|
||||
return [CPString stringWithFormat:ImageDescriptionFormat, [super description], filename, size.width, size.height];
|
||||
}
|
||||
|
||||
/* @ignore */
|
||||
- (void)_derefFromImage
|
||||
{
|
||||
|
||||
@@ -311,10 +311,10 @@ var CPBindingOperationAnd = 0,
|
||||
- (void)bind:(CPString)aBinding toObject:(id)anObject withKeyPath:(CPString)aKeyPath options:(CPDictionary)options
|
||||
{
|
||||
if (!anObject || !aKeyPath)
|
||||
return CPLog.error("Invalid object or path on "+self+" for "+aBinding);
|
||||
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];
|
||||
|
||||
@@ -518,4 +518,4 @@ CPValueTransformerBindingOption = @"CPValueTransformer";
|
||||
CPIsControllerMarker = function(/*id*/anObject)
|
||||
{
|
||||
return anObject === CPMultipleValuesMarker || anObject === CPNoSelectionMarker || anObject === CPNotApplicableMarker || anObject === CPNullMarker;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,9 +149,9 @@ var _CPLevelIndicatorBezelColor = nil,
|
||||
var filledColor = _CPLevelIndicatorSegmentNormalColor,
|
||||
value = [self doubleValue];
|
||||
|
||||
if (value < _criticalValue)
|
||||
if (value <= _criticalValue)
|
||||
filledColor = _CPLevelIndicatorSegmentCriticalColor;
|
||||
else if (value < _warningValue)
|
||||
else if (value <= _warningValue)
|
||||
filledColor = _CPLevelIndicatorSegmentWarningColor;
|
||||
|
||||
for (var i = 0; i < segmentCount; i++)
|
||||
|
||||
@@ -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"];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -622,11 +626,11 @@ var _CPMenuBarVisible = NO,
|
||||
var validator = [CPApp targetForAction:[item action] to:[item target] from:item];
|
||||
|
||||
if (!validator || ![validator respondsToSelector:[item action]])
|
||||
[item _setEnabled:NO];
|
||||
[item setEnabled:NO];
|
||||
else if ([validator respondsToSelector:@selector(validateMenuItem:)])
|
||||
[item _setEnabled:[validator validateMenuItem:item]];
|
||||
[item setEnabled:[validator validateMenuItem:item]];
|
||||
else if ([validator respondsToSelector:@selector(validateUserInterfaceItem:)])
|
||||
[item _setEnabled:[validator validateUserInterfaceItem:item]];
|
||||
[item setEnabled:[validator validateUserInterfaceItem:item]];
|
||||
}
|
||||
|
||||
[[_menuWindow _menuView] tile];
|
||||
@@ -711,10 +715,7 @@ var _CPMenuBarVisible = NO,
|
||||
if (aView && !theWindow)
|
||||
throw "In call to popUpMenuPositioningItem:atLocation:inView:callback:, view is not in any window.";
|
||||
|
||||
var delegate = [self delegate];
|
||||
|
||||
if ([delegate respondsToSelector:@selector(menuWillOpen:)])
|
||||
[delegate menuWillOpen:self];
|
||||
[self _menuWillOpen];
|
||||
|
||||
// Convert location to global coordinates if not already in them.
|
||||
if (aView)
|
||||
@@ -802,10 +803,7 @@ var _CPMenuBarVisible = NO,
|
||||
|
||||
+ (void)popUpContextMenu:(CPMenu)aMenu withEvent:(CPEvent)anEvent forView:(CPView)aView withFont:(CPFont)aFont
|
||||
{
|
||||
var delegate = [aMenu delegate];
|
||||
|
||||
if ([delegate respondsToSelector:@selector(menuWillOpen:)])
|
||||
[delegate menuWillOpen:aMenu];
|
||||
[aMenu _menuWillOpen];
|
||||
|
||||
if (!aFont)
|
||||
aFont = [CPFont systemFontOfSize:12.0];
|
||||
@@ -875,7 +873,15 @@ var _CPMenuBarVisible = NO,
|
||||
*/
|
||||
- (CPMenuItem)highlightedItem
|
||||
{
|
||||
return _highlightedIndex >= 0 ? _items[_highlightedIndex] : nil;
|
||||
if (_highlightedIndex < 0)
|
||||
return nil;
|
||||
|
||||
var highlightedItem = _items[_highlightedIndex];
|
||||
|
||||
if ([highlightedItem isSeparatorItem])
|
||||
return nil;
|
||||
|
||||
return highlightedItem;
|
||||
}
|
||||
|
||||
// Managing the Delegate
|
||||
@@ -890,6 +896,22 @@ var _CPMenuBarVisible = NO,
|
||||
return _delegate;
|
||||
}
|
||||
|
||||
- (void)_menuWillOpen
|
||||
{
|
||||
var delegate = [self delegate];
|
||||
|
||||
if ([delegate respondsToSelector:@selector(menuWillOpen:)])
|
||||
[delegate menuWillOpen:self];
|
||||
}
|
||||
|
||||
- (void)_menuDidClose
|
||||
{
|
||||
var delegate = [self delegate];
|
||||
|
||||
if ([delegate respondsToSelector:@selector(menuDidClose:)])
|
||||
[delegate menuDidClose:self];
|
||||
}
|
||||
|
||||
// Handling Tracking
|
||||
/*!
|
||||
Cancels tracking.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
@import <Foundation/CPObject.j>
|
||||
|
||||
|
||||
_CPMenuManagerScrollingStateUp = -1,
|
||||
_CPMenuManagerScrollingStateDown = 1,
|
||||
_CPMenuManagerScrollingStateUp = -1;
|
||||
_CPMenuManagerScrollingStateDown = 1;
|
||||
_CPMenuManagerScrollingStateNone = 0;
|
||||
|
||||
var STICKY_TIME_INTERVAL = 500,
|
||||
@@ -11,6 +11,7 @@ var STICKY_TIME_INTERVAL = 500,
|
||||
@implementation _CPMenuManager: CPObject
|
||||
{
|
||||
CPTimeInterval _startTime;
|
||||
BOOL _hasMouseGoneUpAfterStartedTracking;
|
||||
int _scrollingState;
|
||||
CGPoint _lastGlobalLocation;
|
||||
|
||||
@@ -60,6 +61,9 @@ var STICKY_TIME_INTERVAL = 500,
|
||||
{
|
||||
var menu = [aMenuContainer menu];
|
||||
|
||||
if ([menu numberOfItems] <= 0)
|
||||
return;
|
||||
|
||||
CPApp._activeMenu = menu;
|
||||
|
||||
_startTime = [anEvent timestamp];//new Date();
|
||||
@@ -87,6 +91,8 @@ var STICKY_TIME_INTERVAL = 500,
|
||||
return [self trackMenuBarButtonEvent:anEvent];
|
||||
}
|
||||
|
||||
_hasMouseGoneUpAfterStartedTracking = NO;
|
||||
|
||||
[self trackEvent:anEvent];
|
||||
}
|
||||
|
||||
@@ -99,7 +105,7 @@ var STICKY_TIME_INTERVAL = 500,
|
||||
if (type === CPAppKitDefined)
|
||||
return [self completeTracking];
|
||||
|
||||
[CPApp setTarget:self selector:@selector(trackEvent:) forNextEventMatchingMask:CPKeyDownMask | CPPeriodicMask | CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask | CPAppKitDefinedMask | CPScrollWheelMask untilDate:nil inMode:nil dequeue:YES];
|
||||
[CPApp setTarget:self selector:@selector(trackEvent:) forNextEventMatchingMask:CPKeyDownMask | CPPeriodicMask | CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask | CPRightMouseUpMask | CPAppKitDefinedMask | CPScrollWheelMask untilDate:nil inMode:nil dequeue:YES];
|
||||
|
||||
if (type === CPKeyDown)
|
||||
{
|
||||
@@ -221,8 +227,20 @@ var STICKY_TIME_INTERVAL = 500,
|
||||
[CPEvent startPeriodicEventsAfterDelay:0.0 withPeriod:0.04];
|
||||
}
|
||||
}
|
||||
else if (type === CPLeftMouseUp && ([anEvent timestamp] - _startTime > (STICKY_TIME_INTERVAL + [activeMenu numberOfItems] * 5)))
|
||||
[trackingMenu cancelTracking];
|
||||
else if (type === CPLeftMouseUp || type === CPRightMouseUp)
|
||||
{
|
||||
if (_hasMouseGoneUpAfterStartedTracking)
|
||||
{
|
||||
// Don't close the menu if the current item has a submenu
|
||||
// and did not override it's default action
|
||||
if ([activeItem action] === @selector(submenuAction:))
|
||||
return;
|
||||
|
||||
[trackingMenu cancelTracking];
|
||||
}
|
||||
else
|
||||
_hasMouseGoneUpAfterStartedTracking = YES;
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent previous selected menu items from opening by stopping the timer if a
|
||||
@@ -306,11 +324,7 @@ var STICKY_TIME_INTERVAL = 500,
|
||||
|
||||
// Hide all submenus.
|
||||
[self showMenu:nil fromMenu:trackingMenu atPoint:nil];
|
||||
|
||||
var delegate = [trackingMenu delegate];
|
||||
|
||||
if ([delegate respondsToSelector:@selector(menuDidClose:)])
|
||||
[delegate menuDidClose:trackingMenu];
|
||||
[trackingMenu _menuDidClose];
|
||||
|
||||
if (_trackingCallback)
|
||||
_trackingCallback([self trackingMenuContainer], trackingMenu);
|
||||
@@ -379,6 +393,8 @@ var STICKY_TIME_INTERVAL = 500,
|
||||
var count = _menuContainerStack.length,
|
||||
index = count;
|
||||
|
||||
[newMenu _menuWillOpen];
|
||||
|
||||
// Hide all menus up to the base menu...
|
||||
while (index--)
|
||||
{
|
||||
@@ -398,6 +414,8 @@ var STICKY_TIME_INTERVAL = 500,
|
||||
|
||||
[_CPMenuWindow poolMenuWindow:menuContainer];
|
||||
[_menuContainerStack removeObjectAtIndex:index];
|
||||
|
||||
[menu _menuDidClose];
|
||||
}
|
||||
|
||||
if (!newMenu)
|
||||
|
||||
@@ -148,14 +148,6 @@ var CPMenuItemStringRepresentationDictionary = [CPDictionary dictionary];
|
||||
@param isEnabled \c YES enables the item. \c NO disables it.
|
||||
*/
|
||||
- (void)setEnabled:(BOOL)isEnabled
|
||||
{
|
||||
if ([_menu autoenablesItems])
|
||||
return;
|
||||
|
||||
[self _setEnabled:isEnabled];
|
||||
}
|
||||
|
||||
- (void)_setEnabled:(BOOL)isEnabled
|
||||
{
|
||||
if (_isEnabled === isEnabled)
|
||||
return;
|
||||
@@ -496,6 +488,7 @@ CPOffState
|
||||
if (_submenu)
|
||||
{
|
||||
[_submenu setSupermenu:_menu];
|
||||
[_submenu setTitle:[self title]]
|
||||
|
||||
[self setTarget:_menu];
|
||||
[self setAction:@selector(submenuAction:)];
|
||||
|
||||
@@ -131,8 +131,8 @@
|
||||
|
||||
_contentObject = aContent;
|
||||
|
||||
[self didChangeValueForKey:@"contentObject"];
|
||||
[self _selectionDidChange];
|
||||
[self didChangeValueForKey:@"contentObject"];
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -1458,6 +1458,44 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
|
||||
userInfo:[CPDictionary dictionaryWithObject:item forKey:"CPObject"]];
|
||||
}
|
||||
|
||||
|
||||
- (void)keyDown:(CPEvent)anEvent
|
||||
{
|
||||
var character = [anEvent charactersIgnoringModifiers],
|
||||
modifierFlags = [anEvent modifierFlags];
|
||||
|
||||
// Check for the key events manually, as opposed to waiting for CPWindow to sent the actual action message
|
||||
// in _processKeyboardUIKey:, because we might not want to handle the arrow events.
|
||||
|
||||
if (character !== CPRightArrowFunctionKey && character !== CPLeftArrowFunctionKey)
|
||||
return [super keyDown:anEvent];
|
||||
|
||||
var rows = [self selectedRowIndexes],
|
||||
indexes = [],
|
||||
items = [];
|
||||
|
||||
[rows getIndexes:indexes maxCount:-1 inIndexRange:nil];
|
||||
|
||||
var i = 0,
|
||||
c = [indexes count];
|
||||
|
||||
for (; i < c; i++)
|
||||
items.push([self itemAtRow:indexes[i]]);
|
||||
|
||||
|
||||
if (character === CPRightArrowFunctionKey)
|
||||
{
|
||||
for (var i = 0; i < c; i++)
|
||||
[self expandItem:items[i]];
|
||||
}
|
||||
else if (character === CPLeftArrowFunctionKey)
|
||||
{
|
||||
for (var i = 0; i < c; i++)
|
||||
[self collapseItem:items[i]];
|
||||
}
|
||||
|
||||
[super keyDown:anEvent];
|
||||
}
|
||||
@end
|
||||
|
||||
// FIX ME: We're using with() here because Safari fails if we use anOutlineView._itemInfosForItems or whatever...
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -0,0 +1,325 @@
|
||||
/*
|
||||
* CPPopover.j
|
||||
* AppKit
|
||||
*
|
||||
* Created by Antoine Mercadal.
|
||||
* Copyright 2011 Antoine Mercadal.
|
||||
*
|
||||
* 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 <Foundation/CPObject.j>
|
||||
|
||||
@import "CPButton.j"
|
||||
@import "CPColor.j"
|
||||
@import "CPImage.j"
|
||||
@import "CPImageView.j"
|
||||
@import "CPResponder.j"
|
||||
@import "CPView.j"
|
||||
@import "_CPAttachedWindow.j"
|
||||
|
||||
|
||||
CPPopoverBehaviorApplicationDefined = 0;
|
||||
CPPopoverBehaviorTransient = 1;
|
||||
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_didClose_ = 1 << 4;
|
||||
|
||||
|
||||
/*! @ingroup appkit
|
||||
@class CPPopover
|
||||
|
||||
This class represent a widget that displays a attached
|
||||
view relative to another one.
|
||||
|
||||
Delegate can implement:
|
||||
– popoverShouldClose:(CPPopover)aPopOver
|
||||
– popoverWillShow:(CPPopover)aPopOver
|
||||
– popoverDidShow:(CPPopover)aPopOver
|
||||
– popoverWillClose:(CPPopover)aPopOver
|
||||
– popoverDidClose:(CPPopover)aPopOver
|
||||
*/
|
||||
@implementation CPPopover : CPResponder
|
||||
{
|
||||
@outlet CPViewController _contentViewController @accessors(property=contentViewController);
|
||||
@outlet id _delegate @accessors(getter=delegate);
|
||||
|
||||
BOOL _animates @accessors(property=animates);
|
||||
BOOL _shown @accessors(getter=shown);
|
||||
int _appearance @accessors(property=appearance);
|
||||
int _behavior @accessors(getter=behavior);
|
||||
|
||||
BOOL _needsCompute;
|
||||
_CPAttachedWindow _attachedWindow;
|
||||
int _implementedDelegateMethods;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization
|
||||
|
||||
/*!
|
||||
Initialize the CPPopover witn default values
|
||||
|
||||
@returns anInitialized CPPopover
|
||||
*/
|
||||
- (CPPopover)init
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
_animates = YES;
|
||||
_appearance = CPPopoverAppearanceMinimal;
|
||||
_behavior = CPPopoverBehaviorApplicationDefined;
|
||||
_needsCompute = YES;
|
||||
_shown = NO;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Getters / Setters
|
||||
|
||||
/*!
|
||||
Returns the current rect of the popover
|
||||
|
||||
@return CPRect represeting the frame of the popover
|
||||
*/
|
||||
- (CPRect)positioningRect
|
||||
{
|
||||
if (!_attachedWindow || ![_attachedWindow isVisible])
|
||||
return nil;
|
||||
return [_attachedWindow frame];
|
||||
}
|
||||
|
||||
/*! Sets the frame of the popover
|
||||
@param aRect the desired frame
|
||||
*/
|
||||
- (void)setPositioningRect:(CPRect)aRect
|
||||
{
|
||||
if (!_attachedWindow || ![_attachedWindow isVisible])
|
||||
return;
|
||||
[_attachedWindow setFrame:aRect];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the size of the popover's view
|
||||
|
||||
@return CPSize represeting the size of the popover's view
|
||||
*/
|
||||
- (CPRect)contentSize
|
||||
{
|
||||
if (!_attachedWindow || ![_attachedWindow isVisible])
|
||||
return nil;
|
||||
return [[_contentViewController view] frameSize];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the size of of the popover's view
|
||||
|
||||
@param aSize the desired size
|
||||
*/
|
||||
- (void)setContentSize:(CPSize)aSize
|
||||
{
|
||||
[[_contentViewController view] setFrameSize:aSize];
|
||||
}
|
||||
|
||||
/*!
|
||||
Indicates if CPPopover is visible
|
||||
|
||||
@returns YES if visible
|
||||
*/
|
||||
- (BOOL)shown
|
||||
{
|
||||
if (!_attachedWindow)
|
||||
return NO;
|
||||
return [_attachedWindow isVisible];
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the behaviour of the CPPopover. It can be
|
||||
- CPPopoverBehaviorTransient: the popover will be close if another control outside the popover become the responder
|
||||
- CPPopoverBehaviorApplicationDefined: (DEFAULT) the application is responsible for closing the popover
|
||||
|
||||
@param aBehaviour the desired behaviour
|
||||
*/
|
||||
- (void)setBehaviour:(int)aBehaviour
|
||||
{
|
||||
if (_behavior == aBehaviour)
|
||||
return;
|
||||
|
||||
_behavior = aBehaviour;
|
||||
_needsCompute = YES;
|
||||
}
|
||||
|
||||
|
||||
- (void)setDelegate:(id)aDelegate
|
||||
{
|
||||
if (_delegate === aDelegate)
|
||||
return;
|
||||
|
||||
_delegate = aDelegate;
|
||||
_implementedDelegateMethods = 0;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(popoverWillShow:)])
|
||||
_implementedDelegateMethods |= CPPopoverDelegate_popover_willShow_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(popoverDidShow:)])
|
||||
_implementedDelegateMethods |= CPPopoverDelegate_popover_didShow_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(popoverShouldClose:)])
|
||||
_implementedDelegateMethods |= CPPopoverDelegate_popover_shouldClose_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(popoverWillClose:)])
|
||||
_implementedDelegateMethods |= CPPopoverDelegate_popover_willClose_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(popoverDidClose:)])
|
||||
_implementedDelegateMethods |= CPPopoverDelegate_popover_didClose_;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#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 preferred positioning.
|
||||
*/
|
||||
- (void)showRelativeToRect:(CPRect)positioningRect ofView:(CPView)positioningView preferredEdge:(CPRectEdge)preferredEdge
|
||||
{
|
||||
if (_implementedDelegateMethods & CPPopoverDelegate_popover_willShow_)
|
||||
[_delegate popoverWillShow:self];
|
||||
|
||||
if (!_contentViewController)
|
||||
[CPException raise:CPInternalInconsistencyException reason:@"contentViewController must not be nil"];
|
||||
|
||||
if (_needsCompute || !_attachedWindow)
|
||||
{
|
||||
var styleMask = (_behavior == CPPopoverBehaviorTransient) ? CPClosableOnBlurWindowMask : nil;
|
||||
_attachedWindow = [[_CPAttachedWindow alloc] initWithContentRect:CPRectMakeZero() styleMask:styleMask];
|
||||
}
|
||||
|
||||
[_attachedWindow setAppearance:_appearance];
|
||||
[_attachedWindow setAnimates:_animates];
|
||||
[_attachedWindow setDelegate:self];
|
||||
[_attachedWindow setMovableByWindowBackground:NO];
|
||||
[_attachedWindow setFrame:[_attachedWindow frameRectForContentRect:[[_contentViewController view] frame]]];
|
||||
[_attachedWindow setContentView:[_contentViewController view]];
|
||||
|
||||
if (positioningRect)
|
||||
[_attachedWindow positionRelativeToRect:positioningRect preferredEdge:preferredEdge];
|
||||
else if (positioningView)
|
||||
[_attachedWindow positionRelativeToView:positioningView preferredEdge:preferredEdge];
|
||||
else
|
||||
[CPException raise:CPInvalidArgumentException reason:@"a value must be passed for positioningRect or positioningView"];
|
||||
|
||||
if (_implementedDelegateMethods & CPPopoverDelegate_popover_didShow_)
|
||||
[_delegate popoverDidShow:self];
|
||||
}
|
||||
|
||||
/*!
|
||||
Closes the popover
|
||||
*/
|
||||
- (void)close
|
||||
{
|
||||
if (_implementedDelegateMethods & CPPopoverDelegate_popover_shouldClose_)
|
||||
if (![_delegate popoverShouldClose:self])
|
||||
return;
|
||||
|
||||
if (_implementedDelegateMethods & CPPopoverDelegate_popover_willClose_)
|
||||
[_delegate popoverWillClose:self];
|
||||
|
||||
[_attachedWindow close];
|
||||
|
||||
if (_implementedDelegateMethods & CPPopoverDelegate_popover_didClose_)
|
||||
[_delegate popoverDidClose:self];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Action
|
||||
|
||||
/*!
|
||||
Close the popover
|
||||
|
||||
@param aSender the sender of the action
|
||||
*/
|
||||
- (IBAction)performClose:(id)aSender
|
||||
{
|
||||
[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)
|
||||
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
self = [super initWithCoder:aCoder];
|
||||
|
||||
if (self)
|
||||
{
|
||||
_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;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
[super encodeWithCoder:aCoder];
|
||||
|
||||
[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
|
||||
@@ -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
|
||||
@@ -458,7 +597,8 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
||||
|
||||
[CPApp setTarget:self selector:@selector(trackKnob:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
|
||||
|
||||
[self sendAction:[self action] to:[self target]];
|
||||
if (type === CPLeftMouseDragged)
|
||||
[self sendAction:[self action] to:[self target]];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -564,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])
|
||||
@@ -582,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)
|
||||
|
||||
@@ -605,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;
|
||||
@@ -630,6 +824,7 @@ var CPScrollerControlSizeKey = "CPScrollerControlSize",
|
||||
|
||||
[aCoder encodeInt:_controlSize forKey:CPScrollerControlSizeKey];
|
||||
[aCoder encodeFloat:_knobProportion forKey:CPScrollerKnobProportionKey];
|
||||
[aCoder encodeInt:_style forKey:CPScrollerStyleKey];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -45,6 +45,7 @@ CPSoundPlayBackStatePause = 2;
|
||||
CPString _name @accessors(property=name);
|
||||
id _delegate @accessors(property=delegate);
|
||||
|
||||
BOOL _playRequestBeforeLoad;
|
||||
HTMLAudioElement _audioTag;
|
||||
int _loadStatus;
|
||||
int _playBackStatus;
|
||||
@@ -61,6 +62,7 @@ CPSoundPlayBackStatePause = 2;
|
||||
_loops = NO;
|
||||
_audioTag = document.createElement("audio");
|
||||
_audioTag.preload = YES;
|
||||
_playRequestBeforeLoad = NO;
|
||||
|
||||
_audioTag.addEventListener("canplay", function()
|
||||
{
|
||||
@@ -138,6 +140,12 @@ CPSoundPlayBackStatePause = 2;
|
||||
- (void)_soundDidload
|
||||
{
|
||||
_loadStatus = CPSoundLoadStateCanBePlayed;
|
||||
|
||||
if (_playRequestBeforeLoad)
|
||||
{
|
||||
_playRequestBeforeLoad = NO;
|
||||
[self play];
|
||||
}
|
||||
}
|
||||
|
||||
/*! @ignore
|
||||
@@ -167,6 +175,12 @@ CPSoundPlayBackStatePause = 2;
|
||||
*/
|
||||
- (BOOL)play
|
||||
{
|
||||
if (_loadStatus === CPSoundLoadStateLoading)
|
||||
{
|
||||
_playRequestBeforeLoad = YES;
|
||||
return YES;
|
||||
}
|
||||
|
||||
if ((_loadStatus !== CPSoundLoadStateCanBePlayed)
|
||||
|| (_playBackStatus === CPSoundPlayBackStatePlay))
|
||||
return NO;
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -509,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];
|
||||
|
||||
@@ -1984,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),
|
||||
@@ -2770,7 +2775,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
||||
*/
|
||||
- (BOOL)canDragRowsWithIndexes:(CPIndexSet)rowIndexes atPoint:(CGPoint)mouseDownPoint
|
||||
{
|
||||
return YES;
|
||||
return [rowIndexes count] > 0 && [self numberOfRows] > 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -3544,16 +3549,16 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
||||
}
|
||||
|
||||
var exposedRows = [self _unboundedRowsInRect:aRect],
|
||||
firstRow = FLOOR(exposedRows.location / colorCount) * colorCount,
|
||||
lastRow = CPMaxRange(exposedRows),
|
||||
colorIndex = 0,
|
||||
groupRowRects = [],
|
||||
row = exposedRows.location;
|
||||
groupRowRects = [];
|
||||
|
||||
//loop through each color so we only draw once for each color
|
||||
while (colorIndex < colorCount)
|
||||
{
|
||||
CGContextBeginPath(context);
|
||||
for (var row = colorIndex; row <= lastRow; row += colorCount)
|
||||
for (var row = firstRow + colorIndex; row <= lastRow; row += colorCount)
|
||||
{
|
||||
// if it's not a group row draw it otherwise we draw it later
|
||||
if (![_groupRows containsIndex:row])
|
||||
@@ -4609,7 +4614,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
||||
}
|
||||
_wasSelectionBroken = true;
|
||||
}
|
||||
else if (_wasSelectionBroken && ((shouldGoUpward && i !== [selectedIndexes firstIndex]) || (!shouldGoUpward && i !== [selectedIndexes lastindex])))
|
||||
else if (_wasSelectionBroken && ((shouldGoUpward && i !== [selectedIndexes firstIndex]) || (!shouldGoUpward && i !== [selectedIndexes lastIndex])))
|
||||
{
|
||||
shouldGoUpward ? i = [selectedIndexes firstIndex] - 1 : i = [selectedIndexes lastIndex];
|
||||
_wasSelectionBroken = false;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/*
|
||||
* CPTextField.j
|
||||
* AppKit
|
||||
@@ -21,13 +20,15 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#import "../Foundation/Ref.h"
|
||||
|
||||
@import "CPControl.j"
|
||||
@import "CPStringDrawing.j"
|
||||
@import "CPCompatibility.j"
|
||||
@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";
|
||||
@@ -83,12 +84,11 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
CPColor _textFieldBackgroundColor;
|
||||
|
||||
id _placeholderString;
|
||||
CPString _placeholderString;
|
||||
CPString _stringValue;
|
||||
|
||||
id _delegate;
|
||||
|
||||
CPString _textDidChangeValue;
|
||||
|
||||
// NS-style Display Properties
|
||||
CPTextFieldBezelStyle _bezelStyle;
|
||||
BOOL _isBordered;
|
||||
@@ -481,17 +481,17 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
[self setNeedsLayout];
|
||||
|
||||
_isEditing = NO;
|
||||
_stringValue = [self stringValue];
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
|
||||
var string = [self stringValue],
|
||||
element = [self _inputElement],
|
||||
var element = [self _inputElement],
|
||||
font = [self currentValueForThemeAttribute:@"font"];
|
||||
|
||||
// generate the font metric
|
||||
[font _getMetrics];
|
||||
|
||||
element.value = string;
|
||||
element.value = _stringValue;
|
||||
element.style.color = [[self currentValueForThemeAttribute:@"text-color"] cssString];
|
||||
element.style.font = [font cssString];
|
||||
element.style.zIndex = 1000;
|
||||
@@ -548,8 +548,6 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
CPTextFieldInputOwner = self;
|
||||
}, 0.0);
|
||||
|
||||
element.value = [self stringValue];
|
||||
|
||||
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
|
||||
|
||||
CPTextFieldInputIsActive = YES;
|
||||
@@ -572,17 +570,39 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
{
|
||||
[self unsetThemeState:CPThemeStateEditing];
|
||||
|
||||
#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:newValue] === NO)
|
||||
{
|
||||
[self setThemeState:CPThemeStateEditing];
|
||||
element.focus();
|
||||
return NO;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Cache the formatted string
|
||||
_stringValue = [self stringValue];
|
||||
|
||||
_willBecomeFirstResponderByClick = NO;
|
||||
|
||||
[self _updatePlaceholderState];
|
||||
|
||||
[self setNeedsLayout];
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
|
||||
var element = [self _inputElement];
|
||||
|
||||
if ([self stringValue] !== element.value)
|
||||
[self _setStringValue:element.value];
|
||||
|
||||
CPTextFieldInputResigning = YES;
|
||||
|
||||
if (CPTextFieldInputIsActive)
|
||||
@@ -610,7 +630,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
#endif
|
||||
|
||||
//post CPControlTextDidEndEditingNotification
|
||||
// post CPControlTextDidEndEditingNotification
|
||||
if (_isEditing)
|
||||
{
|
||||
_isEditing = NO;
|
||||
@@ -625,6 +645,28 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)_valueIsValid:(CPString)aValue
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
|
||||
var error = @"";
|
||||
|
||||
if ([self _setStringValue:aValue isNewValue:NO errorDescription:AT_REF(error)] === NO)
|
||||
{
|
||||
var acceptInvalidValue = NO;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(control:didFailToFormatString:errorDescription:)])
|
||||
acceptInvalidValue = [_delegate control:self didFailToFormatString:[self _inputElement] errorDescription:error];
|
||||
|
||||
if (acceptInvalidValue === NO)
|
||||
return NO;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
/*!
|
||||
Text fields require panels to become key window, so this returns \c YES.
|
||||
*/
|
||||
@@ -685,11 +727,14 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
- (void)keyUp:(CPEvent)anEvent
|
||||
{
|
||||
var oldValue = [self stringValue];
|
||||
[self _setStringValue:[self _inputElement].value];
|
||||
#if PLATFORM(DOM)
|
||||
|
||||
if (oldValue !== [self stringValue])
|
||||
var newValue = [self _inputElement].value;
|
||||
|
||||
if (newValue !== _stringValue)
|
||||
{
|
||||
[self _setStringValue:newValue];
|
||||
|
||||
if (!_isEditing)
|
||||
{
|
||||
_isEditing = YES;
|
||||
@@ -699,14 +744,13 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
[self textDidChange:[CPNotification notificationWithName:CPControlTextDidChangeNotification object:self userInfo:nil]];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
|
||||
}
|
||||
|
||||
- (void)keyDown:(CPEvent)anEvent
|
||||
{
|
||||
if ([anEvent _couldBeKeyEquivalent] && [self performKeyEquivalent:anEvent])
|
||||
return;
|
||||
|
||||
// CPTextField uses an HTML input element to take the input so we need to
|
||||
// propagate the dom event so the element is updated. This has to be done
|
||||
// before interpretKeyEvents: though so individual commands have a chance
|
||||
@@ -735,45 +779,60 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
- (void)insertNewline:(id)sender
|
||||
{
|
||||
if (_isEditing)
|
||||
var newValue = [self _inputElement].value;
|
||||
|
||||
if (newValue !== _stringValue)
|
||||
{
|
||||
_isEditing = NO;
|
||||
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:nil]];
|
||||
[self _setStringValue:newValue];
|
||||
}
|
||||
|
||||
[self sendAction:[self action] to:[self target]];
|
||||
[self selectText:nil];
|
||||
if ([self _valueIsValid:_stringValue])
|
||||
{
|
||||
// If _isEditing == YES then the target action can also be called via
|
||||
// resignFirstResponder, and it is possible that the target action
|
||||
// itself will change this textfield's responder status, so start by
|
||||
// setting the _isEditing flag to NO to prevent the target action being
|
||||
// called twice (once below and once from resignFirstResponder).
|
||||
if (_isEditing)
|
||||
{
|
||||
_isEditing = NO;
|
||||
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:nil]];
|
||||
}
|
||||
|
||||
// If there is no target action, or the sendAction call returns
|
||||
// success.
|
||||
if (![self action] || [self sendAction:[self action] to:[self target]])
|
||||
{
|
||||
[self selectAll:nil];
|
||||
}
|
||||
}
|
||||
|
||||
[[[self window] platformWindow] _propagateCurrentDOMEvent:NO];
|
||||
}
|
||||
|
||||
- (void)insertNewlineIgnoringFieldEditor:(id)sender
|
||||
{
|
||||
var oldValue = [self stringValue];
|
||||
|
||||
[self _inputElement].value += CPNewlineCharacter;
|
||||
[self _setStringValue:[self _inputElement].value];
|
||||
|
||||
if (oldValue !== [self stringValue])
|
||||
{
|
||||
if (!_isEditing)
|
||||
{
|
||||
_isEditing = YES;
|
||||
[self textDidBeginEditing:[CPNotification notificationWithName:CPControlTextDidBeginEditingNotification object:self userInfo:nil]];
|
||||
}
|
||||
|
||||
[self textDidChange:[CPNotification notificationWithName:CPControlTextDidChangeNotification object:self userInfo:nil]];
|
||||
}
|
||||
[self _insertCharacterIgnoringFieldEditor:CPNewlineCharacter];
|
||||
}
|
||||
|
||||
- (void)insertTabIgnoringFieldEditor:(id)sender
|
||||
{
|
||||
var oldValue = [self stringValue];
|
||||
[self _insertCharacterIgnoringFieldEditor:CPTabCharacter];
|
||||
}
|
||||
|
||||
[self _inputElement].value += CPTabCharacter;
|
||||
[self _setStringValue:[self _inputElement].value];
|
||||
- (void)_insertCharacterIgnoringFieldEditor:(CPString)aCharacter
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
|
||||
if (oldValue !== [self stringValue])
|
||||
var oldValue = _stringValue,
|
||||
range = [self selectedRange],
|
||||
element = [self _inputElement];
|
||||
|
||||
element.value = [element.value stringByReplacingCharactersInRange:[self selectedRange] withString:aCharacter];
|
||||
[self _setStringValue:element.value];
|
||||
|
||||
// NOTE: _stringValue is now the current input element value
|
||||
if (oldValue !== _stringValue)
|
||||
{
|
||||
if (!_isEditing)
|
||||
{
|
||||
@@ -783,6 +842,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
[self textDidChange:[CPNotification notificationWithName:CPControlTextDidChangeNotification object:self userInfo:nil]];
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)textDidBlur:(CPNotification)note
|
||||
@@ -813,15 +874,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
[super textDidChange:note];
|
||||
}
|
||||
|
||||
- (void)sendAction:(SEL)anAction to:(id)anObject
|
||||
{
|
||||
[self _reverseSetBinding];
|
||||
|
||||
[CPApp sendAction:anAction to:anObject from:self];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the string the text field.
|
||||
Returns the string in the text field.
|
||||
*/
|
||||
- (id)objectValue
|
||||
{
|
||||
@@ -830,24 +884,84 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
/*
|
||||
@ignore
|
||||
Sets the internal string value without updating the value in the input element
|
||||
Sets the internal string value without updating the value in the input element.
|
||||
This should only be invoked when the underlying text element's value has changed.
|
||||
*/
|
||||
- (void)_setStringValue:(id)aValue
|
||||
- (BOOL)_setStringValue:(CPString)aValue
|
||||
{
|
||||
[self willChangeValueForKey:@"objectValue"];
|
||||
[super setObjectValue:String(aValue)];
|
||||
[self _updatePlaceholderState];
|
||||
[self didChangeValueForKey:@"objectValue"];
|
||||
return [self _setStringValue:aValue isNewValue:YES errorDescription:nil];
|
||||
}
|
||||
|
||||
/*
|
||||
@ignore
|
||||
Sets the internal string value without updating the value in the input element.
|
||||
If there is a formatter and formatting fails, returns NO. Otherwise returns YES.
|
||||
*/
|
||||
- (BOOL)_setStringValue:(CPString)aValue isNewValue:(BOOL)isNewValue errorDescription:(CPStringRef)anError
|
||||
{
|
||||
_stringValue = aValue;
|
||||
|
||||
var objectValue = aValue,
|
||||
formatter = [self formatter],
|
||||
result = YES;
|
||||
|
||||
if (formatter)
|
||||
{
|
||||
var object = nil;
|
||||
|
||||
if ([formatter getObjectValue:AT_REF(object) forString:aValue errorDescription:anError])
|
||||
objectValue = object;
|
||||
else
|
||||
{
|
||||
objectValue = undefined; // Mark the value as invalid
|
||||
result = NO;
|
||||
}
|
||||
|
||||
isNewValue |= objectValue !== [super objectValue];
|
||||
}
|
||||
|
||||
if (isNewValue)
|
||||
{
|
||||
[self willChangeValueForKey:@"objectValue"];
|
||||
[super setObjectValue:objectValue];
|
||||
[self _updatePlaceholderState];
|
||||
[self didChangeValueForKey:@"objectValue"];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (void)setObjectValue:(id)aValue
|
||||
{
|
||||
[super setObjectValue:aValue];
|
||||
|
||||
var formatter = [self formatter];
|
||||
|
||||
if (formatter)
|
||||
{
|
||||
// If there is a formatter, make sure the object value can be formatted successfully
|
||||
var formattedString = [self hasThemeState:CPThemeStateEditing] ? [formatter editingStringForObjectValue:aValue] : [formatter stringForObjectValue:aValue];
|
||||
|
||||
if (formattedString === nil)
|
||||
{
|
||||
var value = nil;
|
||||
|
||||
// Formatting failed, get an "empty" object by formatting an empty string.
|
||||
// If that fails, the value is undefined.
|
||||
if ([formatter getObjectValue:AT_REF(value) forString:@"" errorDescription:nil] === NO)
|
||||
value = undefined;
|
||||
|
||||
[super setObjectValue:value];
|
||||
}
|
||||
}
|
||||
|
||||
_stringValue = [self stringValue];
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
|
||||
if (CPTextFieldInputOwner === self || [[self window] firstResponder] === self)
|
||||
[self _inputElement].value = aValue;
|
||||
[self _inputElement].value = _stringValue;
|
||||
|
||||
#endif
|
||||
|
||||
[self _updatePlaceholderState];
|
||||
@@ -855,9 +969,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
- (void)_updatePlaceholderState
|
||||
{
|
||||
var string = [self stringValue];
|
||||
|
||||
if ((!string || string.length === 0) && ![self hasThemeState:CPThemeStateEditing])
|
||||
if ((!_stringValue || _stringValue.length === 0) && ![self hasThemeState:CPThemeStateEditing])
|
||||
[self setThemeState:CPTextFieldStatePlaceholder];
|
||||
else
|
||||
[self unsetThemeState:CPTextFieldStatePlaceholder];
|
||||
@@ -910,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]];
|
||||
@@ -923,7 +1034,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
minSize = [self currentValueForThemeAttribute:@"min-size"],
|
||||
maxSize = [self currentValueForThemeAttribute:@"max-size"],
|
||||
lineBreakMode = [self lineBreakMode],
|
||||
text = ([self stringValue] || @" "),
|
||||
text = (_stringValue || @" "),
|
||||
textSize = _CGSizeMakeCopy(frameSize),
|
||||
font = [self currentValueForThemeAttribute:@"font"];
|
||||
|
||||
@@ -994,8 +1105,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
return;
|
||||
|
||||
var pasteboard = [CPPasteboard generalPasteboard],
|
||||
stringValue = [self stringValue],
|
||||
stringForPasting = [stringValue substringWithRange:selectedRange];
|
||||
stringForPasting = [_stringValue substringWithRange:selectedRange];
|
||||
|
||||
[pasteboard declareTypes:[CPStringPboardType] owner:nil];
|
||||
[pasteboard setString:stringForPasting forType:CPStringPboardType];
|
||||
@@ -1025,9 +1135,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
[self deleteBackward:sender];
|
||||
|
||||
var selectedRange = [self selectedRange],
|
||||
stringValue = [self stringValue],
|
||||
pasteString = [pasteboard stringForType:CPStringPboardType],
|
||||
newValue = [stringValue stringByReplacingCharactersInRange:selectedRange withString:pasteString];
|
||||
newValue = [_stringValue stringByReplacingCharactersInRange:selectedRange withString:pasteString];
|
||||
|
||||
[self setStringValue:newValue];
|
||||
[self setSelectedRange:CPMakeRange(selectedRange.location + pasteString.length, 0)];
|
||||
@@ -1041,6 +1150,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
if ([[self window] firstResponder] !== self)
|
||||
return CPMakeRange(0, 0);
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
|
||||
// we wrap this in try catch because firefox will throw an exception in certain instances
|
||||
try
|
||||
{
|
||||
@@ -1067,6 +1178,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
// fall through to the return
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return CPMakeRange(0, 0);
|
||||
}
|
||||
|
||||
@@ -1075,6 +1188,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
if (![[self window] firstResponder] === self)
|
||||
return;
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
|
||||
var inputElement = [self _inputElement];
|
||||
|
||||
try
|
||||
@@ -1103,6 +1218,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
catch (e)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)selectAll:(id)sender
|
||||
@@ -1120,8 +1237,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
selectedRange.location += 1;
|
||||
selectedRange.length -= 1;
|
||||
|
||||
var stringValue = [self stringValue],
|
||||
newValue = [stringValue stringByReplacingCharactersInRange:selectedRange withString:""];
|
||||
var newValue = [_stringValue stringByReplacingCharactersInRange:selectedRange withString:""];
|
||||
|
||||
[self setStringValue:newValue];
|
||||
[self setSelectedRange:CPMakeRange(selectedRange.location, 0)];
|
||||
@@ -1274,7 +1390,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
string = [self placeholderString];
|
||||
else
|
||||
{
|
||||
string = [self stringValue];
|
||||
string = _stringValue;
|
||||
|
||||
if ([self isSecure])
|
||||
string = secureStringForString(string);
|
||||
|
||||
@@ -97,61 +97,66 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
{
|
||||
if (self = [super initWithFrame:frame])
|
||||
{
|
||||
_selectedRange = CPMakeRange(0, 0);
|
||||
|
||||
_tokenScrollView = [[CPScrollView alloc] initWithFrame:CGRectMakeZero()];
|
||||
[_tokenScrollView setHasHorizontalScroller:NO];
|
||||
[_tokenScrollView setHasVerticalScroller:NO];
|
||||
[_tokenScrollView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
|
||||
|
||||
var contentView = [[CPView alloc] initWithFrame:CGRectMakeZero()];
|
||||
[contentView setAutoresizingMask:CPViewWidthSizable];
|
||||
[_tokenScrollView setDocumentView:contentView];
|
||||
|
||||
[self addSubview:_tokenScrollView];
|
||||
|
||||
_tokenIndex = 0;
|
||||
|
||||
_cachedCompletions = [];
|
||||
_completionDelay = [CPTokenField defaultCompletionDelay];
|
||||
|
||||
_tokenizingCharacterSet = [[self class] defaultTokenizingCharacterSet];
|
||||
|
||||
_autocompleteContainer = [[CPView alloc] initWithFrame:CPRectMake(0.0, 0.0, frame.size.width, 92.0)];
|
||||
[_autocompleteContainer setBackgroundColor:[_CPMenuWindow backgroundColorForBackgroundStyle:_CPMenuWindowPopUpBackgroundStyle]];
|
||||
|
||||
_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:CPRectMakeZero()];
|
||||
|
||||
var tableColumn = [[CPTableColumn alloc] initWithIdentifier:CPTokenFieldTableColumnIdentifier];
|
||||
[tableColumn setResizingMask:CPTableColumnAutoresizingMask];
|
||||
[_autocompleteView addTableColumn:tableColumn];
|
||||
|
||||
[_autocompleteView setDataSource:self];
|
||||
[_autocompleteView setDelegate:self];
|
||||
[_autocompleteView setAllowsMultipleSelection:NO];
|
||||
[_autocompleteView setHeaderView:nil];
|
||||
[_autocompleteView setCornerView:nil];
|
||||
[_autocompleteView setRowHeight:30.0];
|
||||
[_autocompleteView setGridStyleMask:CPTableViewSolidHorizontalGridLineMask];
|
||||
[_autocompleteView setBackgroundColor:[CPColor clearColor]];
|
||||
[_autocompleteView setGridColor:[CPColor colorWithRed:242.0 / 255.0 green:243.0 / 255.0 blue:245.0 / 255.0 alpha:1.0]];
|
||||
|
||||
[_autocompleteScrollView setDocumentView:_autocompleteView];
|
||||
|
||||
[self setBezeled:YES];
|
||||
|
||||
[self _init];
|
||||
|
||||
[self setObjectValue:[]];
|
||||
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)_init
|
||||
{
|
||||
_selectedRange = CPMakeRange(0, 0);
|
||||
|
||||
var frame = [self frame];
|
||||
|
||||
_tokenScrollView = [[CPScrollView alloc] initWithFrame:CGRectMakeZero()];
|
||||
[_tokenScrollView setHasHorizontalScroller:NO];
|
||||
[_tokenScrollView setHasVerticalScroller:NO];
|
||||
[_tokenScrollView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
|
||||
|
||||
var contentView = [[CPView alloc] initWithFrame:CGRectMakeZero()];
|
||||
[contentView setAutoresizingMask:CPViewWidthSizable];
|
||||
[_tokenScrollView setDocumentView:contentView];
|
||||
|
||||
[self addSubview:_tokenScrollView];
|
||||
|
||||
_cachedCompletions = [];
|
||||
|
||||
_autocompleteContainer = [[CPView alloc] initWithFrame:CPRectMake(0.0, 0.0, frame.size.width, 92.0)];
|
||||
[_autocompleteContainer setBackgroundColor:[_CPMenuWindow backgroundColorForBackgroundStyle:_CPMenuWindowPopUpBackgroundStyle]];
|
||||
|
||||
_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:CPRectMakeZero()];
|
||||
|
||||
var tableColumn = [[CPTableColumn alloc] initWithIdentifier:CPTokenFieldTableColumnIdentifier];
|
||||
[tableColumn setResizingMask:CPTableColumnAutoresizingMask];
|
||||
[_autocompleteView addTableColumn:tableColumn];
|
||||
|
||||
[_autocompleteView setDataSource:self];
|
||||
[_autocompleteView setDelegate:self];
|
||||
[_autocompleteView setAllowsMultipleSelection:NO];
|
||||
[_autocompleteView setHeaderView:nil];
|
||||
[_autocompleteView setCornerView:nil];
|
||||
[_autocompleteView setRowHeight:30.0];
|
||||
[_autocompleteView setGridStyleMask:CPTableViewSolidHorizontalGridLineMask];
|
||||
[_autocompleteView setBackgroundColor:[CPColor clearColor]];
|
||||
[_autocompleteView setGridColor:[CPColor colorWithRed:242.0 / 255.0 green:243.0 / 255.0 blue:245.0 / 255.0 alpha:1.0]];
|
||||
|
||||
[_autocompleteScrollView setDocumentView:_autocompleteView];
|
||||
}
|
||||
|
||||
// ===============
|
||||
// = CONVENIENCE =
|
||||
// ===============
|
||||
@@ -159,7 +164,7 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
{
|
||||
var indexOfSelectedItem = 0;
|
||||
|
||||
_cachedCompletions = [self tokenField:self completionsForSubstring:[self _inputElement].value indexOfToken:_tokenIndex indexOfSelectedItem:indexOfSelectedItem];
|
||||
_cachedCompletions = [self tokenField:self completionsForSubstring:[self _inputElement].value indexOfToken:0 indexOfSelectedItem:indexOfSelectedItem];
|
||||
|
||||
[_autocompleteView selectRowIndexes:[CPIndexSet indexSetWithIndex:indexOfSelectedItem] byExtendingSelection:NO];
|
||||
[_autocompleteView reloadData];
|
||||
@@ -167,19 +172,20 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
|
||||
- (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)
|
||||
@@ -194,7 +200,6 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var objectValue = [self objectValue];
|
||||
|
||||
// Remove the uncompleted token and add the token string.
|
||||
@@ -202,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];
|
||||
@@ -250,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];
|
||||
@@ -291,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 =
|
||||
// =============
|
||||
@@ -575,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
|
||||
@@ -1123,7 +1158,7 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
{
|
||||
if ([[self delegate] respondsToSelector:@selector(tokenField:completionsForSubstring:indexOfToken:indexOfSelectedItem:)])
|
||||
{
|
||||
return [[self delegate] tokenField:tokenField completionsForSubstring:substring indexOfToken:_tokenIndex indexOfSelectedItem:selectedIndex];
|
||||
return [[self delegate] tokenField:tokenField completionsForSubstring:substring indexOfToken:tokenIndex indexOfSelectedItem:selectedIndex];
|
||||
}
|
||||
|
||||
return [];
|
||||
@@ -1149,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
|
||||
@@ -1292,3 +1339,37 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
var CPTokenFieldTokenizingCharacterSetKey = "CPTokenFieldTokenizingCharacterSetKey",
|
||||
CPTokenFieldCompletionDelayKey = "CPTokenFieldCompletionDelay";
|
||||
|
||||
@implementation CPTokenField (CPCoding)
|
||||
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
self = [super initWithCoder:aCoder];
|
||||
|
||||
if (self)
|
||||
{
|
||||
_tokenizingCharacterSet = [aCoder decodeObjectForKey:CPTokenFieldTokenizingCharacterSetKey] || [[self class] defaultTokenizingCharacterSet];
|
||||
_completionDelay = [aCoder decodeDoubleForKey:CPTokenFieldCompletionDelayKey] || [[self class] defaultCompletionDelay];
|
||||
|
||||
[self _init];
|
||||
|
||||
[self setNeedsLayout];
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
[super encodeWithCoder:aCoder];
|
||||
|
||||
[aCoder encodeInt:_tokenizingCharacterSet forKey:CPTokenFieldTokenizingCharacterSetKey];
|
||||
[aCoder encodeDouble:_completionDelay forKey:CPTokenFieldCompletionDelayKey];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -1015,7 +1015,7 @@ var TOP_MARGIN = 5.0,
|
||||
_labelSize = [_labelField frame].size;
|
||||
|
||||
_minSize = CGSizeMake(MAX(_labelSize.width, minSize.width), _labelSize.height + minSize.height + LABEL_MARGIN + TOP_MARGIN);
|
||||
_maxSize = CGSizeMake(MIN(_labelSize.width, maxSize.width), 100000000.0);
|
||||
_maxSize = CGSizeMake(MAX(_labelSize.width, maxSize.width), 100000000.0);
|
||||
|
||||
[_toolbar tile];
|
||||
}
|
||||
|
||||
@@ -111,7 +111,8 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOutEffect";
|
||||
view = [self _targetView:dictionary],
|
||||
startFrame = [self _startFrame:dictionary],
|
||||
endFrame = [self _endFrame:dictionary],
|
||||
differenceFrame = _CGRectMakeZero();
|
||||
differenceFrame = _CGRectMakeZero(),
|
||||
value = [super currentValue];
|
||||
|
||||
differenceFrame.origin.x = endFrame.origin.x - startFrame.origin.x;
|
||||
differenceFrame.origin.y = endFrame.origin.y - startFrame.origin.y;
|
||||
@@ -119,19 +120,19 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOutEffect";
|
||||
differenceFrame.size.height = endFrame.size.height - startFrame.size.height;
|
||||
|
||||
var intermediateFrame = _CGRectMakeZero();
|
||||
intermediateFrame.origin.x = startFrame.origin.x + differenceFrame.origin.x * progress;
|
||||
intermediateFrame.origin.y = startFrame.origin.y + differenceFrame.origin.y * progress;
|
||||
intermediateFrame.size.width = startFrame.size.width + differenceFrame.size.width * progress;
|
||||
intermediateFrame.size.height = startFrame.size.height + differenceFrame.size.height * progress;
|
||||
intermediateFrame.origin.x = startFrame.origin.x + differenceFrame.origin.x * value;
|
||||
intermediateFrame.origin.y = startFrame.origin.y + differenceFrame.origin.y * value;
|
||||
intermediateFrame.size.width = startFrame.size.width + differenceFrame.size.width * value;
|
||||
intermediateFrame.size.height = startFrame.size.height + differenceFrame.size.height * value;
|
||||
|
||||
[view setFrame:intermediateFrame];
|
||||
|
||||
// Update the view's alpha value
|
||||
var effect = [self _effect:dictionary];
|
||||
if (effect === CPViewAnimationFadeInEffect)
|
||||
[view setAlphaValue:1.0 * progress];
|
||||
[view setAlphaValue:1.0 * value];
|
||||
else if (effect === CPViewAnimationFadeOutEffect)
|
||||
[view setAlphaValue:1.0 + ( 0.0 - 1.0 ) * progress];
|
||||
[view setAlphaValue:1.0 + ( 0.0 - 1.0 ) * value];
|
||||
|
||||
if (progress === 1.0)
|
||||
[self _targetView:view setHidden:_CGRectIsNull(endFrame) || [view alphaValue] === 0.0];
|
||||
|
||||
@@ -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,6 +483,7 @@ CPTexturedBackgroundWindowMask
|
||||
[self close];
|
||||
|
||||
_platformWindow = aPlatformWindow;
|
||||
[_platformWindow _setTitle:_title window:self];
|
||||
|
||||
if (wasVisible)
|
||||
[self orderFront:self];
|
||||
@@ -949,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]];
|
||||
|
||||
@@ -1273,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;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1359,6 +1369,7 @@ CPTexturedBackgroundWindowMask
|
||||
_title = aTitle;
|
||||
|
||||
[_windowView setTitle:aTitle];
|
||||
[_platformWindow _setTitle:_title window:self];
|
||||
|
||||
[self _synchronizeMenuBarTitleWithWindowTitle];
|
||||
}
|
||||
@@ -1429,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
|
||||
*/
|
||||
@@ -2485,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];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -2596,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]);
|
||||
|
||||
@@ -2928,5 +2998,6 @@ CPCustomWindowShadowStyle = 3;
|
||||
@import "_CPHUDWindowView.j"
|
||||
@import "_CPBorderlessWindowView.j"
|
||||
@import "_CPBorderlessBridgeWindowView.j"
|
||||
@import "_CPAttachedWindowView.j"
|
||||
@import "CPDragServer.j"
|
||||
@import "CPView.j"
|
||||
|
||||
@@ -0,0 +1,300 @@
|
||||
/*
|
||||
* _CPAttachedWindowView.j
|
||||
* AppKit
|
||||
*
|
||||
* Created by Antoine Mercadal
|
||||
* Copyright 2011 <primalmotion@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
|
||||
* 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 "_CPWindowView.j"
|
||||
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
|
||||
A custom CPWindowView that manage border and cursor
|
||||
*/
|
||||
@implementation _CPAttachedWindowView : _CPWindowView
|
||||
{
|
||||
BOOL _mouseDownPressed @accessors(getter=isMouseDownPressed, setter=setMouseDownPressed:);
|
||||
float _arrowOffsetX @accessors(property=arrowOffsetX);
|
||||
float _arrowOffsetY @accessors(property=arrowOffsetY);
|
||||
int _appearance @accessors(property=appearance);
|
||||
unsigned _preferredEdge @accessors(property=preferredEdge);
|
||||
|
||||
CPSize _cursorSize;
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute the contentView frame from a given window frame
|
||||
|
||||
@param aFrameRect the window frame
|
||||
*/
|
||||
- (CGRect)contentRectForFrameRect:(CGRect)aFrameRect
|
||||
{
|
||||
var contentRect = CGRectMakeCopy(aFrameRect);
|
||||
|
||||
// @todo change border art and remove this pixel perfect adaptation
|
||||
// return CGRectInset(contentRect, 20, 20);
|
||||
|
||||
contentRect.origin.x += 18;
|
||||
contentRect.origin.y += 17;
|
||||
contentRect.size.width -= 35;
|
||||
contentRect.size.height -= 37;
|
||||
|
||||
return contentRect;
|
||||
}
|
||||
|
||||
/*!
|
||||
Compute the window frame from a given contentView frame
|
||||
|
||||
@param aContentRect the contentView frame
|
||||
*/
|
||||
+ (CGRect)frameRectForContentRect:(CGRect)aContentRect
|
||||
{
|
||||
var frameRect = CGRectMakeCopy(aContentRect);
|
||||
|
||||
// @todo change border art and remove this pixel perfect adaptation
|
||||
//return CGRectOffset(frameRect, 20, 20);
|
||||
|
||||
frameRect.origin.x -= 18;
|
||||
frameRect.origin.y -= 17;
|
||||
frameRect.size.width += 35;
|
||||
frameRect.size.height += 37;
|
||||
return frameRect;
|
||||
}
|
||||
|
||||
/*!
|
||||
Initialize the _CPWindowView
|
||||
*/
|
||||
- (id)initWithFrame:(CPRect)aFrame styleMask:(unsigned)aStyleMask
|
||||
{
|
||||
if (self = [super initWithFrame:aFrame styleMask:aStyleMask])
|
||||
{
|
||||
var bundle = [CPBundle bundleForClass:[self class]];
|
||||
_arrowOffsetX = 0.0;
|
||||
_arrowOffsetY = 0.0;
|
||||
|
||||
// @TODO: make this themable
|
||||
_useGlowingEffect = YES;
|
||||
_appearance = CPPopoverAppearanceMinimal;
|
||||
_cursorSize = CPSizeMake(15, 10);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/*!
|
||||
Hide the cursor
|
||||
*/
|
||||
- (void)hideCursor
|
||||
{
|
||||
_cursorSize = CPSizeMakeZero();
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
/*!
|
||||
Show the cursor
|
||||
*/
|
||||
- (void)showCursor
|
||||
{
|
||||
_cursorSize = CPSizeMake(15, 10);
|
||||
[self setNeedsDisplay:YES];
|
||||
_mouseDownPressed = NO;
|
||||
}
|
||||
|
||||
/*!
|
||||
Draw the view
|
||||
*/
|
||||
- (void)drawRect:(CGRect)aRect
|
||||
{
|
||||
[super drawRect:aRect];
|
||||
|
||||
var context = [[CPGraphicsContext currentContext] graphicsPort],
|
||||
radius = 5,
|
||||
arrowWidth = _cursorSize.width,
|
||||
arrowHeight = _cursorSize.height,
|
||||
strokeWidth = 1,
|
||||
strokeColor,
|
||||
shadowColor = [[CPColor blackColor] colorWithAlphaComponent:.2],
|
||||
shadowSize = CGSizeMake(0, 7),
|
||||
shadowBlur = 15,
|
||||
gradient;
|
||||
|
||||
if (_appearance == CPPopoverAppearanceMinimal)
|
||||
{
|
||||
gradient = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [(254.0 / 255), (254.0 / 255), (254.0 / 255), 0.93,
|
||||
(231.0 / 255), (231.0 / 255), (231.0 / 255), 0.93], [0,1], 2);
|
||||
strokeColor = [CPColor colorWithHexString:@"B8B8B8"];
|
||||
}
|
||||
else
|
||||
{
|
||||
gradient = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [(38.0 / 255), (38.0 / 255), (38.0 / 255), 0.93,
|
||||
(18.0 / 255), (18.0 / 255), (18.0 / 255), 0.93], [0,1], 2);
|
||||
strokeColor = [CPColor colorWithHexString:@"222222"];
|
||||
}
|
||||
|
||||
// fix rect to take care of stroke and shadow
|
||||
aRect.origin.x += strokeWidth + shadowBlur;
|
||||
aRect.origin.y += strokeWidth + (shadowBlur + shadowSize.height / 2);
|
||||
aRect.size.width -= (strokeWidth * 2) + (shadowBlur * 2);
|
||||
aRect.size.height -= (strokeWidth * 2) + (shadowBlur * 2 + shadowSize.height);
|
||||
|
||||
CGContextSetStrokeColor(context, strokeColor);
|
||||
CGContextSetLineWidth(context, strokeWidth);
|
||||
CGContextBeginPath(context);
|
||||
CGContextSetShadowWithColor(context, shadowSize, shadowBlur, shadowColor);
|
||||
CGContextDrawLinearGradient(context, gradient, CGPointMake(CPRectGetMidX(aRect), 0.0), CGPointMake(CPRectGetMidX(aRect), aRect.size.height), 0);
|
||||
|
||||
|
||||
var xMin = _CGRectGetMinX(aRect),
|
||||
xMax = _CGRectGetMaxX(aRect),
|
||||
yMin = _CGRectGetMinY(aRect),
|
||||
yMax = _CGRectGetMaxY(aRect);
|
||||
|
||||
// draw!
|
||||
switch (_preferredEdge)
|
||||
{
|
||||
case CPMinXEdge:
|
||||
// origin ne
|
||||
CGContextMoveToPoint(context, xMin + radius, yMin);
|
||||
|
||||
// ne
|
||||
CGContextAddLineToPoint(context, xMax - radius, yMin);
|
||||
CGContextAddCurveToPoint(context, xMax - radius, yMin, xMax, yMin, xMax, yMin + radius);
|
||||
|
||||
// arrow CPMinXEdge
|
||||
CGContextAddLineToPoint(context, xMax, (aRect.size.height / 2) + aRect.origin.y + _arrowOffsetY - (arrowHeight - 2));
|
||||
CGContextAddLineToPoint(context, aRect.size.width + arrowHeight + aRect.origin.x + _arrowOffsetX, (aRect.size.height / 2) + aRect.origin.y + _arrowOffsetY);
|
||||
CGContextAddLineToPoint(context, aRect.size.width + aRect.origin.x + _arrowOffsetX, (aRect.size.height / 2 + (arrowWidth / 2)) + aRect.origin.y + _arrowOffsetY);
|
||||
|
||||
// se
|
||||
CGContextAddLineToPoint(context, xMax, yMax - radius);
|
||||
CGContextAddCurveToPoint(context, xMax, yMax - radius, xMax, yMax, xMax - radius, yMax);
|
||||
|
||||
// sw
|
||||
CGContextAddLineToPoint(context, xMin + radius, yMax);
|
||||
CGContextAddCurveToPoint(context, xMin + radius, yMax, xMin, yMax, xMin, yMax - radius);
|
||||
|
||||
// nw
|
||||
CGContextAddLineToPoint(context, xMin, yMin + radius);
|
||||
CGContextAddCurveToPoint(context, xMin, yMin + radius, xMin, yMin, xMin + radius, yMin);
|
||||
break;
|
||||
|
||||
case CPMaxXEdge:
|
||||
// origin ne
|
||||
CGContextMoveToPoint(context, xMin + radius, yMin);
|
||||
|
||||
// ne
|
||||
CGContextAddLineToPoint(context, xMax - radius, yMin);
|
||||
CGContextAddCurveToPoint(context, xMax - radius, yMin, xMax, yMin, xMax, yMin + radius);
|
||||
|
||||
// se
|
||||
CGContextAddLineToPoint(context, xMax, yMax - radius);
|
||||
CGContextAddCurveToPoint(context, xMax, yMax - radius, xMax, yMax, xMax - radius, yMax);
|
||||
|
||||
// sw
|
||||
CGContextAddLineToPoint(context, xMin + radius, yMax);
|
||||
CGContextAddCurveToPoint(context, xMin + radius, yMax, xMin, yMax, xMin, yMax - radius);
|
||||
|
||||
// arrow CPMaxXEdge
|
||||
CGContextAddLineToPoint(context, xMin, (aRect.size.height / 2 + (arrowWidth / 2) + aRect.origin.y + _arrowOffsetY));
|
||||
CGContextAddLineToPoint(context, aRect.origin.x - arrowHeight + _arrowOffsetX, (aRect.size.height / 2) + aRect.origin.y + _arrowOffsetY);
|
||||
CGContextAddLineToPoint(context, aRect.origin.x + _arrowOffsetX, (aRect.size.height / 2 - (arrowWidth / 2) + aRect.origin.y + _arrowOffsetY));
|
||||
|
||||
// nw
|
||||
CGContextAddLineToPoint(context, xMin, yMin + radius);
|
||||
CGContextAddCurveToPoint(context, xMin, yMin + radius, xMin, yMin, xMin + radius, yMin);
|
||||
break;
|
||||
|
||||
case CPMaxYEdge:
|
||||
// origin nw
|
||||
CGContextMoveToPoint(context, xMin, yMin + yMin);
|
||||
|
||||
// nw
|
||||
CGContextAddLineToPoint(context, xMin, yMin + radius);
|
||||
CGContextAddCurveToPoint(context, xMin, yMin + radius, xMin, yMin, xMin + radius, yMin);
|
||||
|
||||
// arrow CPMaxYEdge
|
||||
CGContextAddLineToPoint(context, (aRect.size.width / 2) + aRect.origin.x + _arrowOffsetX - (arrowWidth / 2), yMin);
|
||||
CGContextAddLineToPoint(context, (aRect.size.width / 2) + aRect.origin.x + _arrowOffsetX, aRect.origin.y - arrowHeight + _arrowOffsetY);
|
||||
CGContextAddLineToPoint(context, (aRect.size.width / 2) + (arrowWidth / 2) + aRect.origin.x + _arrowOffsetX, aRect.origin.y + _arrowOffsetY);
|
||||
|
||||
// ne
|
||||
CGContextAddLineToPoint(context, xMax - radius, yMin);
|
||||
CGContextAddCurveToPoint(context, xMax - radius, yMin, xMax, yMin, xMax, yMin + radius);
|
||||
|
||||
// se
|
||||
CGContextAddLineToPoint(context, xMax, yMax - radius);
|
||||
CGContextAddCurveToPoint(context, xMax, yMax - radius, xMax, yMax, xMax - radius, yMax);
|
||||
|
||||
// sw
|
||||
CGContextAddLineToPoint(context, xMin + radius, yMax);
|
||||
CGContextAddCurveToPoint(context, xMin + radius, yMax, xMin, yMax, xMin, yMax - radius);
|
||||
break;
|
||||
|
||||
case CPMinYEdge:
|
||||
// origin nw
|
||||
CGContextMoveToPoint(context, xMin, yMin + yMin);
|
||||
|
||||
// nw
|
||||
CGContextAddLineToPoint(context, xMin, yMin + radius);
|
||||
CGContextAddCurveToPoint(context, xMin, yMin + radius, xMin, yMin, xMin + radius, yMin);
|
||||
|
||||
// ne
|
||||
CGContextAddLineToPoint(context, xMax - radius, yMin);
|
||||
CGContextAddCurveToPoint(context, xMax - radius, yMin, xMax, yMin, xMax, yMin + radius);
|
||||
|
||||
// se
|
||||
CGContextAddLineToPoint(context, xMax, yMax - radius);
|
||||
CGContextAddCurveToPoint(context, xMax, yMax - radius, xMax, yMax, xMax - radius, yMax);
|
||||
|
||||
// arrow CPMinYEdge
|
||||
CGContextAddLineToPoint(context, (aRect.size.width / 2) + (arrowWidth / 2) + aRect.origin.x + _arrowOffsetX , yMax);
|
||||
CGContextAddLineToPoint(context, (aRect.size.width / 2) + aRect.origin.x + _arrowOffsetX, aRect.size.height + aRect.origin.y + arrowHeight + _arrowOffsetY);
|
||||
CGContextAddLineToPoint(context, (aRect.size.width / 2) - (arrowWidth / 2) + aRect.origin.x + _arrowOffsetX, aRect.size.height + aRect.origin.y + _arrowOffsetY);
|
||||
|
||||
// sw
|
||||
CGContextAddLineToPoint(context, xMin + radius, yMax);
|
||||
CGContextAddCurveToPoint(context, xMin + radius, yMax, xMin, yMax, xMin, yMax - radius);
|
||||
break;
|
||||
|
||||
default:
|
||||
// no computed edge means standard rounded rect
|
||||
CGContextAddPath(context, CGPathWithRoundedRectangleInRect(aRect, radius, radius, YES, YES, YES, YES));
|
||||
}
|
||||
|
||||
CGContextClosePath(context);
|
||||
|
||||
//Draw it
|
||||
CGContextStrokePath(context);
|
||||
CGContextFillPath(context);
|
||||
}
|
||||
|
||||
- (void)mouseDown:(CPEvent)anEvent
|
||||
{
|
||||
_mouseDownPressed = YES;
|
||||
[super mouseDown:anEvent];
|
||||
}
|
||||
|
||||
- (void)mouseUp:(CPEvent)anEvent
|
||||
{
|
||||
_mouseDownPressed = NO;
|
||||
[super mouseUp:anEvent];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -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";
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -42,7 +42,16 @@
|
||||
#include "DOM/CPPlatformString.j"
|
||||
#else
|
||||
@implementation CPPlatformString : CPBasePlatformString
|
||||
|
||||
+ (CGSize)sizeOfString:(CPString)aString withFont:(CPFont)aFont forWidth:(float)aWidth
|
||||
{
|
||||
return _CGSizeMakeZero();
|
||||
}
|
||||
|
||||
+ (CPDictionary)metricsOfFont:(CPFont)aFont
|
||||
{
|
||||
return [CPDictionary dictionaryWithObjectsAndKeys:0, @"ascender", 0, @"descender", 0, @"lineHeight"];
|
||||
}
|
||||
|
||||
@end
|
||||
#endif
|
||||
|
||||
@@ -32,6 +32,7 @@ var PrimaryPlatformWindow = NULL;
|
||||
CPInteger _level;
|
||||
BOOL _hasShadow;
|
||||
unsigned _shadowStyle;
|
||||
CPString _title;
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
DOMWindow _DOMWindow;
|
||||
@@ -258,6 +259,22 @@ var PrimaryPlatformWindow = NULL;
|
||||
return [CPPlatform isBrowser];
|
||||
}
|
||||
|
||||
- (void)_setTitle:(CPString)aTitle window:(CPWindow)aWindow
|
||||
{
|
||||
_title = aTitle;
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
if (_DOMWindow && _DOMWindow.document
|
||||
&& (aWindow === [CPApp mainWindow] || [aWindow platformWindow] !== [CPPlatformWindow primaryPlatformWindow]))
|
||||
_DOMWindow.document.title = _title;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (CPString)title
|
||||
{
|
||||
return _title;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#if PLATFORM(BROWSER)
|
||||
|
||||
@@ -534,13 +534,15 @@ var ModifierKeyCodes = [
|
||||
if (_DOMWindow)
|
||||
return _DOMWindow.focus();
|
||||
|
||||
_DOMWindow = window.open("", "_blank", "menubar=no,location=no,resizable=yes,scrollbars=no,status=no,left=" + _CGRectGetMinX(_contentRect) + ",top=" + _CGRectGetMinY(_contentRect) + ",width=" + _CGRectGetWidth(_contentRect) + ",height=" + _CGRectGetHeight(_contentRect));
|
||||
_DOMWindow = window.open("about:blank", "_blank", "menubar=no,location=no,resizable=yes,scrollbars=no,status=no,left=" + _CGRectGetMinX(_contentRect) + ",top=" + _CGRectGetMinY(_contentRect) + ",width=" + _CGRectGetWidth(_contentRect) + ",height=" + _CGRectGetHeight(_contentRect));
|
||||
|
||||
[PlatformWindows addObject:self];
|
||||
|
||||
// FIXME: cpSetFrame?
|
||||
_DOMWindow.document.write("<!DOCTYPE html><html lang='en'><head></head><body style='background-color:transparent;'></body></html>");
|
||||
_DOMWindow.document.close();
|
||||
if (self != [CPPlatformWindow primaryPlatformWindow])
|
||||
_DOMWindow.document.title = _title;
|
||||
|
||||
if (![CPPlatform isBrowser])
|
||||
{
|
||||
@@ -706,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 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 |
|
After Width: | Height: | Size: 163 B |
|
Before Width: | Height: | Size: 421 B |
|
Before Width: | Height: | Size: 143 B |
|
Before Width: | Height: | Size: 424 B |
|
After Width: | Height: | Size: 154 B |
|
After Width: | Height: | Size: 116 B |
|
After Width: | Height: | Size: 154 B |
|
Before Width: | Height: | Size: 433 B After Width: | Height: | Size: 186 B |
|
After Width: | Height: | Size: 213 B |
|
After Width: | Height: | Size: 145 B |
|
After Width: | Height: | Size: 194 B |
|
After Width: | Height: | Size: 145 B |
|
After Width: | Height: | Size: 178 B |
|
After Width: | Height: | Size: 220 B |
|
After Width: | Height: | Size: 154 B |
|
After Width: | Height: | Size: 116 B |