Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4080fd91b2 | ||
|
|
82c71617d1 | ||
|
|
8dd61155bf | ||
|
|
5a89dfe8f4 | ||
|
|
80b70ec6b9 | ||
|
|
ac81ab458c | ||
|
|
23b76874df | ||
|
|
bc54fcf6c0 | ||
|
|
e0a3a683a5 | ||
|
|
c31786c4c1 | ||
|
|
13a5c7f215 | ||
|
|
ee2f361425 | ||
|
|
9eab2071dc | ||
|
|
61d7fe04e8 | ||
|
|
d3161422db | ||
|
|
c6b3db44da | ||
|
|
d1ae1bd41f | ||
|
|
6384bed9cc | ||
|
|
be75e4948d | ||
|
|
337f5d9e73 | ||
|
|
4afa2bfada | ||
|
|
b94174f9e1 | ||
|
|
bf71045381 | ||
|
|
0ade0e1361 | ||
|
|
0f02e0d8dd | ||
|
|
7c786407a5 | ||
|
|
79ba8fecd5 | ||
|
|
213c81ed4d | ||
|
|
d7432c376d | ||
|
|
b8c7d6ea86 | ||
|
|
983f0a92b2 | ||
|
|
256cc902eb | ||
|
|
f7b766cc4a | ||
|
|
dca66f300d | ||
|
|
fd9dac8122 | ||
|
|
8b168e76af | ||
|
|
5b518797d7 | ||
|
|
e5275514dd | ||
|
|
0d35b38282 | ||
|
|
837dcbf19d | ||
|
|
e68d70cf1d | ||
|
|
e5873caf04 | ||
|
|
c43b80cb91 | ||
|
|
542e491bb4 | ||
|
|
9c9eb519df | ||
|
|
90975c96f9 | ||
|
|
2fd85ab78f | ||
|
|
a0cf7d5787 | ||
|
|
e7fc9d9912 | ||
|
|
bdb0fb1310 | ||
|
|
006f7e0c15 | ||
|
|
93afa11ef9 | ||
|
|
040e7bc9ee | ||
|
|
6bb8514253 | ||
|
|
85283cff38 | ||
|
|
ef68408fff | ||
|
|
71104e4902 | ||
|
|
65362e727a | ||
|
|
5044ce4236 | ||
|
|
b4aca3410f | ||
|
|
b5971eae95 | ||
|
|
4b775796be | ||
|
|
e97af776a0 | ||
|
|
e83e5b7c29 | ||
|
|
179ef85f4e | ||
|
|
5b4603b6a7 | ||
|
|
fc2560eb32 | ||
|
|
2c23c0ffa7 | ||
|
|
fda974458e | ||
|
|
efe4d5f339 | ||
|
|
032fe7cc0c | ||
|
|
50c519ec69 | ||
|
|
af566ec08a | ||
|
|
cb7879eecf | ||
|
|
b1825334dd | ||
|
|
09727909b3 | ||
|
|
f98d3bd44b | ||
|
|
1545f7b60a | ||
|
|
2453e403ef | ||
|
|
2bb16c3617 | ||
|
|
4ef9202e92 | ||
|
|
22668b6b43 | ||
|
|
f9c786f3eb | ||
|
|
0f2ee1966e | ||
|
|
62e520a6a5 | ||
|
|
2f9cf6bc9b | ||
|
|
e03cfe8287 | ||
|
|
0d97dfacd6 | ||
|
|
6ac0191451 | ||
|
|
f5b360f66c | ||
|
|
1d5c21fa72 | ||
|
|
015aca9165 | ||
|
|
d3e1c39e35 | ||
|
|
ae47509aa7 | ||
|
|
5ff798306f | ||
|
|
c41ffc14c7 | ||
|
|
1e7a3bef0d | ||
|
|
243f564396 | ||
|
|
dae1e44a8f | ||
|
|
67bcc29baf | ||
|
|
cdb089778c | ||
|
|
5e43a02ffa | ||
|
|
7395d13c3e | ||
|
|
f6000468db | ||
|
|
09e52d82bf | ||
|
|
0e98f44a93 | ||
|
|
6d595c1344 | ||
|
|
5f6f997095 | ||
|
|
6662fabcb8 | ||
|
|
7577cf8645 | ||
|
|
8340791824 | ||
|
|
14f0d16fae | ||
|
|
e1ad4a2fce | ||
|
|
f67580e2b2 | ||
|
|
31f408478a | ||
|
|
fd93b6e5f7 | ||
|
|
39bb8e3418 | ||
|
|
ab6d5d6a90 | ||
|
|
6b3600d67b | ||
|
|
bf8ff44b84 | ||
|
|
72a3888062 | ||
|
|
4479233bea | ||
|
|
a7021e6b66 | ||
|
|
0f5dd9d469 | ||
|
|
388f008189 | ||
|
|
639a32ea7e | ||
|
|
5838f1aec8 | ||
|
|
d2399b6157 | ||
|
|
b1282b4362 | ||
|
|
bbd402fcff | ||
|
|
a18fb1b686 | ||
|
|
6a72e1b6ff | ||
|
|
b3141f1a62 | ||
|
|
aea8f1f0dc | ||
|
|
8aecf880e5 | ||
|
|
7d5ce51910 | ||
|
|
cfc8ccafce | ||
|
|
e11dfc2875 | ||
|
|
b3ef31ad05 | ||
|
|
70410d6311 | ||
|
|
4cc7dec35b | ||
|
|
47ecd40c4f | ||
|
|
489f2bcfa0 | ||
|
|
16590e0603 | ||
|
|
f50cda9abc | ||
|
|
7543968203 | ||
|
|
54685b1f36 | ||
|
|
abdc601d92 | ||
|
|
9f50f08065 | ||
|
|
aabb1fa6f2 | ||
|
|
4b770714bd | ||
|
|
8175dbca53 | ||
|
|
c91332afb4 | ||
|
|
08fb1b33b4 | ||
|
|
cd6b6afc65 | ||
|
|
cd4a70ea78 | ||
|
|
eb24ba9835 | ||
|
|
468869821f | ||
|
|
0c85dbf9b0 | ||
|
|
2db47e413e | ||
|
|
b8fddc98bf | ||
|
|
467f798147 | ||
|
|
374f3d13f1 | ||
|
|
b0a35a183f | ||
|
|
74e349ed33 | ||
|
|
c57aa2ac5e | ||
|
|
acac29dcda | ||
|
|
675969af6d | ||
|
|
ce32177e1d | ||
|
|
e956d61a08 | ||
|
|
068cdb9817 | ||
|
|
0ec7d4cd9a | ||
|
|
6a8126337c | ||
|
|
12db25a829 | ||
|
|
a347bfb8b1 | ||
|
|
9255af210c | ||
|
|
0b3264a99d | ||
|
|
2bf16da441 | ||
|
|
5c4d890100 | ||
|
|
99282026fa | ||
|
|
8f4b2a7cfd | ||
|
|
c78feda3d6 | ||
|
|
a279d62c88 | ||
|
|
8d1f787179 | ||
|
|
7ab41cf195 | ||
|
|
df728b7a21 | ||
|
|
cba26faf9b | ||
|
|
c4c1cffc01 | ||
|
|
321706e5c6 | ||
|
|
47bf4c0baa | ||
|
|
fc628c1221 | ||
|
|
eb6a03704a | ||
|
|
7b855e6c68 | ||
|
|
fe0818c612 | ||
|
|
74dabcae8a | ||
|
|
daf7870bab | ||
|
|
64da7f8775 | ||
|
|
6cfa11a94d | ||
|
|
db3c6c1463 | ||
|
|
65a669a9a1 | ||
|
|
33f56bb203 | ||
|
|
1ff873e170 | ||
|
|
b0e0156880 | ||
|
|
896f36dffb | ||
|
|
eae975652e | ||
|
|
e46d1a793c | ||
|
|
1c9763eaa8 | ||
|
|
686370ac0e | ||
|
|
e4ca057e4c | ||
|
|
ac5a0e3dfc | ||
|
|
a580b522e3 | ||
|
|
af53c271c7 | ||
|
|
4476dad395 | ||
|
|
b7b2dd2915 | ||
|
|
efb6a0f5c6 | ||
|
|
deba653661 | ||
|
|
eb831dc4ac | ||
|
|
b0d355a71c | ||
|
|
af11b4e423 | ||
|
|
0cf86318ce | ||
|
|
4175b762c3 | ||
|
|
3ddcb5f118 | ||
|
|
d0ad865976 | ||
|
|
7013b34897 | ||
|
|
bbbae36e6a | ||
|
|
34c3a9530b | ||
|
|
78cb522874 | ||
|
|
e8a0d2acf6 | ||
|
|
f8c13f1e30 | ||
|
|
4b272a76fd | ||
|
|
f73d96af08 | ||
|
|
bb0835e2f3 | ||
|
|
ef4c108b9e | ||
|
|
319b9ed00f | ||
|
|
35b62ca53f | ||
|
|
4e1e6f3c0b | ||
|
|
c8f3445fa6 | ||
|
|
7aa1ae6bd4 | ||
|
|
58179939bb | ||
|
|
5d3eae9022 | ||
|
|
05f8a10b3d | ||
|
|
6843df410a | ||
|
|
f324577014 | ||
|
|
df8357e1fc | ||
|
|
35d14939c4 | ||
|
|
f2c19ad403 | ||
|
|
ed9fee3038 | ||
|
|
58e31b9cb4 | ||
|
|
401ee3fd94 | ||
|
|
43b601af9b | ||
|
|
5581dd71fa | ||
|
|
d8fb849691 | ||
|
|
5f4281b851 | ||
|
|
24ab176236 | ||
|
|
9c342ca19c | ||
|
|
3ee3acc948 | ||
|
|
9bdc5fa0fe | ||
|
|
d7a7d8e2ae | ||
|
|
5a9682b1bd | ||
|
|
3c97903ed0 | ||
|
|
c9cf21be80 | ||
|
|
f0818d94e9 | ||
|
|
831555cf5a | ||
|
|
e0483e316e | ||
|
|
c1fe45cbcd | ||
|
|
ef7ad8ee8e | ||
|
|
0ed7d46926 | ||
|
|
ac69879fba | ||
|
|
50e779ef5a | ||
|
|
0032af1468 | ||
|
|
cf1c369dc3 | ||
|
|
ece7996895 | ||
|
|
3cdfc1192a | ||
|
|
8b8998a2b9 | ||
|
|
677cf9e1df | ||
|
|
a08d4c6a06 | ||
|
|
e1e344dad1 | ||
|
|
b9427f84ae | ||
|
|
dc9d79bc3d | ||
|
|
503ce5502e | ||
|
|
0e4d476d76 | ||
|
|
cc2d579bc9 | ||
|
|
94bf2a36cf | ||
|
|
63127bf9c3 | ||
|
|
033765e866 | ||
|
|
1634e4562a | ||
|
|
ed66d78585 | ||
|
|
39e1514620 | ||
|
|
10b7eb83f1 | ||
|
|
672be3991d | ||
|
|
b350c2be91 | ||
|
|
68ab5bd4e7 | ||
|
|
bd21153300 | ||
|
|
9cca7ead17 | ||
|
|
4b1bf1fe65 | ||
|
|
6d353f378d | ||
|
|
cc2bb8f496 | ||
|
|
20853e3ad7 | ||
|
|
67def34e29 | ||
|
|
54549b61e1 | ||
|
|
3e7c3e952b | ||
|
|
e6411d7d90 | ||
|
|
9e7d0d3183 | ||
|
|
3ae4b1cf19 | ||
|
|
2841223c9d | ||
|
|
ba713b8b06 | ||
|
|
c53bff288a | ||
|
|
d85e8798c2 | ||
|
|
6dbb4eedb7 | ||
|
|
33b4b94426 | ||
|
|
3fc99095e2 | ||
|
|
8410198c37 | ||
|
|
d1b325052d | ||
|
|
4c4b42833a | ||
|
|
519a9300e2 | ||
|
|
7522751fd2 | ||
|
|
f2165af48f | ||
|
|
e3a65a1847 |
@@ -26,6 +26,7 @@
|
||||
@import "CPApplication.j"
|
||||
@import "CPBezierPath.j"
|
||||
@import "CPBox.j"
|
||||
@import "CPBrowser.j"
|
||||
@import "CPButton.j"
|
||||
@import "CPButtonBar.j"
|
||||
@import "CPCheckBox.j"
|
||||
|
||||
@@ -96,12 +96,12 @@
|
||||
return _items;
|
||||
}
|
||||
|
||||
- (void)addItem:(CPAccordionItem)anItem
|
||||
- (void)addItem:(CPAccordionViewItem)anItem
|
||||
{
|
||||
[self insertItem:anItem atIndex:_items.length];
|
||||
}
|
||||
|
||||
- (void)insertItem:(CPAccordionItem)anItem atIndex:(CPInteger)anIndex
|
||||
- (void)insertItem:(CPAccordionViewItem)anItem atIndex:(CPInteger)anIndex
|
||||
{
|
||||
// FIXME: SHIFT ITEMS RIGHT
|
||||
[_expandedItemIndexes addIndex:anIndex];
|
||||
@@ -122,7 +122,7 @@
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)removeItem:(CPAccordionItem)anItem
|
||||
- (void)removeItem:(CPAccordionViewItem)anItem
|
||||
{
|
||||
[self removeItemAtIndex:[_items indexOfObjectIdenticalTo:anItem]];
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
@import "CPCibLoading.j"
|
||||
@import "CPPlatform.j"
|
||||
|
||||
#include "Platform/Platform.h"
|
||||
|
||||
var CPMainCibFile = @"CPMainCibFile",
|
||||
CPMainCibFileHumanFriendly = @"Main cib file base name";
|
||||
@@ -53,7 +54,7 @@ CPRunStoppedResponse = -1000;
|
||||
CPRunAbortedResponse = -1001;
|
||||
CPRunContinuesResponse = -1002;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPApplication
|
||||
|
||||
@@ -61,7 +62,7 @@ CPRunContinuesResponse = -1002;
|
||||
Every GUI application has exactly one instance of CPApplication (or of a custom subclass of
|
||||
CPApplication). Your program's main() function can create that instance by calling the
|
||||
\c CPApplicationMain function. A simple example looks like this:
|
||||
|
||||
|
||||
<pre>
|
||||
function main(args, namedArgs)
|
||||
{
|
||||
@@ -81,25 +82,25 @@ CPRunContinuesResponse = -1002;
|
||||
@implementation CPApplication : CPResponder
|
||||
{
|
||||
CPArray _eventListeners;
|
||||
|
||||
|
||||
CPEvent _currentEvent;
|
||||
|
||||
|
||||
CPArray _windows;
|
||||
CPWindow _keyWindow;
|
||||
CPWindow _mainWindow;
|
||||
CPWindow _previousKeyWindow;
|
||||
CPWindow _previousMainWindow;
|
||||
|
||||
|
||||
CPMenu _mainMenu;
|
||||
CPDocumentController _documentController;
|
||||
|
||||
|
||||
CPModalSession _currentSession;
|
||||
|
||||
|
||||
//
|
||||
id _delegate;
|
||||
BOOL _finishedLaunching;
|
||||
BOOL _isActive;
|
||||
|
||||
|
||||
CPDictionary _namedArgs;
|
||||
CPArray _args;
|
||||
CPString _fullArgsString;
|
||||
@@ -118,7 +119,7 @@ CPRunContinuesResponse = -1002;
|
||||
{
|
||||
if (!CPApp)
|
||||
CPApp = [[CPApplication alloc] init];
|
||||
|
||||
|
||||
return CPApp;
|
||||
}
|
||||
|
||||
@@ -130,73 +131,18 @@ CPRunContinuesResponse = -1002;
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
|
||||
CPApp = self;
|
||||
|
||||
if (self)
|
||||
{
|
||||
_eventListeners = [];
|
||||
|
||||
|
||||
_windows = [];
|
||||
|
||||
|
||||
[_windows addObject:nil];
|
||||
|
||||
// FIXME: This should be read from the cib.
|
||||
_mainMenu = [[CPMenu alloc] initWithTitle:@"MainMenu"];
|
||||
|
||||
// FIXME: We should implement autoenabling.
|
||||
[_mainMenu setAutoenablesItems:NO];
|
||||
|
||||
var bundle = [CPBundle bundleForClass:[CPApplication class]],
|
||||
newMenuItem = [[CPMenuItem alloc] initWithTitle:@"New" action:@selector(newDocument:) keyEquivalent:@"N"];
|
||||
|
||||
[newMenuItem setImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/New.png"] size:CGSizeMake(16.0, 16.0)]];
|
||||
[newMenuItem setAlternateImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/NewHighlighted.png"] size:CGSizeMake(16.0, 16.0)]];
|
||||
|
||||
[_mainMenu addItem:newMenuItem];
|
||||
|
||||
var openMenuItem = [[CPMenuItem alloc] initWithTitle:@"Open" action:@selector(openDocument:) keyEquivalent:@"O"];
|
||||
|
||||
[openMenuItem setImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/Open.png"] size:CGSizeMake(16.0, 16.0)]];
|
||||
[openMenuItem setAlternateImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/OpenHighlighted.png"] size:CGSizeMake(16.0, 16.0)]];
|
||||
|
||||
[_mainMenu addItem:openMenuItem];
|
||||
|
||||
var saveMenu = [[CPMenu alloc] initWithTitle:@"Save"],
|
||||
saveMenuItem = [[CPMenuItem alloc] initWithTitle:@"Save" action:@selector(saveDocument:) keyEquivalent:nil];
|
||||
|
||||
[saveMenuItem setImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/Save.png"] size:CGSizeMake(16.0, 16.0)]];
|
||||
[saveMenuItem setAlternateImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/SaveHighlighted.png"] size:CGSizeMake(16.0, 16.0)]];
|
||||
|
||||
[saveMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Save" action:@selector(saveDocument:) keyEquivalent:@"S"]];
|
||||
[saveMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Save As" action:@selector(saveDocumentAs:) keyEquivalent:nil]];
|
||||
|
||||
[saveMenuItem setSubmenu:saveMenu];
|
||||
|
||||
[_mainMenu addItem:saveMenuItem];
|
||||
|
||||
var editMenuItem = [[CPMenuItem alloc] initWithTitle:@"Edit" action:nil keyEquivalent:nil],
|
||||
editMenu = [[CPMenu alloc] initWithTitle:@"Edit"],
|
||||
|
||||
undoMenuItem = [[CPMenuItem alloc] initWithTitle:@"Undo" action:@selector(undo:) keyEquivalent:CPUndoKeyEquivalent],
|
||||
redoMenuItem = [[CPMenuItem alloc] initWithTitle:@"Redo" action:@selector(redo:) keyEquivalent:CPRedoKeyEquivalent];
|
||||
|
||||
[undoMenuItem setKeyEquivalentModifierMask:CPUndoKeyEquivalentModifierMask];
|
||||
[redoMenuItem setKeyEquivalentModifierMask:CPRedoKeyEquivalentModifierMask];
|
||||
|
||||
[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:@"Paste" action:@selector(paste:) keyEquivalent:@"V"]];
|
||||
|
||||
[editMenuItem setSubmenu:editMenu];
|
||||
[editMenuItem setHidden:YES];
|
||||
|
||||
[_mainMenu addItem:editMenuItem];
|
||||
|
||||
[_mainMenu addItem:[CPMenuItem separatorItem]];
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -212,85 +158,46 @@ CPRunContinuesResponse = -1002;
|
||||
{
|
||||
if (_delegate == aDelegate)
|
||||
return;
|
||||
|
||||
var defaultCenter = [CPNotificationCenter defaultCenter];
|
||||
|
||||
|
||||
var defaultCenter = [CPNotificationCenter defaultCenter],
|
||||
delegateNotifications =
|
||||
[
|
||||
CPApplicationWillFinishLaunchingNotification, @selector(applicationWillFinishLaunching:),
|
||||
CPApplicationDidFinishLaunchingNotification, @selector(applicationDidFinishLaunching:),
|
||||
CPApplicationWillBecomeActiveNotification, @selector(applicationWillBecomeActive:),
|
||||
CPApplicationDidBecomeActiveNotification, @selector(applicationDidBecomeActive:),
|
||||
CPApplicationWillResignActiveNotification, @selector(applicationWillResignActive:),
|
||||
CPApplicationDidResignActiveNotification, @selector(applicationDidResignActive:),
|
||||
CPApplicationWillTerminateNotification, @selector(applicationWillTerminate:)
|
||||
],
|
||||
count = [delegateNotifications count];
|
||||
|
||||
if (_delegate)
|
||||
{
|
||||
[defaultCenter
|
||||
removeObserver:_delegate
|
||||
name:CPApplicationWillFinishLaunchingNotification
|
||||
object:self];
|
||||
var index = 0;
|
||||
|
||||
[defaultCenter
|
||||
removeObserver:_delegate
|
||||
name:CPApplicationDidFinishLaunchingNotification
|
||||
object:self];
|
||||
for (; index < count; index += 2)
|
||||
{
|
||||
var notificationName = delegateNotifications[index],
|
||||
selector = delegateNotifications[index + 1];
|
||||
|
||||
[defaultCenter
|
||||
removeObserver:_delegate
|
||||
name:CPApplicationWillBecomeActiveNotification
|
||||
object:self];
|
||||
|
||||
[defaultCenter
|
||||
removeObserver:_delegate
|
||||
name:CPApplicationDidBecomeActiveNotification
|
||||
object:self];
|
||||
|
||||
[defaultCenter
|
||||
removeObserver:_delegate
|
||||
name:CPApplicationWillResignActiveNotification
|
||||
object:self];
|
||||
|
||||
[defaultCenter
|
||||
removeObserver:_delegate
|
||||
name:CPApplicationDidResignActiveNotification
|
||||
object:self];
|
||||
if ([_delegate respondsToSelector:selector])
|
||||
[defaultCenter removeObserver:_delegate name:notificationName object:self];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_delegate = aDelegate;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(applicationWillFinishLaunching:)])
|
||||
[defaultCenter
|
||||
addObserver:_delegate
|
||||
selector:@selector(applicationWillFinishLaunching:)
|
||||
name:CPApplicationWillFinishLaunchingNotification
|
||||
object:self];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(applicationDidFinishLaunching:)])
|
||||
[defaultCenter
|
||||
addObserver:_delegate
|
||||
selector:@selector(applicationDidFinishLaunching:)
|
||||
name:CPApplicationDidFinishLaunchingNotification
|
||||
object:self];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(applicationWillBecomeActive:)])
|
||||
[defaultCenter
|
||||
addObserver:_delegate
|
||||
selector:@selector(applicationWillBecomeActive:)
|
||||
name:CPApplicationWillBecomeActiveNotification
|
||||
object:self];
|
||||
var index = 0;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(applicationDidBecomeActive:)])
|
||||
[defaultCenter
|
||||
addObserver:_delegate
|
||||
selector:@selector(applicationDidBecomeActive:)
|
||||
name:CPApplicationDidBecomeActiveNotification
|
||||
object:self];
|
||||
for (; index < count; index += 2)
|
||||
{
|
||||
var notificationName = delegateNotifications[index],
|
||||
selector = delegateNotifications[index + 1];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(applicationWillResignActive:)])
|
||||
[defaultCenter
|
||||
addObserver:_delegate
|
||||
selector:@selector(applicationWillResignActive:)
|
||||
name:CPApplicationWillResignActiveNotification
|
||||
object:self];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(applicationDidResignActive:)])
|
||||
[defaultCenter
|
||||
addObserver:_delegate
|
||||
selector:@selector(applicationDidResignActive:)
|
||||
name:CPApplicationDidResignActiveNotification
|
||||
object:self];
|
||||
if ([_delegate respondsToSelector:selector])
|
||||
[defaultCenter addObserver:_delegate selector:selector name:notificationName object:self];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -316,28 +223,28 @@ CPRunContinuesResponse = -1002;
|
||||
|
||||
// We also want to set the default cursor on the body, so that buttons and things don't have an iBeam
|
||||
[[CPCursor arrowCursor] set];
|
||||
|
||||
|
||||
var bundle = [CPBundle mainBundle],
|
||||
types = [bundle objectForInfoDictionaryKey:@"CPBundleDocumentTypes"];
|
||||
|
||||
|
||||
if ([types count] > 0)
|
||||
_documentController = [CPDocumentController sharedDocumentController];
|
||||
|
||||
|
||||
var delegateClassName = [bundle objectForInfoDictionaryKey:@"CPApplicationDelegateClass"];
|
||||
|
||||
|
||||
if (delegateClassName)
|
||||
{
|
||||
var delegateClass = objj_getClass(delegateClassName);
|
||||
|
||||
|
||||
if (delegateClass)
|
||||
if ([_documentController class] == delegateClass)
|
||||
[self setDelegate:_documentController];
|
||||
else
|
||||
[self setDelegate:[[delegateClass alloc] init]];
|
||||
}
|
||||
|
||||
|
||||
var defaultCenter = [CPNotificationCenter defaultCenter];
|
||||
|
||||
|
||||
[defaultCenter
|
||||
postNotificationName:CPApplicationWillFinishLaunchingNotification
|
||||
object:self];
|
||||
@@ -369,6 +276,10 @@ CPRunContinuesResponse = -1002;
|
||||
|
||||
- (void)terminate:(id)aSender
|
||||
{
|
||||
[[CPNotificationCenter defaultCenter]
|
||||
postNotificationName:CPApplicationWillTerminateNotification
|
||||
object:self];
|
||||
|
||||
if (![CPPlatform isBrowser])
|
||||
{
|
||||
[[CPDocumentController sharedDocumentController] closeAllDocumentsWithDelegate:self
|
||||
@@ -422,14 +333,14 @@ CPRunContinuesResponse = -1002;
|
||||
versionLabel = [contentView viewWithTag:3],
|
||||
copyrightLabel = [contentView viewWithTag:4],
|
||||
standardPath = [[CPBundle bundleForClass:[self class]] pathForResource:@"standardApplicationIcon.png"];
|
||||
|
||||
|
||||
// FIXME move this into the CIB eventually
|
||||
[applicationLabel setFont:[CPFont boldSystemFontOfSize:14.0]];
|
||||
[applicationLabel setAlignment:CPCenterTextAlignment];
|
||||
[versionLabel setAlignment:CPCenterTextAlignment];
|
||||
[copyrightLabel setAlignment:CPCenterTextAlignment];
|
||||
|
||||
[imageView setImage:applicationIcon || [[CPImage alloc] initWithContentsOfFile:standardPath
|
||||
[imageView setImage:applicationIcon || [[CPImage alloc] initWithContentsOfFile:standardPath
|
||||
size:CGSizeMake(256, 256)]];
|
||||
|
||||
[applicationLabel setStringValue:applicationTitle || ""];
|
||||
@@ -533,10 +444,10 @@ CPRunContinuesResponse = -1002;
|
||||
return;
|
||||
// raise exception;
|
||||
}
|
||||
|
||||
|
||||
_currentSession._state = aCode;
|
||||
_currentSession = _currentSession._previous;
|
||||
|
||||
|
||||
// if (aCode == CPRunAbortedResponse)
|
||||
[self _removeRunModalLoop];
|
||||
}
|
||||
@@ -545,12 +456,12 @@ CPRunContinuesResponse = -1002;
|
||||
- (void)_removeRunModalLoop
|
||||
{
|
||||
var count = _eventListeners.length;
|
||||
|
||||
|
||||
while (count--)
|
||||
if (_eventListeners[count]._callback === _CPRunModalLoop)
|
||||
{
|
||||
_eventListeners.splice(count, 1);
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -588,12 +499,12 @@ CPRunContinuesResponse = -1002;
|
||||
{
|
||||
aModalSession._previous = _currentSession;
|
||||
_currentSession = aModalSession;
|
||||
|
||||
|
||||
var theWindow = aModalSession._window;
|
||||
|
||||
[theWindow center];
|
||||
[theWindow makeKeyAndOrderFront:self];
|
||||
|
||||
|
||||
// [theWindow._bridge _obscureWindowsBelowModalWindow];
|
||||
|
||||
[CPApp setCallback:_CPRunModalLoop forNextEventMatchingMask:CPAnyEventMask untilDate:nil inMode:0 dequeue:NO];
|
||||
@@ -607,7 +518,7 @@ CPRunContinuesResponse = -1002;
|
||||
{
|
||||
if (!_currentSession)
|
||||
return nil;
|
||||
|
||||
|
||||
return _currentSession._window;
|
||||
}
|
||||
|
||||
@@ -652,7 +563,7 @@ CPRunContinuesResponse = -1002;
|
||||
{
|
||||
if (_eventListeners[_eventListeners.length - 1]._mask & (1 << [anEvent type]))
|
||||
_eventListeners.pop()._callback(anEvent);
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -763,11 +674,11 @@ CPRunContinuesResponse = -1002;
|
||||
|
||||
if ([super tryToPerform:anAction with:anObject])
|
||||
return YES;
|
||||
|
||||
|
||||
if([_delegate respondsToSelector:anAction])
|
||||
{
|
||||
[_delegate performSelector:anAction withObject:anObject];
|
||||
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@@ -787,9 +698,9 @@ CPRunContinuesResponse = -1002;
|
||||
|
||||
if (!target)
|
||||
return NO;
|
||||
|
||||
|
||||
[target performSelector:anAction withObject:aSender];
|
||||
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@@ -808,10 +719,10 @@ CPRunContinuesResponse = -1002;
|
||||
{
|
||||
if (!anAction)
|
||||
return nil;
|
||||
|
||||
|
||||
if (aTarget)
|
||||
return aTarget;
|
||||
|
||||
|
||||
return [self targetForAction:anAction];
|
||||
}
|
||||
|
||||
@@ -836,36 +747,35 @@ CPRunContinuesResponse = -1002;
|
||||
{
|
||||
var responder = [aWindow firstResponder],
|
||||
checkWindow = YES;
|
||||
|
||||
|
||||
while (responder)
|
||||
{
|
||||
if ([responder respondsToSelector:anAction])
|
||||
return responder;
|
||||
|
||||
|
||||
if (responder == aWindow)
|
||||
checkWindow = NO;
|
||||
|
||||
|
||||
responder = [responder nextResponder];
|
||||
}
|
||||
|
||||
|
||||
if (checkWindow && [aWindow respondsToSelector:anAction])
|
||||
return aWindow;
|
||||
|
||||
|
||||
var delegate = [aWindow delegate];
|
||||
|
||||
|
||||
if ([delegate respondsToSelector:anAction])
|
||||
return delegate;
|
||||
|
||||
var windowController = [aWindow windowController];
|
||||
|
||||
|
||||
if ([windowController respondsToSelector:anAction])
|
||||
return windowController;
|
||||
|
||||
|
||||
var theDocument = [windowController document];
|
||||
|
||||
if (theDocument != delegate && [theDocument respondsToSelector:anAction])
|
||||
if (theDocument !== delegate && [theDocument respondsToSelector:anAction])
|
||||
return theDocument;
|
||||
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@@ -874,7 +784,7 @@ CPRunContinuesResponse = -1002;
|
||||
Checks for a target in the following order:
|
||||
<ol>
|
||||
<li>a responder from the key window</li>
|
||||
<li>a responder frmo the main window</li>
|
||||
<li>a responder from the main window</li>
|
||||
<li>the CPApplication instance</li>
|
||||
<li>the application delegate</li>
|
||||
<li>the document controller</li>
|
||||
@@ -887,34 +797,32 @@ CPRunContinuesResponse = -1002;
|
||||
{
|
||||
if (!anAction)
|
||||
return nil;
|
||||
|
||||
|
||||
var target = [self _targetForWindow:[self keyWindow] action:anAction];
|
||||
|
||||
|
||||
if (target)
|
||||
return target;
|
||||
|
||||
|
||||
target = [self _targetForWindow:[self mainWindow] action:anAction];
|
||||
|
||||
|
||||
if (target)
|
||||
return target;
|
||||
|
||||
|
||||
if ([self respondsToSelector:anAction])
|
||||
return self;
|
||||
|
||||
|
||||
if ([_delegate respondsToSelector:anAction])
|
||||
return _delegate;
|
||||
|
||||
|
||||
if ([_documentController respondsToSelector:anAction])
|
||||
return _documentController;
|
||||
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)setCallback:(Function)aCallback forNextEventMatchingMask:(unsigned int)aMask untilDate:(CPDate)anExpiration inMode:(CPString)aMode dequeue:(BOOL)shouldDequeue
|
||||
{
|
||||
_eventListeners.push(_CPEventListenerMake(aMask, aCallback));
|
||||
|
||||
if (_eventListeners.length == 3) objj_debug_print_backtrace();
|
||||
}
|
||||
|
||||
- (CPEvent)setTarget:(id)aTarget selector:(SEL)aSelector forNextEventMatchingMask:(unsigned int)aMask untilDate:(CPDate)anExpiration inMode:(CPString)aMode dequeue:(BOOL)shouldDequeue
|
||||
@@ -938,14 +846,14 @@ CPRunContinuesResponse = -1002;
|
||||
@param aContextInfo
|
||||
*/
|
||||
- (void)beginSheet:(CPWindow)aSheet modalForWindow:(CPWindow)aWindow modalDelegate:(id)aModalDelegate didEndSelector:(SEL)aDidEndSelector contextInfo:(id)aContextInfo
|
||||
{
|
||||
{
|
||||
var styleMask = [aSheet styleMask];
|
||||
if (!(styleMask & CPDocModalWindowMask))
|
||||
{
|
||||
[CPException raise:CPInternalInconsistencyException reason:@"Currently only CPDocModalWindowMask style mask is supported for attached sheets"];
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
[aWindow orderFront:self];
|
||||
[aWindow _attachSheet:aSheet modalDelegate:aModalDelegate didEndSelector:aDidEndSelector contextInfo:aContextInfo];
|
||||
}
|
||||
@@ -953,15 +861,15 @@ CPRunContinuesResponse = -1002;
|
||||
- (void)endSheet:(CPWindow)sheet returnCode:(int)returnCode
|
||||
{
|
||||
var count = [_windows count];
|
||||
|
||||
|
||||
while (--count >= 0)
|
||||
{
|
||||
var aWindow = [_windows objectAtIndex:count];
|
||||
var context = aWindow._sheetContext;
|
||||
|
||||
|
||||
if (context != nil && context["sheet"] === sheet)
|
||||
{
|
||||
context["returnCode"] = returnCode;
|
||||
context["returnCode"] = returnCode;
|
||||
[aWindow _detachSheetWindow];
|
||||
return;
|
||||
}
|
||||
@@ -973,12 +881,11 @@ CPRunContinuesResponse = -1002;
|
||||
[self endSheet:sheet returnCode:0];
|
||||
}
|
||||
|
||||
|
||||
- (CPArray)arguments
|
||||
{
|
||||
if(_fullArgsString != window.location.hash)
|
||||
if(_fullArgsString !== window.location.hash)
|
||||
[self _reloadArguments];
|
||||
|
||||
|
||||
return _args;
|
||||
}
|
||||
|
||||
@@ -988,33 +895,39 @@ CPRunContinuesResponse = -1002;
|
||||
{
|
||||
_args = [];
|
||||
window.location.hash = @"#";
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if([args class] != CPArray)
|
||||
args = [CPArray arrayWithObject:args];
|
||||
|
||||
|
||||
_args = args;
|
||||
|
||||
|
||||
var toEncode = [_args copy];
|
||||
for(var i=0, count = toEncode.length; i<count; i++)
|
||||
toEncode[i] = encodeURIComponent(toEncode[i]);
|
||||
|
||||
|
||||
var hash = [toEncode componentsJoinedByString:@"/"];
|
||||
|
||||
|
||||
window.location.hash = @"#" + hash;
|
||||
}
|
||||
|
||||
- (void)_reloadArguments
|
||||
{
|
||||
_fullArgsString = window.location.hash;
|
||||
var args = _fullArgsString.replace("#", "").split("/").slice(0);
|
||||
|
||||
for(var i=0, count = args.length; i<count; i++)
|
||||
args[i] = decodeURIComponent(args[i]);
|
||||
|
||||
_args = args;
|
||||
|
||||
if (_fullArgsString.length)
|
||||
{
|
||||
var args = _fullArgsString.substring(1).split("/");
|
||||
|
||||
for (var i = 0, count = args.length; i < count; i++)
|
||||
args[i] = decodeURIComponent(args[i]);
|
||||
|
||||
_args = args;
|
||||
}
|
||||
else
|
||||
_args = [];
|
||||
}
|
||||
|
||||
- (CPDictionary)namedArguments
|
||||
@@ -1038,18 +951,18 @@ CPRunContinuesResponse = -1002;
|
||||
|
||||
- (void)_willBecomeActive
|
||||
{
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationWillBecomeActiveNotification
|
||||
object:self
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationWillBecomeActiveNotification
|
||||
object:self
|
||||
userInfo:nil];
|
||||
}
|
||||
|
||||
- (void)_didBecomeActive
|
||||
{
|
||||
if (![self keyWindow] && _previousKeyWindow &&
|
||||
if (![self keyWindow] && _previousKeyWindow &&
|
||||
[[self windows] indexOfObjectIdenticalTo:_previousKeyWindow] !== CPNotFound)
|
||||
[_previousKeyWindow makeKeyWindow];
|
||||
|
||||
if (![self mainWindow] && _previousMainWindow &&
|
||||
if (![self mainWindow] && _previousMainWindow &&
|
||||
[[self windows] indexOfObjectIdenticalTo:_previousMainWindow] !== CPNotFound)
|
||||
[_previousMainWindow makeMainWindow];
|
||||
|
||||
@@ -1058,20 +971,20 @@ CPRunContinuesResponse = -1002;
|
||||
else if ([self mainWindow])
|
||||
[[self mainWindow] makeKeyAndOrderFront:self];
|
||||
else
|
||||
[[[self mainMenu] window] makeKeyWindow]; //FIXME this may not actually work
|
||||
[[self mainMenu]._menuWindow makeKeyWindow]; //FIXME this may not actually work
|
||||
|
||||
_previousKeyWindow = nil;
|
||||
_previousMainWindow = nil;
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationDidBecomeActiveNotification
|
||||
object:self
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationDidBecomeActiveNotification
|
||||
object:self
|
||||
userInfo:nil];
|
||||
}
|
||||
|
||||
- (void)_willResignActive
|
||||
{
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationWillResignActiveNotification
|
||||
object:self
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationWillResignActiveNotification
|
||||
object:self
|
||||
userInfo:nil];
|
||||
}
|
||||
|
||||
@@ -1092,8 +1005,8 @@ CPRunContinuesResponse = -1002;
|
||||
[_previousMainWindow resignMainWindow];
|
||||
}
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationDidResignActiveNotification
|
||||
object:self
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationDidResignActiveNotification
|
||||
object:self
|
||||
userInfo:nil];
|
||||
}
|
||||
|
||||
@@ -1121,7 +1034,7 @@ var _CPRunModalLoop = function(anEvent)
|
||||
|
||||
var theWindow = [anEvent window],
|
||||
modalSession = CPApp._currentSession;
|
||||
|
||||
|
||||
if (theWindow == modalSession._window || [theWindow worksWhenModal])
|
||||
[theWindow sendEvent:anEvent];
|
||||
}
|
||||
@@ -1135,6 +1048,13 @@ var _CPRunModalLoop = function(anEvent)
|
||||
|
||||
function CPApplicationMain(args, namedArgs)
|
||||
{
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
// hook to allow recorder, etc to manipulate things before starting AppKit
|
||||
if (window.parent !== window && typeof window.parent._childAppIsStarting === "function")
|
||||
window.parent._childAppIsStarting(window);
|
||||
#endif
|
||||
|
||||
var mainBundle = [CPBundle mainBundle],
|
||||
principalClass = [mainBundle principalClass];
|
||||
|
||||
@@ -1143,29 +1063,8 @@ function CPApplicationMain(args, namedArgs)
|
||||
|
||||
[principalClass sharedApplication];
|
||||
|
||||
//FIXME?
|
||||
if (!args)
|
||||
{
|
||||
var args = [CPApp arguments];
|
||||
|
||||
if([args containsObject:"debug"])
|
||||
CPLogRegister(CPLogPopup);
|
||||
}
|
||||
|
||||
if (!namedArgs)
|
||||
{
|
||||
var searchParams = window.location.search.substring(1).split("&");
|
||||
namedArgs = [CPDictionary dictionary];
|
||||
|
||||
for(var i=0; i<searchParams.length; i++)
|
||||
{
|
||||
var index = searchParams[i].indexOf('=');
|
||||
if(index == -1)
|
||||
[namedArgs setObject: "" forKey:searchParams[i]];
|
||||
else
|
||||
[namedArgs setObject: searchParams[i].substring(index+1) forKey: searchParams[i].substring(0, index)];
|
||||
}
|
||||
}
|
||||
if ([args containsObject:"debug"])
|
||||
CPLogRegister(CPLogPopup);
|
||||
|
||||
CPApp._args = args;
|
||||
CPApp._namedArgs = namedArgs;
|
||||
@@ -1234,15 +1133,83 @@ var _CPAppBootstrapperActions = nil;
|
||||
|
||||
return YES;
|
||||
}
|
||||
else
|
||||
[self loadCiblessBrowserMainMenu];
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
+ (void)loadCiblessBrowserMainMenu
|
||||
{
|
||||
var mainMenu = [[CPMenu alloc] initWithTitle:@"MainMenu"];
|
||||
|
||||
// FIXME: We should implement autoenabling.
|
||||
[mainMenu setAutoenablesItems:NO];
|
||||
|
||||
var bundle = [CPBundle bundleForClass:[CPApplication class]],
|
||||
newMenuItem = [[CPMenuItem alloc] initWithTitle:@"New" action:@selector(newDocument:) keyEquivalent:@"n"];
|
||||
|
||||
[newMenuItem setImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/New.png"] size:CGSizeMake(16.0, 16.0)]];
|
||||
[newMenuItem setAlternateImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/NewHighlighted.png"] size:CGSizeMake(16.0, 16.0)]];
|
||||
|
||||
[mainMenu addItem:newMenuItem];
|
||||
|
||||
var openMenuItem = [[CPMenuItem alloc] initWithTitle:@"Open" action:@selector(openDocument:) keyEquivalent:@"o"];
|
||||
|
||||
[openMenuItem setImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/Open.png"] size:CGSizeMake(16.0, 16.0)]];
|
||||
[openMenuItem setAlternateImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/OpenHighlighted.png"] size:CGSizeMake(16.0, 16.0)]];
|
||||
|
||||
[mainMenu addItem:openMenuItem];
|
||||
|
||||
var saveMenu = [[CPMenu alloc] initWithTitle:@"Save"],
|
||||
saveMenuItem = [[CPMenuItem alloc] initWithTitle:@"Save" action:@selector(saveDocument:) keyEquivalent:nil];
|
||||
|
||||
[saveMenuItem setImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/Save.png"] size:CGSizeMake(16.0, 16.0)]];
|
||||
[saveMenuItem setAlternateImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/SaveHighlighted.png"] size:CGSizeMake(16.0, 16.0)]];
|
||||
|
||||
[saveMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Save" action:@selector(saveDocument:) keyEquivalent:@"s"]];
|
||||
[saveMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Save As" action:@selector(saveDocumentAs:) keyEquivalent:nil]];
|
||||
|
||||
[saveMenuItem setSubmenu:saveMenu];
|
||||
|
||||
[mainMenu addItem:saveMenuItem];
|
||||
|
||||
var editMenuItem = [[CPMenuItem alloc] initWithTitle:@"Edit" action:nil keyEquivalent:nil],
|
||||
editMenu = [[CPMenu alloc] initWithTitle:@"Edit"],
|
||||
|
||||
undoMenuItem = [[CPMenuItem alloc] initWithTitle:@"Undo" action:@selector(undo:) keyEquivalent:CPUndoKeyEquivalent],
|
||||
redoMenuItem = [[CPMenuItem alloc] initWithTitle:@"Redo" action:@selector(redo:) keyEquivalent:CPRedoKeyEquivalent];
|
||||
|
||||
[undoMenuItem setKeyEquivalentModifierMask:CPUndoKeyEquivalentModifierMask];
|
||||
[redoMenuItem setKeyEquivalentModifierMask:CPRedoKeyEquivalentModifierMask];
|
||||
|
||||
[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:@"Paste" action:@selector(paste:) keyEquivalent:@"v"]];
|
||||
|
||||
[editMenuItem setSubmenu:editMenu];
|
||||
[editMenuItem setHidden:YES];
|
||||
|
||||
[mainMenu addItem:editMenuItem];
|
||||
|
||||
[mainMenu addItem:[CPMenuItem separatorItem]];
|
||||
|
||||
[CPApp setMainMenu:mainMenu];
|
||||
}
|
||||
|
||||
+ (void)cibDidFinishLoading:(CPCib)aCib
|
||||
{
|
||||
[self performActions];
|
||||
}
|
||||
|
||||
+ (void)cibDidFailToLoad:(CPCib)aCib
|
||||
{
|
||||
throw new Error("Could not load main cib file (Did you forget to nib2cib it?).");
|
||||
}
|
||||
|
||||
+ (void)reset
|
||||
{
|
||||
_CPAppBootstrapperActions = nil;
|
||||
|
||||
@@ -0,0 +1,952 @@
|
||||
/*
|
||||
* CPBrowser.j
|
||||
* AppKit
|
||||
*
|
||||
* Created by Ross Boucher.
|
||||
* Copyright 2010, 280 North, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
@import "CPControl.j"
|
||||
@import "CPImage.j"
|
||||
@import "CPTableView.j"
|
||||
@import "CPScrollView.j"
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPBrowser
|
||||
*/
|
||||
|
||||
@implementation CPBrowser : CPControl
|
||||
{
|
||||
id _delegate;
|
||||
CPString _pathSeparator;
|
||||
|
||||
CPView _contentView;
|
||||
CPScrollView _horizontalScrollView;
|
||||
CPView _prototypeView;
|
||||
|
||||
CPArray _tableViews;
|
||||
CPArray _tableDelegates;
|
||||
|
||||
id _rootItem;
|
||||
|
||||
BOOL _delegateSupportsImages;
|
||||
|
||||
SEL _doubleAction @accessors(property=doubleAction);
|
||||
|
||||
BOOL _allowsMultipleSelection;
|
||||
BOOL _allowsEmptySelection;
|
||||
|
||||
Class _tableViewClass @accessors(property=tableViewClass);
|
||||
|
||||
float _rowHeight;
|
||||
float _imageWidth;
|
||||
float _leafWidth;
|
||||
float _minColumnWidth;
|
||||
float _defaultColumnWidth @accessors(property=defaultColumnWidth);
|
||||
|
||||
CPArray _columnWidths;
|
||||
}
|
||||
|
||||
+ (CPImage)branchImage
|
||||
{
|
||||
return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPBrowser class]]
|
||||
pathForResource:"browser-leaf.png"]
|
||||
size:CGSizeMake(9,9)];
|
||||
}
|
||||
|
||||
+ (CPImage)highlightedBranchImage
|
||||
{
|
||||
return [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPBrowser class]]
|
||||
pathForResource:"browser-leaf-highlighted.png"]
|
||||
size:CGSizeMake(9,9)];
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
{
|
||||
if (self = [super initWithFrame:aFrame])
|
||||
{
|
||||
_rowHeight = 23.0;
|
||||
_defaultColumnWidth = 140.0;
|
||||
_minColumnWidth = 80.0;
|
||||
_imageWidth = 23.0;
|
||||
_leafWidth = 13.0;
|
||||
_columnWidths = [];
|
||||
|
||||
_pathSeparator = "/";
|
||||
_tableViews = [];
|
||||
_tableDelegates = [];
|
||||
_allowsMultipleSelection = YES;
|
||||
_allowsEmptySelection = YES;
|
||||
_tableViewClass = [_CPBrowserTableView class];
|
||||
|
||||
_prototypeView = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
|
||||
[_prototypeView setVerticalAlignment:CPCenterVerticalTextAlignment];
|
||||
[_prototypeView setValue:[CPColor whiteColor] forThemeAttribute:"text-color" inState:CPThemeStateSelected];
|
||||
[_prototypeView setLineBreakMode:CPLineBreakByTruncatingTail];
|
||||
|
||||
_horizontalScrollView = [[CPScrollView alloc] initWithFrame:[self bounds]];
|
||||
|
||||
[_horizontalScrollView setHasVerticalScroller:NO];
|
||||
[_horizontalScrollView setAutohidesScrollers:YES];
|
||||
[_horizontalScrollView setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
|
||||
|
||||
_contentView = [[CPView alloc] initWithFrame:CGRectMake(0, 0, 0, CGRectGetHeight([self bounds]))];
|
||||
[_contentView setAutoresizingMask:CPViewHeightSizable];
|
||||
|
||||
[_horizontalScrollView setDocumentView:_contentView];
|
||||
|
||||
[self addSubview:_horizontalScrollView];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setPrototypeView:(CPView)aPrototypeView
|
||||
{
|
||||
_prototypeView = [CPKeyedUnarchiver unarchiveObjectWithData:
|
||||
[CPKeyedArchiver archivedDataWithRootObject:aPrototypeView]];
|
||||
}
|
||||
|
||||
- (CPView)prototypeView
|
||||
{
|
||||
return [CPKeyedUnarchiver unarchiveObjectWithData:
|
||||
[CPKeyedArchiver archivedDataWithRootObject:_prototypeView]];
|
||||
}
|
||||
|
||||
- (void)setDelegate:(id)anObject
|
||||
{
|
||||
_delegate = anObject;
|
||||
_delegateSupportsImages = [_delegate respondsToSelector:@selector(browser:imageValueForItem:)];
|
||||
|
||||
[self loadColumnZero];
|
||||
}
|
||||
|
||||
- (id)delegate
|
||||
{
|
||||
return _delegate;
|
||||
}
|
||||
|
||||
- (CPTableView)tableViewInColumn:(unsigned)index
|
||||
{
|
||||
return _tableViews[index];
|
||||
}
|
||||
|
||||
- (unsigned)columnOfTableView:(CPTableView)aTableView
|
||||
{
|
||||
return [_tableViews indexOfObject:aTableView];
|
||||
}
|
||||
|
||||
- (void)loadColumnZero
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(rootItemForBrowser:)])
|
||||
_rootItem = [_delegate rootItemForBrowser:self];
|
||||
else
|
||||
_rootItem = nil;
|
||||
|
||||
[self setLastColumn:-1];
|
||||
[self addColumn];
|
||||
}
|
||||
|
||||
- (void)setLastColumn:(int)columnIndex
|
||||
{
|
||||
if (columnIndex >= _tableViews.length)
|
||||
return;
|
||||
|
||||
var oldValue = _tableViews.length - 1;
|
||||
|
||||
// unloads all later columns.
|
||||
var indexPlusOne = columnIndex + 1;
|
||||
|
||||
[[_tableViews.slice(indexPlusOne) valueForKey:"enclosingScrollView"]
|
||||
makeObjectsPerformSelector:@selector(removeFromSuperview)];
|
||||
|
||||
_tableViews = _tableViews.slice(0, indexPlusOne);
|
||||
_tableDelegates = _tableDelegates.slice(0, indexPlusOne);
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browser:didChangeLastColumn:toColumn:)])
|
||||
[_delegate browser:self didChangeLastColumn:oldValue toColumn:columnIndex];
|
||||
|
||||
[self tile];
|
||||
}
|
||||
|
||||
- (int)lastColumn
|
||||
{
|
||||
return _tableViews.length - 1;
|
||||
}
|
||||
|
||||
- (void)addColumn
|
||||
{
|
||||
var lastIndex = [self lastColumn],
|
||||
lastColumn = _tableViews[lastIndex],
|
||||
selectionIndexes = [lastColumn selectedRowIndexes];
|
||||
|
||||
if (lastIndex >= 0 && [selectionIndexes count] > 1)
|
||||
[CPException raise:CPInvalidArgumentException
|
||||
reason:"Can't add column, column "+lastIndex+" has invalid selection."];
|
||||
|
||||
var index = lastIndex+1,
|
||||
item = index === 0 ? _rootItem : [_tableDelegates[lastIndex] childAtIndex:[selectionIndexes firstIndex]];
|
||||
|
||||
if (index > 0 && item && [self isLeafItem:item])
|
||||
return;
|
||||
|
||||
var table = [[_tableViewClass alloc] initWithFrame:CGRectMakeZero() browser:self];
|
||||
|
||||
[table setHeaderView:nil];
|
||||
[table setCornerView:nil];
|
||||
[table setAllowsMultipleSelection:_allowsMultipleSelection];
|
||||
[table setAllowsEmptySelection:_allowsEmptySelection];
|
||||
[table registerForDraggedTypes:[self registeredDraggedTypes]];
|
||||
|
||||
[self _addTableColumnsToTableView:table forColumnIndex:index];
|
||||
|
||||
var delegate = [[_CPBrowserTableDelegate alloc] init];
|
||||
|
||||
[delegate _setDelegate:_delegate];
|
||||
[delegate _setBrowser:self];
|
||||
[delegate _setIndex:index];
|
||||
[delegate _setItem:item];
|
||||
|
||||
_tableViews[index] = table;
|
||||
_tableDelegates[index] = delegate;
|
||||
|
||||
[table setDelegate:delegate];
|
||||
[table setDataSource:delegate];
|
||||
[table setTarget:delegate];
|
||||
[table setAction:@selector(_tableViewClicked:)];
|
||||
[table setDoubleAction:@selector(_tableViewDoubleClicked:)];
|
||||
[table setDraggingDestinationFeedbackStyle:CPTableViewDraggingDestinationFeedbackStyleRegular];
|
||||
|
||||
var scrollView = [[_CPBrowserScrollView alloc] initWithFrame:CGRectMakeZero()];
|
||||
[scrollView _setBrowser:self];
|
||||
[scrollView setDocumentView:table];
|
||||
[scrollView setHasHorizontalScroller:NO];
|
||||
[scrollView setAutoresizingMask:CPViewHeightSizable];
|
||||
|
||||
[_contentView addSubview:scrollView];
|
||||
|
||||
[self tile];
|
||||
|
||||
[self scrollColumnToVisible:index];
|
||||
}
|
||||
|
||||
- (void)_addTableColumnsToTableView:(CPTableView)aTableView forColumnIndex:(unsigned)index
|
||||
{
|
||||
if (_delegateSupportsImages)
|
||||
{
|
||||
var column = [[CPTableColumn alloc] initWithIdentifier:@"Image"],
|
||||
view = [[CPImageView alloc] initWithFrame:CGRectMakeZero()];
|
||||
|
||||
[view setImageScaling:CPScaleProportionally];
|
||||
|
||||
[column setDataView:view];
|
||||
[column setResizingMask:CPTableColumnNoResizing];
|
||||
|
||||
[aTableView addTableColumn:column];
|
||||
}
|
||||
|
||||
var column = [[CPTableColumn alloc] initWithIdentifier:@"Content"];
|
||||
|
||||
[column setDataView:_prototypeView];
|
||||
[column setResizingMask:CPTableColumnNoResizing];
|
||||
|
||||
[aTableView addTableColumn:column];
|
||||
|
||||
var column = [[CPTableColumn alloc] initWithIdentifier:@"Leaf"],
|
||||
view = [[_CPBrowserLeafView alloc] initWithFrame:CGRectMakeZero()];
|
||||
|
||||
[view setBranchImage:[[self class] branchImage]];
|
||||
[view setHighlightedBranchImage:[[self class] highlightedBranchImage]];
|
||||
|
||||
[column setDataView:view];
|
||||
[column setResizingMask:CPTableColumnNoResizing];
|
||||
|
||||
[aTableView addTableColumn:column];
|
||||
}
|
||||
|
||||
- (void)reloadColumn:(int)column
|
||||
{
|
||||
[[self tableViewInColumn:column] reloadData];
|
||||
}
|
||||
|
||||
- (void)tile
|
||||
{
|
||||
var xOrigin = 0,
|
||||
scrollerWidth = [CPScroller scrollerWidth],
|
||||
height = CGRectGetHeight([_contentView bounds]);
|
||||
|
||||
for (var i = 0, count = _tableViews.length; i < count; i++)
|
||||
{
|
||||
var tableView = _tableViews[i],
|
||||
scrollView = [tableView enclosingScrollView],
|
||||
width = [self widthOfColumn:i],
|
||||
tableHeight = CGRectGetHeight([tableView bounds]);
|
||||
|
||||
[[tableView tableColumnWithIdentifier:"Image"] setWidth:_imageWidth];
|
||||
[[tableView tableColumnWithIdentifier:"Content"] setWidth:width - (_leafWidth + _delegateSupportsImages ? _imageWidth : 0) - scrollerWidth - scrollerWidth];
|
||||
[[tableView tableColumnWithIdentifier:"Leaf"] setWidth:_leafWidth];
|
||||
|
||||
[tableView setRowHeight:_rowHeight];
|
||||
[tableView setFrameSize:CGSizeMake(width - scrollerWidth, tableHeight)];
|
||||
[scrollView setFrameOrigin:CGPointMake(xOrigin, 0)];
|
||||
[scrollView setFrameSize:CGSizeMake(width, height)];
|
||||
|
||||
xOrigin += width;
|
||||
}
|
||||
|
||||
[_contentView setFrameSize:CGSizeMake(xOrigin, height)];
|
||||
}
|
||||
|
||||
- (unsigned)rowAtPoint:(CGPoint)aPoint
|
||||
{
|
||||
var column = [self columnAtPoint:aPoint];
|
||||
if (column === -1)
|
||||
return -1;
|
||||
|
||||
var tableView = _tableViews[column];
|
||||
return [tableView rowAtPoint:[tableView convertPoint:aPoint fromView:self]];
|
||||
}
|
||||
|
||||
- (unsigned)columnAtPoint:(CGPoint)aPoint
|
||||
{
|
||||
var adjustedPoint = [_contentView convertPoint:aPoint fromView:self];
|
||||
|
||||
for (var i = 0, count = _tableViews.length; i < count; i++)
|
||||
{
|
||||
var frame = [[_tableViews[i] enclosingScrollView] frame];
|
||||
if (CGRectContainsPoint(frame, adjustedPoint))
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
- (CGRect)rectOfRow:(unsigned)aRow inColumn:(unsigned)aColumn
|
||||
{
|
||||
var tableView = _tableViews[aColumn],
|
||||
rect = [tableView rectOfRow:aRow];
|
||||
|
||||
rect.origin = [self convertPoint:rect.origin fromView:tableView];
|
||||
return rect;
|
||||
}
|
||||
|
||||
// ITEMS
|
||||
|
||||
- (id)itemAtRow:(int)row inColumn:(int)column
|
||||
{
|
||||
return [_tableDelegates[column] childAtIndex:row];
|
||||
}
|
||||
|
||||
- (BOOL)isLeafItem:(id)item
|
||||
{
|
||||
return [_delegate respondsToSelector:@selector(browser:isLeafItem:)] && [_delegate browser:self isLeafItem:item];
|
||||
}
|
||||
|
||||
- (id)parentForItemsInColumn:(int)column
|
||||
{
|
||||
return [_tableDelegates[column] _item];
|
||||
}
|
||||
|
||||
- (CPSet)selectedItems
|
||||
{
|
||||
var selectedColumn = [self selectedColumn],
|
||||
selectedIndexes = [self selectedRowIndexesInColumn:selectedColumn],
|
||||
set = [CPSet set],
|
||||
index = [selectedIndexes firstIndex];
|
||||
|
||||
while (index !== CPNotFound)
|
||||
{
|
||||
[set addObject:[self itemAtRow:index inColumn:selectedColumn]];
|
||||
index = [selectedIndexes indexGreaterThanIndex:index];
|
||||
}
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
- (id)selectedItem
|
||||
{
|
||||
var selectedColumn = [self selectedColumn],
|
||||
selectedRow = [self selectedRowInColumn:selectedColumn];
|
||||
|
||||
return [self itemAtRow:selectedRow inColumn:selectedColumn];
|
||||
}
|
||||
|
||||
// CLICK EVENTS
|
||||
|
||||
- (void)trackMouse:(CPEvent)anEvent
|
||||
{
|
||||
}
|
||||
|
||||
- (void)_column:(unsigned)columnIndex clickedRow:(unsigned)rowIndex
|
||||
{
|
||||
[self setLastColumn:columnIndex];
|
||||
|
||||
if (rowIndex >= 0)
|
||||
[self addColumn];
|
||||
|
||||
[self doClick:self];
|
||||
}
|
||||
|
||||
- (void)sendAction
|
||||
{
|
||||
[self sendAction:_action to:_target];
|
||||
}
|
||||
|
||||
- (void)doClick:(id)sender
|
||||
{
|
||||
[self sendAction:_action to:_target];
|
||||
}
|
||||
|
||||
- (void)doDoubleClick:(id)sender
|
||||
{
|
||||
[self sendAction:_doubleAction to:_target];
|
||||
}
|
||||
|
||||
- (void)keyDown:(CPEvent)anEvent
|
||||
{
|
||||
var column = [self selectedColumn];
|
||||
if (column === -1)
|
||||
return;
|
||||
|
||||
[_tableViews[column] keyDown:anEvent];
|
||||
}
|
||||
|
||||
// SIZING
|
||||
|
||||
- (float)columnContentWidthForColumnWidth:(float)aWidth
|
||||
{
|
||||
return aWidth - (_leafWidth + _delegateSupportsImages ? _imageWidth : 0) - [CPScroller scrollerWidth];
|
||||
}
|
||||
|
||||
- (float)columnWidthForColumnContentWidth:(float)aWidth
|
||||
{
|
||||
return aWidth + (_leafWidth + _delegateSupportsImages ? _imageWidth : 0) + [CPScroller scrollerWidth];
|
||||
}
|
||||
|
||||
- (void)setImageWidth:(float)aWidth
|
||||
{
|
||||
_imageWidth = aWidth;
|
||||
[self tile];
|
||||
}
|
||||
|
||||
- (float)imageWidth
|
||||
{
|
||||
return _imageWidth;
|
||||
}
|
||||
|
||||
- (void)setMinColumnWidth:(float)minWidth
|
||||
{
|
||||
_minColumnWidth = minWidth;
|
||||
[self tile];
|
||||
}
|
||||
|
||||
- (float)minColumnWidth
|
||||
{
|
||||
return _minColumnWidth;
|
||||
}
|
||||
|
||||
- (void)setWidth:(float)aWidth ofColumn:(unsigned)column
|
||||
{
|
||||
_columnWidths[column] = aWidth;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browser:didResizeColumn:)])
|
||||
[_delegate browser:self didResizeColumn:column];
|
||||
|
||||
[self tile];
|
||||
}
|
||||
|
||||
- (float)widthOfColumn:(unsigned)column
|
||||
{
|
||||
var width = _columnWidths[column];
|
||||
|
||||
if (width == null)
|
||||
width = _defaultColumnWidth;
|
||||
|
||||
return MAX([CPScroller scrollerWidth], MAX(_minColumnWidth, width));
|
||||
}
|
||||
|
||||
- (void)setRowHeight:(float)aHeight
|
||||
{
|
||||
_rowHeight = aHeight;
|
||||
}
|
||||
|
||||
- (float)rowHeight
|
||||
{
|
||||
return _rowHeight;
|
||||
}
|
||||
|
||||
// SCROLLERS
|
||||
|
||||
- (void)scrollColumnToVisible:(unsigned)columnIndex
|
||||
{
|
||||
[_contentView scrollRectToVisible:[[[self tableViewInColumn:columnIndex] enclosingScrollView] frame]];
|
||||
}
|
||||
|
||||
– (void)scrollRowToVisible:(unsigned)rowIndex inColumn:(unsigned)columnIndex
|
||||
{
|
||||
[self scrollColumnToVisible:columnIndex];
|
||||
[[self tableViewInColumn:columnIndex] scrollRowToVisible:rowIndex];
|
||||
}
|
||||
|
||||
- (BOOL)autohidesScroller
|
||||
{
|
||||
return [_horizontalScrollView autohidesScrollers];
|
||||
}
|
||||
|
||||
- (void)setAutohidesScroller:(BOOL)shouldHide
|
||||
{
|
||||
[_horizontalScrollView setAutohidesScrollers:shouldHide];
|
||||
}
|
||||
|
||||
// SELECTION
|
||||
|
||||
- (unsigned)selectedRowInColumn:(unsigned)columnIndex
|
||||
{
|
||||
if (columnIndex > [self lastColumn] || columnIndex < 0)
|
||||
return -1;
|
||||
|
||||
return [_tableViews[columnIndex] selectedRow];
|
||||
}
|
||||
|
||||
- (unsigned)selectedColumn
|
||||
{
|
||||
var column = [self lastColumn],
|
||||
row = [self selectedRowInColumn:column];
|
||||
|
||||
if (row >= 0)
|
||||
return column;
|
||||
else
|
||||
return column - 1;
|
||||
}
|
||||
|
||||
- (void)selectRow:(unsigned)row inColumn:(unsigned)column
|
||||
{
|
||||
var selectedIndexes = row === -1 ? [CPIndexSet indexSet] : [CPIndexSet indexSetWithIndex:row];
|
||||
[self selectRowIndexes:selectedIndexes inColumn:column];
|
||||
}
|
||||
|
||||
- (BOOL)allowsMultipleSelection
|
||||
{
|
||||
return _allowsMultipleSelection;
|
||||
}
|
||||
|
||||
- (void)setAllowsMultipleSelection:(BOOL)shouldAllow
|
||||
{
|
||||
if (_allowsMultipleSelection === shouldAllow)
|
||||
return;
|
||||
|
||||
_allowsMultipleSelection = shouldAllow;
|
||||
[_tableViews makeObjectsPerformSelector:@selector(setAllowsMultipleSelection:) withObject:shouldAllow];
|
||||
}
|
||||
|
||||
- (BOOL)allowsEmptySelection
|
||||
{
|
||||
return _allowsEmptySelection;
|
||||
}
|
||||
|
||||
- (void)setAllowsEmptySelection:(BOOL)shouldAllow
|
||||
{
|
||||
if (_allowsEmptySelection === shouldAllow)
|
||||
return;
|
||||
|
||||
_allowsEmptySelection = shouldAllow;
|
||||
[_tableViews makeObjectsPerformSelector:@selector(setAllowsEmptySelection:) withObject:shouldAllow];
|
||||
}
|
||||
|
||||
- (CPIndexSet)selectedRowIndexesInColumn:(unsigned)column
|
||||
{
|
||||
if (column < 0 || column > [self lastColumn] +1)
|
||||
return [CPIndexSet indexSet];
|
||||
|
||||
return [[self tableViewInColumn:column] selectedRowIndexes];
|
||||
}
|
||||
|
||||
- (void)selectRowIndexes:(CPIndexSet)indexSet inColumn:(unsigned)column
|
||||
{
|
||||
if (column < 0 || column > [self lastColumn] + 1)
|
||||
return;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browser:selectionIndexesForProposedSelection:inColumn:)])
|
||||
indexSet = [_delegate browser:self selectionIndexesForProposedSelection:indexSet inColumn:column];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browser:shouldSelectRowIndexes:inColumn:)] &&
|
||||
![_delegate browser:self shouldSelectRowIndexes:indexSet inColumn:column])
|
||||
return;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browserSelectionIsChanging:)])
|
||||
[_delegate browserSelectionIsChanging:self];
|
||||
|
||||
if (column > [self lastColumn])
|
||||
[self addColumn];
|
||||
|
||||
[self setLastColumn:column];
|
||||
|
||||
[[self tableViewInColumn:column] selectRowIndexes:indexSet byExtendingSelection:NO];
|
||||
|
||||
[self scrollColumnToVisible:column];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browserSelectionDidChange:)])
|
||||
[_delegate browserSelectionDidChange:self];
|
||||
}
|
||||
|
||||
- (void)setBackgroundColor:(CPColor)aColor
|
||||
{
|
||||
[super setBackgroundColor:aColor];
|
||||
[_contentView setBackgroundColor:aColor];
|
||||
}
|
||||
|
||||
- (BOOL)acceptsFirstResponder
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
// DRAG AND DROP
|
||||
|
||||
- (void)registerForDraggedTypes:(CPArray)types
|
||||
{
|
||||
[super registerForDraggedTypes:types];
|
||||
[_tableViews makeObjectsPerformSelector:@selector(registerForDraggedTypes:) withObject:types];
|
||||
}
|
||||
|
||||
- (BOOL)canDragRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(int)columnIndex withEvent:(CPEvent)dragEvent
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(browser:canDragRowsWithIndexes:inColumn:withEvent:)])
|
||||
return [_delegate browser:self canDragRowsWithIndexes:rowIndexes inColumn:columnIndex withEvent:dragEvent];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (CPImage)draggingImageForRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(int)columnIndex withEvent:(CPEvent)dragEvent offset:(CGPoint)dragImageOffset
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(browser:draggingImageForRowsWithIndexes:inColumn:withEvent:offset:)])
|
||||
return [_delegate browser:self draggingImageForRowsWithIndexes:rowIndexes inColumn:columnIndex withEvent:dragEvent offset:dragImageOffset];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (CPView)draggingViewForRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(int)columnIndex withEvent:(CPEvent)dragEvent offset:(CGPoint)dragImageOffset
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(browser:draggingViewForRowsWithIndexes:inColumn:withEvent:offset:)])
|
||||
return [_delegate browser:self draggingViewForRowsWithIndexes:rowIndexes inColumn:columnIndex withEvent:dragEvent offset:dragImageOffset];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var _CPBrowserResizeControlBackgroundImage = nil;
|
||||
|
||||
@implementation _CPBrowserResizeControl : CPView
|
||||
{
|
||||
CGPoint _mouseDownX;
|
||||
CPBrowser _browser;
|
||||
unsigned _index;
|
||||
unsigned _width;
|
||||
}
|
||||
|
||||
+ (CPImage)backgroundImage
|
||||
{
|
||||
if (!_CPBrowserResizeControlBackgroundImage)
|
||||
{
|
||||
var path = [[CPBundle bundleForClass:[self class]] pathForResource:"browser-resize-control.png"];
|
||||
_CPBrowserResizeControlBackgroundImage = [[CPImage alloc] initWithContentsOfFile:path
|
||||
size:CGSizeMake(15, 14)];
|
||||
}
|
||||
|
||||
return _CPBrowserResizeControlBackgroundImage;
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
{
|
||||
if (self = [super initWithFrame:aFrame])
|
||||
[self setBackgroundColor:[CPColor colorWithPatternImage:[[self class] backgroundImage]]];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)mouseDown:(CPEvent)anEvent
|
||||
{
|
||||
_mouseDownX = [anEvent locationInWindow].x;
|
||||
_browser = [[self superview] _browser];
|
||||
_index = [_browser columnOfTableView:[[self superview] documentView]];
|
||||
_width = [_browser widthOfColumn:_index];
|
||||
}
|
||||
|
||||
- (void)mouseDragged:(CPEvent)anEvent
|
||||
{
|
||||
var deltaX = [anEvent locationInWindow].x - _mouseDownX;
|
||||
[_browser setWidth:_width + deltaX ofColumn:_index];
|
||||
}
|
||||
|
||||
- (void)mouseUp:(CPEvent)anEvent
|
||||
{
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPBrowserScrollView : CPScrollView
|
||||
{
|
||||
_CPBrowserResizeControl _resizeControl;
|
||||
CPBrowser _browser @accessors;
|
||||
}
|
||||
|
||||
- (void)initWithFrame:(CGRect)aFrame
|
||||
{
|
||||
if (self = [super initWithFrame:aFrame])
|
||||
{
|
||||
_resizeControl = [[_CPBrowserResizeControl alloc] initWithFrame:CGRectMakeZero()];
|
||||
[self addSubview:_resizeControl];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)reflectScrolledClipView:(CPClipView)aClipView
|
||||
{
|
||||
[super reflectScrolledClipView:aClipView];
|
||||
|
||||
var frame = [_verticalScroller frame];
|
||||
frame.size.height = CGRectGetHeight([self bounds]) - 14.0 - frame.origin.y;
|
||||
[_verticalScroller setFrameSize:frame.size];
|
||||
|
||||
var resizeFrame = CGRectMake(CGRectGetMinX(frame), CGRectGetMaxY(frame), [CPScroller scrollerWidth], 14.0);
|
||||
[_resizeControl setFrame:resizeFrame];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPBrowserTableView : CPTableView
|
||||
{
|
||||
CPBrowser _browser;
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame browser:(CPBrowser)aBrowser
|
||||
{
|
||||
if (self = [super initWithFrame:aFrame])
|
||||
_browser = aBrowser;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)acceptsFirstResponder
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)mouseDown:(CPEvent)anEvent
|
||||
{
|
||||
[super mouseDown:anEvent];
|
||||
[[self window] makeFirstResponder:_browser];
|
||||
}
|
||||
|
||||
- (CPView)browserView
|
||||
{
|
||||
return _browser;
|
||||
}
|
||||
|
||||
- (BOOL)canDragRowsWithIndexes:(CPIndexSet)rowIndexes atPoint:(CGPoint)mouseDownPoint
|
||||
{
|
||||
return [_browser canDragRowsWithIndexes:rowIndexes inColumn:[_browser columnOfTableView:self] withEvent:[CPApp currentEvent]];
|
||||
}
|
||||
|
||||
- (CPImage)dragImageForRowsWithIndexes:(CPIndexSet)dragRows tableColumns:(CPArray)theTableColumns event:(CPEvent)dragEvent offset:(CPPointPointer)dragImageOffset
|
||||
{
|
||||
return [_browser draggingImageForRowsWithIndexes:dragRows inColumn:[_browser columnOfTableView:self] withEvent:dragEvent offset:dragImageOffset] ||
|
||||
[super dragImageForRowsWithIndexes:dragRows tableColumns:theTableColumns event:dragEvent offset:dragImageOffset];
|
||||
}
|
||||
|
||||
- (CPView)dragViewForRowsWithIndexes:(CPIndexSet)dragRows tableColumns:(CPArray)theTableColumns event:(CPEvent)dragEvent offset:(CPPoint)dragViewOffset
|
||||
{
|
||||
var count = theTableColumns.length;
|
||||
while (count--)
|
||||
{
|
||||
if ([theTableColumns[count] identifier] === "Leaf")
|
||||
[theTableColumns removeObject:theTableColumns[count]];
|
||||
}
|
||||
|
||||
return [_browser draggingViewForRowsWithIndexes:dragRows inColumn:[_browser columnOfTableView:self] withEvent:dragEvent offset:dragViewOffset] ||
|
||||
[super dragViewForRowsWithIndexes:dragRows tableColumns:theTableColumns event:dragEvent offset:dragViewOffset];
|
||||
}
|
||||
|
||||
- (void)moveUp:(id)sender
|
||||
{
|
||||
[super moveUp:sender];
|
||||
[_browser selectRow:[self selectedRow] inColumn:[_browser selectedColumn]];
|
||||
}
|
||||
|
||||
- (void)moveDown:(id)sender
|
||||
{
|
||||
[super moveDown:sender];
|
||||
[_browser selectRow:[self selectedRow] inColumn:[_browser selectedColumn]];
|
||||
}
|
||||
|
||||
- (void)moveLeft:(id)sender
|
||||
{
|
||||
var previousColumn = [_browser selectedColumn] - 1,
|
||||
selectedRow = [_browser selectedRowInColumn:previousColumn];
|
||||
|
||||
[_browser selectRow:selectedRow inColumn:previousColumn];
|
||||
}
|
||||
|
||||
- (void)moveRight:(id)sender
|
||||
{
|
||||
[_browser selectRow:0 inColumn:[_browser selectedColumn] + 1];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPBrowserTableDelegate : CPObject
|
||||
{
|
||||
CPBrowser _browser @accessors;
|
||||
unsigned _index @accessors;
|
||||
id _delegate @accessors;
|
||||
id _item @accessors;
|
||||
}
|
||||
|
||||
- (unsigned)numberOfRowsInTableView:(CPTableView)aTableView
|
||||
{
|
||||
return [_delegate browser:_browser numberOfChildrenOfItem:_item];
|
||||
}
|
||||
|
||||
- (void)tableView:(CPTableView)aTableView objectValueForTableColumn:(CPTableColumn)column row:(unsigned)row
|
||||
{
|
||||
if ([column identifier] === "Image")
|
||||
return [_delegate browser:_browser imageValueForItem:[self childAtIndex:row]];
|
||||
else if ([column identifier] === "Leaf")
|
||||
return ![_browser isLeafItem:[self childAtIndex:row]];
|
||||
else
|
||||
return [_delegate browser:_browser objectValueForItem:[self childAtIndex:row]];
|
||||
}
|
||||
|
||||
- (void)_tableViewDoubleClicked:(CPTableView)aTableView
|
||||
{
|
||||
[_browser doDoubleClick:self];
|
||||
}
|
||||
|
||||
- (void)_tableViewClicked:(CPTableView)aTableView
|
||||
{
|
||||
var selectedIndexes = [aTableView selectedRowIndexes];
|
||||
[_browser _column:_index clickedRow:[selectedIndexes count] === 1 ? [selectedIndexes firstIndex] : -1];
|
||||
}
|
||||
|
||||
- (id)childAtIndex:(unsigned)index
|
||||
{
|
||||
return [_delegate browser:_browser child:index ofItem:_item];
|
||||
}
|
||||
|
||||
- (BOOL)tableView:(CPTableView)aTableView acceptDrop:(id)info row:(int)row dropOperation:(CPTableViewDropOperation)operation
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(browser:acceptDrop:atRow:column:dropOperation:)])
|
||||
return [_delegate browser:_browser acceptDrop:info atRow:row column:_index dropOperation:operation];
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(id)info proposedRow:(int)row proposedDropOperation:(CPTableViewDropOperation)operation
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(browser:validateDrop:proposedRow:column:dropOperation:)])
|
||||
[_delegate browser:_browser validateDrop:info proposedRow:row column:_index dropOperation:operation];
|
||||
else
|
||||
return CPDragOperationNone;
|
||||
}
|
||||
|
||||
- (BOOL)tableView:(CPTableView)aTableView writeRowsWithIndexes:(CPIndexSet)rowIndexes toPasteboard:(CPPasteboard)pboard
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(browser:writeRowsWithIndexes:inColumn:toPasteboard:)])
|
||||
return [_delegate browser:_browser writeRowsWithIndexes:rowIndexes inColumn:_index toPasteboard:pboard];
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)respondsToSelector:(SEL)aSelector
|
||||
{
|
||||
if (aSelector === @selector(browser:writeRowsWithIndexes:inColumn:toPasteboard:))
|
||||
return [_delegate respondsToSelector:@selector(browser:writeRowsWithIndexes:inColumn:toPasteboard:)];
|
||||
else
|
||||
return [super respondsToSelector:aSelector];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPBrowserLeafView : CPView
|
||||
{
|
||||
BOOL _isLeaf @accessors(readonly, property=isLeaf);
|
||||
CPImage _branchImage @accessors(property=branchImage);
|
||||
CPImage _highlightedBranchImage @accessors(property=highlightedBranchImage);
|
||||
}
|
||||
|
||||
- (BOOL)objectValue
|
||||
{
|
||||
return _isLeaf;
|
||||
}
|
||||
|
||||
- (void)setObjectValue:(id)aValue
|
||||
{
|
||||
_isLeaf = !!aValue;
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aName
|
||||
{
|
||||
if (aName === "image-view")
|
||||
return CGRectInset([self bounds], 1, 1);
|
||||
|
||||
return [super rectForEphemeralSubviewNamed:aName];
|
||||
}
|
||||
|
||||
- (CPView)createEphemeralSubviewNamed:(CPString)aName
|
||||
{
|
||||
if (aName === "image-view")
|
||||
return [[CPImageView alloc] initWithFrame:CGRectMakeZero()];
|
||||
|
||||
return [super createEphemeralSubviewNamed:aName];
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
var imageView = [self layoutEphemeralSubviewNamed:@"image-view"
|
||||
positioned:CPWindowAbove
|
||||
relativeToEphemeralSubviewNamed:nil];
|
||||
|
||||
var isHighlighted = [self themeState] & CPThemeStateSelected;
|
||||
[imageView setImage: _isLeaf ? (isHighlighted ? _highlightedBranchImage : _branchImage) : nil];
|
||||
[imageView setImageScaling:CPScaleNone];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
[super encodeWithCoder:aCoder];
|
||||
|
||||
[aCoder encodeBool:_isLeaf forKey:"_CPBrowserLeafViewIsLeafKey"];
|
||||
[aCoder encodeObject:_branchImage forKey:"_CPBrowserLeafViewBranchImageKey"];
|
||||
[aCoder encodeObject:_highlightedBranchImage forKey:"_CPBrowserLeafViewHighlightedBranchImageKey"];
|
||||
}
|
||||
|
||||
- (void)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
if (self = [super initWithCoder:aCoder])
|
||||
{
|
||||
_isLeaf = [aCoder decodeBoolForKey:"_CPBrowserLeafViewIsLeafKey"];
|
||||
_branchImage = [aCoder decodeObjectForKey:"_CPBrowserLeafViewBranchImageKey"];
|
||||
_highlightedBranchImage = [aCoder decodeObjectForKey:"_CPBrowserLeafViewHighlightedBranchImageKey"];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -502,8 +502,6 @@ CPButtonStateMixed = CPThemeState("mixed");
|
||||
}
|
||||
else
|
||||
return [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()];
|
||||
|
||||
return [super createEphemeralSubviewNamed:aName];
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
@@ -511,9 +509,8 @@ CPButtonStateMixed = CPThemeState("mixed");
|
||||
var bezelView = [self layoutEphemeralSubviewNamed:@"bezel-view"
|
||||
positioned:CPWindowBelow
|
||||
relativeToEphemeralSubviewNamed:@"content-view"];
|
||||
|
||||
if (bezelView)
|
||||
[bezelView setBackgroundColor:[self currentValueForThemeAttribute:@"bezel-color"]];
|
||||
|
||||
[bezelView setBackgroundColor:[self currentValueForThemeAttribute:@"bezel-color"]];
|
||||
|
||||
var contentView = [self layoutEphemeralSubviewNamed:@"content-view"
|
||||
positioned:CPWindowAbove
|
||||
@@ -533,6 +530,7 @@ CPButtonStateMixed = CPThemeState("mixed");
|
||||
[contentView setTextShadowOffset:[self currentValueForThemeAttribute:@"text-shadow-offset"]];
|
||||
[contentView setImagePosition:[self currentValueForThemeAttribute:@"image-position"]];
|
||||
[contentView setImageScaling:[self currentValueForThemeAttribute:@"image-scaling"]];
|
||||
[contentView setDimsImage:[self hasThemeState:CPThemeStateDisabled] && _imageDimsWhenDisabled];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,18 +4,50 @@
|
||||
#include "CoreGraphics/CGGeometry.h"
|
||||
|
||||
|
||||
@implementation CPButtonBar : CPControl
|
||||
@implementation CPButtonBar : CPView
|
||||
{
|
||||
BOOL _hasResizeControl;
|
||||
BOOL _resizeControlIsLeftAligned;
|
||||
CPArray _buttons;
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
+ (id)plusButton
|
||||
{
|
||||
self = [super initWithFrame:aFrame];
|
||||
var button = [[CPButton alloc] initWithFrame:CGRectMake(0, 0, 35, 25)],
|
||||
image = [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPButtonBar class]] pathForResource:@"plus_button.png"] size:CGSizeMake(11, 12)];
|
||||
|
||||
if (self)
|
||||
[self setNeedsLayout];
|
||||
[button setBordered:NO];
|
||||
[button setImage:image];
|
||||
[button setImagePosition:CPImageOnly];
|
||||
|
||||
return self;
|
||||
return button;
|
||||
}
|
||||
|
||||
+ (id)minusButton
|
||||
{
|
||||
var button = [[CPButton alloc] initWithFrame:CGRectMake(0, 0, 35, 25)],
|
||||
image = [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPButtonBar class]] pathForResource:@"minus_button.png"] size:CGSizeMake(11, 4)];
|
||||
|
||||
[button setBordered:NO];
|
||||
[button setImage:image];
|
||||
[button setImagePosition:CPImageOnly];
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
+ (id)actionPopupButton
|
||||
{
|
||||
var button = [[CPPopUpButton alloc] initWithFrame:CGRectMake(0, 0, 35, 25)],
|
||||
image = [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPButtonBar class]] pathForResource:@"action_button.png"] size:CGSizeMake(22, 14)];
|
||||
|
||||
[button addItemWithTitle:nil];
|
||||
[[button lastItem] setImage:image];
|
||||
[button setImagePosition:CPImageOnly];
|
||||
[button setValue:CGInsetMake(0, 0, 0, 0) forThemeAttribute:"content-inset"];
|
||||
|
||||
[button setPullsDown:YES];
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
+ (CPString)themeClass
|
||||
@@ -25,47 +57,223 @@
|
||||
|
||||
+ (id)themeAttributes
|
||||
{
|
||||
return [CPDictionary dictionaryWithObjects:[[CPNull null]]
|
||||
forKeys:[@"bezel-color"]];
|
||||
return [CPDictionary dictionaryWithObjects:[CGInsetMake(0.0, 0.0, 0.0, 0.0), CGSizeMakeZero(), [CPNull null], [CPNull null], [CPNull null], [CPNull null]]
|
||||
forKeys:[@"resize-control-inset", @"resize-control-size", @"resize-control-color", @"bezel-color", @"button-bezel-color", @"button-text-color"]];
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
{
|
||||
self = [super initWithFrame:aFrame];
|
||||
|
||||
if (self)
|
||||
{
|
||||
_buttons = [];
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)awakeFromCib
|
||||
{
|
||||
var view = [self superview],
|
||||
subview = self;
|
||||
|
||||
while (view)
|
||||
{
|
||||
if ([view isKindOfClass:[CPSplitView class]])
|
||||
{
|
||||
var viewIndex = [[view subviews] indexOfObject:subview];
|
||||
[view setButtonBar:self forDividerAtIndex:viewIndex];
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
subview = view;
|
||||
view = [view superview];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setButtons:(CPArray)buttons
|
||||
{
|
||||
_buttons = [CPArray arrayWithArray:buttons];
|
||||
|
||||
for (var i = 0, count = [_buttons count]; i < count; i++)
|
||||
[_buttons[i] setBordered:YES];
|
||||
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (CPArray)buttons
|
||||
{
|
||||
return [CPArray arrayWithArray:_buttons];
|
||||
}
|
||||
|
||||
- (void)setHasResizeControl:(BOOL)shouldHaveResizeControl
|
||||
{
|
||||
if (_hasResizeControl === shouldHaveResizeControl)
|
||||
return;
|
||||
|
||||
_hasResizeControl = !!shouldHaveResizeControl;
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (BOOL)hasResizeControl
|
||||
{
|
||||
return _hasResizeControl;
|
||||
}
|
||||
|
||||
- (void)setResizeControlIsLeftAligned:(BOOL)shouldBeLeftAligned
|
||||
{
|
||||
if (_resizeControlIsLeftAligned === shouldBeLeftAligned)
|
||||
return;
|
||||
|
||||
_resizeControlIsLeftAligned = !!shouldBeLeftAligned;
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (BOOL)resizeControlIsLeftAligned
|
||||
{
|
||||
return _resizeControlIsLeftAligned;
|
||||
}
|
||||
|
||||
- (CGRect)resizeControlFrame
|
||||
{
|
||||
var inset = [self currentValueForThemeAttribute:@"resize-control-inset"],
|
||||
size = [self currentValueForThemeAttribute:@"resize-control-size"],
|
||||
currentSize = [self bounds],
|
||||
leftOrigin = _resizeControlIsLeftAligned ? 0 : currentSize.size.width - size.width - inset.right - inset.left;
|
||||
|
||||
return CGRectMake(leftOrigin, 0, size.width + inset.left + inset.right, size.height + inset.top + inset.bottom);
|
||||
}
|
||||
|
||||
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aName
|
||||
{
|
||||
if (aName === "bezel-view")
|
||||
return [self bounds];
|
||||
|
||||
if (aName === "resize-control-view")
|
||||
{
|
||||
var inset = [self currentValueForThemeAttribute:@"resize-control-inset"],
|
||||
size = [self currentValueForThemeAttribute:@"resize-control-size"],
|
||||
currentSize = [self bounds];
|
||||
|
||||
if (_resizeControlIsLeftAligned)
|
||||
return CGRectMake(inset.left, inset.top, size.width, size.height);
|
||||
else
|
||||
return CGRectMake(currentSize.size.width - size.width - inset.right, inset.top, size.width, size.height);
|
||||
}
|
||||
|
||||
return [super rectForEphemeralSubviewNamed:aName];
|
||||
}
|
||||
|
||||
- (CPView)createEphemeralSubviewNamed:(CPString)aName
|
||||
{
|
||||
if (aName === "bezel-view")
|
||||
{
|
||||
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
|
||||
if (aName === "resize-control-view")
|
||||
return [[CPView alloc] initWithFrame:CGRectMakeZero()];
|
||||
|
||||
[view setHitTests:NO];
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
return [super createEphemeralSubviewNamed:aName];
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
var bezelView = [self layoutEphemeralSubviewNamed:@"bezel-view"
|
||||
positioned:CPWindowBelow
|
||||
relativeToEphemeralSubviewNamed:@""];
|
||||
|
||||
if (bezelView)
|
||||
[bezelView setBackgroundColor:[self currentValueForThemeAttribute:@"bezel-color"]];
|
||||
[self setBackgroundColor:[self currentValueForThemeAttribute:@"bezel-color"]];
|
||||
|
||||
var normalColor = [self valueForThemeAttribute:@"button-bezel-color" inState:CPThemeStateNormal],
|
||||
highlightedColor = [self valueForThemeAttribute:@"button-bezel-color" inState:CPThemeStateHighlighted],
|
||||
disabledColor = [self valueForThemeAttribute:@"button-bezel-color" inState:CPThemeStateDisabled],
|
||||
textColor = [self valueForThemeAttribute:@"button-text-color" inState:CPThemeStateNormal];
|
||||
|
||||
var buttonsNotHidden = [CPArray arrayWithArray:_buttons],
|
||||
count = [buttonsNotHidden count];
|
||||
|
||||
while (count--)
|
||||
if ([buttonsNotHidden[count] isHidden])
|
||||
[buttonsNotHidden removeObject:buttonsNotHidden[count]];
|
||||
|
||||
var currentButtonOffset = _resizeControlIsLeftAligned ? CGRectGetMaxX([self bounds]) + 1 : -1,
|
||||
bounds = [self bounds],
|
||||
height = CGRectGetHeight(bounds) - 1,
|
||||
frameWidth = CGRectGetWidth(bounds),
|
||||
resizeRect = _hasResizeControl ? [self rectForEphemeralSubviewNamed:"resize-control-view"] : CGRectMakeZero(),
|
||||
resizeWidth = CGRectGetWidth(resizeRect),
|
||||
availableWidth = frameWidth - resizeWidth - 1;
|
||||
|
||||
for (var i = 0, count = [buttonsNotHidden count]; i < count; i++)
|
||||
{
|
||||
var button = buttonsNotHidden[i],
|
||||
width = CGRectGetWidth([button frame]);
|
||||
|
||||
if (availableWidth > width)
|
||||
availableWidth -=width;
|
||||
else
|
||||
break;
|
||||
|
||||
if (_resizeControlIsLeftAligned)
|
||||
{
|
||||
[button setFrame:CGRectMake(currentButtonOffset - width, 1, width, height)];
|
||||
currentButtonOffset -= width - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
[button setFrame:CGRectMake(currentButtonOffset, 1, width, height)];
|
||||
currentButtonOffset += width - 1;
|
||||
}
|
||||
|
||||
[button setValue:normalColor forThemeAttribute:@"bezel-color" inState:CPThemeStateNormal|CPThemeStateBordered];
|
||||
[button setValue:highlightedColor forThemeAttribute:@"bezel-color" inState:CPThemeStateHighlighted|CPThemeStateBordered];
|
||||
[button setValue:disabledColor forThemeAttribute:@"bezel-color" inState:CPThemeStateDisabled|CPThemeStateBordered];
|
||||
[button setValue:textColor forThemeAttribute:@"text-color" inState:CPThemeStateBordered];
|
||||
|
||||
// FIXME shouldn't need this
|
||||
[button setValue:normalColor forThemeAttribute:@"bezel-color" inState:CPThemeStateNormal|CPThemeStateBordered|CPPopUpButtonStatePullsDown];
|
||||
[button setValue:highlightedColor forThemeAttribute:@"bezel-color" inState:CPThemeStateHighlighted|CPThemeStateBordered|CPPopUpButtonStatePullsDown];
|
||||
[button setValue:disabledColor forThemeAttribute:@"bezel-color" inState:CPThemeStateDisabled|CPThemeStateBordered|CPPopUpButtonStatePullsDown];
|
||||
|
||||
[self addSubview:button];
|
||||
}
|
||||
|
||||
if (_hasResizeControl)
|
||||
{
|
||||
var resizeControlView = [self layoutEphemeralSubviewNamed:@"resize-control-view"
|
||||
positioned:CPWindowAbove
|
||||
relativeToEphemeralSubviewNamed:nil];
|
||||
|
||||
[resizeControlView setAutoresizingMask: _resizeControlIsLeftAligned ? CPViewMaxXMargin : CPViewMinXMargin];
|
||||
[resizeControlView setBackgroundColor:[self currentValueForThemeAttribute:@"resize-control-color"]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)addSubview:(CPView)aSubview
|
||||
- (void)setFrameSize:(CGSize)aSize
|
||||
{
|
||||
[super addSubview:aSubview];
|
||||
|
||||
[aSubview setAutoresizingMask:CPViewMinXMargin];
|
||||
[super setFrameSize:aSize];
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var CPButtonBarHasResizeControlKey = @"CPButtonBarHasResizeControlKey",
|
||||
CPButtonBarResizeControlIsLeftAlignedKey = @"CPButtonBarResizeControlIsLeftAlignedKey",
|
||||
CPButtonBarButtonsKey = @"CPButtonBarButtonsKey";
|
||||
|
||||
@implementation CPButtonBar (CPCoding)
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
[super encodeWithCoder:aCoder];
|
||||
|
||||
[aCoder encodeBool:_hasResizeControl forKey:CPButtonBarHasResizeControlKey];
|
||||
[aCoder encodeBool:_resizeControlIsLeftAligned forKey:CPButtonBarResizeControlIsLeftAlignedKey];
|
||||
[aCoder encodeObject:_buttons forKey:CPButtonBarButtonsKey];
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
if (self = [super initWithCoder:aCoder])
|
||||
{
|
||||
_buttons = [aCoder decodeObjectForKey:CPButtonBarButtonsKey] || [];
|
||||
_hasResizeControl = [aCoder decodeBoolForKey:CPButtonBarHasResizeControlKey];
|
||||
_resizeControlIsLeftAligned = [aCoder decodeBoolForKey:CPButtonBarResizeControlIsLeftAlignedKey];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -61,4 +61,27 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)takeStateFromKeyPath:(CPString)aKeyPath ofObjects:(CPArray)objects
|
||||
{
|
||||
var count = objects.length,
|
||||
value = [objects[0] valueForKeyPath:aKeyPath] ? CPOnState : CPOffState;
|
||||
|
||||
[self setAllowsMixedState:NO];
|
||||
[self setState:value];
|
||||
|
||||
while (count-- > 1)
|
||||
{
|
||||
if (value !== ([objects[count] valueForKeyPath:aKeyPath] ? CPOnState : CPOffState))
|
||||
{
|
||||
[self setAllowsMixedState:YES];
|
||||
[self setState:CPMixedState];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)takeValueFromKeyPath:(CPString)aKeyPath ofObjects:(CPArray)objects
|
||||
{
|
||||
[self takeStateFromKeyPath:aKeyPath ofObjects:objects];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -120,9 +120,13 @@
|
||||
|
||||
[super setBoundsOrigin:aPoint];
|
||||
|
||||
var superview = [self superview];
|
||||
|
||||
if([superview isKindOfClass:[CPScrollView class]])
|
||||
var superview = [self superview],
|
||||
|
||||
// This is hack to avoid having to import CPScrollView.
|
||||
// FIXME: Should CPScrollView be finding out about this on its own somehow?
|
||||
scrollViewClass = objj_getClass("CPScrollView");
|
||||
|
||||
if([superview isKindOfClass:scrollViewClass])
|
||||
[superview reflectScrolledClipView:self];
|
||||
}
|
||||
|
||||
@@ -173,26 +177,52 @@
|
||||
return;
|
||||
|
||||
// ... and we're in a scroll view of course.
|
||||
var superview = [self superview];
|
||||
|
||||
if ([superview isKindOfClass:[CPScrollView class]])
|
||||
var superview = [self superview],
|
||||
|
||||
// This is hack to avoid having to import CPScrollView.
|
||||
// FIXME: Should CPScrollView be finding out about this on its own somehow?
|
||||
scrollViewClass = objj_getClass("CPScrollView");
|
||||
|
||||
if ([superview isKindOfClass:scrollViewClass])
|
||||
[superview reflectScrolledClipView:self];
|
||||
}
|
||||
|
||||
- (BOOL)autoscroll:(CPEvent)anEvent
|
||||
{
|
||||
var bounds = [self bounds],
|
||||
eventLocation = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
||||
eventLocation = [self convertPoint:[anEvent locationInWindow] fromView:nil],
|
||||
superview = [self superview],
|
||||
deltaX = 0,
|
||||
deltaY = 0;
|
||||
|
||||
if (CPRectContainsPoint(bounds, eventLocation))
|
||||
if (CGRectContainsPoint(bounds, eventLocation))
|
||||
return NO;
|
||||
|
||||
var newRect = CGRectMakeZero();
|
||||
if (![superview isKindOfClass:[CPScrollView class]] || [superview hasVerticalScroller])
|
||||
{
|
||||
if (eventLocation.y < CGRectGetMinY(bounds))
|
||||
deltaY = CGRectGetMinY(bounds) - eventLocation.y;
|
||||
else if (eventLocation.y > CGRectGetMaxY(bounds))
|
||||
deltaY = CGRectGetMaxY(bounds) - eventLocation.y;
|
||||
if (deltaY < -bounds.size.height)
|
||||
deltaY = -bounds.size.height;
|
||||
if (deltaY > bounds.size.height)
|
||||
deltaY = bounds.size.height;
|
||||
}
|
||||
|
||||
newRect.origin = eventLocation;
|
||||
newRect.size = CPSizeMake(10, 10);
|
||||
if (![superview isKindOfClass:[CPScrollView class]] || [superview hasHorizontalScroller])
|
||||
{
|
||||
if (eventLocation.x < CGRectGetMinX(bounds))
|
||||
deltaX = CGRectGetMinX(bounds) - eventLocation.x;
|
||||
else if (eventLocation.x > CGRectGetMaxX(bounds))
|
||||
deltaX = CGRectGetMaxX(bounds) - eventLocation.x;
|
||||
if (deltaX < -bounds.size.width)
|
||||
deltaX = -bounds.size.width;
|
||||
if (deltaX > bounds.size.width)
|
||||
deltaX = bounds.size.width;
|
||||
}
|
||||
|
||||
return [_documentView scrollRectToVisible:newRect];
|
||||
return [self scrollToPoint:CGPointMake(bounds.origin.x - deltaX, bounds.origin.y - deltaY)];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -30,16 +30,16 @@
|
||||
@import "CPCollectionViewItem.j"
|
||||
|
||||
|
||||
/*!
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPCollectionView
|
||||
|
||||
This class displays an array as a grid of objects, where each object is represented by a view.
|
||||
The view is controlled by creating a CPCollectionViewItem and specifying its view, then
|
||||
This class displays an array as a grid of objects, where each object is represented by a view.
|
||||
The view is controlled by creating a CPCollectionViewItem and specifying its view, then
|
||||
setting that item as the collection view prototype.
|
||||
|
||||
|
||||
@par Delegate Methods
|
||||
|
||||
|
||||
@delegate -(void)collectionViewDidChangeSelection:(CPCollectionView)collectionView;
|
||||
Called when the selection in the collection view has changed.
|
||||
@param collectionView the collection view who's selection changed
|
||||
@@ -67,35 +67,35 @@
|
||||
{
|
||||
CPArray _content;
|
||||
CPArray _items;
|
||||
|
||||
|
||||
CPData _itemData;
|
||||
CPCollectionViewItem _itemPrototype;
|
||||
CPCollectionViewItem _itemForDragging;
|
||||
CPMutableArray _cachedItems;
|
||||
|
||||
|
||||
unsigned _maxNumberOfRows;
|
||||
unsigned _maxNumberOfColumns;
|
||||
|
||||
|
||||
CGSize _minItemSize;
|
||||
CGSize _maxItemSize;
|
||||
|
||||
CPArray _backgroundColors;
|
||||
|
||||
float _tileWidth;
|
||||
|
||||
|
||||
BOOL _isSelectable;
|
||||
BOOL _allowsMultipleSelection;
|
||||
BOOL _allowsEmptySelection;
|
||||
CPIndexSet _selectionIndexes;
|
||||
|
||||
|
||||
CGSize _itemSize;
|
||||
|
||||
|
||||
float _horizontalMargin;
|
||||
float _verticalMargin;
|
||||
|
||||
|
||||
unsigned _numberOfRows;
|
||||
unsigned _numberOfColumns;
|
||||
|
||||
|
||||
id _delegate;
|
||||
|
||||
CPEvent _mouseDownEvent;
|
||||
@@ -104,14 +104,14 @@
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
{
|
||||
self = [super initWithFrame:aFrame];
|
||||
|
||||
|
||||
if (self)
|
||||
{
|
||||
_items = [];
|
||||
_content = [];
|
||||
|
||||
|
||||
_cachedItems = [];
|
||||
|
||||
|
||||
_itemSize = CGSizeMakeZero();
|
||||
_minItemSize = CGSizeMakeZero();
|
||||
_maxItemSize = CGSizeMakeZero();
|
||||
@@ -120,12 +120,12 @@
|
||||
|
||||
_verticalMargin = 5.0;
|
||||
_tileWidth = -1.0;
|
||||
|
||||
|
||||
_selectionIndexes = [CPIndexSet indexSet];
|
||||
_allowsEmptySelection = YES;
|
||||
_isSelectable = YES;
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -196,8 +196,8 @@
|
||||
|
||||
// Setting the Content
|
||||
/*!
|
||||
Sets the content of the collection view to the content in \c anArray.
|
||||
This array can be of any type, and each element will be passed to the \c -setRepresentedObject: method.
|
||||
Sets the content of the collection view to the content in \c anArray.
|
||||
This array can be of any type, and each element will be passed to the \c -setRepresentedObject: method.
|
||||
It's the responsibility of your custom collection view item to interpret the object.
|
||||
@param anArray the content array
|
||||
*/
|
||||
@@ -205,9 +205,9 @@
|
||||
{
|
||||
if (_content == anArray)
|
||||
return;
|
||||
|
||||
|
||||
_content = anArray;
|
||||
|
||||
|
||||
[self reloadContent];
|
||||
}
|
||||
|
||||
@@ -236,13 +236,13 @@
|
||||
{
|
||||
if (_isSelectable == isSelectable)
|
||||
return;
|
||||
|
||||
|
||||
_isSelectable = isSelectable;
|
||||
|
||||
|
||||
if (!_isSelectable)
|
||||
{
|
||||
var index = CPNotFound;
|
||||
|
||||
|
||||
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
|
||||
[_items[index] setSelected:NO];
|
||||
}
|
||||
@@ -299,19 +299,19 @@
|
||||
{
|
||||
if (_selectionIndexes == anIndexSet || !_isSelectable)
|
||||
return;
|
||||
|
||||
|
||||
var index = CPNotFound;
|
||||
|
||||
|
||||
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
|
||||
[_items[index] setSelected:NO];
|
||||
|
||||
|
||||
_selectionIndexes = anIndexSet;
|
||||
|
||||
|
||||
var index = CPNotFound;
|
||||
|
||||
|
||||
while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound)
|
||||
[_items[index] setSelected:YES];
|
||||
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(collectionViewDidChangeSelection:)])
|
||||
[_delegate collectionViewDidChangeSelection:self]
|
||||
}
|
||||
@@ -326,10 +326,10 @@
|
||||
|
||||
/* @ignore */
|
||||
- (void)reloadContent
|
||||
{
|
||||
{
|
||||
// Remove current views
|
||||
var count = _items.length;
|
||||
|
||||
|
||||
while (count--)
|
||||
{
|
||||
[[_items[count] view] removeFromSuperview];
|
||||
@@ -337,7 +337,7 @@
|
||||
|
||||
_cachedItems.push(_items[count]);
|
||||
}
|
||||
|
||||
|
||||
_items = [];
|
||||
|
||||
if (!_itemPrototype || !_content)
|
||||
@@ -350,7 +350,7 @@
|
||||
for (; index < count; ++index)
|
||||
{
|
||||
_items.push([self newItemForRepresentedObject:_content[index]]);
|
||||
|
||||
|
||||
[self addSubview:[_items[index] view]];
|
||||
}
|
||||
|
||||
@@ -365,49 +365,49 @@
|
||||
- (void)tile
|
||||
{
|
||||
var width = CGRectGetWidth([self bounds]);
|
||||
|
||||
|
||||
if (![_content count] || width == _tileWidth)
|
||||
return;
|
||||
|
||||
// We try to fit as many views per row as possible. Any remaining space is then
|
||||
|
||||
// We try to fit as many views per row as possible. Any remaining space is then
|
||||
// either proportioned out to the views (if their minSize != maxSize) or used as
|
||||
// margin
|
||||
var itemSize = CGSizeMakeCopy(_minItemSize);
|
||||
|
||||
|
||||
_numberOfColumns = MAX(1.0, FLOOR(width / itemSize.width));
|
||||
|
||||
|
||||
if (_maxNumberOfColumns > 0)
|
||||
_numberOfColumns = MIN(_maxNumberOfColumns, _numberOfColumns);
|
||||
|
||||
|
||||
var remaining = width - _numberOfColumns * itemSize.width,
|
||||
itemsNeedSizeUpdate = NO;
|
||||
|
||||
|
||||
if (remaining > 0 && itemSize.width < _maxItemSize.width)
|
||||
itemSize.width = MIN(_maxItemSize.width, itemSize.width + FLOOR(remaining / _numberOfColumns));
|
||||
|
||||
|
||||
// When we ONE column and a non-integral width, the FLOORing above can cause the item width to be smaller than the total width.
|
||||
if (_maxNumberOfColumns == 1 && itemSize.width < _maxItemSize.width && itemSize.width < width)
|
||||
itemSize.width = MIN(_maxItemSize.width, width);
|
||||
|
||||
|
||||
if (!CGSizeEqualToSize(_itemSize, itemSize))
|
||||
{
|
||||
_itemSize = itemSize;
|
||||
itemsNeedSizeUpdate = YES;
|
||||
}
|
||||
|
||||
|
||||
var index = 0,
|
||||
count = _items.length;
|
||||
|
||||
|
||||
if (_maxNumberOfColumns > 0 && _maxNumberOfRows > 0)
|
||||
count = MIN(count, _maxNumberOfColumns * _maxNumberOfRows);
|
||||
|
||||
|
||||
_numberOfRows = CEIL(count / _numberOfColumns);
|
||||
|
||||
_horizontalMargin = FLOOR((width - _numberOfColumns * itemSize.width) / (_numberOfColumns + 1));
|
||||
|
||||
|
||||
var x = _horizontalMargin,
|
||||
y = -itemSize.height;
|
||||
|
||||
|
||||
for (; index < count; ++index)
|
||||
{
|
||||
if (index % _numberOfColumns == 0)
|
||||
@@ -415,19 +415,28 @@
|
||||
x = _horizontalMargin;
|
||||
y += _verticalMargin + itemSize.height;
|
||||
}
|
||||
|
||||
|
||||
var view = [_items[index] view];
|
||||
|
||||
|
||||
[view setFrameOrigin:CGPointMake(x, y)];
|
||||
|
||||
|
||||
if (itemsNeedSizeUpdate)
|
||||
[view setFrameSize:_itemSize];
|
||||
|
||||
|
||||
x += itemSize.width + _horizontalMargin;
|
||||
}
|
||||
|
||||
|
||||
var superview = [self superview],
|
||||
proposedHeight = y + itemSize.height + _verticalMargin;
|
||||
|
||||
if ([superview isKindOfClass:[CPClipView class]])
|
||||
{
|
||||
var superviewSize = [superview bounds].size;
|
||||
proposedHeight = MAX(superviewSize.height, proposedHeight);
|
||||
}
|
||||
|
||||
_tileWidth = width;
|
||||
[self setFrameSize:CGSizeMake(width, y + itemSize.height + _verticalMargin)];
|
||||
[self setFrameSize:CGSizeMake(width, proposedHeight)];
|
||||
_tileWidth = -1.0;
|
||||
}
|
||||
|
||||
@@ -445,9 +454,9 @@
|
||||
{
|
||||
if (_maxNumberOfRows == aMaxNumberOfRows)
|
||||
return;
|
||||
|
||||
|
||||
_maxNumberOfRows = aMaxNumberOfRows;
|
||||
|
||||
|
||||
[self tile];
|
||||
}
|
||||
|
||||
@@ -467,9 +476,9 @@
|
||||
{
|
||||
if (_maxNumberOfColumns == aMaxNumberOfColumns)
|
||||
return;
|
||||
|
||||
|
||||
_maxNumberOfColumns = aMaxNumberOfColumns;
|
||||
|
||||
|
||||
[self tile];
|
||||
}
|
||||
|
||||
@@ -506,9 +515,9 @@
|
||||
{
|
||||
if (CGSizeEqualToSize(_minItemSize, aSize))
|
||||
return;
|
||||
|
||||
|
||||
_minItemSize = CGSizeMakeCopy(aSize);
|
||||
|
||||
|
||||
[self tile];
|
||||
}
|
||||
|
||||
@@ -528,9 +537,9 @@
|
||||
{
|
||||
if (CGSizeEqualToSize(_maxItemSize, aSize))
|
||||
return;
|
||||
|
||||
|
||||
_maxItemSize = CGSizeMakeCopy(aSize);
|
||||
|
||||
|
||||
[self tile];
|
||||
}
|
||||
|
||||
@@ -590,6 +599,14 @@
|
||||
|
||||
- (void)mouseDragged:(CPEvent)anEvent
|
||||
{
|
||||
var locationInWindow = [anEvent locationInWindow],
|
||||
mouseDownLocationInWindow = [_mouseDownEvent locationInWindow];
|
||||
|
||||
// FIXME: This is because Safari's drag hysteresis is 3px x 3px
|
||||
if ((ABS(locationInWindow.x - mouseDownLocationInWindow.x) < 3) &&
|
||||
(ABS(locationInWindow.y - mouseDownLocationInWindow.y) < 3))
|
||||
return;
|
||||
|
||||
if (![_delegate respondsToSelector:@selector(collectionView:dragTypesForItemsAtIndexes:)])
|
||||
return;
|
||||
|
||||
@@ -597,6 +614,10 @@
|
||||
if (![_selectionIndexes count])
|
||||
return;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(collectionView:canDragItemsAtIndexes:withEvent:)] &&
|
||||
![_delegate collectionView:self canDragItemsAtIndexes:_selectionIndexes withEvent:_mouseDownEvent])
|
||||
return;
|
||||
|
||||
// Set up the pasteboard
|
||||
var dragTypes = [_delegate collectionView:self dragTypesForItemsAtIndexes:_selectionIndexes];
|
||||
|
||||
@@ -644,9 +665,9 @@
|
||||
{
|
||||
if (_verticalMargin == aVerticalMargin)
|
||||
return;
|
||||
|
||||
|
||||
_verticalMargin = aVerticalMargin;
|
||||
|
||||
|
||||
[self tile];
|
||||
}
|
||||
|
||||
@@ -676,47 +697,48 @@
|
||||
return _delegate;
|
||||
}
|
||||
|
||||
- (CPCollectionViewItem)itemAtIndex:(unsigned)anIndex
|
||||
{
|
||||
return [_items objectAtIndex:anIndex];
|
||||
}
|
||||
|
||||
- (CGRect)frameForItemAtIndex:(unsigned)anIndex
|
||||
{
|
||||
return [[[self itemAtIndex:anIndex] view] frame];
|
||||
}
|
||||
|
||||
- (CGRect)frameForItemsAtIndexes:(CPIndexSet)anIndexSet
|
||||
{
|
||||
var indexArray = [],
|
||||
frame = CGRectNull;
|
||||
|
||||
[anIndexSet getIndexes:indexArray maxCount:-1 inIndexRange:nil];
|
||||
|
||||
var index = 0,
|
||||
count = [indexArray count];
|
||||
|
||||
for (; index < count; ++index)
|
||||
frame = CGRectUnion(frame, [self frameForItemAtIndex:indexArray[index]]);
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPCollectionView (KeyboardInteraction)
|
||||
|
||||
- (CGRect)rectForItemAtIndex:(int)index
|
||||
{
|
||||
// Don't re-compute anything just grab the current frame
|
||||
// This allows subclasses to override tile without messing this up.
|
||||
return [[_items[index] view] frame];
|
||||
}
|
||||
|
||||
- (CGRect)rectForItemsAtIndexes:(CPIndexSet)indexSet
|
||||
{
|
||||
var indexArray = [],
|
||||
rect = nil;
|
||||
|
||||
[indexSet getIndexes:indexArray maxCount:-1 inIndexRange:nil];
|
||||
|
||||
for (var i = 0, count = indexArray.length; i < count; ++i)
|
||||
{
|
||||
var index = indexArray[i];
|
||||
if (rect == nil)
|
||||
rect = [self rectForItemAtIndex:index];
|
||||
else
|
||||
rect = CGRectUnion(rect, [self rectForItemAtIndex:index]);
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
- (void)_scrollToSelection
|
||||
{
|
||||
var rect = [self rectForItemsAtIndexes:[self selectionIndexes]];
|
||||
if (rect)
|
||||
[self scrollRectToVisible:rect];
|
||||
var frame = [self frameForItemsAtIndexes:[self selectionIndexes]];
|
||||
|
||||
if (!CGRectIsNull(frame))
|
||||
[self scrollRectToVisible:frame];
|
||||
}
|
||||
|
||||
- (void)moveLeft:(id)sender
|
||||
{
|
||||
var index = [[self selectionIndexes] firstIndex];
|
||||
if (index === CPNotFound)
|
||||
if (index === CPNotFound)
|
||||
index = [[self items] count];
|
||||
|
||||
index = MAX(index - 1, 0);
|
||||
@@ -744,7 +766,7 @@
|
||||
- (void)moveUp:(id)sender
|
||||
{
|
||||
var index = [[self selectionIndexes] firstIndex];
|
||||
if (index == CPNotFound)
|
||||
if (index == CPNotFound)
|
||||
index = [[self items] count];
|
||||
|
||||
index = MAX(0, index - [self numberOfColumns]);
|
||||
@@ -753,7 +775,7 @@
|
||||
[self _scrollToSelection];
|
||||
}
|
||||
|
||||
- (void)deleteBackwards:(id)sender
|
||||
- (void)deleteBackward:(id)sender
|
||||
{
|
||||
if ([[self delegate] respondsToSelector:@selector(collectionView:shouldDeleteItemsAtIndexes:)])
|
||||
{
|
||||
@@ -775,6 +797,26 @@
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPCollectionView (Deprecated)
|
||||
|
||||
- (CGRect)rectForItemAtIndex:(int)anIndex
|
||||
{
|
||||
_CPReportLenientDeprecation([self class], _cmd, @selector(frameForItemAtIndex:));
|
||||
|
||||
// Don't re-compute anything just grab the current frame
|
||||
// This allows subclasses to override tile without messing this up.
|
||||
return [self frameForItemAtIndex:anIndex];
|
||||
}
|
||||
|
||||
- (CGRect)rectForItemsAtIndexes:(CPIndexSet)anIndexSet
|
||||
{
|
||||
_CPReportLenientDeprecation([self class], _cmd, @selector(frameForItemsAtIndexes:));
|
||||
|
||||
return [self frameForItemsAtIndexes:anIndexSet];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeKey",
|
||||
CPCollectionViewMaxItemSizeKey = @"CPCollectionViewMaxItemSizeKey",
|
||||
CPCollectionViewVerticalMarginKey = @"CPCollectionViewVerticalMarginKey",
|
||||
@@ -796,20 +838,20 @@ var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeKey",
|
||||
_cachedItems = [];
|
||||
|
||||
_itemSize = CGSizeMakeZero();
|
||||
|
||||
|
||||
_minItemSize = [aCoder decodeSizeForKey:CPCollectionViewMinItemSizeKey] || CGSizeMakeZero();
|
||||
_maxItemSize = [aCoder decodeSizeForKey:CPCollectionViewMaxItemSizeKey] || CGSizeMakeZero();
|
||||
|
||||
|
||||
_verticalMargin = [aCoder decodeFloatForKey:CPCollectionViewVerticalMarginKey];
|
||||
|
||||
|
||||
_isSelectable = [aCoder decodeBoolForKey:CPCollectionViewSelectableKey];
|
||||
|
||||
[self setBackgroundColors:[aCoder decodeObjectForKey:CPCollectionViewBackgroundColorsKey]];
|
||||
|
||||
|
||||
_tileWidth = -1.0;
|
||||
|
||||
_selectionIndexes = [CPIndexSet indexSet];
|
||||
|
||||
|
||||
_allowsEmptySelection = YES;
|
||||
}
|
||||
|
||||
@@ -822,12 +864,12 @@ var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeKey",
|
||||
|
||||
if (!CGSizeEqualToSize(_minItemSize, CGSizeMakeZero()))
|
||||
[aCoder encodeSize:_minItemSize forKey:CPCollectionViewMinItemSizeKey];
|
||||
|
||||
|
||||
if (!CGSizeEqualToSize(_maxItemSize, CGSizeMakeZero()))
|
||||
[aCoder encodeSize:_maxItemSize forKey:CPCollectionViewMaxItemSizeKey];
|
||||
|
||||
|
||||
[aCoder encodeBool:_isSelectable forKey:CPCollectionViewSelectableKey];
|
||||
|
||||
|
||||
[aCoder encodeFloat:_verticalMargin forKey:CPCollectionViewVerticalMarginKey];
|
||||
|
||||
[aCoder encodeObject:_backgroundColors forKey:CPCollectionViewBackgroundColorsKey];
|
||||
|
||||
@@ -437,51 +437,16 @@ var cachedBlackColor,
|
||||
if (self)
|
||||
{
|
||||
_components = components;
|
||||
|
||||
if (!CPFeatureIsCompatible(CPCSSRGBAFeature) && _components[3] != 1.0 && window.Base64 && window.CRC32)
|
||||
{
|
||||
var bytes = [0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1,0x8,0x3,0x0,0x0,0x0,0x28,0xcb,0x34,0xbb,0x0,0x0,0x3,0x0,0x50,0x4c,0x54,0x45,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x17,0x89,0x99,0x55,0x0,0x0,0x0,0x1,0x74,0x52,0x4e,0x53,0x0,0x40,0xe6,0xd8,0x66,0x0,0x0,0x0,0x10,0x49,0x44,0x41,0x54,0x78,0xda,0x62,0x60,0x0,0x0,0x0,0x0,0xff,0xff,0x3,0x0,0x0,0x2,0x0,0x1,0x24,0x7f,0x24,0xf1,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82,0xff];
|
||||
var r_off = 41;
|
||||
var g_off = 42;
|
||||
var b_off = 43;
|
||||
var a_off = 821;
|
||||
var plte_crc_off = 809;
|
||||
var trns_crc_off = 822;
|
||||
var plte_type_off = 37;
|
||||
var trns_type_off = 817;
|
||||
|
||||
bytes[r_off] = Math.round(_components[0]*255);
|
||||
bytes[g_off] = Math.round(_components[1]*255);
|
||||
bytes[b_off] = Math.round(_components[2]*255);
|
||||
bytes[a_off] = Math.round(_components[3]*255);
|
||||
|
||||
// calculate new CRCs
|
||||
var new_plte_crc = integerToBytes(CRC32.getCRC(bytes, plte_type_off, 4+768), 4);
|
||||
var new_trns_crc = integerToBytes(CRC32.getCRC(bytes, trns_type_off, 4+1), 4);
|
||||
|
||||
// overwrite old CRCs with new ones
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
bytes[plte_crc_off+i] = new_plte_crc[i];
|
||||
bytes[trns_crc_off+i] = new_trns_crc[i];
|
||||
}
|
||||
|
||||
// Base64 encode, strip whitespace and build data URL
|
||||
var base64image = Base64.encode(bytes); //.replace(/[\s]/g, "");
|
||||
|
||||
_cssString = "url(\"data:image/png;base64," + base64image + "\")";
|
||||
}
|
||||
else
|
||||
{
|
||||
var hasAlpha = CPFeatureIsCompatible(CPCSSRGBAFeature) && _components[3] != 1.0;
|
||||
|
||||
_cssString = (hasAlpha ? "rgba(" : "rgb(") +
|
||||
parseInt(_components[0] * 255.0) + ", " +
|
||||
parseInt(_components[1] * 255.0) + ", " +
|
||||
parseInt(_components[2] * 255.0) +
|
||||
(hasAlpha ? (", " + _components[3]) : "") + ")";
|
||||
}
|
||||
|
||||
var hasAlpha = CPFeatureIsCompatible(CPCSSRGBAFeature) && _components[3] != 1.0;
|
||||
|
||||
_cssString = (hasAlpha ? "rgba(" : "rgb(") +
|
||||
parseInt(_components[0] * 255.0) + ", " +
|
||||
parseInt(_components[1] * 255.0) + ", " +
|
||||
parseInt(_components[2] * 255.0) +
|
||||
(hasAlpha ? (", " + _components[3]) : "") + ")";
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -494,6 +459,7 @@ var cachedBlackColor,
|
||||
{
|
||||
_patternImage = anImage;
|
||||
_cssString = "url(\"" + [_patternImage filename] + "\")";
|
||||
_components = [0.0, 0.0, 0.0, 1.0];
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -736,7 +702,7 @@ var CPColorComponentsKey = @"CPColorComponentsKey",
|
||||
var hexCharacters = "0123456789ABCDEF";
|
||||
|
||||
// HACK: prevent these from becoming globals. workaround for obj-j "function foo(){}" behavior
|
||||
var hexToRGB, integerToBytes, rgbToHex, byteToHex;
|
||||
var hexToRGB, rgbToHex, byteToHex;
|
||||
|
||||
/*!
|
||||
Used for the CPColor \c +colorWithHexString: implementation
|
||||
@@ -764,18 +730,6 @@ function hexToRGB(hex)
|
||||
return [red, green, blue, 1.0];
|
||||
}
|
||||
|
||||
function integerToBytes(integer, length) {
|
||||
if (!length)
|
||||
length = (integer == 0) ? 1 : Math.round((Math.log(integer)/Math.log(2))/8+0.5);
|
||||
|
||||
var bytes = new Array(length);
|
||||
for (var i = length-1; i >= 0; i--) {
|
||||
bytes[i] = integer & 255;
|
||||
integer = integer >> 8
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function rgbToHex(r,g,b) {
|
||||
return byteToHex(r) + byteToHex(g) + byteToHex(b);
|
||||
}
|
||||
|
||||
@@ -231,11 +231,17 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
|
||||
|
||||
- (void)mouseDown:(CPEvent)anEvent
|
||||
{
|
||||
if (![self isEnabled])
|
||||
return;
|
||||
|
||||
[self drawBezelWithHighlight:YES];
|
||||
}
|
||||
|
||||
- (void)mouseDragged:(CPEvent)anEvent
|
||||
{
|
||||
if (![self isEnabled])
|
||||
return;
|
||||
|
||||
[self drawBezelWithHighlight:CGRectContainsPoint([self bounds], [self convertPoint:[anEvent locationInWindow] fromView:nil])];
|
||||
}
|
||||
|
||||
@@ -243,7 +249,7 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
|
||||
{
|
||||
[self drawBezelWithHighlight:NO];
|
||||
|
||||
if (!CGRectContainsPoint([self bounds], [self convertPoint:[anEvent locationInWindow] fromView:nil]))
|
||||
if (!CGRectContainsPoint([self bounds], [self convertPoint:[anEvent locationInWindow] fromView:nil]) || ![self isEnabled])
|
||||
return;
|
||||
|
||||
[self activate:YES];
|
||||
|
||||
@@ -65,8 +65,6 @@ CPInputTypeCanBeChangedFeature = 1 << 25;
|
||||
CPHTML5DragAndDropSourceYOffBy1 = 1 << 26;
|
||||
|
||||
|
||||
|
||||
|
||||
var USER_AGENT = "",
|
||||
PLATFORM_ENGINE = CPUnknownBrowserEngine,
|
||||
PLATFORM_FEATURES = 0;
|
||||
@@ -75,7 +73,7 @@ var USER_AGENT = "",
|
||||
|
||||
PLATFORM_FEATURES |= CPInputTypeCanBeChangedFeature;
|
||||
|
||||
if (typeof window != "undfined" && typeof window.navigator != "undefined")
|
||||
if (typeof window !== "undefined" && typeof window.navigator !== "undefined")
|
||||
USER_AGENT = window.navigator.userAgent;
|
||||
|
||||
// Opera
|
||||
|
||||
@@ -488,10 +488,10 @@ var CPDocumentUntitledCount = 0;
|
||||
|
||||
[_writeRequest setValue:@"close" forHTTPHeaderField:@"Connection"];
|
||||
|
||||
if (aSaveOperation == CPSaveOperation)
|
||||
if (aSaveOperation === CPSaveOperation)
|
||||
[_writeRequest setValue:@"true" forHTTPHeaderField:@"x-cappuccino-overwrite"];
|
||||
|
||||
if (aSaveOperation != CPSaveToOperation)
|
||||
if (aSaveOperation !== CPSaveToOperation)
|
||||
[self updateChangeCount:CPChangeCleared];
|
||||
|
||||
// FIXME: Oh man is this every looking for trouble, we need to handle login at the Cappuccino level, with HTTP Errors.
|
||||
|
||||
@@ -40,29 +40,10 @@ CPDragOperationEvery = -1;
|
||||
|
||||
#define DRAGGING_WINDOW(anObject) ([anObject isKindOfClass:[CPWindow class]] ? anObject : [anObject window])
|
||||
|
||||
var CPDragServerPreviousEvent = nil,
|
||||
CPDragServerAutoscrollInterval = nil;
|
||||
/*
|
||||
var CPDragServerAutoscroll = function()
|
||||
{
|
||||
[CPDragServerSource autoscroll:CPDragServerPreviousEvent];
|
||||
}
|
||||
var CPDragServerPreviousEvent = nil,
|
||||
CPDragServerPeriodicUpdateInterval = 0.05;
|
||||
|
||||
if (CPDragServerAutoscrollInterval === nil)
|
||||
{
|
||||
if ([CPDragServerSource respondsToSelector:@selector(autoscroll:)])
|
||||
CPDragServerAutoscrollInterval = setInterval(CPDragServerAutoscroll, 100);
|
||||
}
|
||||
|
||||
CPDragServerPreviousEvent = anEvent;
|
||||
|
||||
if (CPDragServerAutoscrollInterval !== nil)
|
||||
clearInterval(CPDragServerAutoscrollInterval);
|
||||
|
||||
CPDragServerAutoscrollInterval = nil;
|
||||
*/
|
||||
|
||||
var CPSharedDragServer = nil;
|
||||
var CPSharedDragServer = nil;
|
||||
|
||||
var CPDragServerSource = nil;
|
||||
var CPDragServerDraggingInfo = nil;
|
||||
@@ -127,7 +108,7 @@ var CPDragServerDraggingInfo = nil;
|
||||
@end
|
||||
|
||||
var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
|
||||
CPDraggingSource_draggedImage_endAt_operation_ = 1 << 1,
|
||||
CPDraggingSource_draggedImage_endedAt_operation_ = 1 << 1,
|
||||
CPDraggingSource_draggedView_movedTo_ = 1 << 2,
|
||||
CPDraggingSource_draggedView_endedAt_operation_ = 1 << 3;
|
||||
|
||||
@@ -150,10 +131,13 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
|
||||
|
||||
CGPoint _draggingLocation;
|
||||
id _draggingDestination;
|
||||
BOOL _draggingDestinationWantsPeriodicUpdates;
|
||||
|
||||
CGPoint _startDragLocation;
|
||||
BOOL _shouldSlideBack;
|
||||
unsigned _dragOperation;
|
||||
|
||||
CPTimer _draggingUpdateTimer;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -234,6 +218,9 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
|
||||
|
||||
- (CPDragOperation)draggingUpdatedInPlatformWindow:(CPPlatformWindow)aPlatformWindow location:(CGPoint)aLocation
|
||||
{
|
||||
[_draggingUpdateTimer invalidate];
|
||||
_draggingUpdateTimer = nil;
|
||||
|
||||
var dragOperation = CPDragOperationCopy;
|
||||
// We have to convert base to bridge since the drag event comes from the source window, not the drag window.
|
||||
var draggingDestination = [aPlatformWindow _dragHitTest:aLocation pasteboard:[CPDragServerDraggingInfo draggingPasteboard]];
|
||||
@@ -243,31 +230,95 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
|
||||
|
||||
if(draggingDestination !== _draggingDestination)
|
||||
{
|
||||
if (_draggingDestination && [_draggingDestination respondsToSelector:@selector(draggingExited:)])
|
||||
if ([_draggingDestination respondsToSelector:@selector(draggingExited:)])
|
||||
[_draggingDestination draggingExited:CPDragServerDraggingInfo];
|
||||
|
||||
_draggingDestination = draggingDestination;
|
||||
|
||||
if (_draggingDestination && [_draggingDestination respondsToSelector:@selector(draggingEntered:)])
|
||||
if ([_draggingDestination respondsToSelector:@selector(wantsPeriodicDraggingUpdates)])
|
||||
_draggingDestinationWantsPeriodicUpdates = [_draggingDestination wantsPeriodicDraggingUpdates];
|
||||
else
|
||||
_draggingDestinationWantsPeriodicUpdates = YES;
|
||||
|
||||
if ([_draggingDestination respondsToSelector:@selector(draggingEntered:)])
|
||||
dragOperation = [_draggingDestination draggingEntered:CPDragServerDraggingInfo];
|
||||
}
|
||||
else if (_draggingDestination && [_draggingDestination respondsToSelector:@selector(draggingUpdated:)])
|
||||
else if ([_draggingDestination respondsToSelector:@selector(draggingUpdated:)])
|
||||
dragOperation = [_draggingDestination draggingUpdated:CPDragServerDraggingInfo];
|
||||
|
||||
if (!_draggingDestination)
|
||||
dragOperation = CPDragOperationNone;
|
||||
else
|
||||
{
|
||||
if (_draggingDestinationWantsPeriodicUpdates)
|
||||
_draggingUpdateTimer = [CPTimer scheduledTimerWithTimeInterval:CPDragServerPeriodicUpdateInterval
|
||||
target:self
|
||||
selector:@selector(_sendPeriodicDraggingUpdate:)
|
||||
userInfo:[CPDictionary dictionaryWithJSObject:{platformWindow:aPlatformWindow, location:aLocation}]
|
||||
repeats:NO];
|
||||
|
||||
var scrollView = [_draggingDestination isKindOfClass:[CPView class]] ? [_draggingDestination enclosingScrollView] : nil;
|
||||
if (scrollView)
|
||||
{
|
||||
var contentView = [scrollView contentView],
|
||||
bounds = [contentView bounds],
|
||||
insetBounds = CGRectInset(bounds, 10, 10)
|
||||
eventLocation = [contentView convertPoint:_draggingLocation fromView:nil],
|
||||
deltaX = 0,
|
||||
deltaY = 0;
|
||||
|
||||
if (!CGRectContainsPoint(insetBounds, eventLocation))
|
||||
{
|
||||
if ([scrollView hasVerticalScroller])
|
||||
{
|
||||
if (eventLocation.y < CGRectGetMinY(insetBounds))
|
||||
deltaY = CGRectGetMinY(insetBounds) - eventLocation.y;
|
||||
else if (eventLocation.y > CGRectGetMaxY(insetBounds))
|
||||
deltaY = CGRectGetMaxY(insetBounds) - eventLocation.y;
|
||||
if (deltaY < -insetBounds.size.height)
|
||||
deltaY = -insetBounds.size.height;
|
||||
if (deltaY > insetBounds.size.height)
|
||||
deltaY = insetBounds.size.height;
|
||||
}
|
||||
|
||||
if ([scrollView hasHorizontalScroller])
|
||||
{
|
||||
if (eventLocation.x < CGRectGetMinX(insetBounds))
|
||||
deltaX = CGRectGetMinX(insetBounds) - eventLocation.x;
|
||||
else if (eventLocation.x > CGRectGetMaxX(insetBounds))
|
||||
deltaX = CGRectGetMaxX(insetBounds) - eventLocation.x;
|
||||
if (deltaX < -insetBounds.size.width)
|
||||
deltaX = -insetBounds.size.width;
|
||||
if (deltaX > insetBounds.size.width)
|
||||
deltaX = insetBounds.size.width;
|
||||
}
|
||||
|
||||
[contentView scrollToPoint:CGPointMake(bounds.origin.x - deltaX, bounds.origin.y - deltaY)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dragOperation;
|
||||
}
|
||||
|
||||
- (void)_sendPeriodicDraggingUpdate:(CPTimer)aTimer
|
||||
{
|
||||
var userInfo = [aTimer userInfo];
|
||||
_dragOperation = [self draggingUpdatedInPlatformWindow:[userInfo objectForKey:@"platformWindow"]
|
||||
location:[userInfo objectForKey:@"location"]];
|
||||
}
|
||||
|
||||
- (void)draggingEndedInPlatformWindow:(CPPlatformWindow)aPlatformWindow globalLocation:(CGPoint)aLocation operation:(CPDragOperation)anOperation
|
||||
{
|
||||
[_draggingUpdateTimer invalidate];
|
||||
_draggingUpdateTimer = nil;
|
||||
|
||||
[_draggedView removeFromSuperview];
|
||||
|
||||
if (![CPPlatform supportsDragAndDrop])
|
||||
[_draggedWindow orderOut:self];
|
||||
|
||||
if (_implementedDraggingSourceMethods & CPDraggingSource_draggedImage_endAt_operation_)
|
||||
if (_implementedDraggingSourceMethods & CPDraggingSource_draggedImage_endedAt_operation_)
|
||||
[_draggingSource draggedImage:[_draggedView image] endedAt:aLocation operation:anOperation];
|
||||
else if (_implementedDraggingSourceMethods & CPDraggingSource_draggedView_endedAt_operation_)
|
||||
[_draggingSource draggedView:_draggedView endedAt:aLocation operation:anOperation];
|
||||
@@ -342,8 +393,8 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
|
||||
if ([_draggingSource respondsToSelector:@selector(draggedImage:movedTo:)])
|
||||
_implementedDraggingSourceMethods |= CPDraggingSource_draggedImage_movedTo_;
|
||||
|
||||
if ([_draggingSource respondsToSelector:@selector(draggedImage:endAt:operation:)])
|
||||
_implementedDraggingSourceMethods |= CPDraggingSource_draggedImage_endAt_operation_;
|
||||
if ([_draggingSource respondsToSelector:@selector(draggedImage:endedAt:operation:)])
|
||||
_implementedDraggingSourceMethods |= CPDraggingSource_draggedImage_endedAt_operation_;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -404,13 +455,25 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
|
||||
// Stop tracking events.
|
||||
return;
|
||||
}
|
||||
|
||||
[self draggingSourceUpdatedWithGlobalLocation:platformWindowLocation];
|
||||
_dragOperation = [self draggingUpdatedInPlatformWindow:platformWindow location:platformWindowLocation];
|
||||
else if (type === CPKeyDown)
|
||||
{
|
||||
var keyCode = [anEvent keyCode];
|
||||
if (keyCode === CPEscapeKeyCode)
|
||||
{
|
||||
_dragOperation = CPDragOperationNone;
|
||||
[self draggingEndedInPlatformWindow:platformWindow globalLocation:CGPointMakeZero() operation:_dragOperation];
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[self draggingSourceUpdatedWithGlobalLocation:platformWindowLocation];
|
||||
_dragOperation = [self draggingUpdatedInPlatformWindow:platformWindow location:platformWindowLocation];
|
||||
}
|
||||
|
||||
// If we're not a mouse up, then we're going to want to grab the next event.
|
||||
[CPApp setTarget:self selector:@selector(trackDragging:)
|
||||
forNextEventMatchingMask:CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask
|
||||
forNextEventMatchingMask:CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask | CPKeyDownMask
|
||||
untilDate:nil inMode:0 dequeue:NO];
|
||||
}
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
BOOL _isARepeat;
|
||||
unsigned _keyCode;
|
||||
DOMEvent _DOMEvent;
|
||||
|
||||
|
||||
float _deltaX;
|
||||
float _deltaY;
|
||||
float _deltaZ;
|
||||
@@ -345,7 +345,10 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
*/
|
||||
- (int)buttonNumber
|
||||
{
|
||||
return _buttonNumber;
|
||||
if (_type === CPRightMouseDown || _type === CPRightMouseUp || _type === CPRightMouseDragged)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -51,7 +51,7 @@ var CPSharedFontManager = nil,
|
||||
|
||||
// Changing the Default Font Conversion Classes
|
||||
/*!
|
||||
Sets the class that will be used to create the applcation's
|
||||
Sets the class that will be used to create the application's
|
||||
font manager.
|
||||
*/
|
||||
+ (void)setFontManagerFactory:(Class)aClass
|
||||
|
||||
@@ -365,12 +365,17 @@ var LEFT_SHADOW_INSET = 3.0,
|
||||
return _isEditable;
|
||||
}
|
||||
|
||||
- (void)performDragOperation:(CPDraggingInfo)aSender
|
||||
- (BOOL)performDragOperation:(CPDraggingInfo)aSender
|
||||
{
|
||||
var images = [CPKeyedUnarchiver unarchiveObjectWithData:[[aSender draggingPasteboard] dataForType:CPImagesPboardType]];
|
||||
|
||||
if ([images count])
|
||||
{
|
||||
[self setImage:images[0]];
|
||||
[self sendAction:[self action] to:[self target]];
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -747,6 +747,9 @@ var _CPMenuBarVisible = NO,
|
||||
}
|
||||
|
||||
// Show it.
|
||||
if ([CPPlatform isBrowser])
|
||||
[menuWindow setPlatformWindow:[[aView window] platformWindow]];
|
||||
|
||||
[menuWindow orderFront:self];
|
||||
|
||||
// Track it.
|
||||
@@ -816,6 +819,9 @@ var _CPMenuBarVisible = NO,
|
||||
[menuWindow setFrameOrigin:CGRectIntersection(unconstrainedFrame, constraintRect).origin];
|
||||
}
|
||||
|
||||
if ([CPPlatform isBrowser])
|
||||
[menuWindow setPlatformWindow:[[aView window] platformWindow]];
|
||||
|
||||
[menuWindow orderFront:self];
|
||||
|
||||
[[_CPMenuManager sharedMenuManager]
|
||||
|
||||
@@ -227,8 +227,8 @@ var SelectionColor = nil,
|
||||
|
||||
CGContextClosePath(context);
|
||||
|
||||
CGContextSetShadowWithColor(context, CGSizeMake(0.0, 1.0), 1.1, _shadowColor);
|
||||
CGContextSetFillColor(context, _color);
|
||||
CGContextSetShadowWithColor(context, CGSizeMake(0.0, 1.0), 1.1, _shadowColor || [CPColor whiteColor]);
|
||||
CGContextSetFillColor(context, _color || [CPColor blackColor]);
|
||||
CGContextFillPath(context);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,9 +52,10 @@ var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_
|
||||
|
||||
|
||||
var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ = 1 << 1,
|
||||
CPOutlineViewDelegate_outlineView_shouldSelectItem_ = 1 << 2;
|
||||
CPOutlineViewDelegate_outlineView_shouldSelectItem_ = 1 << 2,
|
||||
CPOutlineViewDelegate_outlineView_heightOfRowByItem_ = 1 << 3,
|
||||
CPOutlineViewDelegate_outlineView_willDisplayView_forTableColumn_item_ = 1 << 4;
|
||||
CPOutlineViewDelegate_outlineView_willDisplayView_forTableColumn_item_ = 1 << 4,
|
||||
CPOutlineViewDelegate_outlineView_isGroupItem_ = 1 << 5;
|
||||
|
||||
CPOutlineViewDropOnItemIndex = -1;
|
||||
|
||||
@@ -84,6 +85,8 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
|
||||
BOOL _shouldRetargetChildIndex;
|
||||
CPInteger _retargedChildIndex;
|
||||
CPTimer _dragHoverTimer;
|
||||
id _dropItem;
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
@@ -107,6 +110,7 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
|
||||
_retargedChildIndex = nil;
|
||||
_shouldRetargetChildIndex = NO;
|
||||
_startHoverTime = nil;
|
||||
|
||||
[self setIndentationPerLevel:16.0];
|
||||
[self setIndentationMarkerFollowsDataView:YES];
|
||||
@@ -381,43 +385,14 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
return frame;
|
||||
}
|
||||
|
||||
- (void)selectRowIndexes:(CPIndexSet)rows byExtendingSelection:(BOOL)shouldExtendSelection
|
||||
- (void)_performSelection:(BOOL)select forRow:(CPInteger)rowIndex context:(id)context
|
||||
{
|
||||
// First un highlight the old disclosure controls
|
||||
var previousSelectedRows = [];
|
||||
[[self selectedRowIndexes] getIndexes:previousSelectedRows maxCount:-1 inIndexRange:nil];
|
||||
[super _performSelection:select forRow:rowIndex context:context];
|
||||
|
||||
var index = [previousSelectedRows count];
|
||||
while (index--)
|
||||
{
|
||||
var rowIndex = previousSelectedRows[index],
|
||||
item = [self itemAtRow:rowIndex];
|
||||
var control = _disclosureControlsForRows[rowIndex],
|
||||
selector = select ? @"setThemeState:" : @"unsetThemeState:";
|
||||
|
||||
if (![self isExpandable:item])
|
||||
continue;
|
||||
|
||||
var control = _disclosureControlsForRows[rowIndex];
|
||||
[control setHighlighted:NO];
|
||||
}
|
||||
|
||||
[super selectRowIndexes:rows byExtendingSelection:shouldExtendSelection];
|
||||
|
||||
// Now highlight the new disclosure controls
|
||||
var selectedRows = [];
|
||||
[rows getIndexes:selectedRows maxCount:-1 inIndexRange:nil];
|
||||
|
||||
var index = [selectedRows count];
|
||||
while (index--)
|
||||
{
|
||||
var rowIndex = selectedRows[index],
|
||||
item = [self itemAtRow:rowIndex];
|
||||
|
||||
if (![self isExpandable:item])
|
||||
continue;
|
||||
|
||||
var control = _disclosureControlsForRows[rowIndex];
|
||||
[control setHighlighted:YES];
|
||||
}
|
||||
[control performSelector:CPSelectorFromString(selector) withObject:CPThemeStateSelected];
|
||||
}
|
||||
|
||||
- (void)setDelegate:(id)aDelegate
|
||||
@@ -468,7 +443,10 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
|
||||
if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:willDisplayView:forTableColumn:item:)])
|
||||
_implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_willDisplayView_forTableColumn_item_;
|
||||
|
||||
|
||||
if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:isGroupItem:)])
|
||||
_implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_isGroupItem_;
|
||||
|
||||
if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewColumnDidMove:)])
|
||||
[defaultCenter
|
||||
addObserver:_outlineViewDelegate
|
||||
@@ -530,6 +508,29 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
|
||||
- (void)setDropItem:(id)theItem dropChildIndex:(int)theIndex
|
||||
{
|
||||
if (_dropItem !== theItem && theIndex < 0 && [self isExpandable:theItem] && ![self isItemExpanded:theItem])
|
||||
{
|
||||
if (_dragHoverTimer)
|
||||
[_dragHoverTimer invalidate];
|
||||
|
||||
var autoExpandCallBack = function(){
|
||||
if (_dropItem)
|
||||
{
|
||||
[_dropOperationFeedbackView blink];
|
||||
[CPTimer scheduledTimerWithTimeInterval:.3 callback:objj_msgSend(self, "expandItem:", _dropItem) repeats:NO]; //[self expandItem:_dropItem];
|
||||
}
|
||||
}
|
||||
|
||||
_dragHoverTimer = [CPTimer scheduledTimerWithTimeInterval:.8 callback:autoExpandCallBack repeats:NO];
|
||||
}
|
||||
|
||||
if (theIndex >= 0)
|
||||
{
|
||||
[_dragHoverTimer invalidate];
|
||||
_dragHoverTimer = nil;
|
||||
}
|
||||
|
||||
_dropItem = theItem;
|
||||
_retargetedItem = theItem;
|
||||
_shouldRetargetItem = YES;
|
||||
|
||||
@@ -537,6 +538,14 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
_shouldRetargetChildIndex = YES;
|
||||
}
|
||||
|
||||
- (void)_draggingEnded
|
||||
{
|
||||
[super _draggingEnded];
|
||||
_dropItem = nil;
|
||||
[_dragHoverTimer invalidate];
|
||||
_dragHoverTimer = nil;
|
||||
}
|
||||
|
||||
- (id)_parentItemForUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex atMouseOffset:(CPPoint)theOffset
|
||||
{
|
||||
if (_shouldRetargetItem)
|
||||
@@ -615,6 +624,8 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
_disclosureControlsForRows[row] = control;
|
||||
|
||||
[control setState:[self isItemExpanded:item] ? CPOnState : CPOffState];
|
||||
var selector = [self isRowSelected:row] ? @"setThemeState:" : @"unsetThemeState:";
|
||||
[control performSelector:CPSelectorFromString(selector) withObject:CPThemeStateSelected];
|
||||
[control setFrame:frame];
|
||||
|
||||
[self addSubview:control];
|
||||
@@ -1020,7 +1031,13 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)tableView:(CPTableView)aTableView isGroupRow:(int)row
|
||||
{
|
||||
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_isGroupItem_))
|
||||
return [_outlineView._outlineViewDelegate outlineView:_outlineView isGroupItem:[_outlineView itemAtRow:theRow]];
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -1070,8 +1087,10 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
|
||||
CGContextAddLineToPoint(context, 0.0, 0.0);
|
||||
|
||||
CGContextClosePath(context);
|
||||
|
||||
CGContextSetFillColor(context, [self isHighlighted] ? [CPColor whiteColor] : [CPColor grayColor]);
|
||||
var isHighlighted = [self hasThemeState:CPThemeStateHighlighted];
|
||||
var color = [self hasThemeState:CPThemeStateSelected] ? (isHighlighted ? [CPColor lightGrayColor] : [CPColor whiteColor]) : (isHighlighted ? [CPColor blackColor] : [CPColor grayColor]);
|
||||
|
||||
CGContextSetFillColor(context, color);
|
||||
CGContextFillPath(context);
|
||||
}
|
||||
|
||||
|
||||
@@ -703,6 +703,23 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
[self sendAction:[self action] to:[self target]];
|
||||
}
|
||||
|
||||
- (void)takeValueFromKeyPath:(CPString)aKeyPath ofObjects:(CPArray)objects
|
||||
{
|
||||
var count = objects.length,
|
||||
value = [objects[0] valueForKeyPath:aKeyPath];
|
||||
|
||||
[self selectItemWithTag:value];
|
||||
[self setEnabled:YES];
|
||||
|
||||
while (count-- > 1)
|
||||
{
|
||||
if (value !== [objects[count] valueForKeyPath:aKeyPath])
|
||||
{
|
||||
[[self selectedItem] setState:CPOffState];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
|
||||
|
||||
@@ -152,6 +152,15 @@ CPDownArrowKeyCode = 40;
|
||||
[_nextResponder performSelector:_cmd withObject:anEvent];
|
||||
}
|
||||
|
||||
/*!
|
||||
Notifies the receiver that the user has clicked the right mouse down in its area.
|
||||
@param anEvent contains information about the right click
|
||||
*/
|
||||
- (void)rightMouseDown:(CPEvent)anEvent
|
||||
{
|
||||
[_nextResponder performSelector:_cmd withObject:anEvent];
|
||||
}
|
||||
|
||||
/*!
|
||||
Notifies the receiver that the user has initiated a drag
|
||||
over it. A drag is a mouse movement while the left button is down.
|
||||
@@ -171,6 +180,15 @@ CPDownArrowKeyCode = 40;
|
||||
[_nextResponder performSelector:_cmd withObject:anEvent];
|
||||
}
|
||||
|
||||
/*!
|
||||
Notifies the receiver that the user has released the right mouse button.
|
||||
@param anEvent contains information about the release
|
||||
*/
|
||||
- (void)rightMouseUp:(CPEvent)anEvent
|
||||
{
|
||||
[_nextResponder performSelector:_cmd withObject:anEvent];
|
||||
}
|
||||
|
||||
/*!
|
||||
Notifies the receiver that the user has moved the mouse (with no buttons down).
|
||||
@param anEvent contains information about the movement
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
@import <Foundation/CPObject.j>
|
||||
|
||||
|
||||
#import "CoreGraphics/CGGeometry.h"
|
||||
#import "Platform/Platform.h"
|
||||
|
||||
@implementation CPScreen : CPObject
|
||||
{
|
||||
@@ -10,7 +10,11 @@
|
||||
|
||||
- (CGRect)visibleFrame
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
return _CGRectMake(window.screen.availLeft, window.screen.availTop, window.screen.availWidth, window.screen.availHeight);
|
||||
#else
|
||||
return _CGRectMakeZero();
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -445,9 +445,7 @@
|
||||
|
||||
- (CPView)_headerView
|
||||
{
|
||||
var headerClipViewSubviews = [_headerClipView subviews];
|
||||
|
||||
return [headerClipViewSubviews count] ? headerClipViewSubviews[0] : nil;
|
||||
return [_headerClipView documentView];
|
||||
}
|
||||
|
||||
- (CGRect)_cornerViewFrame
|
||||
@@ -670,15 +668,32 @@
|
||||
*/
|
||||
- (void)scrollWheel:(CPEvent)anEvent
|
||||
{
|
||||
var documentFrame = [[self documentView] frame],
|
||||
contentBounds = [_contentView bounds];
|
||||
[self _respondToScrollWheelEventWithDeltaX:[anEvent deltaX] * _horizontalLineScroll
|
||||
deltaY:[anEvent deltaY] * _verticalLineScroll];
|
||||
}
|
||||
|
||||
- (void)_respondToScrollWheelEventWithDeltaX:(float)deltaX deltaY:(float)deltaY
|
||||
{
|
||||
var documentFrame = [[self documentView] frame],
|
||||
contentBounds = [_contentView bounds],
|
||||
contentFrame = [_contentView frame],
|
||||
enclosingScrollView = [self enclosingScrollView],
|
||||
extraX = 0,
|
||||
extraY = 0;
|
||||
|
||||
// We want integral bounds!
|
||||
contentBounds.origin.x = ROUND(contentBounds.origin.x + [anEvent deltaX] * _horizontalLineScroll);
|
||||
contentBounds.origin.y = ROUND(contentBounds.origin.y + [anEvent deltaY] * _verticalLineScroll);
|
||||
contentBounds.origin.x = ROUND(contentBounds.origin.x + deltaX);
|
||||
contentBounds.origin.y = ROUND(contentBounds.origin.y + deltaY);
|
||||
|
||||
[_contentView scrollToPoint:contentBounds.origin];
|
||||
[_headerClipView scrollToPoint:CGPointMake(contentBounds.origin.x, 0.0)];
|
||||
var constrainedOrigin = [_contentView constrainScrollPoint:CGPointCreateCopy(contentBounds.origin)];
|
||||
extraX = ((contentBounds.origin.x - constrainedOrigin.x) / _horizontalLineScroll) * [enclosingScrollView horizontalLineScroll];
|
||||
extraY = ((contentBounds.origin.y - constrainedOrigin.y) / _verticalLineScroll) * [enclosingScrollView verticalLineScroll];
|
||||
|
||||
[_contentView scrollToPoint:constrainedOrigin];
|
||||
[_headerClipView scrollToPoint:CGPointMake(constrainedOrigin.x, 0.0)];
|
||||
|
||||
if (extraX || extraY)
|
||||
[enclosingScrollView _respondToScrollWheelEventWithDeltaX:extraX deltaY:extraY];
|
||||
}
|
||||
|
||||
- (void)keyDown:(CPEvent)anEvent
|
||||
@@ -759,7 +774,13 @@ var CPScrollViewContentViewKey = "CPScrollViewContentView",
|
||||
|
||||
_contentView = [aCoder decodeObjectForKey:CPScrollViewContentViewKey];
|
||||
_headerClipView = [aCoder decodeObjectForKey:CPScrollViewHeaderClipViewKey];
|
||||
|
||||
|
||||
if (!_headerClipView)
|
||||
{
|
||||
_headerClipView = [[CPClipView alloc] init];
|
||||
[self addSubview:_headerClipView];
|
||||
}
|
||||
|
||||
_verticalScroller = [aCoder decodeObjectForKey:CPScrollViewVScrollerKey];
|
||||
_horizontalScroller = [aCoder decodeObjectForKey:CPScrollViewHScrollerKey];
|
||||
|
||||
|
||||
@@ -235,7 +235,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
||||
*/
|
||||
- (void)checkSpaceForParts
|
||||
{
|
||||
var bounds = [self bounds];
|
||||
var bounds = [self bounds];
|
||||
|
||||
// Assume we won't be needing the arrows.
|
||||
if (_knobProportion === 1.0)
|
||||
@@ -290,8 +290,7 @@ NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
|
||||
_partRects[CPScrollerDecrementLine] = _CGRectMakeZero();
|
||||
_partRects[CPScrollerKnobSlot] = _CGRectMake(trackInset.left, 0, width - trackInset.left - trackInset.right, height);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
var decrementLineSize = [self currentValueForThemeAttribute:"decrement-line-size"],
|
||||
|
||||
@@ -24,26 +24,10 @@
|
||||
|
||||
#include "Platform/Platform.h"
|
||||
|
||||
/*!
|
||||
@global
|
||||
@group Menu tags
|
||||
*/
|
||||
CPSearchFieldRecentsTitleMenuItemTag = 1000;
|
||||
/*!
|
||||
@global
|
||||
@group Menu tags
|
||||
*/
|
||||
CPSearchFieldRecentsMenuItemTag = 1001;
|
||||
/*!
|
||||
@global
|
||||
@group Menu tags
|
||||
*/
|
||||
CPSearchFieldClearRecentsMenuItemTag = 1002;
|
||||
/*!
|
||||
@global
|
||||
@group Menu tags
|
||||
*/
|
||||
CPSearchFieldNoRecentsMenuItemTag = 1003;
|
||||
CPSearchFieldRecentsTitleMenuItemTag = 1000;
|
||||
CPSearchFieldRecentsMenuItemTag = 1001;
|
||||
CPSearchFieldClearRecentsMenuItemTag = 1002;
|
||||
CPSearchFieldNoRecentsMenuItemTag = 1003;
|
||||
|
||||
var CPSearchFieldSearchImage = nil,
|
||||
CPSearchFieldFindImage = nil,
|
||||
@@ -79,64 +63,49 @@ var CPSearchFieldSearchImage = nil,
|
||||
return;
|
||||
|
||||
var bundle = [CPBundle bundleForClass:self];
|
||||
CPSearchFieldSearchImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldSearch.png"]];
|
||||
CPSearchFieldFindImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldFind.png"]];
|
||||
CPSearchFieldCancelImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldCancel.png"]];
|
||||
CPSearchFieldCancelPressedImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldCancelPressed.png"]];
|
||||
CPSearchFieldSearchImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldSearch.png"] size:CGSizeMake(25, 22)];
|
||||
CPSearchFieldFindImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldFind.png"] size:CGSizeMake(25, 22)];
|
||||
CPSearchFieldCancelImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldCancel.png"] size:CGSizeMake(22, 22)];
|
||||
CPSearchFieldCancelPressedImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldCancelPressed.png"] size:CGSizeMake(22, 22)];
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CPRect)frame
|
||||
- (id)initWithFrame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self != nil)
|
||||
if (self = [super initWithFrame:frame])
|
||||
{
|
||||
_recentSearches = [CPArray array];
|
||||
_maximumRecents = 10;
|
||||
_sendsWholeSearchString = NO;
|
||||
_sendsSearchStringImmediately = NO;
|
||||
_recentsAutosaveName = nil;
|
||||
|
||||
[self setBezeled:YES];
|
||||
[self setBezelStyle:CPTextFieldRoundedBezel];
|
||||
[self setBordered:YES];
|
||||
[self setEditable:YES];
|
||||
[self setDelegate:self];
|
||||
|
||||
_cancelButton = [[CPButton alloc] initWithFrame:CPMakeRect(frame.size.width - 27,(frame.size.height-22)/2,22,22)];
|
||||
[self resetCancelButton];
|
||||
[_cancelButton setHidden:YES];
|
||||
[_cancelButton setAutoresizingMask:CPViewMinXMargin];
|
||||
[self addSubview:_cancelButton];
|
||||
|
||||
_searchButton = [[CPButton alloc] initWithFrame:CPMakeRect(5,(frame.size.height-25)/2,25,25)];
|
||||
[self resetSearchButton];
|
||||
[self addSubview:_searchButton];
|
||||
|
||||
[self _initWithFrame:frame];
|
||||
#if PLATFORM(DOM)
|
||||
_cancelButton._DOMElement.style.cursor = "default";
|
||||
_searchButton._DOMElement.style.cursor = "default";
|
||||
#endif
|
||||
|
||||
_cancelButton._DOMElement.style.cursor = "default";
|
||||
_searchButton._DOMElement.style.cursor = "default";
|
||||
#endif
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)copy
|
||||
- (void)_initWithFrame:(CGRect)frame
|
||||
{
|
||||
var copy = [super copy];
|
||||
[self setBezeled:YES];
|
||||
[self setBezelStyle:CPTextFieldRoundedBezel];
|
||||
[self setBordered:YES];
|
||||
[self setEditable:YES];
|
||||
[self setDelegate:self];
|
||||
|
||||
[copy setCancelButton:[_cancelButton copy]];
|
||||
[copy setSearchButton:[_searchButton copy]];
|
||||
[copy setSendsWholeSearchString:[_sendsWholeSearchString copy]];
|
||||
[copy setSendsSearchStringImmediately:[_sendsSearchStringImmediately copy]];
|
||||
[copy setMaximumRecents:_maximumRecents];
|
||||
if (_recentsAutosaveName)
|
||||
[copy setrecentsAutosaveName:[_recentsAutosaveName copy]];
|
||||
if (_searchMenuTemplate)
|
||||
[copy setSearchMenutemplate:[_searchMenuTemplate copy]];
|
||||
_cancelButton = [[CPButton alloc] initWithFrame:CGRectMake(frame.size.width - 27,(frame.size.height-22)/2,22,22)];
|
||||
[self resetCancelButton];
|
||||
[_cancelButton setHidden:YES];
|
||||
[_cancelButton setAutoresizingMask:CPViewMinXMargin];
|
||||
[self addSubview:_cancelButton];
|
||||
|
||||
return copy;
|
||||
_searchButton = [[CPButton alloc] initWithFrame:CGRectMake(5,(frame.size.height-25)/2,25,25)];
|
||||
[self resetSearchButton];
|
||||
[self addSubview:_searchButton];
|
||||
}
|
||||
|
||||
// Managing Buttons
|
||||
@@ -695,9 +664,7 @@ var CPSearchFieldSearchImage = nil,
|
||||
|
||||
@end
|
||||
|
||||
var CPSearchButtonKey = @"CPSearchButtonKey",
|
||||
CPCancelButtonKey = @"CPCancelButtonKey",
|
||||
CPRecentsAutosaveNameKey = @"CPRecentsAutosaveNameKey",
|
||||
var CPRecentsAutosaveNameKey = @"CPRecentsAutosaveNameKey",
|
||||
CPSendsWholeSearchStringKey = @"CPSendsWholeSearchStringKey",
|
||||
CPSendsSearchStringImmediatelyKey = @"CPSendsSearchStringImmediatelyKey",
|
||||
CPMaximumRecentsKey = @"CPMaximumRecentsKey",
|
||||
@@ -707,13 +674,20 @@ var CPSearchButtonKey = @"CPSearchButtonKey",
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)coder
|
||||
{
|
||||
[super encodeWithCoder:coder];
|
||||
|
||||
[coder encodeObject:_searchButton forKey:CPSearchButtonKey];
|
||||
[coder encodeObject:_cancelButton forKey:CPCancelButtonKey];
|
||||
[_searchButton removeFromSuperview];
|
||||
[_cancelButton removeFromSuperview];
|
||||
|
||||
[super encodeWithCoder:coder];
|
||||
|
||||
if (_searchButton)
|
||||
[self addSubview:_searchButton];
|
||||
if (_cancelButton)
|
||||
[self addSubview:_cancelButton];
|
||||
|
||||
[coder encodeBool:_sendsWholeSearchString forKey:CPSendsWholeSearchStringKey];
|
||||
[coder encodeBool:_sendsSearchStringImmediately forKey:CPSendsSearchStringImmediatelyKey];
|
||||
[coder encodeInt:_maximumRecents forKey:CPMaximumRecentsKey];
|
||||
|
||||
if (_recentsAutosaveName)
|
||||
[coder encodeObject:_recentsAutosaveName forKey:CPRecentsAutosaveNameKey];
|
||||
if (_searchMenuTemplate)
|
||||
@@ -722,21 +696,23 @@ var CPSearchButtonKey = @"CPSearchButtonKey",
|
||||
|
||||
- (id)initWithCoder:(CPCoder)coder
|
||||
{
|
||||
self = [super initWithCoder:coder];
|
||||
|
||||
_searchButton = [coder decodeObjectForKey:CPSearchButtonKey];
|
||||
_cancelButton = [coder decodeObjectForKey:CPCancelButtonKey];
|
||||
_recentsAutosaveName = [coder decodeObjectForKey:CPRecentsAutosaveNameKey];
|
||||
_sendsWholeSearchString = [coder decodeBoolForKey:CPSendsWholeSearchStringKey];
|
||||
_sendsSearchStringImmediately = [coder decodeBoolForKey:CPSendsSearchStringImmediatelyKey];
|
||||
_maximumRecents = [coder decodeIntForKey:CPMaximumRecentsKey];
|
||||
var template = [coder decodeObjectForKey:CPSearchMenuTemplateKey];
|
||||
if (template)
|
||||
[self setSearchMenuTemplate:template];
|
||||
|
||||
[self setDelegate:self];
|
||||
if (self = [super initWithCoder:coder])
|
||||
{
|
||||
[self _initWithFrame:[self frame]];
|
||||
|
||||
_recentsAutosaveName = [coder decodeObjectForKey:CPRecentsAutosaveNameKey];
|
||||
_sendsWholeSearchString = [coder decodeBoolForKey:CPSendsWholeSearchStringKey];
|
||||
_sendsSearchStringImmediately = [coder decodeBoolForKey:CPSendsSearchStringImmediatelyKey];
|
||||
_maximumRecents = [coder decodeIntForKey:CPMaximumRecentsKey];
|
||||
|
||||
var template = [coder decodeObjectForKey:CPSearchMenuTemplateKey];
|
||||
if (template)
|
||||
[self setSearchMenuTemplate:template];
|
||||
|
||||
[self setDelegate:self];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
@end
|
||||
|
||||
@@ -396,6 +396,18 @@ CPCircularSlider = 1;
|
||||
_sendActionOn &= ~CPLeftMouseDraggedMask;
|
||||
}
|
||||
|
||||
- (void)takeValueFromKeyPath:(CPString)aKeyPath ofObjects:(CPArray)objects
|
||||
{
|
||||
var count = objects.length,
|
||||
value = [objects[0] valueForKeyPath:aKeyPath];
|
||||
|
||||
[self setObjectValue:value];
|
||||
|
||||
while (count-- > 1)
|
||||
if (value !== ([objects[count] valueForKeyPath:aKeyPath]))
|
||||
return [self setFloatValue:1.0];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var CPSliderMinValueKey = "CPSliderMinValueKey",
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
@import "CPButtonBar.j"
|
||||
@import "CPImage.j"
|
||||
@import "CPView.j"
|
||||
|
||||
@@ -43,18 +44,20 @@ var CPSplitViewHorizontalImage = nil,
|
||||
id _delegate;
|
||||
BOOL _isVertical;
|
||||
BOOL _isPaneSplitter;
|
||||
|
||||
|
||||
int _currentDivider;
|
||||
float _initialOffset;
|
||||
|
||||
|
||||
CPString _originComponent;
|
||||
CPString _sizeComponent;
|
||||
|
||||
|
||||
CPArray _DOMDividerElements;
|
||||
CPString _dividerImagePath;
|
||||
int _drawingDivider;
|
||||
|
||||
|
||||
BOOL _needsResizeSubviews;
|
||||
|
||||
CPArray _buttonBars;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -77,10 +80,11 @@ var CPSplitViewHorizontalImage = nil,
|
||||
_currentDivider = CPNotFound;
|
||||
|
||||
_DOMDividerElements = [];
|
||||
_buttonBars = [];
|
||||
|
||||
[self _setVertical:YES];
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -98,7 +102,7 @@ var CPSplitViewHorizontalImage = nil,
|
||||
{
|
||||
if (![self _setVertical:shouldBeVertical])
|
||||
return;
|
||||
|
||||
|
||||
// Just re-adjust evenly.
|
||||
var frame = [self frame],
|
||||
dividerThickness = [self dividerThickness];
|
||||
@@ -125,13 +129,13 @@ var CPSplitViewHorizontalImage = nil,
|
||||
- (BOOL)_setVertical:(BOOL)shouldBeVertical
|
||||
{
|
||||
var changed = (_isVertical != shouldBeVertical);
|
||||
|
||||
|
||||
_isVertical = shouldBeVertical;
|
||||
|
||||
|
||||
_originComponent = [self isVertical] ? "x" : "y";
|
||||
_sizeComponent = [self isVertical] ? "width" : "height";
|
||||
_dividerImagePath = [self isVertical] ? [CPSplitViewVerticalImage filename] : [CPSplitViewHorizontalImage filename];
|
||||
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
@@ -150,7 +154,7 @@ var CPSplitViewHorizontalImage = nil,
|
||||
if(_DOMDividerElements[_drawingDivider])
|
||||
[self _setupDOMDivider]
|
||||
|
||||
// The divider changes size when pane splitter mode is toggled, so the
|
||||
// The divider changes size when pane splitter mode is toggled, so the
|
||||
// subviews need to change size too.
|
||||
_needsResizeSubviews = YES;
|
||||
[self setNeedsDisplay:YES];
|
||||
@@ -209,19 +213,13 @@ var CPSplitViewHorizontalImage = nil,
|
||||
{
|
||||
_DOMDividerElements[_drawingDivider] = document.createElement("div");
|
||||
|
||||
if(_isVertical)
|
||||
_DOMDividerElements[_drawingDivider].style.cursor = [[CPCursor resizeLeftRightCursor] _cssString];
|
||||
else
|
||||
_DOMDividerElements[_drawingDivider].style.cursor = [[CPCursor resizeUpDownCursor] _cssString];
|
||||
|
||||
_DOMDividerElements[_drawingDivider].style.position = "absolute";
|
||||
_DOMDividerElements[_drawingDivider].style.backgroundRepeat = "repeat";
|
||||
|
||||
CPDOMDisplayServerAppendChild(_DOMElement, _DOMDividerElements[_drawingDivider]);
|
||||
}
|
||||
|
||||
[self _setupDOMDivider];
|
||||
}
|
||||
|
||||
[self _setupDOMDivider];
|
||||
CPDOMDisplayServerSetStyleLeftTop(_DOMDividerElements[_drawingDivider], NULL, _CGRectGetMinX(aRect), _CGRectGetMinY(aRect));
|
||||
CPDOMDisplayServerSetStyleSize(_DOMDividerElements[_drawingDivider], _CGRectGetWidth(aRect), _CGRectGetHeight(aRect));
|
||||
#endif
|
||||
@@ -256,7 +254,7 @@ var CPSplitViewHorizontalImage = nil,
|
||||
var subviews = [self subviews],
|
||||
count = subviews.length,
|
||||
oldSize = CGSizeMakeZero();
|
||||
|
||||
|
||||
if ([self isVertical])
|
||||
{
|
||||
oldSize.width += [self dividerThickness] * (count - 1);
|
||||
@@ -279,15 +277,25 @@ var CPSplitViewHorizontalImage = nil,
|
||||
var frame = [_subviews[anIndex] frame],
|
||||
startPosition = frame.origin[_originComponent] + frame.size[_sizeComponent],
|
||||
effectiveRect = [self effectiveRectOfDividerAtIndex:anIndex],
|
||||
buttonBar = _buttonBars[anIndex],
|
||||
buttonBarRect = null,
|
||||
additionalRect = null;
|
||||
|
||||
|
||||
if (buttonBar != null)
|
||||
{
|
||||
buttonBarRect = [buttonBar resizeControlFrame];
|
||||
buttonBarRect.origin = [self convertPoint:buttonBarRect.origin fromView:buttonBar];
|
||||
}
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitView:effectiveRect:forDrawnRect:ofDividerAtIndex:)])
|
||||
effectiveRect = [_delegate splitView:self effectiveRect:effectiveRect forDrawnRect:effectiveRect ofDividerAtIndex:anIndex];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitView:additionalEffectiveRectOfDividerAtIndex:)])
|
||||
additionalRect = [_delegate splitView:self additionalEffectiveRectOfDividerAtIndex:anIndex];
|
||||
|
||||
return CGRectContainsPoint(effectiveRect, aPoint) || (additionalRect && CGRectContainsPoint(additionalRect, aPoint));
|
||||
return CGRectContainsPoint(effectiveRect, aPoint) ||
|
||||
(additionalRect && CGRectContainsPoint(additionalRect, aPoint)) ||
|
||||
(buttonBarRect && CGRectContainsPoint(buttonBarRect, aPoint));
|
||||
}
|
||||
|
||||
- (CPView)hitTest:(CGPoint)aPoint
|
||||
@@ -303,7 +311,7 @@ var CPSplitViewHorizontalImage = nil,
|
||||
if ([self cursorAtPoint:point hitDividerAtIndex:i])
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
return [super hitTest:aPoint];
|
||||
}
|
||||
|
||||
@@ -320,12 +328,13 @@ var CPSplitViewHorizontalImage = nil,
|
||||
if (_currentDivider != CPNotFound)
|
||||
{
|
||||
_currentDivider = CPNotFound;
|
||||
[self _updateResizeCursor:anEvent];
|
||||
[self _postNotificationDidResize];
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (type == CPLeftMouseDown)
|
||||
{
|
||||
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
||||
@@ -342,7 +351,7 @@ var CPSplitViewHorizontalImage = nil,
|
||||
if ([anEvent clickCount] == 2 &&
|
||||
[_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)] &&
|
||||
[_delegate respondsToSelector:@selector(splitView:shouldCollapseSubview:forDoubleClickOnDividerAtIndex:)])
|
||||
{
|
||||
{
|
||||
var minPosition = [self minPossiblePositionOfDividerAtIndex:i],
|
||||
maxPosition = [self maxPossiblePositionOfDividerAtIndex:i];
|
||||
|
||||
@@ -374,14 +383,16 @@ var CPSplitViewHorizontalImage = nil,
|
||||
if (_currentDivider === CPNotFound)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
else if (type == CPLeftMouseDragged && _currentDivider != CPNotFound)
|
||||
{
|
||||
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
||||
|
||||
|
||||
[self setPosition:(point[_originComponent] + _initialOffset) ofDividerAtIndex:_currentDivider];
|
||||
// Cursor might change if we reach a resize limit.
|
||||
[self _updateResizeCursor:anEvent];
|
||||
}
|
||||
|
||||
|
||||
[CPApp setTarget:self selector:@selector(trackDivider:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
|
||||
}
|
||||
|
||||
@@ -391,13 +402,81 @@ var CPSplitViewHorizontalImage = nil,
|
||||
[self trackDivider:anEvent];
|
||||
}
|
||||
|
||||
- (void)viewDidMoveToWindow
|
||||
{
|
||||
// Enable split view resize cursors. Commented out pending CPTrackingArea implementation.
|
||||
//[[self window] setAcceptsMouseMovedEvents:YES];
|
||||
}
|
||||
|
||||
- (void)mouseEntered:(CPEvent)anEvent
|
||||
{
|
||||
// Tracking code handles cursor by itself.
|
||||
if (_currentDivider == CPNotFound)
|
||||
[self _updateResizeCursor:anEvent];
|
||||
}
|
||||
|
||||
- (void)mouseMoved:(CPEvent)anEvent
|
||||
{
|
||||
if (_currentDivider == CPNotFound)
|
||||
[self _updateResizeCursor:anEvent];
|
||||
}
|
||||
|
||||
- (void)mouseExited:(CPEvent)anEvent
|
||||
{
|
||||
if (_currentDivider == CPNotFound)
|
||||
// FIXME: we should use CPCursor push/pop (if previous currentCursor != arrow).
|
||||
[[CPCursor arrowCursor] set];
|
||||
}
|
||||
|
||||
- (void)_updateResizeCursor:(CPEvent)anEvent
|
||||
{
|
||||
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
||||
|
||||
if ([anEvent type] === CPLeftMouseUp && ![[self window] acceptsMouseMovedEvents])
|
||||
{
|
||||
[[CPCursor arrowCursor] set];
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0, count = [_subviews count] - 1; i < count; i++)
|
||||
{
|
||||
// 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],
|
||||
startPosition = frame.origin[_originComponent] + frame.size[_sizeComponent],
|
||||
canShrink = [self _realPositionForPosition:startPosition-1 ofDividerAtIndex:i] < startPosition,
|
||||
canGrow = [self _realPositionForPosition:startPosition+1 ofDividerAtIndex:i] > startPosition,
|
||||
cursor = [CPCursor arrowCursor];
|
||||
|
||||
if (_isVertical && canShrink && canGrow)
|
||||
cursor = [CPCursor resizeLeftRightCursor];
|
||||
else if (_isVertical && canShrink)
|
||||
cursor = [CPCursor resizeLeftCursor];
|
||||
else if (_isVertical && canGrow)
|
||||
cursor = [CPCursor resizeRightCursor];
|
||||
else if (canShrink && canGrow)
|
||||
cursor = [CPCursor resizeUpDownCursor];
|
||||
else if (canShrink)
|
||||
cursor = [CPCursor resizeUpCursor];
|
||||
else if (canGrow)
|
||||
cursor = [CPCursor resizeDownCursor];
|
||||
|
||||
[cursor set];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
[[CPCursor arrowCursor] set];
|
||||
}
|
||||
|
||||
- (float)maxPossiblePositionOfDividerAtIndex:(int)dividerIndex
|
||||
{
|
||||
var frame = [_subviews[dividerIndex + 1] frame];
|
||||
|
||||
|
||||
if (dividerIndex + 1 < [_subviews count] - 1)
|
||||
return frame.origin[_originComponent] + frame.size[_sizeComponent] - [self dividerThickness];
|
||||
else
|
||||
else
|
||||
return [self frame].size[_sizeComponent] - [self dividerThickness];
|
||||
}
|
||||
|
||||
@@ -406,17 +485,15 @@ var CPSplitViewHorizontalImage = nil,
|
||||
if (dividerIndex > 0)
|
||||
{
|
||||
var frame = [_subviews[dividerIndex - 1] frame];
|
||||
|
||||
|
||||
return frame.origin[_originComponent] + frame.size[_sizeComponent] + [self dividerThickness];
|
||||
}
|
||||
else
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (void)setPosition:(float)position ofDividerAtIndex:(int)dividerIndex
|
||||
- (int)_realPositionForPosition:(float)position ofDividerAtIndex:(int)dividerIndex
|
||||
{
|
||||
[self _adjustSubviewsWithCalculatedSize];
|
||||
|
||||
// not sure where this should override other positions?
|
||||
if ([_delegate respondsToSelector:@selector(splitView:constrainSplitPosition:ofSubviewAt:)])
|
||||
position = [_delegate splitView:self constrainSplitPosition:position ofSubviewAt:dividerIndex];
|
||||
@@ -425,47 +502,56 @@ var CPSplitViewHorizontalImage = nil,
|
||||
proposedMin = [self minPossiblePositionOfDividerAtIndex:dividerIndex],
|
||||
actualMax = proposedMax,
|
||||
actualMin = proposedMin;
|
||||
|
||||
|
||||
if([_delegate respondsToSelector:@selector(splitView:constrainMinCoordinate:ofSubviewAt:)])
|
||||
actualMin = [_delegate splitView:self constrainMinCoordinate:proposedMin ofSubviewAt:dividerIndex];
|
||||
|
||||
|
||||
if([_delegate respondsToSelector:@selector(splitView:constrainMaxCoordinate:ofSubviewAt:)])
|
||||
actualMax = [_delegate splitView:self constrainMaxCoordinate:proposedMax ofSubviewAt:dividerIndex];
|
||||
|
||||
var frame = [self frame],
|
||||
viewA = _subviews[dividerIndex],
|
||||
frameA = [viewA frame],
|
||||
viewB = _subviews[dividerIndex + 1],
|
||||
frameB = [viewB frame];
|
||||
var viewA = _subviews[dividerIndex],
|
||||
realPosition = MAX(MIN(position, actualMax), actualMin);
|
||||
|
||||
var realPosition = MAX(MIN(position, actualMax), actualMin);
|
||||
|
||||
if (position < proposedMin + (actualMin - proposedMin) / 2)
|
||||
if ([_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)])
|
||||
if ([_delegate splitView:self canCollapseSubview:viewA])
|
||||
realPosition = proposedMin;
|
||||
|
||||
|
||||
return realPosition;
|
||||
}
|
||||
|
||||
- (void)setPosition:(float)position ofDividerAtIndex:(int)dividerIndex
|
||||
{
|
||||
[self _adjustSubviewsWithCalculatedSize];
|
||||
|
||||
var realPosition = [self _realPositionForPosition:position ofDividerAtIndex:dividerIndex];
|
||||
|
||||
var viewA = _subviews[dividerIndex],
|
||||
frameA = [viewA frame],
|
||||
viewB = _subviews[dividerIndex + 1],
|
||||
frameB = [viewB frame];
|
||||
|
||||
frameA.size[_sizeComponent] = realPosition - frameA.origin[_originComponent];
|
||||
[_subviews[dividerIndex] setFrame:frameA];
|
||||
|
||||
|
||||
frameB.size[_sizeComponent] = frameB.origin[_originComponent] + frameB.size[_sizeComponent] - realPosition - [self dividerThickness];
|
||||
frameB.origin[_originComponent] = realPosition + [self dividerThickness];
|
||||
[_subviews[dividerIndex + 1] setFrame:frameB];
|
||||
|
||||
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
- (void)setFrameSize:(CGSize)aSize
|
||||
{
|
||||
[self _adjustSubviewsWithCalculatedSize];
|
||||
|
||||
|
||||
[super setFrameSize:aSize];
|
||||
|
||||
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
- (void)resizeSubviewsWithOldSize:(CPSize)oldSize
|
||||
{
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(splitView:resizeSubviewsWithOldSize:)])
|
||||
{
|
||||
[_delegate splitView:self resizeSubviewsWithOldSize:oldSize];
|
||||
@@ -473,7 +559,7 @@ var CPSplitViewHorizontalImage = nil,
|
||||
}
|
||||
|
||||
[self _postNotificationWillResize];
|
||||
|
||||
|
||||
var index = 0,
|
||||
count = [_subviews count],
|
||||
bounds = [self bounds],
|
||||
@@ -524,7 +610,7 @@ var CPSplitViewHorizontalImage = nil,
|
||||
else if (totalSizableSpace && !isSizable)
|
||||
viewFrame.size[_sizeComponent] = [view frame].size[_sizeComponent];
|
||||
|
||||
bounds.origin[_originComponent] += viewFrame.size[_sizeComponent] + dividerThickness;
|
||||
bounds.origin[_originComponent] += viewFrame.size[_sizeComponent] + dividerThickness;
|
||||
|
||||
[view setFrame:viewFrame];
|
||||
}
|
||||
@@ -538,7 +624,7 @@ var CPSplitViewHorizontalImage = nil,
|
||||
[[CPNotificationCenter defaultCenter] removeObserver:_delegate name:CPSplitViewDidResizeSubviewsNotification object:self];
|
||||
if ([_delegate respondsToSelector:@selector(splitViewWillResizeSubviews:)])
|
||||
[[CPNotificationCenter defaultCenter] removeObserver:_delegate name:CPSplitViewWillResizeSubviewsNotification object:self];
|
||||
|
||||
|
||||
_delegate = delegate;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitViewDidResizeSubviews:)])
|
||||
@@ -553,6 +639,47 @@ var CPSplitViewHorizontalImage = nil,
|
||||
object:self];
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the button bar who's resize control should act as a control for this splitview.
|
||||
Each divider can have at most one button bar assigned to it, and that button bar must be
|
||||
a subview of one of the split view's subviews.
|
||||
|
||||
Calling this method with nil as the button bar will remove any currently assigned button bar
|
||||
for the divider at that index. Indexes will not be adjusted as new subviews are added, so you
|
||||
should usually call this method after adding all the desired subviews to the split view.
|
||||
|
||||
This method will automatically configure the hasResizeControl and resizeControlIsLeftAligned
|
||||
parameters of the button bar, and will override any currently set values.
|
||||
*/
|
||||
- (void)setButtonBar:(CPButtonBar)aButtonBar forDividerAtIndex:(unsigned)dividerIndex
|
||||
{
|
||||
if (!aButtonBar)
|
||||
{
|
||||
_buttonBars[dividerIndex] = nil;
|
||||
return;
|
||||
}
|
||||
|
||||
var view = [aButtonBar superview],
|
||||
subview = aButtonBar;
|
||||
|
||||
while (view && view !== self)
|
||||
{
|
||||
subview = view;
|
||||
view = [view superview];
|
||||
}
|
||||
|
||||
if (view !== self)
|
||||
[CPException raise:CPInvalidArgumentException
|
||||
reason:@"CPSplitView button bar must be a subview of the split view."];
|
||||
|
||||
var viewIndex = [[self subviews] indexOfObject:subview];
|
||||
|
||||
[aButtonBar setHasResizeControl:YES];
|
||||
[aButtonBar setResizeControlIsLeftAligned:dividerIndex < viewIndex];
|
||||
|
||||
_buttonBars[dividerIndex] = aButtonBar;
|
||||
}
|
||||
|
||||
- (void)_postNotificationWillResize
|
||||
{
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPSplitViewWillResizeSubviewsNotification object:self];
|
||||
@@ -567,7 +694,8 @@ var CPSplitViewHorizontalImage = nil,
|
||||
|
||||
var CPSplitViewDelegateKey = "CPSplitViewDelegateKey",
|
||||
CPSplitViewIsVerticalKey = "CPSplitViewIsVerticalKey",
|
||||
CPSplitViewIsPaneSplitterKey = "CPSplitViewIsPaneSplitterKey";
|
||||
CPSplitViewIsPaneSplitterKey = "CPSplitViewIsPaneSplitterKey",
|
||||
CPSplitViewButtonBarsKey = "CPSplitViewButtonBarsKey";
|
||||
|
||||
@implementation CPSplitView (CPCoding)
|
||||
|
||||
@@ -578,19 +706,21 @@ var CPSplitViewDelegateKey = "CPSplitViewDelegateKey",
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
self = [super initWithCoder:aCoder];
|
||||
|
||||
|
||||
if (self)
|
||||
{
|
||||
_currentDivider = CPNotFound;
|
||||
|
||||
|
||||
_DOMDividerElements = [];
|
||||
|
||||
_buttonBars = [aCoder decodeObjectForKey:CPSplitViewButtonBarsKey] || [];
|
||||
|
||||
_delegate = [aCoder decodeObjectForKey:CPSplitViewDelegateKey];;
|
||||
|
||||
_delegate = [aCoder decodeObjectForKey:CPSplitViewDelegateKey];
|
||||
|
||||
_isPaneSplitter = [aCoder decodeBoolForKey:CPSplitViewIsPaneSplitterKey];
|
||||
[self _setVertical:[aCoder decodeBoolForKey:CPSplitViewIsVerticalKey]];
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -601,9 +731,12 @@ var CPSplitViewDelegateKey = "CPSplitViewDelegateKey",
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
[super encodeWithCoder:aCoder];
|
||||
|
||||
|
||||
//FIXME how should we handle this?
|
||||
//[aCoder encodeObject:_buttonBars forKey:CPSplitViewButtonBarsKey];
|
||||
|
||||
[aCoder encodeConditionalObject:_delegate forKey:CPSplitViewDelegateKey];
|
||||
|
||||
|
||||
[aCoder encodeBool:_isVertical forKey:CPSplitViewIsVerticalKey];
|
||||
[aCoder encodeBool:_isPaneSplitter forKey:CPSplitViewIsPaneSplitterKey];
|
||||
}
|
||||
|
||||
@@ -81,8 +81,8 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
var textDataView = [CPTextField new];
|
||||
[textDataView setLineBreakMode:CPLineBreakByTruncatingTail];
|
||||
[textDataView setValue:[CPColor colorWithHexString:@"333333"] forThemeAttribute:@"text-color"];
|
||||
[textDataView setValue:[CPColor whiteColor] forThemeAttribute:@"text-color" inState:CPThemeStateHighlighted];
|
||||
[textDataView setValue:[CPFont boldSystemFontOfSize:12] forThemeAttribute:@"font" inState:CPThemeStateHighlighted];
|
||||
[textDataView setValue:[CPColor whiteColor] forThemeAttribute:@"text-color" inState:CPThemeStateSelected];
|
||||
[textDataView setValue:[CPFont boldSystemFontOfSize:12] forThemeAttribute:@"font" inState:CPThemeStateSelected];
|
||||
[textDataView setValue:CPCenterVerticalTextAlignment forThemeAttribute:@"vertical-alignment"];
|
||||
[self setDataView:textDataView];
|
||||
}
|
||||
@@ -348,7 +348,14 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
|
||||
- (void)setHidden:(BOOL)shouldBeHidden
|
||||
{
|
||||
shouldBeHidden = !!shouldBeHidden
|
||||
if (_isHidden === shouldBeHidden)
|
||||
return;
|
||||
|
||||
_isHidden = shouldBeHidden;
|
||||
|
||||
[[self headerView] setHidden:shouldBeHidden];
|
||||
[[self tableView] _tableColumnVisibilityDidChange:self];
|
||||
}
|
||||
|
||||
- (BOOL)isHidden
|
||||
|
||||
@@ -24,11 +24,9 @@
|
||||
@import "CPTableView.j"
|
||||
@import "CPView.j"
|
||||
|
||||
var CPThemeStatePressed = CPThemeState("pressed");
|
||||
|
||||
@implementation _CPTableColumnHeaderView : CPView
|
||||
{
|
||||
_CPImageAndTextView _textField;
|
||||
_CPImageAndTextView _textField;
|
||||
}
|
||||
|
||||
- (void)initWithFrame:(CGRect)frame
|
||||
@@ -38,7 +36,7 @@ var CPThemeStatePressed = CPThemeState("pressed");
|
||||
{
|
||||
[self _init];
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -46,7 +44,7 @@ var CPThemeStatePressed = CPThemeState("pressed");
|
||||
{
|
||||
_textField = [[_CPImageAndTextView alloc] initWithFrame:CGRectMake(5, 1, CGRectGetWidth([self bounds]) - 10, CGRectGetHeight([self bounds]) - 1)];
|
||||
[_textField setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
|
||||
|
||||
|
||||
[_textField setLineBreakMode:CPLineBreakByTruncatingTail];
|
||||
[_textField setTextColor: [CPColor colorWithHexString: @"333333"]];
|
||||
[_textField setFont:[CPFont boldSystemFontOfSize:12.0]];
|
||||
@@ -62,11 +60,11 @@ var CPThemeStatePressed = CPThemeState("pressed");
|
||||
{
|
||||
var themeState = [self themeState];
|
||||
|
||||
if(themeState & CPThemeStateHighlighted && themeState & CPThemeStatePressed)
|
||||
if(themeState & CPThemeStateSelected && themeState & CPThemeStateHighlighted)
|
||||
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-highlighted-pressed.png", CGSizeMake(1.0, 22.0))]];
|
||||
else if (themeState & CPThemeStateHighlighted)
|
||||
else if (themeState & CPThemeStateSelected)
|
||||
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-highlighted.png", CGSizeMake(1.0, 22.0))]];
|
||||
else if (themeState & CPThemeStatePressed)
|
||||
else if (themeState & CPThemeStateHighlighted)
|
||||
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview-pressed.png", CGSizeMake(1.0, 22.0))]];
|
||||
else
|
||||
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 22.0))]];
|
||||
@@ -139,7 +137,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
[super encodeWithCoder:aCoder];
|
||||
|
||||
|
||||
[aCoder encodeObject:[_textField text] forKey:_CPTableColumnHeaderViewStringValueKey];
|
||||
[aCoder encodeObject:[_textField image] forKey:_CPTableColumnHeaderViewImageKey];
|
||||
[aCoder encodeObject:[_textField font] forKey:_CPTableColumnHeaderViewFontKey];
|
||||
@@ -149,58 +147,60 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
|
||||
|
||||
@implementation CPTableHeaderView : CPView
|
||||
{
|
||||
int _resizedColumn @accessors(readonly, property=resizedColumn);
|
||||
int _draggedColumn @accessors(readonly, property=draggedColumn);
|
||||
int _pressedColumn @accessors(readonly, property=pressedColumn);
|
||||
|
||||
float _draggedDistance @accessors(readonly, property=draggedDistance);
|
||||
float _lastLocation;
|
||||
float _columnOldWidth;
|
||||
|
||||
CPTableView _tableView @accessors(property=tableView);
|
||||
CPPoint _mouseDownLocation;
|
||||
CPPoint _previousTrackingLocation;
|
||||
int _activeColumn;
|
||||
int _pressedColumn;
|
||||
|
||||
BOOL _isResizing;
|
||||
BOOL _isDragging;
|
||||
BOOL _isTrackingColumn;
|
||||
|
||||
float _columnOldWidth;
|
||||
|
||||
CPTableView _tableView @accessors(property=tableView);
|
||||
}
|
||||
|
||||
- (void)initWithFrame:(CGRect)aFrame
|
||||
- (void)_init
|
||||
{
|
||||
_mouseDownLocation = CPPointMakeZero();
|
||||
_previousTrackingLocation = CPPointMakeZero();
|
||||
_activeColumn = -1;
|
||||
_pressedColumn = -1;
|
||||
|
||||
_isResizing = NO;
|
||||
_isDragging = NO;
|
||||
_isTrackingColumn = NO;
|
||||
|
||||
_columnOldWidth = 0.0;
|
||||
|
||||
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 22.0))]];
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
{
|
||||
self = [super initWithFrame:aFrame];
|
||||
|
||||
if (self)
|
||||
{
|
||||
_resizedColumn = -1;
|
||||
_draggedColumn = -1;
|
||||
_pressedColumn = -1;
|
||||
_draggedDistance = 0.0;
|
||||
_lastLocation = nil;
|
||||
_columnOldWidth = nil;
|
||||
|
||||
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 22.0))]];
|
||||
}
|
||||
[self _init];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (int)columnAtPoint:(CGPoint)aPoint
|
||||
{
|
||||
return [_tableView columnAtPoint:CGPointMake(aPoint.x, 0)];
|
||||
return [_tableView columnAtPoint:CGPointMake(aPoint.x, aPoint.y)];
|
||||
}
|
||||
|
||||
- (CGRect)headerRectOfColumn:(int)aColumnIndex
|
||||
{
|
||||
var tableColumns = [_tableView tableColumns];
|
||||
var headerRect = [self bounds],
|
||||
columnRect = [_tableView rectOfColumn:aColumnIndex];
|
||||
|
||||
if (aColumnIndex < 0 || aColumnIndex > [tableColumns count])
|
||||
[CPException raise:"invalid" reason:"tried to get headerRectOfColumn: on invalid column"];
|
||||
headerRect.origin.x = CPRectGetMinX(columnRect);
|
||||
headerRect.size.width = CPRectGetWidth(columnRect);
|
||||
|
||||
// UPDATE COLUMN RANGES ?
|
||||
|
||||
var tableRange = _tableView._tableColumnRanges[aColumnIndex],
|
||||
bounds = [self bounds];
|
||||
|
||||
var rMinX = ROUND(tableRange.location);
|
||||
bounds.origin.x = rMinX;
|
||||
bounds.size.width = FLOOR(tableRange.length + tableRange.location - rMinX);
|
||||
|
||||
return bounds;
|
||||
return headerRect;
|
||||
}
|
||||
|
||||
- (CGRect)_cursorRectForColumn:(int)column
|
||||
@@ -221,118 +221,294 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
|
||||
if (_pressedColumn != -1)
|
||||
{
|
||||
var headerView = [_tableView._tableColumns[_pressedColumn] headerView];
|
||||
[headerView unsetThemeState:CPThemeStatePressed];
|
||||
[headerView unsetThemeState:CPThemeStateHighlighted];
|
||||
}
|
||||
|
||||
|
||||
if (column != -1)
|
||||
{
|
||||
var headerView = [_tableView._tableColumns[column] headerView];
|
||||
[headerView setThemeState:CPThemeStatePressed];
|
||||
[headerView setThemeState:CPThemeStateHighlighted];
|
||||
}
|
||||
|
||||
|
||||
_pressedColumn = column;
|
||||
}
|
||||
|
||||
- (void)mouseDown:(CPEvent)theEvent
|
||||
{
|
||||
var mouseLocation = [self convertPoint:[theEvent locationInWindow] fromView:nil],
|
||||
clickedColumn = [self columnAtPoint:mouseLocation];
|
||||
|
||||
// should we send column -1 ?
|
||||
[_tableView _sendDelegateDidMouseDownInHeader:clickedColumn];
|
||||
|
||||
var resizeLocation = CGPointMake(mouseLocation.x - 5, mouseLocation.y),
|
||||
resizedColumn = [self columnAtPoint:resizeLocation];
|
||||
|
||||
if (resizedColumn == -1)
|
||||
return;
|
||||
|
||||
// 2 different tracking methods: one for resizing/stop-resizing, another one for selection/reordering
|
||||
if ([_tableView allowsColumnResizing]
|
||||
&& CGRectContainsPoint([self _cursorRectForColumn:resizedColumn], mouseLocation))
|
||||
{
|
||||
_resizedColumn = resizedColumn;
|
||||
[_tableView._tableColumns[_resizedColumn] setDisableResizingPosting:YES];
|
||||
[_tableView setDisableAutomaticResizing:YES];
|
||||
[self trackResizeWithEvent:theEvent];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self _setPressedColumn:clickedColumn];
|
||||
[self trackMouseWithEvent:theEvent];
|
||||
}
|
||||
[self trackMouse:theEvent];
|
||||
}
|
||||
|
||||
- (void)trackMouseWithEvent:(CPEvent)theEvent
|
||||
- (void)trackMouse:(CPEvent)theEvent
|
||||
{
|
||||
var type = [theEvent type];
|
||||
|
||||
if (type == CPLeftMouseUp)
|
||||
{
|
||||
var location = [self convertPoint:[theEvent locationInWindow] fromView:nil],
|
||||
clickedColumn = [self columnAtPoint:location];
|
||||
var type = [theEvent type],
|
||||
currentLocation = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
||||
|
||||
[self _setPressedColumn:-1];
|
||||
|
||||
if (clickedColumn != -1)
|
||||
[_tableView _didClickTableColumn:clickedColumn modifierFlags:[theEvent modifierFlags]];
|
||||
|
||||
return;
|
||||
}
|
||||
// Take the right columns resize tracking area into account
|
||||
currentLocation.x -= 5.0;
|
||||
|
||||
[CPApp setTarget:self selector:@selector(trackMouseWithEvent:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask | CPLeftMouseDownMask untilDate:nil inMode:nil dequeue:YES];
|
||||
}
|
||||
|
||||
- (void)trackResizeWithEvent:(CPEvent)anEvent
|
||||
{
|
||||
var location = [self convertPoint:[anEvent locationInWindow] fromView:nil],
|
||||
tableColumn = [[_tableView tableColumns] objectAtIndex:_resizedColumn],
|
||||
type = [anEvent type];
|
||||
|
||||
if (_lastLocation == nil)
|
||||
_lastLocation = location;
|
||||
|
||||
if (_columnOldWidth == nil)
|
||||
_columnOldWidth = [tableColumn width];
|
||||
var columnIndex = [self columnAtPoint:currentLocation],
|
||||
shouldResize = [self shouldResizeTableColumn:columnIndex at:CPPointMake(currentLocation.x + 5.0, currentLocation.y)];
|
||||
|
||||
if (type === CPLeftMouseUp)
|
||||
{
|
||||
[self _updateResizeCursor:anEvent];
|
||||
|
||||
[tableColumn _postDidResizeNotificationWithOldWidth:_columnOldWidth];
|
||||
[tableColumn setDisableResizingPosting:NO];
|
||||
[_tableView setDisableAutomaticResizing:NO];
|
||||
|
||||
_resizedColumn = -1;
|
||||
_lastLocation = nil;
|
||||
_columnOldWidth = nil;
|
||||
|
||||
return;
|
||||
}
|
||||
else if (type === CPLeftMouseDragged)
|
||||
{
|
||||
var newWidth = [tableColumn width] + location.x - _lastLocation.x;
|
||||
|
||||
if (newWidth < [tableColumn minWidth])
|
||||
[[CPCursor resizeRightCursor] set];
|
||||
else if (newWidth > [tableColumn maxWidth])
|
||||
[[CPCursor resizeLeftCursor] set];
|
||||
if (shouldResize)
|
||||
[self stopResizingTableColumn:_activeColumn at:currentLocation];
|
||||
else if ([self _shouldStopTrackingTableColumn:columnIndex at:currentLocation])
|
||||
{
|
||||
[_tableView _didClickTableColumn:columnIndex modifierFlags:[theEvent modifierFlags]];
|
||||
[self stopTrackingTableColumn:columnIndex at:currentLocation];
|
||||
|
||||
_isTrackingColumn = NO;
|
||||
}
|
||||
|
||||
[self _updateResizeCursor:[CPApp currentEvent]];
|
||||
|
||||
_activeColumn = CPNotFound;
|
||||
return;
|
||||
}
|
||||
|
||||
if (type === CPLeftMouseDown)
|
||||
{
|
||||
if (columnIndex === -1)
|
||||
return;
|
||||
|
||||
_mouseDownLocation = currentLocation;
|
||||
_activeColumn = columnIndex;
|
||||
|
||||
[_tableView _sendDelegateDidMouseDownInHeader:columnIndex];
|
||||
|
||||
if (shouldResize)
|
||||
[self startResizingTableColumn:columnIndex at:currentLocation];
|
||||
else
|
||||
{
|
||||
_tableView._lastColumnShouldSnap = NO;
|
||||
[tableColumn setWidth:newWidth];
|
||||
// FIXME: there has to be a better way to do this...
|
||||
// We should refactor the auto resizing crap.
|
||||
// We need to figure out the exact cocoa behavior here though.
|
||||
_lastLocation = location;
|
||||
[self startTrackingTableColumn:columnIndex at:currentLocation];
|
||||
_isTrackingColumn = YES;
|
||||
}
|
||||
}
|
||||
else if (type === CPLeftMouseDragged)
|
||||
{
|
||||
if (shouldResize)
|
||||
[self continueResizingTableColumn:_activeColumn at:currentLocation];
|
||||
else
|
||||
{
|
||||
if (_activeColumn === columnIndex && CPRectContainsPoint([self headerRectOfColumn:columnIndex], currentLocation))
|
||||
{
|
||||
if (_isTrackingColumn && _pressedColumn !== -1)
|
||||
{
|
||||
if (![self continueTrackingTableColumn:columnIndex at:currentLocation])
|
||||
return; // Stop tracking the column, because it's being dragged
|
||||
} else
|
||||
[self startTrackingTableColumn:columnIndex at:currentLocation];
|
||||
|
||||
[[CPCursor resizeLeftRightCursor] set];
|
||||
[self setNeedsLayout];
|
||||
[self setNeedsDisplay:YES];
|
||||
} else if (_isTrackingColumn && _pressedColumn !== -1)
|
||||
[self stopTrackingTableColumn:_activeColumn at:currentLocation];
|
||||
}
|
||||
}
|
||||
|
||||
[CPApp setTarget:self selector:@selector(trackResizeWithEvent:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
|
||||
_previousTrackingLocation = currentLocation;
|
||||
[CPApp setTarget:self selector:@selector(trackMouse:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
|
||||
}
|
||||
|
||||
- (void)startTrackingTableColumn:(int)aColumnIndex at:(CPPoint)aPoint
|
||||
{
|
||||
[self _setPressedColumn:aColumnIndex];
|
||||
}
|
||||
|
||||
- (BOOL)continueTrackingTableColumn:(int)aColumnIndex at:(CPPoint)aPoint
|
||||
{
|
||||
if ([self _shouldDragTableColumn:aColumnIndex at:aPoint])
|
||||
{
|
||||
var columnRect = [self headerRectOfColumn:aColumnIndex],
|
||||
offset = CPPointMakeZero(),
|
||||
view = [_tableView _dragViewForColumn:aColumnIndex event:[CPApp currentEvent] offset:offset],
|
||||
viewLocation = CPPointMakeZero();
|
||||
|
||||
viewLocation.x = ( CPRectGetMinX(columnRect) + offset.x ) + ( aPoint.x - _mouseDownLocation.x );
|
||||
viewLocation.y = CPRectGetMinY(columnRect) + offset.y;
|
||||
|
||||
[self dragView:view at:viewLocation offset:CPSizeMakeZero() event:[CPApp currentEvent]
|
||||
pasteboard:[CPPasteboard pasteboardWithName:CPDragPboard] source:self slideBack:YES];
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)_shouldStopTrackingTableColumn:(int)aColumnIndex at:(CPPoint)aPoint
|
||||
{
|
||||
return _isTrackingColumn && _activeColumn === aColumnIndex &&
|
||||
CPRectContainsPoint([self headerRectOfColumn:aColumnIndex], aPoint);
|
||||
}
|
||||
|
||||
- (void)stopTrackingTableColumn:(int)aColumnIndex at:(CPPoint)aPoint
|
||||
{
|
||||
[self _setPressedColumn:CPNotFound];
|
||||
[self _updateResizeCursor:[CPApp currentEvent]];
|
||||
}
|
||||
|
||||
- (BOOL)_shouldDragTableColumn:(int)aColumnIndex at:(CPPoint)aPoint
|
||||
{
|
||||
return [_tableView allowsColumnReordering] && ABS(aPoint.x - _mouseDownLocation.x) >= 10.0;
|
||||
}
|
||||
|
||||
- (CPRect)_headerRectOfLastVisibleColumn
|
||||
{
|
||||
var tableColumns = [_tableView tableColumns],
|
||||
columnIndex = [tableColumns count];
|
||||
|
||||
while (columnIndex--)
|
||||
{
|
||||
var tableColumn = [tableColumns objectAtIndex:columnIndex];
|
||||
|
||||
if (![tableColumn isHidden])
|
||||
return [self headerRectOfColumn:columnIndex];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)_constrainDragView:(CPView)theDragView at:(CPPoint)aPoint
|
||||
{
|
||||
var tableColumns = [_tableView tableColumns],
|
||||
lastColumnRect = [self _headerRectOfLastVisibleColumn];
|
||||
activeColumnRect = [self headerRectOfColumn:_activeColumn];
|
||||
dragWindow = [theDragView window],
|
||||
frame = [dragWindow frame];
|
||||
|
||||
// Convert the frame origin from the global coordinate system to the windows' coordinate system
|
||||
frame.origin = [[self window] convertGlobalToBase:frame.origin];
|
||||
// the from the window to the view
|
||||
frame.origin = [self convertPoint:frame.origin fromView:nil];
|
||||
|
||||
// This effectively clamps the value between the minimum and maximum
|
||||
frame.origin.x = MAX(0.0, MIN(CGRectGetMinX(frame), CGRectGetMaxX(lastColumnRect) - CGRectGetWidth(activeColumnRect)));
|
||||
|
||||
// Make sure the column cannot move vertically
|
||||
frame.origin.y = CPRectGetMinY(lastColumnRect);
|
||||
|
||||
// Convert the calculated origin back to the window coordinate system
|
||||
frame.origin = [self convertPoint:frame.origin toView:nil];
|
||||
// Then back to the global coordinate system
|
||||
frame.origin = [[self window] convertBaseToGlobal:frame.origin];
|
||||
|
||||
[dragWindow setFrame:frame];
|
||||
}
|
||||
|
||||
- (void)_moveColumn:(int)aFromIndex toColumn:(int)aToIndex
|
||||
{
|
||||
[_tableView moveColumn:aFromIndex toColumn:aToIndex];
|
||||
_activeColumn = aToIndex;
|
||||
_pressedColumn = _activeColumn;
|
||||
|
||||
[_tableView _setDraggedColumn:_activeColumn];
|
||||
}
|
||||
|
||||
- (void)draggedView:(CPView)aView beganAt:(CPPoint)aPoint
|
||||
{
|
||||
_isDragging = YES;
|
||||
|
||||
[[[[_tableView tableColumns] objectAtIndex:_activeColumn] headerView] setHidden:YES];
|
||||
[_tableView _setDraggedColumn:_activeColumn];
|
||||
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
- (void)draggedView:(CPView)aView movedTo:(CPPoint)aPoint
|
||||
{
|
||||
[self _constrainDragView:aView at:aPoint];
|
||||
|
||||
var dragWindow = [aView window],
|
||||
dragWindowFrame = [dragWindow frame];
|
||||
|
||||
var hoverPoint = CGPointCreateCopy(aPoint);
|
||||
|
||||
if (aPoint.x < _previousTrackingLocation.x)
|
||||
hoverPoint = CGPointMake(CGRectGetMinX(dragWindowFrame), CGRectGetMinY(dragWindowFrame));
|
||||
else if (aPoint.x > _previousTrackingLocation.x)
|
||||
hoverPoint = CGPointMake(CGRectGetMaxX(dragWindowFrame), CGRectGetMinY(dragWindowFrame));
|
||||
|
||||
// Convert the hover point from the global coordinate system to windows' coordinate system
|
||||
hoverPoint = [[self window] convertGlobalToBase:hoverPoint];
|
||||
// then to the view
|
||||
hoverPoint = [self convertPoint:hoverPoint fromView:nil];
|
||||
|
||||
var hoveredColumn = [self columnAtPoint:hoverPoint];
|
||||
|
||||
if (hoveredColumn !== -1)
|
||||
{
|
||||
var columnRect = [self headerRectOfColumn:hoveredColumn],
|
||||
columnCenterPoint = [self convertPoint:CGPointMake(CGRectGetMidX(columnRect), CGRectGetMidY(columnRect)) fromView:self];
|
||||
if (hoveredColumn < _activeColumn && hoverPoint.x < columnCenterPoint.x)
|
||||
[self _moveColumn:_activeColumn toColumn:hoveredColumn];
|
||||
else if (hoveredColumn > _activeColumn && hoverPoint.x > columnCenterPoint.x)
|
||||
[self _moveColumn:_activeColumn toColumn:hoveredColumn];
|
||||
}
|
||||
|
||||
_previousTrackingLocation = aPoint;
|
||||
}
|
||||
|
||||
- (void)draggedView:(CPImage)aView endedAt:(CGPoint)aLocation operation:(CPDragOperation)anOperation
|
||||
{
|
||||
_isDragging = NO;
|
||||
_isTrackingColumn = NO; // We need to do this explicitly because the mouse up section of trackMouse is never reached
|
||||
|
||||
[_tableView _setDraggedColumn:-1];
|
||||
[[[[_tableView tableColumns] objectAtIndex:_activeColumn] headerView] setHidden:NO];
|
||||
[self stopTrackingTableColumn:_activeColumn at:aLocation];
|
||||
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
- (BOOL)shouldResizeTableColumn:(int)aColumnIndex at:(CPPoint)aPoint
|
||||
{
|
||||
if (_isResizing)
|
||||
return YES;
|
||||
|
||||
if (_isTrackingColumn)
|
||||
return NO;
|
||||
|
||||
return [_tableView allowsColumnResizing] && CPRectContainsPoint([self _cursorRectForColumn:aColumnIndex], aPoint);
|
||||
}
|
||||
|
||||
- (void)startResizingTableColumn:(int)aColumnIndex at:(CPPoint)aPoint
|
||||
{
|
||||
_isResizing = YES;
|
||||
|
||||
var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex];
|
||||
|
||||
[tableColumn setDisableResizingPosting:YES];
|
||||
[_tableView setDisableAutomaticResizing:YES];
|
||||
}
|
||||
|
||||
- (void)continueResizingTableColumn:(int)aColumnIndex at:(CPPoint)aPoint
|
||||
{
|
||||
var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex],
|
||||
newWidth = [tableColumn width] + aPoint.x - _previousTrackingLocation.x;
|
||||
|
||||
if (newWidth < [tableColumn minWidth])
|
||||
[[CPCursor resizeRightCursor] set];
|
||||
else if (newWidth > [tableColumn maxWidth])
|
||||
[[CPCursor resizeLeftCursor] set];
|
||||
else
|
||||
{
|
||||
_tableView._lastColumnShouldSnap = NO;
|
||||
[tableColumn setWidth:newWidth];
|
||||
|
||||
[[CPCursor resizeLeftRightCursor] set];
|
||||
[self setNeedsLayout];
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)stopResizingTableColumn:(int)aColumnIndex at:(CPPoint)aPoint
|
||||
{
|
||||
var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex];
|
||||
[tableColumn _postDidResizeNotificationWithOldWidth:_columnOldWidth];
|
||||
[tableColumn setDisableResizingPosting:NO];
|
||||
[_tableView setDisableAutomaticResizing:NO];
|
||||
|
||||
_isResizing = NO;
|
||||
}
|
||||
|
||||
- (void)_updateResizeCursor:(CPEvent)theEvent
|
||||
@@ -347,12 +523,12 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
|
||||
var mouseLocation = [self convertPoint:[theEvent locationInWindow] fromView:nil],
|
||||
mouseOverLocation = CGPointMake(mouseLocation.x - 5, mouseLocation.y),
|
||||
overColumn = [self columnAtPoint:mouseOverLocation];
|
||||
|
||||
|
||||
if (overColumn >= 0 && CGRectContainsPoint([self _cursorRectForColumn:overColumn], mouseLocation))
|
||||
{
|
||||
var tableColumn = [[_tableView tableColumns] objectAtIndex:overColumn],
|
||||
width = [tableColumn width];
|
||||
|
||||
|
||||
if (width == [tableColumn minWidth])
|
||||
[[CPCursor resizeRightCursor] set];
|
||||
else if (width == [tableColumn maxWidth])
|
||||
@@ -364,12 +540,6 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
|
||||
[[CPCursor arrowCursor] set];
|
||||
}
|
||||
|
||||
- (void)viewDidMoveToWindow
|
||||
{
|
||||
//if ([_tableView allowsColumnResizing])
|
||||
// [[self window] setAcceptsMouseMovedEvents:YES];
|
||||
}
|
||||
|
||||
- (void)mouseEntered:(CPEvent)theEvent
|
||||
{
|
||||
[self _updateResizeCursor:theEvent];
|
||||
@@ -390,12 +560,12 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
|
||||
{
|
||||
var tableColumns = [_tableView tableColumns],
|
||||
count = [tableColumns count];
|
||||
|
||||
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var column = [tableColumns objectAtIndex:i],
|
||||
headerView = [column headerView];
|
||||
|
||||
|
||||
var frame = [self headerRectOfColumn:i];
|
||||
frame.size.height -= 0.5;
|
||||
if (i > 0)
|
||||
@@ -403,9 +573,9 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
|
||||
frame.origin.x += 0.5;
|
||||
frame.size.width -= 1;
|
||||
}
|
||||
|
||||
|
||||
[headerView setFrame:frame];
|
||||
|
||||
|
||||
if([headerView superview] != self)
|
||||
[self addSubview:headerView];
|
||||
}
|
||||
@@ -432,43 +602,28 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
|
||||
var columnArrayIndex = 0,
|
||||
columnArrayCount = columnsArray.length,
|
||||
columnMaxX;
|
||||
|
||||
|
||||
CGContextBeginPath(context);
|
||||
for(; columnArrayIndex < columnArrayCount; columnArrayIndex++)
|
||||
{
|
||||
// grab each column rect and add vertical lines
|
||||
var columnIndex = columnsArray[columnArrayIndex],
|
||||
columnToStroke = [self headerRectOfColumn:columnIndex];
|
||||
|
||||
|
||||
columnMaxX = CGRectGetMaxX(columnToStroke);
|
||||
|
||||
|
||||
CGContextMoveToPoint(context, ROUND(columnMaxX) + 0.5, ROUND(CGRectGetMinY(columnToStroke)));
|
||||
CGContextAddLineToPoint(context, ROUND(columnMaxX) + 0.5, ROUND(CGRectGetMaxY(columnToStroke)));
|
||||
}
|
||||
|
||||
|
||||
CGContextClosePath(context);
|
||||
CGContextStrokePath(context);
|
||||
|
||||
/*
|
||||
var maxY = CGRectGetMaxY([self bounds]);
|
||||
// draw normal gradient for remaining space
|
||||
if (supportsCanvasGradient)
|
||||
|
||||
if (_isDragging)
|
||||
{
|
||||
aRect.origin.x = columnMaxX - 0.5;
|
||||
aRect.size.width -= columnMaxX;
|
||||
CGContextBeginPath(context);
|
||||
CGContextAddRect(context, CGRectMake(columnMaxX + 1, 0, CGRectGetMaxX([self bounds]) - columnMaxX, CGRectGetHeight([self bounds])));
|
||||
CGContextClosePath(context);
|
||||
CGContextDrawLinearGradient(context, [_CPTableColumnHeaderView headerGradient], CGPointMake(0,0), CGPointMake(0, maxY - 1),0);
|
||||
}
|
||||
|
||||
// Draw bottom line
|
||||
CGContextBeginPath(context);
|
||||
CGContextMoveToPoint(context, 0, maxY - 0.5);
|
||||
CGContextAddLineToPoint(context, CGRectGetMaxX([self bounds]), maxY - 0.5);
|
||||
CGContextClosePath(context);
|
||||
CGContextStrokePath(context);
|
||||
*/
|
||||
CGContextSetFillColor(context, [CPColor grayColor]);
|
||||
CGContextFillRect(context, [self headerRectOfColumn:_activeColumn])
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -481,12 +636,7 @@ var CPTableHeaderViewTableViewKey = @"CPTableHeaderViewTableViewKey";
|
||||
{
|
||||
if (self = [super initWithCoder:aCoder])
|
||||
{
|
||||
_resizedColumn = -1;
|
||||
_draggedColumn = -1;
|
||||
_pressedColumn = -1;
|
||||
_draggedDistance = 0.0;
|
||||
_lastLocation = nil;
|
||||
_columnOldWidth = nil;
|
||||
[self _init];
|
||||
_tableView = [aCoder decodeObjectForKey:CPTableHeaderViewTableViewKey];
|
||||
}
|
||||
|
||||
@@ -499,5 +649,4 @@ var CPTableHeaderViewTableViewKey = @"CPTableHeaderViewTableViewKey";
|
||||
[aCoder encodeObject:_tableView forKey:CPTableHeaderViewTableViewKey];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@end
|
||||
@@ -67,29 +67,29 @@ var CPTableViewDelegate_selectionShouldChangeInTableView_
|
||||
CPTableViewDelegate_tableViewSelectionIsChanging_ = 1 << 19;
|
||||
|
||||
//CPTableViewDraggingDestinationFeedbackStyles
|
||||
CPTableViewDraggingDestinationFeedbackStyleNone = -1,
|
||||
CPTableViewDraggingDestinationFeedbackStyleRegular = 0,
|
||||
CPTableViewDraggingDestinationFeedbackStyleNone = -1;
|
||||
CPTableViewDraggingDestinationFeedbackStyleRegular = 0;
|
||||
CPTableViewDraggingDestinationFeedbackStyleSourceList = 1;
|
||||
|
||||
//CPTableViewDropOperations
|
||||
CPTableViewDropOn = 0,
|
||||
CPTableViewDropOn = 0;
|
||||
CPTableViewDropAbove = 1;
|
||||
|
||||
// TODO: add docs
|
||||
|
||||
CPTableViewSelectionHighlightStyleNone = -1,
|
||||
CPTableViewSelectionHighlightStyleRegular = 0,
|
||||
CPTableViewSelectionHighlightStyleNone = -1;
|
||||
CPTableViewSelectionHighlightStyleRegular = 0;
|
||||
CPTableViewSelectionHighlightStyleSourceList = 1;
|
||||
|
||||
CPTableViewGridNone = 0;
|
||||
CPTableViewSolidVerticalGridLineMask = 1 << 0;
|
||||
CPTableViewSolidHorizontalGridLineMask = 1 << 1;
|
||||
|
||||
CPTableViewNoColumnAutoresizing = 0,
|
||||
CPTableViewUniformColumnAutoresizingStyle = 1,
|
||||
CPTableViewSequentialColumnAutoresizingStyle = 2,
|
||||
CPTableViewReverseSequentialColumnAutoresizingStyle = 3,
|
||||
CPTableViewLastColumnOnlyAutoresizingStyle = 4,
|
||||
CPTableViewNoColumnAutoresizing = 0;
|
||||
CPTableViewUniformColumnAutoresizingStyle = 1; // FIX ME: This is FUBAR
|
||||
CPTableViewSequentialColumnAutoresizingStyle = 2;
|
||||
CPTableViewReverseSequentialColumnAutoresizingStyle = 3;
|
||||
CPTableViewLastColumnOnlyAutoresizingStyle = 4;
|
||||
CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
|
||||
@@ -194,15 +194,17 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
SEL _doubleAction;
|
||||
unsigned _columnAutoResizingStyle;
|
||||
|
||||
int _lastTrackedRowIndex;
|
||||
CGPoint _originalMouseDownPoint;
|
||||
BOOL _verticalMotionCanDrag;
|
||||
unsigned _destinationDragStyle;
|
||||
BOOL _isSelectingSession;
|
||||
CPIndexSet _draggedRowIndexes;
|
||||
_dropOperationDrawingView _dropOperationFeedbackView;
|
||||
CPDragOperation _dragOperationDefaultMask;
|
||||
int _retargetedDropRow;
|
||||
CPDragOperation _retargetedDropOperation;
|
||||
|
||||
_CPDropOperationDrawingView _dropOperationFeedbackView;
|
||||
CPDragOperation _dragOperationDefaultMask;
|
||||
int _retargetedDropRow;
|
||||
CPDragOperation _retargetedDropOperation;
|
||||
|
||||
BOOL _disableAutomaticResizing @accessors(property=disableAutomaticResizing);
|
||||
BOOL _lastColumnShouldSnap;
|
||||
@@ -210,6 +212,9 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
CPGradient _sourceListActiveGradient;
|
||||
CPColor _sourceListActiveTopLineColor;
|
||||
CPColor _sourceListActiveBottomLineColor;
|
||||
|
||||
int _draggedColumnIndex;
|
||||
|
||||
/*
|
||||
CPGradient _sourceListInactiveGradient;
|
||||
CPColor _sourceListInactiveTopLineColor;
|
||||
@@ -230,7 +235,6 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
_allowsEmptySelection = YES;
|
||||
_allowsColumnSelection = NO;
|
||||
_disableAutomaticResizing = NO;
|
||||
_tableViewFlags = 0;
|
||||
|
||||
//Setting Display Attributes
|
||||
_selectionHighlightStyle = CPTableViewSelectionHighlightStyleRegular;
|
||||
@@ -243,32 +247,17 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
_dirtyTableColumnRangeIndex = CPNotFound;
|
||||
_numberOfHiddenColumns = 0;
|
||||
|
||||
_objectValues = { };
|
||||
_dataViewsForTableColumns = { };
|
||||
_dataViews= [];
|
||||
_numberOfRows = 0;
|
||||
_exposedRows = [CPIndexSet indexSet];
|
||||
_exposedColumns = [CPIndexSet indexSet];
|
||||
_cachedDataViews = { };
|
||||
_intercellSpacing = _CGSizeMake(0.0, 0.0);
|
||||
_rowHeight = 23.0;
|
||||
|
||||
[self setGridColor:[CPColor colorWithHexString:@"dce0e2"]];
|
||||
[self setGridStyleMask:CPTableViewGridNone];
|
||||
|
||||
_headerView = [[CPTableHeaderView alloc] initWithFrame:CGRectMake(0, 0, [self bounds].size.width, _rowHeight)];
|
||||
|
||||
[_headerView setTableView:self];
|
||||
|
||||
_cornerView = [[_CPCornerView alloc] initWithFrame:CGRectMake(0, 0, [CPScroller scrollerWidth], CGRectGetHeight([_headerView frame]))];
|
||||
|
||||
_lastSelectedRow = -1;
|
||||
_selectedColumnIndexes = [CPIndexSet indexSet];
|
||||
_selectedRowIndexes = [CPIndexSet indexSet];
|
||||
_currentHighlightedTableColumn = nil;
|
||||
|
||||
|
||||
_sortDescriptors = [CPArray array];
|
||||
|
||||
|
||||
_draggedRowIndexes = [CPIndexSet indexSet];
|
||||
_verticalMotionCanDrag = YES;
|
||||
_isSelectingSession = NO;
|
||||
@@ -276,16 +265,9 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
_retargetedDropOperation = nil;
|
||||
_dragOperationDefaultMask = nil;
|
||||
_destinationDragStyle = CPTableViewDraggingDestinationFeedbackStyleRegular;
|
||||
_dropOperationFeedbackView = [[_dropOperationDrawingView alloc] initWithFrame:_CGRectMakeZero()];
|
||||
[self addSubview:_dropOperationFeedbackView];
|
||||
[_dropOperationFeedbackView setHidden:YES];
|
||||
[_dropOperationFeedbackView setTableView:self];
|
||||
|
||||
_tableDrawView = [[_CPTableDrawView alloc] initWithTableView:self];
|
||||
[_tableDrawView setBackgroundColor:[CPColor clearColor]];
|
||||
[self addSubview:_tableDrawView];
|
||||
[self setBackgroundColor:[CPColor whiteColor]];
|
||||
[self _init];
|
||||
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -294,9 +276,45 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
// FIX ME: we have a lot of redundent init stuff in initWithFrame: and initWithCoder: we should move it all into here.
|
||||
- (void)_init
|
||||
{
|
||||
_lastColumnShouldSnap = NO;
|
||||
_backgroundColor = [CPColor whiteColor];
|
||||
_tableViewFlags = 0;
|
||||
|
||||
_selectedColumnIndexes = [CPIndexSet indexSet];
|
||||
_selectedRowIndexes = [CPIndexSet indexSet];
|
||||
|
||||
_dropOperationFeedbackView = [[_CPDropOperationDrawingView alloc] initWithFrame:_CGRectMakeZero()];
|
||||
[_dropOperationFeedbackView setTableView:self];
|
||||
|
||||
_lastColumnShouldSnap = NO;
|
||||
|
||||
if (!_alternatingRowBackgroundColors)
|
||||
_alternatingRowBackgroundColors = [[CPColor whiteColor], [CPColor colorWithHexString:@"e4e7ff"]];
|
||||
|
||||
_tableColumnRanges = [];
|
||||
_dirtyTableColumnRangeIndex = 0;
|
||||
_numberOfHiddenColumns = 0;
|
||||
|
||||
_objectValues = { };
|
||||
_dataViewsForTableColumns = { };
|
||||
_dataViews= [];
|
||||
_numberOfRows = 0;
|
||||
_exposedRows = [CPIndexSet indexSet];
|
||||
_exposedColumns = [CPIndexSet indexSet];
|
||||
_cachedDataViews = { };
|
||||
|
||||
_tableDrawView = [[_CPTableDrawView alloc] initWithTableView:self];
|
||||
[_tableDrawView setBackgroundColor:[CPColor clearColor]];
|
||||
[self addSubview:_tableDrawView];
|
||||
|
||||
if (!_headerView)
|
||||
_headerView = [[CPTableHeaderView alloc] initWithFrame:CGRectMake(0, 0, [self bounds].size.width, _rowHeight)];
|
||||
|
||||
[_headerView setTableView:self];
|
||||
|
||||
if (!_cornerView)
|
||||
_cornerView = [[_CPCornerView alloc] initWithFrame:CGRectMake(0, 0, [CPScroller scrollerWidth], CGRectGetHeight([_headerView frame]))];
|
||||
|
||||
_draggedColumnIndex = -1;
|
||||
|
||||
// Gradients for the source list
|
||||
_sourceListActiveGradient = CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [89.0/255.0, 153.0/255.0, 209.0/255.0,1.0, 33.0/255.0, 94.0/255.0, 208.0/255.0,1.0], [0,1], 2);
|
||||
_sourceListActiveTopLineColor = [CPColor colorWithCalibratedRed:(61.0/255.0) green:(123.0/255.0) blue:(218.0/255.0) alpha:1.0];
|
||||
@@ -659,6 +677,15 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)_setDraggedColumn:(int)aColumnIndex
|
||||
{
|
||||
if (_draggedColumnIndex === aColumnIndex)
|
||||
return;
|
||||
|
||||
_draggedColumnIndex = aColumnIndex;
|
||||
|
||||
[self reloadDataForRowIndexes:_exposedRows columnIndexes:[CPIndexSet indexSetWithIndex:aColumnIndex]];
|
||||
}
|
||||
|
||||
/*!
|
||||
Moves the column and heading at a given index to a new given index.
|
||||
@@ -678,15 +705,37 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
else
|
||||
_dirtyTableColumnRangeIndex = MIN(fromIndex, toIndex, _dirtyTableColumnRangeIndex);
|
||||
|
||||
if (toIndex > fromIndex)
|
||||
--toIndex;
|
||||
|
||||
var tableColumn = _tableColumns[fromIndex];
|
||||
|
||||
[_tableColumns removeObjectAtIndex:fromIndex];
|
||||
[_tableColumns insertObject:tableColumn atIndex:toIndex];
|
||||
|
||||
[[self headerView] setNeedsLayout];
|
||||
[[self headerView] setNeedsDisplay:YES];
|
||||
|
||||
[self setNeedsLayout];
|
||||
var rowIndexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self numberOfRows])],
|
||||
columnIndexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(fromIndex, toIndex)];
|
||||
|
||||
[self reloadDataForRowIndexes:rowIndexes columnIndexes:columnIndexes];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)_tableColumnVisibilityDidChange:(CPTableColumn)aColumn
|
||||
{
|
||||
var columnIndex = [[self tableColumns] indexOfObjectIdenticalTo:aColumn];
|
||||
|
||||
if (_dirtyTableColumnRangeIndex < 0)
|
||||
_dirtyTableColumnRangeIndex = columnIndex;
|
||||
else
|
||||
_dirtyTableColumnRangeIndex = MIN(columnIndex, _dirtyTableColumnRangeIndex);
|
||||
|
||||
[[self headerView] setNeedsLayout];
|
||||
[[self headerView] setNeedsDisplay:YES];
|
||||
|
||||
var rowIndexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self numberOfRows])];
|
||||
[self reloadDataForRowIndexes:rowIndexes columnIndexes:[CPIndexSet indexSetWithIndex:columnIndex]];
|
||||
}
|
||||
|
||||
- (CPArray)tableColumns
|
||||
@@ -804,22 +853,22 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
var count = deselectRows.length;
|
||||
while (count--)
|
||||
{
|
||||
var rowIndex = deselectRows[count];
|
||||
var view = dataViewsInTableColumn[rowIndex];
|
||||
[view unsetThemeState:CPThemeStateHighlighted];
|
||||
}
|
||||
|
||||
[self _performSelection:NO forRow:deselectRows[count] context:dataViewsInTableColumn];
|
||||
|
||||
count = selectRows.length;
|
||||
while (count--)
|
||||
{
|
||||
var rowIndex = selectRows[count];
|
||||
var view = dataViewsInTableColumn[rowIndex];
|
||||
[view setThemeState:CPThemeStateHighlighted];
|
||||
}
|
||||
[self _performSelection:YES forRow:selectRows[count] context:dataViewsInTableColumn];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_performSelection:(BOOL)select forRow:(CPInteger)rowIndex context:(id)context
|
||||
{
|
||||
var view = context[rowIndex],
|
||||
selector = select ? @"setThemeState:" : @"unsetThemeState:";
|
||||
|
||||
[view performSelector:CPSelectorFromString(selector) withObject:CPThemeStateSelected];
|
||||
}
|
||||
|
||||
- (void)_updateHighlightWithOldColumns:(CPIndexSet)oldColumns newColumns:(CPIndexSet)newColumns
|
||||
{
|
||||
var firstExposedColumn = [_exposedColumns firstIndex],
|
||||
@@ -847,13 +896,13 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
{
|
||||
var rowIndex = selectRows[i],
|
||||
dataView = dataViewsInTableColumn[rowIndex];
|
||||
[dataView unsetThemeState:CPThemeStateHighlighted];
|
||||
[dataView unsetThemeState:CPThemeStateSelected];
|
||||
}
|
||||
|
||||
if (_headerView)
|
||||
{
|
||||
var headerView = [_tableColumns[columnIndex] headerView];
|
||||
[headerView unsetThemeState:CPThemeStateHighlighted];
|
||||
[headerView unsetThemeState:CPThemeStateSelected];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -868,16 +917,21 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
{
|
||||
var rowIndex = selectRows[i],
|
||||
dataView = dataViewsInTableColumn[rowIndex];
|
||||
[dataView setThemeState:CPThemeStateHighlighted];
|
||||
[dataView setThemeState:CPThemeStateSelected];
|
||||
}
|
||||
if (_headerView)
|
||||
{
|
||||
var headerView = [_tableColumns[columnIndex] headerView];
|
||||
[headerView setThemeState:CPThemeStateHighlighted];
|
||||
[headerView setThemeState:CPThemeStateSelected];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (int)selectedColumn
|
||||
{
|
||||
[_selectedColumnIndexes lastIndex];
|
||||
}
|
||||
|
||||
- (CPIndexSet)selectedColumnIndexes
|
||||
{
|
||||
return _selectedColumnIndexes;
|
||||
@@ -1038,6 +1092,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
if (_dirtyTableColumnRangeIndex < 0)
|
||||
return;
|
||||
|
||||
_numberOfHiddenColumns = 0;
|
||||
|
||||
var index = _dirtyTableColumnRangeIndex,
|
||||
count = NUMBER_OF_COLUMNS(),
|
||||
x = index === 0 ? 0.0 : CPMaxRange(_tableColumnRanges[index - 1]);
|
||||
@@ -1047,7 +1103,10 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
var tableColumn = _tableColumns[index];
|
||||
|
||||
if ([tableColumn isHidden])
|
||||
{
|
||||
_numberOfHiddenColumns += 1;
|
||||
_tableColumnRanges[index] = CPMakeRange(x, 0.0);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
@@ -1068,8 +1127,10 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
- (CGRect)rectOfColumn:(CPInteger)aColumnIndex
|
||||
{
|
||||
aColumnIndex = +aColumnIndex;
|
||||
|
||||
var column = [[self tableColumns] objectAtIndex:aColumnIndex];
|
||||
|
||||
if (aColumnIndex < 0 || aColumnIndex >= NUMBER_OF_COLUMNS())
|
||||
if ([column isHidden] || aColumnIndex < 0 || aColumnIndex >= NUMBER_OF_COLUMNS())
|
||||
return _CGRectMakeZero();
|
||||
|
||||
UPDATE_COLUMN_RANGES_IF_NECESSARY();
|
||||
@@ -1222,68 +1283,63 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
return _CGRectMake(tableColumnRange.location, _CGRectGetMinY(rectOfRow), tableColumnRange.length, _CGRectGetHeight(rectOfRow));
|
||||
}
|
||||
|
||||
//FIX ME: We should refactor this!
|
||||
- (void)resizeWithOldSuperviewSize:(CGSize)aSize
|
||||
{
|
||||
[super resizeWithOldSuperviewSize:aSize];
|
||||
|
||||
|
||||
if (_disableAutomaticResizing)
|
||||
return;
|
||||
|
||||
var mask = _columnAutoResizingStyle;
|
||||
|
||||
if(mask === CPTableViewUniformColumnAutoresizingStyle)
|
||||
{
|
||||
[self _resizeAllColumnUniformlyWithOldSize:aSize];
|
||||
}
|
||||
|
||||
if(mask === CPTableViewLastColumnOnlyAutoresizingStyle)
|
||||
{
|
||||
else if(mask === CPTableViewLastColumnOnlyAutoresizingStyle)
|
||||
[self sizeLastColumnToFit];
|
||||
}
|
||||
else if(mask === CPTableViewFirstColumnOnlyAutoresizingStyle)
|
||||
[self _autoResizeFirstColumn];
|
||||
}
|
||||
|
||||
if(mask === CPTableViewFirstColumnOnlyAutoresizingStyle)
|
||||
{
|
||||
var superview = [self superview];
|
||||
- (void)_autoResizeFirstColumn
|
||||
{
|
||||
var superview = [self superview];
|
||||
|
||||
if (!superview)
|
||||
return;
|
||||
if (!superview)
|
||||
return;
|
||||
|
||||
var superviewSize = [superview bounds].size;
|
||||
var superviewSize = [superview bounds].size;
|
||||
|
||||
UPDATE_COLUMN_RANGES_IF_NECESSARY();
|
||||
UPDATE_COLUMN_RANGES_IF_NECESSARY();
|
||||
|
||||
var count = NUMBER_OF_COLUMNS();
|
||||
var count = NUMBER_OF_COLUMNS(),
|
||||
visColumns = [[CPArray alloc] init],
|
||||
totalWidth = 0,
|
||||
i = 0;
|
||||
|
||||
var visColumns = [[CPArray alloc] init];
|
||||
var totalWidth = 0;
|
||||
for(; i < count; i++)
|
||||
{
|
||||
if(![_tableColumns[i] isHidden])
|
||||
{
|
||||
[visColumns addObject:i];
|
||||
totalWidth += [_tableColumns[i] width];
|
||||
}
|
||||
}
|
||||
|
||||
for(var i=0; i < count; i++)
|
||||
{
|
||||
if(![_tableColumns[i] isHidden])
|
||||
{
|
||||
[visColumns addObject:i];
|
||||
totalWidth += [_tableColumns[i] width];
|
||||
}
|
||||
}
|
||||
count = [visColumns count];
|
||||
|
||||
count = [visColumns count];
|
||||
//if there are rows
|
||||
if (count > 0)
|
||||
{
|
||||
var columnToResize = _tableColumns[visColumns[0]];
|
||||
var newWidth = superviewSize.width - totalWidth;// - [columnToResize width];
|
||||
newWidth += [columnToResize width];
|
||||
newWidth = (newWidth < [columnToResize minWidth]) ? [columnToResize minWidth] : newWidth;
|
||||
newWidth = (newWidth > [columnToResize maxWidth]) ? [columnToResize maxWidth] : newWidth;
|
||||
|
||||
//if there are rows
|
||||
if (count > 0)
|
||||
{
|
||||
var columnToResize = _tableColumns[visColumns[0]];
|
||||
var newWidth = superviewSize.width - totalWidth;// - [columnToResize width];
|
||||
newWidth += [columnToResize width];
|
||||
newWidth = (newWidth < [columnToResize minWidth]) ? [columnToResize minWidth] : newWidth;
|
||||
newWidth = (newWidth > [columnToResize maxWidth]) ? [columnToResize maxWidth] : newWidth;
|
||||
|
||||
[columnToResize setWidth:FLOOR(newWidth)];
|
||||
}
|
||||
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
[columnToResize setWidth:FLOOR(newWidth)];
|
||||
}
|
||||
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)_resizeAllColumnUniformlyWithOldSize:(CGSize)oldSize
|
||||
@@ -1738,10 +1794,10 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
if (_headerView)
|
||||
{
|
||||
if (_currentHighlightedTableColumn != nil)
|
||||
[[_currentHighlightedTableColumn headerView] unsetThemeState:CPThemeStateHighlighted];
|
||||
[[_currentHighlightedTableColumn headerView] unsetThemeState:CPThemeStateSelected];
|
||||
|
||||
if (aTableColumn != nil)
|
||||
[[aTableColumn headerView] setThemeState:CPThemeStateHighlighted];
|
||||
[[aTableColumn headerView] setThemeState:CPThemeStateSelected];
|
||||
}
|
||||
|
||||
_currentHighlightedTableColumn = aTableColumn;
|
||||
@@ -1757,66 +1813,96 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (CPImage)dragImageForRowsWithIndexes:(CPIndexSet)dragRows
|
||||
tableColumns:(CPArray)theTableColumns
|
||||
event:(CPEvent)dragEvent
|
||||
offset:(CPPointPointer)dragImageOffset
|
||||
- (CPImage)dragImageForRowsWithIndexes:(CPIndexSet)dragRows tableColumns:(CPArray)theTableColumns event:(CPEvent)dragEvent offset:(CPPointPointer)dragImageOffset
|
||||
{
|
||||
return [[CPImage alloc] initWithContentsOfFile:@"Frameworks/AppKit/Resources/GenericFile.png" size:CGSizeMake(32,32)];
|
||||
}
|
||||
|
||||
- (CPView)dragViewForRowsWithIndexes:(CPIndexSet)theDraggedRows
|
||||
tableColumns:(CPArray)theTableColumns
|
||||
event:(CPEvent)theDragEvent
|
||||
offset:(CPPoint)dragViewOffset
|
||||
- (CPView)dragViewForRowsWithIndexes:(CPIndexSet)theDraggedRows tableColumns:(CPArray)theTableColumns event:(CPEvent)theDragEvent offset:(CPPointPointer)dragViewOffset
|
||||
{
|
||||
var bounds = [self bounds],
|
||||
view = [[CPView alloc] initWithFrame:bounds];
|
||||
|
||||
[view setBackgroundColor:[CPColor clearColor]];
|
||||
|
||||
[view setAlphaValue:0.7];
|
||||
|
||||
|
||||
// We have to fetch all the data views for the selected rows and columns
|
||||
// After that we can copy these add them to a transparent drag view and use that drag view
|
||||
// to make it appear we are dragging images of those rows (as you would do in regular Cocoa)
|
||||
var firstExposedColumn = [_exposedColumns firstIndex],
|
||||
firstExposedRow = [_exposedRows firstIndex],
|
||||
exposedColumnsLength = [_exposedColumns lastIndex] - firstExposedColumn + 1,
|
||||
exposedRowsLength = [_exposedRows lastIndex] - firstExposedRow + 1,
|
||||
columns = [],
|
||||
rows = [];
|
||||
|
||||
[_exposedColumns getIndexes:columns maxCount:-1 inIndexRange:CPMakeRange(firstExposedColumn, exposedColumnsLength)];
|
||||
[theDraggedRows getIndexes:rows maxCount:-1 inIndexRange:CPMakeRange(firstExposedRow, exposedRowsLength)];
|
||||
|
||||
var columnIndex = [columns count];
|
||||
|
||||
var columnIndex = [theTableColumns count];
|
||||
while (columnIndex--)
|
||||
{
|
||||
var column = columns[columnIndex],
|
||||
tableColumn = [_tableColumns objectAtIndex:column],
|
||||
rowIndex = [rows count];
|
||||
|
||||
while (rowIndex--)
|
||||
var tableColumn = [theTableColumns objectAtIndex:columnIndex],
|
||||
row = [theDraggedRows firstIndex];
|
||||
|
||||
while (row !== CPNotFound)
|
||||
{
|
||||
var row = rows[rowIndex];
|
||||
var dataView = [self _newDataViewForRow:row tableColumn:tableColumn];
|
||||
|
||||
[dataView setBackgroundColor:[CPColor clearColor]];
|
||||
[dataView setFrame:[self frameOfDataViewAtColumn:column row:row]];
|
||||
|
||||
[dataView setFrame:[self frameOfDataViewAtColumn:columnIndex row:row]];
|
||||
[dataView setObjectValue:[self _objectValueForTableColumn:tableColumn row:row]];
|
||||
|
||||
|
||||
[view addSubview:dataView];
|
||||
|
||||
row = [theDraggedRows indexGreaterThanIndex:row];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var dragPoint = [self convertPoint:[theDragEvent locationInWindow] fromView:nil];
|
||||
dragViewOffset.x = CGRectGetWidth(bounds)/2 - dragPoint.x;
|
||||
dragViewOffset.y = CGRectGetHeight(bounds)/2 - dragPoint.y;
|
||||
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
// Fetches all the data views (from the datasource) for the column and it's visible rows
|
||||
// Copy the dataviews add them to a transparent drag view and use that drag view
|
||||
// to make it appear we are dragging images of those rows (as you would do in regular Cocoa)
|
||||
*/
|
||||
- (CPView)_dragViewForColumn:(int)theColumnIndex event:(CPEvent)theDragEvent offset:(CPPointPointer)theDragViewOffset
|
||||
{
|
||||
var dragView = [[CPView alloc] initWithFrame:CPRectMakeZero()];
|
||||
tableColumn = [[self tableColumns] objectAtIndex:theColumnIndex],
|
||||
bounds = CPRectMake(0.0, 0.0, [tableColumn width], CPRectGetHeight([self _exposedRect]) + 23.0),
|
||||
columnRect = [self rectOfColumn:theColumnIndex],
|
||||
headerView = [tableColumn headerView];
|
||||
|
||||
row = [_exposedRows firstIndex];
|
||||
while (row !== CPNotFound)
|
||||
{
|
||||
var dataView = [self _newDataViewForRow:row tableColumn:tableColumn],
|
||||
dataViewFrame = [self frameOfDataViewAtColumn:theColumnIndex row:row];
|
||||
|
||||
// Only one column is ever dragged so we just place the view at
|
||||
dataViewFrame.origin.x = 0.0;
|
||||
|
||||
// Offset by table header height - scroll position
|
||||
dataViewFrame.origin.y = ( CPRectGetMinY(dataViewFrame) - CPRectGetMinY([self _exposedRect]) ) + 23.0;
|
||||
[dataView setFrame:dataViewFrame];
|
||||
|
||||
[dataView setObjectValue:[self _objectValueForTableColumn:tableColumn row:row]];
|
||||
[dragView addSubview:dataView];
|
||||
|
||||
row = [_exposedRows indexGreaterThanIndex:row];
|
||||
}
|
||||
|
||||
// Add the column header view
|
||||
var headerFrame = [headerView frame];
|
||||
headerFrame.origin = CPPointMakeZero();
|
||||
|
||||
columnHeaderView = [[_CPTableColumnHeaderView alloc] initWithFrame:headerFrame];
|
||||
[columnHeaderView setStringValue:[headerView stringValue]];
|
||||
[columnHeaderView setThemeState:[headerView themeState]];
|
||||
[dragView addSubview:columnHeaderView];
|
||||
|
||||
[dragView setBackgroundColor:[CPColor whiteColor]];
|
||||
[dragView setAlphaValue:0.7];
|
||||
[dragView setFrame:bounds];
|
||||
|
||||
return dragView;
|
||||
}
|
||||
|
||||
- (void)setDraggingSourceOperationMask:(CPDragOperation)mask forLocal:(BOOL)isLocal
|
||||
{
|
||||
//ignoral local for the time being since only one capp app can run at a time...
|
||||
@@ -1835,7 +1921,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
var numberOfRows = [self numberOfRows] + 1;
|
||||
var reason = @"Attempt to set dropRow=" + row +
|
||||
" dropOperation=CPTableViewDropOn when [0 - " + numberOfRows + "] is valid range of rows."
|
||||
|
||||
|
||||
[[CPException exceptionWithName:@"Error" reason:reason userInfo:nil] raise];
|
||||
}
|
||||
|
||||
@@ -1891,7 +1977,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
return;
|
||||
|
||||
_sortDescriptors = newSortDescriptors;
|
||||
|
||||
|
||||
[self _sendDataSourceSortDescriptorsDidChange:oldSortDescriptors];
|
||||
}
|
||||
|
||||
@@ -1991,7 +2077,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
// Now clear all the leftovers
|
||||
// FIXME: this could be faster!
|
||||
for (identifier in _cachedDataViews)
|
||||
for (var identifier in _cachedDataViews)
|
||||
{
|
||||
var dataViews = _cachedDataViews[identifier],
|
||||
count = dataViews.length;
|
||||
@@ -2055,10 +2141,14 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
columnsCount = columnArray.length;
|
||||
|
||||
for (; columnIndex < columnsCount; ++columnIndex)
|
||||
{
|
||||
{
|
||||
var column = columnArray[columnIndex],
|
||||
tableColumn = _tableColumns[column],
|
||||
tableColumnUID = [tableColumn UID];
|
||||
tableColumn = _tableColumns[column];
|
||||
|
||||
if ([tableColumn isHidden] || columnIndex === _draggedColumnIndex)
|
||||
continue;
|
||||
|
||||
var tableColumnUID = [tableColumn UID];
|
||||
|
||||
if (!_dataViewsForTableColumns[tableColumnUID])
|
||||
_dataViewsForTableColumns[tableColumnUID] = [];
|
||||
@@ -2078,9 +2168,9 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
[dataView setObjectValue:[self _objectValueForTableColumn:tableColumn row:row]];
|
||||
|
||||
if (isColumnSelected || [self isRowSelected:row])
|
||||
[dataView setThemeState:CPThemeStateHighlighted];
|
||||
[dataView setThemeState:CPThemeStateSelected];
|
||||
else
|
||||
[dataView unsetThemeState:CPThemeStateHighlighted];
|
||||
[dataView unsetThemeState:CPThemeStateSelected];
|
||||
|
||||
if (_implementedDelegateMethods & CPTableViewDelegate_tableView_willDisplayView_forTableColumn_row_)
|
||||
[_delegate tableView:self willDisplayView:dataView forTableColumn:tableColumn row:row];
|
||||
@@ -2149,12 +2239,12 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_commitDataViewObjectValue:(CPTextView)sender
|
||||
- (void)_commitDataViewObjectValue:(id)sender
|
||||
{
|
||||
[_dataSource tableView:self
|
||||
setObjectValue:[sender objectValue]
|
||||
forTableColumn:sender.tableViewEditedColumnObj
|
||||
row:sender.tableViewEditedRowIndex];
|
||||
[_dataSource tableView:self setObjectValue:[sender objectValue] forTableColumn:sender.tableViewEditedColumnObj row:sender.tableViewEditedRowIndex];
|
||||
|
||||
if ([sender respondsToSelector:@selector(setEditable:)])
|
||||
[sender setEditable:NO];
|
||||
}
|
||||
|
||||
- (CPView)_newDataViewForRow:(CPInteger)aRow tableColumn:(CPTableColumn)aTableColumn
|
||||
@@ -2171,6 +2261,9 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
- (void)_enqueueReusableDataView:(CPView)aDataView
|
||||
{
|
||||
if (!aDataView)
|
||||
return;
|
||||
|
||||
// FIXME: yuck!
|
||||
var identifier = aDataView.identifier;
|
||||
|
||||
@@ -2208,20 +2301,21 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
[self drawBackgroundInClipRect:exposedRect];
|
||||
[self drawGridInClipRect:exposedRect];
|
||||
[self highlightSelectionInClipRect:exposedRect];
|
||||
|
||||
if (_draggedColumnIndex === -1)
|
||||
return;
|
||||
|
||||
var context = [[CPGraphicsContext currentContext] graphicsPort],
|
||||
columnRect = [self rectOfColumn:_draggedColumnIndex];
|
||||
|
||||
CGContextSetFillColor(context, [CPColor grayColor]);
|
||||
CGContextFillRect(context, columnRect);
|
||||
}
|
||||
|
||||
- (void)drawBackgroundInClipRect:(CGRect)aRect
|
||||
{
|
||||
if (!_usesAlternatingRowBackgroundColors)
|
||||
{
|
||||
var context = [[CPGraphicsContext currentContext] graphicsPort];
|
||||
|
||||
CGContextSetFillColor(context, _backgroundColor);
|
||||
CGContextFillRect(context, aRect);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var rowColors = [self alternatingRowBackgroundColors],
|
||||
colorCount = [rowColors count];
|
||||
@@ -2360,6 +2454,9 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
- (void)highlightSelectionInClipRect:(CGRect)aRect
|
||||
{
|
||||
if (_selectionHighlightStyle === CPTableViewDraggingDestinationFeedbackStyleNone)
|
||||
return;
|
||||
|
||||
var context = [[CPGraphicsContext currentContext] graphicsPort],
|
||||
indexes = [],
|
||||
rectSelector = @selector(rectOfRow:);
|
||||
@@ -2389,9 +2486,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
if (!count)
|
||||
return;
|
||||
|
||||
var drawGradient = (_selectionHighlightStyle === CPTableViewSelectionHighlightStyleSourceList && [_selectedRowIndexes count] >= 1);
|
||||
|
||||
var deltaHeight = 0.5 * (_gridStyleMask & CPTableViewSolidHorizontalGridLineMask);
|
||||
var drawGradient = (_selectionHighlightStyle === CPTableViewSelectionHighlightStyleSourceList && [_selectedRowIndexes count] >= 1),
|
||||
deltaHeight = 0.5 * (_gridStyleMask & CPTableViewSolidHorizontalGridLineMask);
|
||||
|
||||
CGContextBeginPath(context);
|
||||
while (count--)
|
||||
@@ -2454,10 +2550,9 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
for(var c = firstExposedColumn; c < exposedColumnCount; c++)
|
||||
{
|
||||
//console.log(columnIndexes);
|
||||
var colRect = [self rectOfColumn:exposedColumnIndexes[c]],
|
||||
colX = CGRectGetMaxX(colRect) + 0.5;
|
||||
//console.log(colX);
|
||||
|
||||
CGContextMoveToPoint(context, colX, minY);
|
||||
CGContextAddLineToPoint(context, colX, maxY);
|
||||
}
|
||||
@@ -2581,7 +2676,10 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
{
|
||||
// Prevent CPControl from eating the mouse events when we are in a drag session
|
||||
if (![_draggedRowIndexes count])
|
||||
{
|
||||
[self autoscroll:anEvent];
|
||||
[super trackMouse:anEvent];
|
||||
}
|
||||
else
|
||||
[CPApp sendEvent:anEvent];
|
||||
}
|
||||
@@ -2649,8 +2747,11 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
}
|
||||
|
||||
_isSelectingSession = YES;
|
||||
if(row >= 0)
|
||||
if(row >= 0 && row !== _lastTrackedRowIndex)
|
||||
{
|
||||
_lastTrackedRowIndex = row;
|
||||
[self _updateSelectionWithMouseAtRow:row];
|
||||
}
|
||||
|
||||
if ((_implementedDataSourceMethods & CPTableViewDataSource_tableView_setObjectValue_forTableColumn_row_)
|
||||
&& !_trackingPointMovedOutOfClickSlop)
|
||||
@@ -2760,7 +2861,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
*/
|
||||
- (void)draggingExited:(id)sender
|
||||
{
|
||||
[_dropOperationFeedbackView setHidden:YES];
|
||||
[_dropOperationFeedbackView removeFromSuperview];
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2776,7 +2877,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
_retargetedDropOperation = nil;
|
||||
_retargetedDropRow = nil;
|
||||
_draggedRowIndexes = [CPIndexSet indexSet];
|
||||
[_dropOperationFeedbackView setHidden:YES];
|
||||
[_dropOperationFeedbackView removeFromSuperview];
|
||||
}
|
||||
/*
|
||||
@ignore
|
||||
@@ -2891,14 +2992,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
[_dropOperationFeedbackView setFrame:rect];
|
||||
[_dropOperationFeedbackView setCurrentRow:row];
|
||||
[self addSubview:_dropOperationFeedbackView];
|
||||
|
||||
// FIXME : Maybe we should do this in a timer outside this method.
|
||||
// Problem: we don't know when the scroll ends or when the next -draggingUpdated is called.
|
||||
if (row > 0 && location.y - CGRectGetMinY(exposedClipRect) < _rowHeight)
|
||||
[self scrollRowToVisible:row - 1];
|
||||
else if (row < numberOfRows && CGRectGetMaxY(exposedClipRect) - location.y < _rowHeight)
|
||||
[self scrollRowToVisible:row + 1];
|
||||
|
||||
|
||||
return dragOperation;
|
||||
}
|
||||
|
||||
@@ -2909,7 +3003,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
{
|
||||
// FIX ME: is there anything else that needs to happen here?
|
||||
// actual validation is called in dragginUpdated:
|
||||
[_dropOperationFeedbackView setHidden:YES];
|
||||
[_dropOperationFeedbackView removeFromSuperview];
|
||||
|
||||
return (_implementedDataSourceMethods & CPTableViewDataSource_tableView_validateDrop_proposedRow_proposedDropOperation_);
|
||||
}
|
||||
@@ -3066,7 +3160,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
- (void)keyDown:(CPEvent)anEvent
|
||||
{
|
||||
[self interpretKeyEvents:[CPArray arrayWithObject:anEvent]];
|
||||
[self interpretKeyEvents:[anEvent]];
|
||||
}
|
||||
|
||||
- (void)moveDown:(id)sender
|
||||
@@ -3185,6 +3279,7 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey",
|
||||
CPTableViewGridColorKey = @"CPTableViewGridColorKey",
|
||||
CPTableViewGridStyleMaskKey = @"CPTableViewGridStyleMaskKey",
|
||||
CPTableViewUsesAlternatingBackgroundKey = @"CPTableViewUsesAlternatingBackgroundKey",
|
||||
CPTableViewAlternatingRowColorsKey = @"CPTableViewAlternatingRowColorsKey",
|
||||
CPTableViewHeaderViewKey = @"CPTableViewHeaderViewKey",
|
||||
CPTableViewCornerViewKey = @"CPTableViewCornerViewKey";
|
||||
|
||||
@@ -3203,50 +3298,31 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey",
|
||||
_allowsEmptySelection = [aCoder decodeBoolForKey:CPTableViewEmptySelectionKey];
|
||||
_allowsColumnSelection = [aCoder decodeBoolForKey:CPTableViewColumnSelectionKey];
|
||||
|
||||
_tableViewFlags = 0;
|
||||
|
||||
//Setting Display Attributes
|
||||
_selectionHighlightStyle = CPTableViewSelectionHighlightStyleRegular;
|
||||
|
||||
_usesAlternatingRowBackgroundColors = [aCoder decodeBoolForKey:CPTableViewUsesAlternatingBackgroundKey];
|
||||
[self setAlternatingRowBackgroundColors:[[CPColor whiteColor], [CPColor colorWithHexString:@"e4e7ff"]]];
|
||||
|
||||
_tableColumns = [aCoder decodeObjectForKey:CPTableViewTableColumnsKey];
|
||||
_tableColumns = [aCoder decodeObjectForKey:CPTableViewTableColumnsKey] || [];
|
||||
[_tableColumns makeObjectsPerformSelector:@selector(setTableView:) withObject:self];
|
||||
|
||||
_tableColumnRanges = [];
|
||||
_dirtyTableColumnRangeIndex = 0;
|
||||
_numberOfHiddenColumns = 0;
|
||||
|
||||
_objectValues = { };
|
||||
_dataViewsForTableColumns = { };
|
||||
_dataViews= [];
|
||||
_numberOfRows = 0;
|
||||
_exposedRows = [CPIndexSet indexSet];
|
||||
_exposedColumns = [CPIndexSet indexSet];
|
||||
_cachedDataViews = { };
|
||||
_rowHeight = [aCoder decodeFloatForKey:CPTableViewRowHeightKey];
|
||||
|
||||
if ([aCoder containsValueForKey:CPTableViewIntercellSpacingKey])
|
||||
_intercellSpacing = [aCoder decodeSizeForKey:CPTableViewIntercellSpacingKey];
|
||||
if ([aCoder containsValueForKey:CPTableViewRowHeightKey])
|
||||
_rowHeight = [aCoder decodeFloatForKey:CPTableViewRowHeightKey];
|
||||
else
|
||||
_intercellSpacing = _CGSizeMake(0.0, 0.0);
|
||||
_rowHeight = 23.0;
|
||||
|
||||
_intercellSpacing = [aCoder decodeSizeForKey:CPTableViewIntercellSpacingKey] || _CGSizeMake(0.0, 0.0);
|
||||
|
||||
_gridColor = [aCoder decodeObjectForKey:CPTableViewGridColorKey] || [CPColor grayColor];
|
||||
_gridStyleMask = [aCoder decodeIntForKey:CPTableViewGridStyleMaskKey] || CPTableViewGridNone;
|
||||
|
||||
_alternatingRowBackgroundColors = [aCoder decodeObjectForKey:CPTableViewAlternatingRowColorsKey];
|
||||
_usesAlternatingRowBackgroundColors = [aCoder decodeObjectForKey:CPTableViewUsesAlternatingBackgroundKey]
|
||||
|
||||
_headerView = [aCoder decodeObjectForKey:CPTableViewHeaderViewKey];
|
||||
_cornerView = [aCoder decodeObjectForKey:CPTableViewCornerViewKey];
|
||||
|
||||
_selectedColumnIndexes = [CPIndexSet indexSet];
|
||||
_selectedRowIndexes = [CPIndexSet indexSet];
|
||||
|
||||
_dataSource = [aCoder decodeObjectForKey:CPTableViewDataSourceKey];
|
||||
_delegate = [aCoder decodeObjectForKey:CPTableViewDelegateKey];
|
||||
|
||||
_tableDrawView = [[_CPTableDrawView alloc] initWithTableView:self];
|
||||
[_tableDrawView setBackgroundColor:[CPColor clearColor]];
|
||||
[self addSubview:_tableDrawView];
|
||||
[self _init];
|
||||
|
||||
[self viewWillMoveToSuperview:[self superview]];
|
||||
@@ -3277,6 +3353,7 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey",
|
||||
[aCoder encodeInt:_gridStyleMask forKey:CPTableViewGridStyleMaskKey];
|
||||
|
||||
[aCoder encodeBool:_usesAlternatingRowBackgroundColors forKey:CPTableViewUsesAlternatingBackgroundKey];
|
||||
[aCoder encodeObject:_alternatingRowBackgroundColors forKey:CPTableViewAlternatingRowColorsKey]
|
||||
|
||||
[aCoder encodeObject:_cornerView forKey:CPTableViewCornerViewKey];
|
||||
[aCoder encodeObject:_headerView forKey:CPTableViewHeaderViewKey];
|
||||
@@ -3321,16 +3398,17 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey",
|
||||
|
||||
@end
|
||||
|
||||
@implementation _dropOperationDrawingView : CPView
|
||||
@implementation _CPDropOperationDrawingView : CPView
|
||||
{
|
||||
unsigned dropOperation @accessors;
|
||||
CPTableView tableView @accessors;
|
||||
int currentRow @accessors;
|
||||
BOOL isBlinking @accessors;
|
||||
}
|
||||
|
||||
- (void)drawRect:(CGRect)aRect
|
||||
{
|
||||
if(tableView._destinationDragStyle === CPTableViewDraggingDestinationFeedbackStyleNone)
|
||||
if(tableView._destinationDragStyle === CPTableViewDraggingDestinationFeedbackStyleNone || isBlinking)
|
||||
return;
|
||||
|
||||
var context = [[CPGraphicsContext currentContext] graphicsPort];
|
||||
@@ -3396,7 +3474,28 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey",
|
||||
CGContextStrokePath(context);
|
||||
//CGContextStrokeLineSegments(context, [aRect.origin.x + 8, aRect.origin.y + 8, 300 , aRect.origin.y + 8]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (void)blink
|
||||
{
|
||||
if (dropOperation !== CPTableViewDropOn)
|
||||
return;
|
||||
|
||||
isBlinking = YES;
|
||||
|
||||
var showCallback = function() {
|
||||
objj_msgSend(self, "setHidden:", NO)
|
||||
isBlinking = NO;
|
||||
}
|
||||
|
||||
var hideCallback = function() {
|
||||
objj_msgSend(self, "setHidden:", YES)
|
||||
isBlinking = YES;
|
||||
}
|
||||
|
||||
objj_msgSend(self, "setHidden:", YES);
|
||||
[CPTimer scheduledTimerWithTimeInterval:0.1 callback:showCallback repeats:NO];
|
||||
[CPTimer scheduledTimerWithTimeInterval:0.19 callback:hideCallback repeats:NO];
|
||||
[CPTimer scheduledTimerWithTimeInterval:0.27 callback:showCallback repeats:NO];
|
||||
}
|
||||
@end
|
||||
|
||||
@@ -813,7 +813,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
if (![CPPlatform isBrowser])
|
||||
{
|
||||
[self copy:sender];
|
||||
[self deleteBackwards:sender];
|
||||
[self deleteBackward:sender];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -826,7 +826,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
if (![[pasteboard types] containsObject:CPStringPboardType])
|
||||
return;
|
||||
|
||||
[self deleteBackwards:sender];
|
||||
[self deleteBackward:sender];
|
||||
|
||||
var selectedRange = [self selectedRange],
|
||||
stringValue = [self stringValue],
|
||||
@@ -912,7 +912,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
[self selectText:sender];
|
||||
}
|
||||
|
||||
- (void)deleteBackwards:(id)sender
|
||||
- (void)deleteBackward:(id)sender
|
||||
{
|
||||
var selectedRange = [self selectedRange],
|
||||
stringValue = [self stringValue],
|
||||
@@ -997,7 +997,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
return bounds;
|
||||
}
|
||||
|
||||
- (CGRect)bezelRectForBounds:(CFRect)bounds
|
||||
- (CGRect)bezelRectForBounds:(CGRect)bounds
|
||||
{
|
||||
var bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"];
|
||||
|
||||
@@ -1087,6 +1087,22 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)takeValueFromKeyPath:(CPString)aKeyPath ofObjects:(CPArray)objects
|
||||
{
|
||||
var count = objects.length,
|
||||
value = [objects[0] valueForKeyPath:aKeyPath];
|
||||
|
||||
[self setStringValue:value];
|
||||
[self setPlaceholderString:@""];
|
||||
|
||||
while (count-- > 1)
|
||||
if (value !== [objects[count] valueForKeyPath:aKeyPath])
|
||||
{
|
||||
[self setPlaceholderString:@"Multiple Values"];
|
||||
[self setStringValue:@""];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var secureStringForString = function(aString)
|
||||
|
||||
@@ -449,6 +449,9 @@ CPToolbarItemVisibilityPriorityUser
|
||||
|
||||
- (void)validate
|
||||
{
|
||||
var action = [self action],
|
||||
target = [self target];
|
||||
|
||||
// View items do not do any target-action analysis.
|
||||
if (_view)
|
||||
{
|
||||
@@ -458,13 +461,9 @@ CPToolbarItemVisibilityPriorityUser
|
||||
return;
|
||||
}
|
||||
|
||||
var action = [self action];
|
||||
|
||||
if (!action)
|
||||
return [self setEnabled:NO];
|
||||
|
||||
var target = [self target];
|
||||
|
||||
if (target && ![target respondsToSelector:action])
|
||||
return [self setEnabled:NO];
|
||||
|
||||
|
||||
@@ -94,7 +94,8 @@ var DOMElementPrototype = nil,
|
||||
BackgroundTrivialColor = 0,
|
||||
BackgroundVerticalThreePartImage = 1,
|
||||
BackgroundHorizontalThreePartImage = 2,
|
||||
BackgroundNinePartImage = 3;
|
||||
BackgroundNinePartImage = 3,
|
||||
BackgroundTransparentColor = 4;
|
||||
#endif
|
||||
|
||||
var CPViewFlags = { },
|
||||
@@ -139,6 +140,7 @@ var CPViewFlags = { },
|
||||
|
||||
BOOL _isHidden;
|
||||
BOOL _hitTests;
|
||||
BOOL _clipsToBounds;
|
||||
|
||||
BOOL _postsFrameChangedNotifications;
|
||||
BOOL _postsBoundsChangedNotifications;
|
||||
@@ -243,6 +245,11 @@ var CPViewFlags = { },
|
||||
return [CPSet setWithObjects:@"boundsOrigin", @"boundsSize"];
|
||||
}
|
||||
|
||||
+ (CPMenu)defaultMenu
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
return [self initWithFrame:CGRectMakeZero()];
|
||||
@@ -272,6 +279,7 @@ var CPViewFlags = { },
|
||||
|
||||
_autoresizingMask = CPViewNotSizable;
|
||||
_autoresizesSubviews = YES;
|
||||
_clipsToBounds = YES;
|
||||
|
||||
_opacity = 1.0;
|
||||
_isHidden = NO;
|
||||
@@ -668,7 +676,7 @@ var CPViewFlags = { },
|
||||
return _tag;
|
||||
}
|
||||
|
||||
- (void)viewWithTag:(CPInteger)aTag
|
||||
- (CPView)viewWithTag:(CPInteger)aTag
|
||||
{
|
||||
if ([self tag] == aTag)
|
||||
return self;
|
||||
@@ -830,28 +838,33 @@ var CPViewFlags = { },
|
||||
|
||||
if (_backgroundType !== BackgroundTrivialColor)
|
||||
{
|
||||
var images = [[_backgroundColor patternImage] imageSlices];
|
||||
|
||||
if (_backgroundType === BackgroundVerticalThreePartImage)
|
||||
if (_backgroundType === BackgroundTransparentColor)
|
||||
{
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], size.width, size.height - _DOMImageSizes[0].height - _DOMImageSizes[2].height);
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[0], size.width, size.height);
|
||||
}
|
||||
|
||||
else if (_backgroundType === BackgroundHorizontalThreePartImage)
|
||||
else
|
||||
{
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], size.width - _DOMImageSizes[0].width - _DOMImageSizes[2].width, size.height);
|
||||
}
|
||||
var images = [[_backgroundColor patternImage] imageSlices];
|
||||
|
||||
else if (_backgroundType === BackgroundNinePartImage)
|
||||
{
|
||||
var width = size.width - _DOMImageSizes[0].width - _DOMImageSizes[2].width,
|
||||
height = size.height - _DOMImageSizes[0].height - _DOMImageSizes[6].height;
|
||||
if (_backgroundType === BackgroundVerticalThreePartImage)
|
||||
{
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], size.width, size.height - _DOMImageSizes[0].height - _DOMImageSizes[2].height);
|
||||
}
|
||||
else if (_backgroundType === BackgroundHorizontalThreePartImage)
|
||||
{
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], size.width - _DOMImageSizes[0].width - _DOMImageSizes[2].width, size.height);
|
||||
}
|
||||
else if (_backgroundType === BackgroundNinePartImage)
|
||||
{
|
||||
var width = size.width - _DOMImageSizes[0].width - _DOMImageSizes[2].width,
|
||||
height = size.height - _DOMImageSizes[0].height - _DOMImageSizes[6].height;
|
||||
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], width, _DOMImageSizes[0].height);
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[3], _DOMImageSizes[3].width, height);
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[4], width, height);
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[5], _DOMImageSizes[5].width, height);
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[7], width, _DOMImageSizes[7].height);
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], width, _DOMImageSizes[0].height);
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[3], _DOMImageSizes[3].width, height);
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[4], width, height);
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[5], _DOMImageSizes[5].width, height);
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[7], width, _DOMImageSizes[7].height);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1183,6 +1196,23 @@ var CPViewFlags = { },
|
||||
return _isHidden;
|
||||
}
|
||||
|
||||
- (void)setClipsToBounds:(BOOL)shouldClip
|
||||
{
|
||||
if (_clipsToBounds === shouldClip)
|
||||
return;
|
||||
|
||||
_clipsToBounds = shouldClip;
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
_DOMElement.style.overflow = _clipsToBounds ? "hidden" : "visible";
|
||||
#endif
|
||||
}
|
||||
|
||||
- (BOOL)clipsToBounds
|
||||
{
|
||||
return _clipsToBounds;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the opacity of the receiver. The value must be in the range of 0.0 to 1.0, where 0.0 is
|
||||
completely transparent and 1.0 is completely opaque.
|
||||
@@ -1199,7 +1229,7 @@ var CPViewFlags = { },
|
||||
|
||||
if (CPFeatureIsCompatible(CPOpacityRequiresFilterFeature))
|
||||
{
|
||||
if (anAlphaValue == 1.0)
|
||||
if (anAlphaValue === 1.0)
|
||||
try { _DOMElement.style.removeAttribute("filter") } catch (anException) { }
|
||||
else
|
||||
_DOMElement.style.filter = "alpha(opacity=" + anAlphaValue * 100 + ")";
|
||||
@@ -1309,6 +1339,22 @@ var CPViewFlags = { },
|
||||
[super mouseDown:anEvent];
|
||||
}
|
||||
|
||||
- (void)rightMouseDown:(CPEvent)anEvent
|
||||
{
|
||||
var menu = [self menuForEvent:anEvent];
|
||||
if (menu)
|
||||
[CPMenu popUpContextMenu:menu withEvent:anEvent forView:self];
|
||||
else if ([[self nextResponder] isKindOfClass:CPView])
|
||||
[super rightMouseDown:anEvent];
|
||||
else
|
||||
[[[anEvent window] platformWindow] _propagateContextMenuDOMEvent:YES];
|
||||
}
|
||||
|
||||
- (CPMenu)menuForEvent:(CPEvent)anEvent
|
||||
{
|
||||
return [self menu] || [[self class] defaultMenu];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the background color of the receiver.
|
||||
@param aColor the new color for the receiver's background
|
||||
@@ -1317,56 +1363,72 @@ var CPViewFlags = { },
|
||||
{
|
||||
if (_backgroundColor == aColor)
|
||||
return;
|
||||
|
||||
|
||||
_backgroundColor = aColor;
|
||||
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
var patternImage = [_backgroundColor patternImage],
|
||||
colorExists = _backgroundColor && ([_backgroundColor patternImage] || [_backgroundColor alphaComponent] > 0.0),
|
||||
colorHasAlpha = colorExists && [_backgroundColor alphaComponent] < 1.0,
|
||||
supportsRGBA = CPFeatureIsCompatible(CPCSSRGBAFeature),
|
||||
colorNeedsDOMElement = colorHasAlpha && !supportsRGBA,
|
||||
amount = 0;
|
||||
|
||||
|
||||
if ([patternImage isThreePartImage])
|
||||
{
|
||||
_backgroundType = [patternImage isVertical] ? BackgroundVerticalThreePartImage : BackgroundHorizontalThreePartImage;
|
||||
|
||||
amount = 3 - _DOMImageParts.length;
|
||||
}
|
||||
else if ([patternImage isNinePartImage])
|
||||
{
|
||||
_backgroundType = BackgroundNinePartImage;
|
||||
|
||||
amount = 9 - _DOMImageParts.length;
|
||||
amount = 9 - _DOMImageParts.length;
|
||||
}
|
||||
else
|
||||
{
|
||||
_backgroundType = BackgroundTrivialColor;
|
||||
|
||||
amount = 0 - _DOMImageParts.length;
|
||||
_backgroundType = colorNeedsDOMElement ? BackgroundTransparentColor : BackgroundTrivialColor;
|
||||
amount = (colorNeedsDOMElement ? 1 : 0) - _DOMImageParts.length;
|
||||
}
|
||||
|
||||
if (amount > 0)
|
||||
{
|
||||
while (amount--)
|
||||
{
|
||||
var DOMElement = DOMElementPrototype.cloneNode(false);
|
||||
|
||||
|
||||
DOMElement.style.zIndex = -1000;
|
||||
|
||||
|
||||
_DOMImageParts.push(DOMElement);
|
||||
_DOMElement.appendChild(DOMElement);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
amount = -amount;
|
||||
|
||||
while (amount--)
|
||||
_DOMElement.removeChild(_DOMImageParts.pop());
|
||||
}
|
||||
|
||||
if (_backgroundType == BackgroundTrivialColor)
|
||||
|
||||
// Opera doesn't like DOM properties set to nil.
|
||||
// https://trac.280north.com/ticket/7
|
||||
_DOMElement.style.background = _backgroundColor ? [_backgroundColor cssString] : "";
|
||||
|
||||
|
||||
if (_backgroundType === BackgroundTrivialColor || _backgroundType === BackgroundTransparentColor)
|
||||
{
|
||||
var colorCSS = colorExists ? [_backgroundColor cssString] : "";
|
||||
|
||||
if (colorNeedsDOMElement)
|
||||
{
|
||||
_DOMElement.style.background = "";
|
||||
_DOMImageParts[0].style.background = [_backgroundColor cssString];
|
||||
|
||||
if (CPFeatureIsCompatible(CPOpacityRequiresFilterFeature))
|
||||
_DOMImageParts[0].style.filter = "alpha(opacity=" + [_backgroundColor alphaComponent] * 100 + ")";
|
||||
else
|
||||
_DOMImageParts[0].style.opacity = [_backgroundColor alphaComponent];
|
||||
|
||||
var size = [self bounds].size;
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[0], size.width, size.height);
|
||||
}
|
||||
else
|
||||
_DOMElement.style.background = colorCSS;
|
||||
}
|
||||
else
|
||||
{
|
||||
var slices = [patternImage imageSlices],
|
||||
@@ -1377,23 +1439,31 @@ var CPViewFlags = { },
|
||||
{
|
||||
var image = slices[count],
|
||||
size = _DOMImageSizes[count] = image ? [image size] : _CGSizeMakeZero();
|
||||
|
||||
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[count], size.width, size.height);
|
||||
|
||||
_DOMImageParts[count].style.background = image ? "url(\"" + [image filename] + "\")" : "";
|
||||
|
||||
if (!supportsRGBA)
|
||||
{
|
||||
if (CPFeatureIsCompatible(CPOpacityRequiresFilterFeature))
|
||||
try { _DOMImageParts[count].style.removeAttribute("filter") } catch (anException) { }
|
||||
else
|
||||
_DOMImageParts[count].style.opacity = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (_backgroundType == BackgroundNinePartImage)
|
||||
{
|
||||
var width = frameSize.width - _DOMImageSizes[0].width - _DOMImageSizes[2].width,
|
||||
height = frameSize.height - _DOMImageSizes[0].height - _DOMImageSizes[6].height;
|
||||
|
||||
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], width, _DOMImageSizes[0].height);
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[3], _DOMImageSizes[3].width, height);
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[4], width, height);
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[5], _DOMImageSizes[5].width, height);
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[7], width, _DOMImageSizes[7].height);
|
||||
|
||||
|
||||
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[0], NULL, 0.0, 0.0);
|
||||
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[1], NULL, _DOMImageSizes[0].width, 0.0);
|
||||
CPDOMDisplayServerSetStyleRightTop(_DOMImageParts[2], NULL, 0.0, 0.0);
|
||||
@@ -1407,7 +1477,7 @@ var CPViewFlags = { },
|
||||
else if (_backgroundType == BackgroundVerticalThreePartImage)
|
||||
{
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], frameSize.width, frameSize.height - _DOMImageSizes[0].height - _DOMImageSizes[2].height);
|
||||
|
||||
|
||||
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[0], NULL, 0.0, 0.0);
|
||||
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[1], NULL, 0.0, _DOMImageSizes[0].height);
|
||||
CPDOMDisplayServerSetStyleLeftBottom(_DOMImageParts[2], NULL, 0.0, 0.0);
|
||||
@@ -1415,7 +1485,7 @@ var CPViewFlags = { },
|
||||
else if (_backgroundType == BackgroundHorizontalThreePartImage)
|
||||
{
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], frameSize.width - _DOMImageSizes[0].width - _DOMImageSizes[2].width, frameSize.height);
|
||||
|
||||
|
||||
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[0], NULL, 0.0, 0.0);
|
||||
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[1], NULL, _DOMImageSizes[0].width, 0.0);
|
||||
CPDOMDisplayServerSetStyleRightTop(_DOMImageParts[2], NULL, 0.0, 0.0);
|
||||
|
||||
@@ -69,11 +69,13 @@ CPWebViewScrollNative = 2;
|
||||
|
||||
CPString _url;
|
||||
CPString _html;
|
||||
|
||||
|
||||
Function _loadCallback;
|
||||
|
||||
|
||||
int _scrollMode;
|
||||
CGSize _scrollSize;
|
||||
|
||||
int _loadHTMLStringTimer;
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CPRect)frameRect frameName:(CPString)frameName groupName:(CPString)groupName
|
||||
@@ -110,6 +112,7 @@ CPWebViewScrollNative = 2;
|
||||
_iframe.style.width = "100%";
|
||||
_iframe.style.height = "100%";
|
||||
_iframe.style.borderWidth = "0px";
|
||||
_iframe.frameBorder = "0";
|
||||
|
||||
[self setDrawsBackground:YES];
|
||||
|
||||
@@ -171,7 +174,32 @@ CPWebViewScrollNative = 2;
|
||||
[self _resizeWebFrame];
|
||||
}
|
||||
|
||||
- (BOOL)_resizeWebFrame
|
||||
- (void)_attachScrollEventIfNecessary
|
||||
{
|
||||
if (_scrollMode !== CPWebViewScrollAppKit)
|
||||
return;
|
||||
|
||||
var win = null;
|
||||
try { win = [self DOMWindow]; } catch (e) {}
|
||||
|
||||
if (win && win.addEventListener)
|
||||
{
|
||||
var scrollEventHandler = function(anEvent)
|
||||
{
|
||||
var frameBounds = [self bounds],
|
||||
frameCenter = CGPointMake(CGRectGetMidX(frameBounds), CGRectGetMidY(frameBounds)),
|
||||
windowOrigin = [self convertPoint:frameCenter toView:nil],
|
||||
globalOrigin = [[self window] convertBaseToBridge:windowOrigin];
|
||||
|
||||
anEvent._overrideLocation = globalOrigin;
|
||||
[[[self window] platformWindow] scrollEvent:anEvent];
|
||||
};
|
||||
|
||||
win.addEventListener("DOMMouseScroll", scrollEventHandler, false);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_resizeWebFrame
|
||||
{
|
||||
if (_scrollMode === CPWebViewScrollAppKit)
|
||||
{
|
||||
@@ -181,13 +209,14 @@ CPWebViewScrollNative = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
[_frameView setFrameSize:[_scrollView contentSize]];
|
||||
var visibleRect = [_frameView visibleRect];
|
||||
[_frameView setFrameSize:CGSizeMake(CGRectGetMaxX(visibleRect), CGRectGetMaxY(visibleRect))];
|
||||
|
||||
// try to get the document size so we can correctly set the frame
|
||||
var win = null;
|
||||
try { win = [self DOMWindow]; } catch (e) {}
|
||||
|
||||
if (win && win.document)
|
||||
if (win && win.document && win.document.body)
|
||||
{
|
||||
var width = win.document.body.scrollWidth,
|
||||
height = win.document.body.scrollHeight;
|
||||
@@ -203,6 +232,8 @@ CPWebViewScrollNative = 2;
|
||||
|
||||
[_frameView setFrameSize:CGSizeMake(800, 1600)];
|
||||
}
|
||||
|
||||
[_frameView scrollRectToVisible:visibleRect];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -217,7 +248,10 @@ CPWebViewScrollNative = 2;
|
||||
|
||||
- (void)_setScrollMode:(int)aScrollMode
|
||||
{
|
||||
_scrollMode = aScrollMode;
|
||||
if (CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
|
||||
_scrollMode = CPWebViewScrollNative;
|
||||
else
|
||||
_scrollMode = aScrollMode;
|
||||
|
||||
_ignoreLoadStart = YES;
|
||||
_ignoreLoadEnd = YES;
|
||||
@@ -256,6 +290,8 @@ CPWebViewScrollNative = 2;
|
||||
|
||||
[self _setScrollMode:CPWebViewScrollAppKit];
|
||||
|
||||
[_frameView setFrameSize:[_scrollView contentSize]];
|
||||
|
||||
[self _startedLoading];
|
||||
|
||||
_ignoreLoadStart = YES;
|
||||
@@ -293,8 +329,15 @@ CPWebViewScrollNative = 2;
|
||||
// clear the iframe
|
||||
_iframe.src = "";
|
||||
|
||||
if (_loadHTMLStringTimer !== nil)
|
||||
{
|
||||
window.clearTimeout(_loadHTMLStringTimer);
|
||||
_loadHTMLStringTimer = nil;
|
||||
}
|
||||
|
||||
// need to give the browser a chance to reset iframe, otherwise we'll be document.write()-ing the previous document
|
||||
window.setTimeout(function() {
|
||||
_loadHTMLStringTimer = window.setTimeout(function()
|
||||
{
|
||||
var win = [self DOMWindow];
|
||||
|
||||
win.document.write(_html);
|
||||
@@ -315,7 +358,8 @@ CPWebViewScrollNative = 2;
|
||||
- (void)_finishedLoading
|
||||
{
|
||||
[self _resizeWebFrame];
|
||||
|
||||
[self _attachScrollEventIfNecessary];
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPWebViewProgressFinishedNotification object:self];
|
||||
|
||||
if ([_frameLoadDelegate respondsToSelector:@selector(webView:didFinishLoadForFrame:)])
|
||||
|
||||
@@ -372,6 +372,15 @@ CPTexturedBackgroundWindowMask
|
||||
[self setPlatformWindow:[CPPlatformWindow primaryPlatformWindow]];
|
||||
else
|
||||
{
|
||||
// give zero sized borderless bridge windows a default size if we're not in the browser so they show up in NativeHost.
|
||||
if ((aStyleMask & CPBorderlessBridgeWindowMask) && aContentRect.size.width === 0 && aContentRect.size.height === 0)
|
||||
{
|
||||
var visibleFrame = [[[CPScreen alloc] init] visibleFrame];
|
||||
_frame.size.height = MIN(768.0, visibleFrame.size.height);
|
||||
_frame.size.width = MIN(1024.0, visibleFrame.size.width);
|
||||
_frame.origin.x = (visibleFrame.size.width - _frame.size.width) / 2;
|
||||
_frame.origin.y = (visibleFrame.size.height - _frame.size.height) / 2;
|
||||
}
|
||||
[self setPlatformWindow:[[CPPlatformWindow alloc] initWithContentRect:_frame]];
|
||||
[self platformWindow]._only = self;
|
||||
}
|
||||
@@ -472,9 +481,6 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
- (void)awakeFromCib
|
||||
{
|
||||
if (_initialFirstResponder)
|
||||
[self makeFirstResponder:_initialFirstResponder];
|
||||
|
||||
_keyViewLoopIsDirty = ![self _hasKeyViewLoop];
|
||||
}
|
||||
|
||||
@@ -738,6 +744,15 @@ CPTexturedBackgroundWindowMask
|
||||
{
|
||||
[_platformWindow orderFront:self];
|
||||
[_platformWindow order:CPWindowAbove window:self relativeTo:nil];
|
||||
|
||||
if (_firstResponder === self || !_firstResponder)
|
||||
[self makeFirstResponder:[self initialFirstResponder]];
|
||||
|
||||
if (!CPApp._keyWindow)
|
||||
[self makeKeyWindow];
|
||||
|
||||
if (!CPApp._mainWindow)
|
||||
[self makeMainWindow];
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -877,6 +892,23 @@ CPTexturedBackgroundWindowMask
|
||||
return _contentView;
|
||||
}
|
||||
|
||||
/*!
|
||||
Applies an alpha value to the window.
|
||||
@param aValue the alpha value to apply
|
||||
*/
|
||||
- (void)setAlphaValue:(float)aValue
|
||||
{
|
||||
[_windowView setAlphaValue:aValue];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the alpha value of the window.
|
||||
*/
|
||||
- (float)alphaValue
|
||||
{
|
||||
return [_windowView alphaValue];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the window's background color.
|
||||
@param aColor the new color for the background
|
||||
@@ -1161,6 +1193,16 @@ CPTexturedBackgroundWindowMask
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (id)initialFirstResponder
|
||||
{
|
||||
return _initialFirstResponder;
|
||||
}
|
||||
|
||||
- (void)setInitialFirstResponder:(id)aResponder
|
||||
{
|
||||
_initialFirstResponder = aResponder;
|
||||
}
|
||||
|
||||
/*!
|
||||
Attempts to make the \c aResponder the first responder. Before trying
|
||||
to make it the first responder, the receiver will ask the current first responder
|
||||
@@ -1170,7 +1212,7 @@ CPTexturedBackgroundWindowMask
|
||||
*/
|
||||
- (BOOL)makeFirstResponder:(CPResponder)aResponder
|
||||
{
|
||||
if (_firstResponder == aResponder)
|
||||
if (_firstResponder === aResponder)
|
||||
return YES;
|
||||
|
||||
if(![_firstResponder resignFirstResponder])
|
||||
@@ -1331,44 +1373,58 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
case CPScrollWheel: return [[_windowView hitTest:point] scrollWheel:anEvent];
|
||||
|
||||
case CPLeftMouseUp: if (!_leftMouseDownView)
|
||||
return [[_windowView hitTest:point] mouseUp:anEvent];
|
||||
case CPLeftMouseUp:
|
||||
case CPRightMouseUp: var hitTestedView = _leftMouseDownView,
|
||||
selector = type == CPRightMouseUp ? @selector(rightMouseUp:) : @selector(mouseUp:);
|
||||
|
||||
[_leftMouseDownView mouseUp:anEvent]
|
||||
if (!hitTestedView)
|
||||
hitTestedView = [_windowView hitTest:point];
|
||||
|
||||
[hitTestedView performSelector:selector withObject:anEvent];
|
||||
|
||||
_leftMouseDownView = nil;
|
||||
|
||||
return;
|
||||
case CPLeftMouseDown: _leftMouseDownView = [_windowView hitTest:point];
|
||||
case CPLeftMouseDown:
|
||||
case CPRightMouseDown: _leftMouseDownView = [_windowView hitTest:point];
|
||||
|
||||
if (_leftMouseDownView != _firstResponder && [_leftMouseDownView acceptsFirstResponder])
|
||||
[self makeFirstResponder:_leftMouseDownView];
|
||||
|
||||
[CPApp activateIgnoringOtherApps:YES];
|
||||
|
||||
var theWindow = [anEvent window];
|
||||
var theWindow = [anEvent window],
|
||||
selector = type == CPRightMouseDown ? @selector(rightMouseDown:) : @selector(mouseDown:);
|
||||
|
||||
if ([theWindow isKeyWindow] || [theWindow becomesKeyOnlyIfNeeded] && ![_leftMouseDownView needsPanelToBecomeKey])
|
||||
return [_leftMouseDownView mouseDown:anEvent];
|
||||
return [_leftMouseDownView performSelector:selector withObject:anEvent];
|
||||
else
|
||||
{
|
||||
// FIXME: delayed ordering?
|
||||
[self makeKeyAndOrderFront:self];
|
||||
|
||||
if ([_leftMouseDownView acceptsFirstMouse:anEvent])
|
||||
return [_leftMouseDownView mouseDown:anEvent]
|
||||
return [_leftMouseDownView performSelector:selector withObject:anEvent];
|
||||
}
|
||||
break;
|
||||
case CPLeftMouseDragged: if (!_leftMouseDownView)
|
||||
|
||||
case CPLeftMouseDragged:
|
||||
case CPRightMouseDragged: if (!_leftMouseDownView)
|
||||
return [[_windowView hitTest:point] mouseDragged:anEvent];
|
||||
|
||||
return [_leftMouseDownView mouseDragged:anEvent];
|
||||
|
||||
case CPRightMouseUp: return [_rightMouseDownView mouseUp:anEvent];
|
||||
case CPRightMouseDown: _rightMouseDownView = [_windowView hitTest:point];
|
||||
return [_rightMouseDownView mouseDown:anEvent];
|
||||
case CPRightMouseDragged: return [_rightMouseDownView mouseDragged:anEvent];
|
||||
|
||||
var selector;
|
||||
if (type == CPRightMouseDragged)
|
||||
{
|
||||
selector = @selector(rightMouseDragged:)
|
||||
if (![_leftMouseDownView respondsToSelector:selector])
|
||||
selector = nil;
|
||||
}
|
||||
|
||||
if (!selector)
|
||||
selector = @selector(mouseDragged:)
|
||||
|
||||
return [_leftMouseDownView performSelector:selector withObject:anEvent];
|
||||
|
||||
case CPMouseMoved: if (!_acceptsMouseMovedEvents)
|
||||
return;
|
||||
|
||||
@@ -1494,10 +1550,11 @@ CPTexturedBackgroundWindowMask
|
||||
*/
|
||||
- (void)resignKeyWindow
|
||||
{
|
||||
if (_firstResponder != self && [_firstResponder respondsToSelector:@selector(resignKeyWindow)])
|
||||
if (_firstResponder !== self && [_firstResponder respondsToSelector:@selector(resignKeyWindow)])
|
||||
[_firstResponder resignKeyWindow];
|
||||
|
||||
CPApp._keyWindow = nil;
|
||||
if (CPApp._keyWindow === self)
|
||||
CPApp._keyWindow = nil;
|
||||
|
||||
[[CPNotificationCenter defaultCenter]
|
||||
postNotificationName:CPWindowDidResignKeyNotification
|
||||
@@ -1858,7 +1915,8 @@ CPTexturedBackgroundWindowMask
|
||||
postNotificationName:CPWindowDidResignMainNotification
|
||||
object:self];
|
||||
|
||||
CPApp._mainWindow = nil;
|
||||
if (CPApp._mainWindow === self)
|
||||
CPApp._mainWindow = nil;
|
||||
}
|
||||
|
||||
- (void)_updateMainAndKeyWindows
|
||||
@@ -1866,9 +1924,6 @@ CPTexturedBackgroundWindowMask
|
||||
var allWindows = [CPApp orderedWindows],
|
||||
windowCount = [allWindows count];
|
||||
|
||||
if (!windowCount)
|
||||
return;
|
||||
|
||||
if ([self isKeyWindow])
|
||||
{
|
||||
var keyWindow = [CPApp keyWindow];
|
||||
@@ -1878,7 +1933,8 @@ CPTexturedBackgroundWindowMask
|
||||
[keyWindow makeKeyWindow];
|
||||
else
|
||||
{
|
||||
var menuWindow = [CPApp mainMenu]._menuWindow;
|
||||
var mainMenu = [CPApp mainMenu],
|
||||
menuWindow = mainMenu ? mainMenu._menuWindow : nil;
|
||||
for (var i = 0; i < windowCount; i++)
|
||||
{
|
||||
var currentWindow = allWindows[i];
|
||||
@@ -1893,11 +1949,10 @@ CPTexturedBackgroundWindowMask
|
||||
}
|
||||
|
||||
if (![CPApp keyWindow])
|
||||
[keyWindow makeKeyWindow];
|
||||
[menuWindow makeKeyWindow];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ([self isMainWindow])
|
||||
{
|
||||
var mainWindow = [CPApp mainWindow];
|
||||
@@ -1907,7 +1962,8 @@ CPTexturedBackgroundWindowMask
|
||||
[mainWindow makeMainWindow];
|
||||
else
|
||||
{
|
||||
var menuWindow = [CPApp mainMenu]._menuWindow;
|
||||
var mainMenu = [CPApp mainMenu],
|
||||
menuWindow = mainMenu ? mainMenu._menuWindow : nil;
|
||||
for (var i = 0; i < windowCount; i++)
|
||||
{
|
||||
var currentWindow = allWindows[i];
|
||||
|
||||
@@ -71,11 +71,12 @@ var _CPToolbarViewBackgroundColor = nil;
|
||||
[self addSubview:_toolbarBackgroundView positioned:CPWindowBelow relativeTo:nil];
|
||||
}
|
||||
|
||||
var frame = CGRectMakeZero();
|
||||
|
||||
frame.origin = CGPointMakeCopy([self toolbarOffset]);
|
||||
var frame = CGRectMakeZero(),
|
||||
toolbarOffset = [self toolbarOffset];
|
||||
|
||||
frame.origin = CGPointMake(toolbarOffset.width, toolbarOffset.height);
|
||||
frame.size = [_toolbarView frame].size;
|
||||
|
||||
|
||||
[_toolbarBackgroundView setFrame:frame];
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ var _CPWindowViewResizeIndicatorImage = nil;
|
||||
CGSize _resizeIndicatorOffset;
|
||||
|
||||
CPView _toolbarView;
|
||||
CGSize _toolbarOffset;
|
||||
// BOOL _isAnimatingToolbar;
|
||||
|
||||
|
||||
@@ -80,8 +81,8 @@ var _CPWindowViewResizeIndicatorImage = nil;
|
||||
if (self)
|
||||
{
|
||||
_styleMask = aStyleMask;
|
||||
_resizeIndicatorOffset = CGSizeMake(0.0, 0.0);
|
||||
_toolbarOffset = CGSizeMake(0.0, 0.0);
|
||||
_resizeIndicatorOffset = CGSizeMakeZero();
|
||||
_toolbarOffset = CGSizeMakeZero();
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -269,7 +270,7 @@ var _CPWindowViewResizeIndicatorImage = nil;
|
||||
|
||||
- (CGSize)toolbarOffset
|
||||
{
|
||||
return CGSizeMakeZero();
|
||||
return _toolbarOffset;
|
||||
}
|
||||
|
||||
- (CPColor)toolbarLabelColor
|
||||
|
||||
@@ -322,25 +322,6 @@
|
||||
return _documents;
|
||||
}
|
||||
|
||||
- (void)setViewController:(CPViewController)aViewController
|
||||
{
|
||||
var containerView = [self viewControllerContainerView] || [[self window] contentView],
|
||||
view = [_viewController view],
|
||||
frame = view ? [view frame] : [containerView bounds];
|
||||
|
||||
[view removeFromSuperview];
|
||||
|
||||
_viewController = aViewController;
|
||||
|
||||
view = [_viewController view];
|
||||
|
||||
if (view)
|
||||
{
|
||||
[view setFrame:frame];
|
||||
[containerView addSubview:view];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setViewControllerContainerView:(CPView)aView
|
||||
{
|
||||
_viewControllerContainerView = aView;
|
||||
|
||||
@@ -171,12 +171,17 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey";
|
||||
|
||||
- (void)connection:(CPURLConnection)aConnection didReceiveData:(CPString)data
|
||||
{
|
||||
// FIXME: Why aren't we getting connection:didFailWithError:
|
||||
if (!data)
|
||||
return [self connection:aConnection didFailWithError:nil];
|
||||
|
||||
_data = [CPData dataWithRawString:data];
|
||||
}
|
||||
|
||||
- (void)connection:(CPURLConnection)aConnection didFailWithError:(CPError)anError
|
||||
{
|
||||
alert("cib: connection failed.");
|
||||
if ([_loadDelegate respondsToSelector:@selector(cibDidFailToLoad:)])
|
||||
[_loadDelegate cibDidFailToLoad:self];
|
||||
|
||||
_loadDelegate = nil;
|
||||
}
|
||||
|
||||
@@ -37,12 +37,12 @@ var CPCibOwner = @"CPCibOwner";
|
||||
|
||||
@implementation CPBundle (CPCibLoading)
|
||||
|
||||
+ (void)loadCibFile:(CPString)anAbsolutePath externalNameTable:(CPDictionary)aNameTable
|
||||
+ (CPCib)loadCibFile:(CPString)anAbsolutePath externalNameTable:(CPDictionary)aNameTable
|
||||
{
|
||||
[[[CPCib alloc] initWithContentsOfURL:anAbsolutePath] instantiateCibWithExternalNameTable:aNameTable];
|
||||
return [[[CPCib alloc] initWithContentsOfURL:anAbsolutePath] instantiateCibWithExternalNameTable:aNameTable];
|
||||
}
|
||||
|
||||
+ (void)loadCibNamed:(CPString)aName owner:(id)anOwner
|
||||
+ (CPCib)loadCibNamed:(CPString)aName owner:(id)anOwner
|
||||
{
|
||||
if (![aName hasSuffix:@".cib"])
|
||||
aName = [aName stringByAppendingString:@".cib"];
|
||||
@@ -51,24 +51,24 @@ var CPCibOwner = @"CPCibOwner";
|
||||
var bundle = anOwner ? [CPBundle bundleForClass:[anOwner class]] : [CPBundle mainBundle],
|
||||
path = [bundle pathForResource:aName];
|
||||
|
||||
[self loadCibFile:path externalNameTable:[CPDictionary dictionaryWithObject:anOwner forKey:CPCibOwner]];
|
||||
return [self loadCibFile:path externalNameTable:[CPDictionary dictionaryWithObject:anOwner forKey:CPCibOwner]];
|
||||
}
|
||||
|
||||
- (void)loadCibFile:(CPString)aFileName externalNameTable:(CPDictionary)aNameTable
|
||||
- (CPCib)loadCibFile:(CPString)aFileName externalNameTable:(CPDictionary)aNameTable
|
||||
{
|
||||
[[[CPCib alloc] initWithContentsOfURL:aFileName] instantiateCibWithExternalNameTable:aNameTable];
|
||||
return [[[CPCib alloc] initWithContentsOfURL:aFileName] instantiateCibWithExternalNameTable:aNameTable];
|
||||
}
|
||||
|
||||
+ (void)loadCibFile:(CPString)anAbsolutePath externalNameTable:(CPDictionary)aNameTable loadDelegate:aDelegate
|
||||
+ (CPCib)loadCibFile:(CPString)anAbsolutePath externalNameTable:(CPDictionary)aNameTable loadDelegate:aDelegate
|
||||
{
|
||||
[[CPCib alloc]
|
||||
return ([[CPCib alloc]
|
||||
initWithContentsOfURL:anAbsolutePath
|
||||
loadDelegate:[[_CPCibLoadDelegate alloc]
|
||||
initWithLoadDelegate:aDelegate
|
||||
externalNameTable:aNameTable]];
|
||||
externalNameTable:aNameTable]]);
|
||||
}
|
||||
|
||||
+ (void)loadCibNamed:(CPString)aName owner:(id)anOwner loadDelegate:(id)aDelegate
|
||||
+ (CPCib)loadCibNamed:(CPString)aName owner:(id)anOwner loadDelegate:(id)aDelegate
|
||||
{
|
||||
if (![aName hasSuffix:@".cib"])
|
||||
aName = [aName stringByAppendingString:@".cib"];
|
||||
@@ -77,17 +77,17 @@ var CPCibOwner = @"CPCibOwner";
|
||||
var bundle = anOwner ? [CPBundle bundleForClass:[anOwner class]] : [CPBundle mainBundle],
|
||||
path = [bundle pathForResource:aName];
|
||||
|
||||
[self loadCibFile:path externalNameTable:[CPDictionary dictionaryWithObject:anOwner forKey:CPCibOwner] loadDelegate:aDelegate];
|
||||
return [self loadCibFile:path externalNameTable:[CPDictionary dictionaryWithObject:anOwner forKey:CPCibOwner] loadDelegate:aDelegate];
|
||||
}
|
||||
|
||||
- (void)loadCibFile:(CPString)aFileName externalNameTable:(CPDictionary)aNameTable loadDelegate:(id)aDelegate
|
||||
- (CPCib)loadCibFile:(CPString)aFileName externalNameTable:(CPDictionary)aNameTable loadDelegate:(id)aDelegate
|
||||
{
|
||||
[[CPCib alloc]
|
||||
return ([[CPCib alloc]
|
||||
initWithCibNamed:aFileName
|
||||
bundle:self
|
||||
loadDelegate:[[_CPCibLoadDelegate alloc]
|
||||
initWithLoadDelegate:aDelegate
|
||||
externalNameTable:aNameTable]];
|
||||
externalNameTable:aNameTable]]);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -118,4 +118,9 @@ var CPCibOwner = @"CPCibOwner";
|
||||
[_loadDelegate cibDidFinishLoading:aCib];
|
||||
}
|
||||
|
||||
- (void)cibDidFailToLoad:(CPCib)aCib
|
||||
{
|
||||
[_loadDelegate cibDidFailToLoad:aCib];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -777,8 +777,7 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
|
||||
@ignore
|
||||
*/
|
||||
+ (void)runLoopUpdateLayers
|
||||
{if (window.oops) {alert(window.latest); objj_debug_print_backtrace();}
|
||||
window.loop = true;
|
||||
{
|
||||
for (UID in CALayerRegisteredRunLoopUpdates)
|
||||
{
|
||||
var layer = CALayerRegisteredRunLoopUpdates[UID],
|
||||
|
||||
@@ -210,7 +210,7 @@ function CGPathAddQuadCurveToPoint(aPath, aTransform, cpx, cpy, x, y)
|
||||
|
||||
if (aTransform)
|
||||
{
|
||||
cp = _CGPointApplyAffineTransform(control, aTransform);
|
||||
cp = _CGPointApplyAffineTransform(cp, aTransform);
|
||||
end = _CGPointApplyAffineTransform(end, aTransform);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ appKitTask = framework ("AppKit", function(appKitTask)
|
||||
appKitTask.setEmail("feedback @nospam@ 280north.com");
|
||||
appKitTask.setSummary("AppKit classes for Cappuccino");
|
||||
appKitTask.setIdentifier("com.280n.AppKit");
|
||||
appKitTask.setVersion("0.8.0");
|
||||
appKitTask.setVersion(getCappuccinoVersion());
|
||||
appKitTask.setLicense(BundleTask.License.LGPL_v2_1);
|
||||
appKitTask.setSources(AppKitFiles);
|
||||
appKitTask.setResources(new FileList("Resources/**/*"));
|
||||
|
||||
@@ -41,11 +41,13 @@ var PrimaryPlatformWindow = NULL;
|
||||
|
||||
DOMElement _DOMBodyElement;
|
||||
DOMElement _DOMFocusElement;
|
||||
DOMElement _DOMEventGuard;
|
||||
|
||||
CPArray _windowLevels;
|
||||
CPDictionary _windowLayers;
|
||||
|
||||
BOOL _mouseIsDown;
|
||||
BOOL _mouseDownIsRightClick;
|
||||
CPWindow _mouseDownWindow;
|
||||
CPTimeInterval _lastMouseUp;
|
||||
CPTimeInterval _lastMouseDown;
|
||||
@@ -72,6 +74,15 @@ var PrimaryPlatformWindow = NULL;
|
||||
return [CPSet set];
|
||||
}
|
||||
|
||||
+ (BOOL)supportsMultipleInstances
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
return !CPBrowserIsEngine(CPInternetExplorerBrowserEngine);
|
||||
#else
|
||||
return NO;
|
||||
#endif
|
||||
}
|
||||
|
||||
+ (CPPlatformWindow)primaryPlatformWindow
|
||||
{
|
||||
return PrimaryPlatformWindow;
|
||||
|
||||
@@ -40,6 +40,16 @@ var screenNeedsInitialization = NO,
|
||||
return;
|
||||
|
||||
screenNeedsInitialization = [CPPlatform isBrowser];
|
||||
|
||||
// We do this here because doing it later breaks IE.
|
||||
if (document.documentElement)
|
||||
document.documentElement.style.overflow = "hidden";
|
||||
|
||||
if ([CPPlatform isBrowser])
|
||||
window.onunload = function()
|
||||
{
|
||||
[CPApp terminate:nil];
|
||||
}
|
||||
}
|
||||
|
||||
+ (BOOL)isBrowser
|
||||
@@ -121,9 +131,6 @@ var screenNeedsInitialization = NO,
|
||||
|
||||
bodyElement.style.overflow = "hidden";
|
||||
|
||||
if (document.documentElement)
|
||||
document.documentElement.style.overflow = "hidden";
|
||||
|
||||
[[CPNotificationCenter defaultCenter]
|
||||
postNotificationName:CPPlatformDidClearBodyElementNotification
|
||||
object:self];
|
||||
|
||||
@@ -22,9 +22,10 @@
|
||||
|
||||
#include "../CoreGraphics/CGGeometry.h"
|
||||
|
||||
var DOMSpanElement = nil,
|
||||
DOMIFrameElement = nil,
|
||||
DefaultFont = nil;
|
||||
var DOMFixedWidthSpanElement = nil,
|
||||
DOMFlexibleWidthSpanElement = nil,
|
||||
DOMIFrameElement = nil,
|
||||
DefaultFont = nil;
|
||||
|
||||
@implementation CPPlatformString : CPBasePlatformString
|
||||
{
|
||||
@@ -37,25 +38,30 @@ var DOMSpanElement = nil,
|
||||
|
||||
+ (void)createDOMElements
|
||||
{
|
||||
var style;
|
||||
|
||||
DOMIFrameElement = document.createElement("iframe");
|
||||
// necessary for Safari caching bug:
|
||||
DOMIFrameElement.name = "iframe_" + FLOOR(RAND() * 10000);
|
||||
DOMIFrameElement.style.position = "absolute";
|
||||
DOMIFrameElement.style.left = "-100px";
|
||||
DOMIFrameElement.style.top = "-100px";
|
||||
DOMIFrameElement.style.width = "1px";
|
||||
DOMIFrameElement.style.height = "1px";
|
||||
DOMIFrameElement.style.borderWidth = "0px";
|
||||
DOMIFrameElement.style.overflow = "hidden";
|
||||
DOMIFrameElement.style.zIndex = 100000000000;
|
||||
DOMIFrameElement.className = "cpdontremove";
|
||||
|
||||
style = DOMIFrameElement.style;
|
||||
style.position = "absolute";
|
||||
style.left = "-100px";
|
||||
style.top = "-100px";
|
||||
style.width = "1px";
|
||||
style.height = "1px";
|
||||
style.borderWidth = "0px";
|
||||
style.overflow = "hidden";
|
||||
style.zIndex = 100000000000;
|
||||
|
||||
var bodyElement = [CPPlatform mainBodyElement];
|
||||
|
||||
bodyElement.appendChild(DOMIFrameElement);
|
||||
|
||||
var DOMIFrameDocument = (DOMIFrameElement.contentDocument || DOMIFrameElement.contentWindow.document);
|
||||
DOMIFrameDocument.write("<html><head></head><body></body></html>");
|
||||
DOMIFrameDocument.write('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'+
|
||||
'<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"><head></head><body></body></html>');
|
||||
DOMIFrameDocument.close();
|
||||
|
||||
// IE needs this wide <div> to prevent unwanted text wrapping:
|
||||
@@ -65,14 +71,39 @@ var DOMSpanElement = nil,
|
||||
|
||||
DOMIFrameDocument.body.appendChild(DOMDivElement);
|
||||
|
||||
DOMSpanElement = DOMIFrameDocument.createElement("span");
|
||||
DOMSpanElement.style.position = "absolute";
|
||||
DOMSpanElement.style.whiteSpace = "pre";
|
||||
DOMSpanElement.style.visibility = "visible";
|
||||
DOMSpanElement.style.padding = "0px";
|
||||
DOMSpanElement.style.margin = "0px";
|
||||
DOMFlexibleWidthSpanElement = DOMIFrameDocument.createElement("span");
|
||||
style = DOMFlexibleWidthSpanElement.style;
|
||||
style.position = "absolute";
|
||||
style.visibility = "visible";
|
||||
style.padding = "0px";
|
||||
style.margin = "0px";
|
||||
style.whiteSpace = "pre";
|
||||
|
||||
DOMDivElement.appendChild(DOMSpanElement);
|
||||
DOMFixedWidthSpanElement = DOMIFrameDocument.createElement("span");
|
||||
style = DOMFixedWidthSpanElement.style;
|
||||
style.display = "block";
|
||||
style.position = "absolute";
|
||||
style.visibility = "visible";
|
||||
style.padding = "0px";
|
||||
style.margin = "0px";
|
||||
style.width = "1px";
|
||||
style.wordWrap = "break-word";
|
||||
try
|
||||
{
|
||||
style.whiteSpace = "pre";
|
||||
style.whiteSpace = "-o-pre-wrap";
|
||||
style.whiteSpace = "-pre-wrap";
|
||||
style.whiteSpace = "-moz-pre-wrap";
|
||||
style.whiteSpace = "pre-wrap";
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
//some versions of IE throw exceptions for unsupported properties.
|
||||
style.whiteSpace = "pre";
|
||||
}
|
||||
|
||||
DOMDivElement.appendChild(DOMFlexibleWidthSpanElement);
|
||||
DOMDivElement.appendChild(DOMFixedWidthSpanElement);
|
||||
}
|
||||
|
||||
+ (CGSize)sizeOfString:(CPString)aString withFont:(CPFont)aFont forWidth:(float)aWidth
|
||||
@@ -88,31 +119,23 @@ var DOMSpanElement = nil,
|
||||
if (!DOMIFrameElement)
|
||||
[self createDOMElements];
|
||||
|
||||
var style = DOMSpanElement.style;
|
||||
|
||||
var span;
|
||||
if (!aWidth)
|
||||
{
|
||||
style.width = "";
|
||||
style.whiteSpace = "pre";
|
||||
}
|
||||
span = DOMFlexibleWidthSpanElement;
|
||||
else
|
||||
{
|
||||
style.width = ROUND(aWidth) + "px";
|
||||
style.wordWrap = "break-word";
|
||||
style.whiteSpace = "-o-pre-wrap";
|
||||
style.whiteSpace = "-pre-wrap";
|
||||
style.whiteSpace = "-moz-pre-wrap";
|
||||
style.whiteSpace = "pre-wrap";
|
||||
span = DOMFixedWidthSpanElement;
|
||||
span.style.width = ROUND(aWidth) + "px";
|
||||
}
|
||||
|
||||
style.font = [aFont cssString];
|
||||
span.style.font = [aFont cssString];
|
||||
|
||||
if (CPFeatureIsCompatible(CPJavascriptInnerTextFeature))
|
||||
DOMSpanElement.innerText = aString;
|
||||
span.innerText = aString;
|
||||
else if (CPFeatureIsCompatible(CPJavascriptTextContentFeature))
|
||||
DOMSpanElement.textContent = aString;
|
||||
span.textContent = aString;
|
||||
|
||||
return _CGSizeMake(DOMSpanElement.clientWidth, DOMSpanElement.clientHeight);
|
||||
return _CGSizeMake(span.clientWidth, span.clientHeight);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -127,7 +127,8 @@ var PlatformWindows = [CPSet set];
|
||||
// Define up here so compressor knows about em.
|
||||
var CPDOMEventGetClickCount,
|
||||
CPDOMEventStop,
|
||||
StopDOMEventPropagation;
|
||||
StopDOMEventPropagation,
|
||||
StopContextMenuDOMEventPropagation;
|
||||
|
||||
//right now we hard code q, w, r and t as keys to propogate
|
||||
//these aren't normal keycodes, they are with modifier key codes
|
||||
@@ -255,6 +256,19 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
|
||||
// Make sure the pastboard element is blurred.
|
||||
_DOMPasteboardElement.blur();
|
||||
|
||||
// Create a full screen div to protect against iframes and other elements from consuming events during tracking
|
||||
// FIXME: multiple windows
|
||||
_DOMEventGuard = theDocument.createElement("div");
|
||||
_DOMEventGuard.style.position = "absolute";
|
||||
_DOMEventGuard.style.top = "0px";
|
||||
_DOMEventGuard.style.left = "0px";
|
||||
_DOMEventGuard.style.width = "100%";
|
||||
_DOMEventGuard.style.height = "100%";
|
||||
_DOMEventGuard.style.zIndex = "999";
|
||||
_DOMEventGuard.style.display = "none";
|
||||
_DOMEventGuard.className = "cpdontremove";
|
||||
_DOMBodyElement.appendChild(_DOMEventGuard);
|
||||
}
|
||||
|
||||
- (void)registerDOMWindow
|
||||
@@ -264,7 +278,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
_DOMBodyElement = theDocument.getElementById("cappuccino-body") || theDocument.body;
|
||||
|
||||
// FIXME: Always do this?
|
||||
if ([CPPlatform supportsDragAndDrop])
|
||||
if (supportsNativeDragAndDrop)
|
||||
_DOMBodyElement.style["-khtml-user-select"] = "none";
|
||||
|
||||
_DOMBodyElement.webkitTouchCallout = "none";
|
||||
@@ -297,6 +311,10 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
mouseEventImplementation = class_getMethodImplementation(theClass, mouseEventSelector),
|
||||
mouseEventCallback = function (anEvent) { mouseEventImplementation(self, nil, anEvent); },
|
||||
|
||||
contextMenuEventSelector = @selector(contextMenuEvent:),
|
||||
contextMenuEventImplementation = class_getMethodImplementation(theClass, contextMenuEventSelector),
|
||||
contextMenuEventCallback = function (anEvent) { return contextMenuEventImplementation(self, nil, anEvent); },
|
||||
|
||||
scrollEventSelector = @selector(scrollEvent:),
|
||||
scrollEventImplementation = class_getMethodImplementation(theClass, scrollEventSelector),
|
||||
scrollEventCallback = function (anEvent) { scrollEventImplementation(self, nil, anEvent); },
|
||||
@@ -320,6 +338,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
theDocument.addEventListener("mouseup", mouseEventCallback, NO);
|
||||
theDocument.addEventListener("mousedown", mouseEventCallback, NO);
|
||||
theDocument.addEventListener("mousemove", mouseEventCallback, NO);
|
||||
theDocument.addEventListener("contextmenu", contextMenuEventCallback, NO);
|
||||
|
||||
theDocument.addEventListener("beforecopy", copyEventCallback, NO);
|
||||
theDocument.addEventListener("beforecut", copyEventCallback, NO);
|
||||
@@ -347,6 +366,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
theDocument.removeEventListener("mouseup", mouseEventCallback, NO);
|
||||
theDocument.removeEventListener("mousedown", mouseEventCallback, NO);
|
||||
theDocument.removeEventListener("mousemove", mouseEventCallback, NO);
|
||||
theDocument.removeEventListener("contextmenu", contextMenuEventCallback, NO);
|
||||
|
||||
theDocument.removeEventListener("keyup", keyEventCallback, NO);
|
||||
theDocument.removeEventListener("keydown", keyEventCallback, NO);
|
||||
@@ -379,6 +399,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
theDocument.attachEvent("onmousedown", mouseEventCallback);
|
||||
theDocument.attachEvent("onmousemove", mouseEventCallback);
|
||||
theDocument.attachEvent("ondblclick", mouseEventCallback);
|
||||
theDocument.attachEvent("oncontextmenu", contextMenuEventCallback);
|
||||
|
||||
theDocument.attachEvent("onkeyup", keyEventCallback);
|
||||
theDocument.attachEvent("onkeydown", keyEventCallback);
|
||||
@@ -401,6 +422,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
theDocument.detachEvent("onmousedown", mouseEventCallback);
|
||||
theDocument.detachEvent("onmousemove", mouseEventCallback);
|
||||
theDocument.detachEvent("ondblclick", mouseEventCallback);
|
||||
theDocument.detachEvent("oncontextmenu", contextMenuEventCallback);
|
||||
|
||||
theDocument.detachEvent("onkeyup", keyEventCallback);
|
||||
theDocument.detachEvent("onkeydown", keyEventCallback);
|
||||
@@ -445,7 +467,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
[PlatformWindows addObject:self];
|
||||
|
||||
// FIXME: cpSetFrame?
|
||||
_DOMWindow.document.write("<html><head></head><body style = 'background-color:transparent;'></body></html>");
|
||||
_DOMWindow.document.write("<!DOCTYPE html><html lang='en'><head></head><body style='background-color:transparent;'></body></html>");
|
||||
_DOMWindow.document.close();
|
||||
|
||||
if (![CPPlatform isBrowser])
|
||||
@@ -492,6 +514,11 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
DOMDragElement.style.left = -_CGRectGetWidth(draggedWindowFrame) + "px";
|
||||
DOMDragElement.style.top = -_CGRectGetHeight(draggedWindowFrame) + "px";
|
||||
|
||||
var parentNode = DOMDragElement.parentNode;
|
||||
|
||||
if (parentNode)
|
||||
parentNode.removeChild(DOMDragElement);
|
||||
|
||||
_DOMBodyElement.appendChild(DOMDragElement);
|
||||
|
||||
var draggingOffset = [dragServer draggingOffset];
|
||||
@@ -789,7 +816,6 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void)_checkPasteboardElement
|
||||
{
|
||||
var value = _DOMPasteboardElement.value;
|
||||
@@ -825,12 +851,13 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
if(!aDOMEvent)
|
||||
aDOMEvent = window.event;
|
||||
|
||||
var location = nil;
|
||||
if (CPFeatureIsCompatible(CPJavaScriptMouseWheelValues_8_15))
|
||||
{
|
||||
var x = 0.0,
|
||||
y = 0.0,
|
||||
var x = aDOMEvent._offsetX || 0.0,
|
||||
y = aDOMEvent._offsetY || 0.0,
|
||||
element = aDOMEvent.target;
|
||||
|
||||
|
||||
while (element.nodeType !== 1)
|
||||
element = element.parentNode;
|
||||
|
||||
@@ -844,11 +871,13 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
} while (element = element.offsetParent);
|
||||
}
|
||||
|
||||
var location = _CGPointMake((x + ((aDOMEvent.clientX - 8) / 15)), (y + ((aDOMEvent.clientY - 8) / 15)));
|
||||
location = _CGPointMake((x + ((aDOMEvent.clientX - 8) / 15)), (y + ((aDOMEvent.clientY - 8) / 15)));
|
||||
}
|
||||
else if (aDOMEvent._overrideLocation)
|
||||
location = aDOMEvent._overrideLocation;
|
||||
else
|
||||
var location = _CGPointMake(aDOMEvent.clientX, aDOMEvent.clientY);
|
||||
|
||||
location = _CGPointMake(aDOMEvent.clientX, aDOMEvent.clientY);
|
||||
|
||||
var deltaX = 0.0,
|
||||
deltaY = 0.0,
|
||||
windowNumber = 0,
|
||||
@@ -857,7 +886,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
(aDOMEvent.ctrlKey ? CPControlKeyMask : 0) |
|
||||
(aDOMEvent.altKey ? CPAlternateKeyMask : 0) |
|
||||
(aDOMEvent.metaKey ? CPCommandKeyMask : 0);
|
||||
|
||||
|
||||
StopDOMEventPropagation = YES;
|
||||
|
||||
var theWindow = [self hitTest:location];
|
||||
@@ -1032,11 +1061,12 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
{
|
||||
if(_mouseIsDown)
|
||||
{
|
||||
event = _CPEventFromNativeMouseEvent(aDOMEvent, CPLeftMouseUp, location, modifierFlags, timestamp, windowNumber, nil, -1, CPDOMEventGetClickCount(_lastMouseUp, timestamp, location), 0);
|
||||
event = _CPEventFromNativeMouseEvent(aDOMEvent, _mouseDownIsRightClick ? CPRightMouseUp : CPLeftMouseUp, location, modifierFlags, timestamp, windowNumber, nil, -1, CPDOMEventGetClickCount(_lastMouseUp, timestamp, location), 0);
|
||||
|
||||
_mouseIsDown = NO;
|
||||
_lastMouseUp = event;
|
||||
_mouseDownWindow = nil;
|
||||
_mouseDownIsRightClick = NO;
|
||||
}
|
||||
|
||||
if(_DOMEventMode)
|
||||
@@ -1076,8 +1106,13 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
_DOMBodyElement.style["-khtml-user-drag"] = "element";
|
||||
}
|
||||
|
||||
event = _CPEventFromNativeMouseEvent(aDOMEvent, CPLeftMouseDown, location, modifierFlags, timestamp, windowNumber, nil, -1, CPDOMEventGetClickCount(_lastMouseDown, timestamp, location), 0);
|
||||
|
||||
var button = aDOMEvent.button;
|
||||
_mouseDownIsRightClick = button == 2 || (button == 0 && modifierFlags & CPControlKeyMask);
|
||||
|
||||
StopContextMenuDOMEventPropagation = YES;
|
||||
|
||||
event = _CPEventFromNativeMouseEvent(aDOMEvent, _mouseDownIsRightClick ? CPRightMouseDown : CPLeftMouseDown, location, modifierFlags, timestamp, windowNumber, nil, -1, CPDOMEventGetClickCount(_lastMouseDown, timestamp, location), 0);
|
||||
|
||||
_mouseIsDown = YES;
|
||||
_lastMouseDown = event;
|
||||
}
|
||||
@@ -1087,7 +1122,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
if (_DOMEventMode)
|
||||
return;
|
||||
|
||||
event = _CPEventFromNativeMouseEvent(aDOMEvent, _mouseIsDown ? CPLeftMouseDragged : CPMouseMoved, location, modifierFlags, timestamp, windowNumber, nil, -1, 1, 0);
|
||||
event = _CPEventFromNativeMouseEvent(aDOMEvent, _mouseIsDown ? (_mouseDownIsRightClick ? CPRightMouseDragged : CPLeftMouseDragged) : CPMouseMoved, location, modifierFlags, timestamp, windowNumber, nil, -1, 1, 0);
|
||||
}
|
||||
|
||||
var isDragging = [[CPDragServer sharedDragServer] isDragging];
|
||||
@@ -1102,10 +1137,21 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
if (StopDOMEventPropagation && (!supportsNativeDragAndDrop || type !== "mousedown" && !isDragging))
|
||||
CPDOMEventStop(aDOMEvent, self);
|
||||
|
||||
// if there are any tracking event listeners then show the event guard so we don't lose events to iframes
|
||||
_DOMEventGuard.style.display = (CPApp._eventListeners.length === 0) ? "none" : "";
|
||||
|
||||
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
||||
}
|
||||
|
||||
(CPArray)orderedWindowsAtLevel:(int)aLevel
|
||||
- (void)contextMenuEvent:(DOMEvent)aDOMEvent
|
||||
{
|
||||
if (StopContextMenuDOMEventPropagation)
|
||||
CPDOMEventStop(aDOMEvent, self);
|
||||
|
||||
return !StopContextMenuDOMEventPropagation;
|
||||
}
|
||||
|
||||
- (CPArray)orderedWindowsAtLevel:(int)aLevel
|
||||
{
|
||||
var layer = [self layerAtLevel:aLevel create:NO];
|
||||
|
||||
@@ -1149,6 +1195,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
|
||||
[_windowLevels insertObject:aLevel atIndex:insertionIndex];
|
||||
layer._DOMElement.style.zIndex = aLevel;
|
||||
|
||||
_DOMBodyElement.appendChild(layer._DOMElement);
|
||||
}
|
||||
|
||||
@@ -1246,6 +1293,19 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
return !StopDOMEventPropagation;
|
||||
}
|
||||
|
||||
- (void)_propagateContextMenuDOMEvent:(BOOL)aFlag
|
||||
{
|
||||
if (aFlag && CPBrowserIsEngine(CPGeckoBrowserEngine))
|
||||
StopDOMEventPropagation = !aFlag;
|
||||
|
||||
StopContextMenuDOMEventPropagation = !aFlag;
|
||||
}
|
||||
|
||||
- (BOOL)_willPropagateContextMenuDOMEvent
|
||||
{
|
||||
return StopContextMenuDOMEventPropagation;
|
||||
}
|
||||
|
||||
- (CPWindow)hitTest:(CPPoint)location
|
||||
{
|
||||
if (self._only)
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<div>Test custom cursors with .cur images.</div>
|
||||
<div style="width: 20px; height: 20px; margin: 10px; background: #ddd; cursor: url(disappearingItemCursor.cur), default">disappearingItemCursor</div>
|
||||
<div style="width: 20px; height: 20px; margin: 10px; background: #ddd; cursor: url(closedHandCursor.cur), default">closedHandCursor</div>
|
||||
<div style="width: 20px; height: 20px; margin: 10px; background: #ddd; cursor: url(contextMenuCursor.cur), default">contextMenuCursor</div>
|
||||
<div style="width: 20px; height: 20px; margin: 10px; background: #ddd; cursor: url(dragCopyCursor.cur), default">dragCopyCursor</div>
|
||||
<div style="width: 20px; height: 20px; margin: 10px; background: #ddd; cursor: url(dragLinkCursor.cur), default">dragLinkCursor</div>
|
||||
<div style="width: 20px; height: 20px; margin: 10px; background: #ddd; cursor: url(openHandCursor.cur), default">openHandCursor</div>
|
||||
<div style="width: 20px; height: 20px; margin: 10px; background: #ddd; cursor: url(resizeDownCursor.cur), default">resizeDownCursor</div>
|
||||
<div style="width: 20px; height: 20px; margin: 10px; background: #ddd; cursor: url(resizeLeftCursor.cur), default">resizeLeftCursor</div>
|
||||
<div style="width: 20px; height: 20px; margin: 10px; background: #ddd; cursor: url(resizeRightCursor.cur), default">resizeRightCursor</div>
|
||||
<div style="width: 20px; height: 20px; margin: 10px; background: #ddd; cursor: url(resizeUpCursor.cur), default">resizeUpCursor</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
After Width: | Height: | Size: 506 B |
|
After Width: | Height: | Size: 304 B |
|
After Width: | Height: | Size: 321 B |
|
After Width: | Height: | Size: 162 B |
|
After Width: | Height: | Size: 115 B |
|
After Width: | Height: | Size: 159 B |
|
Before Width: | Height: | Size: 340 B |
|
After Width: | Height: | Size: 134 B |
|
After Width: | Height: | Size: 120 B |
|
After Width: | Height: | Size: 118 B |
|
After Width: | Height: | Size: 118 B |
|
After Width: | Height: | Size: 134 B |
|
After Width: | Height: | Size: 118 B |
|
After Width: | Height: | Size: 117 B |
|
After Width: | Height: | Size: 118 B |
|
After Width: | Height: | Size: 118 B |
|
After Width: | Height: | Size: 187 B |
@@ -439,7 +439,7 @@
|
||||
isVertical:NO]);
|
||||
|
||||
[button setValue:CPLeftTextAlignment forThemeAttribute:@"alignment" inState:CPThemeStateBordered];
|
||||
[button setValue:[CPFont boldSystemFontOfSize:12.0] forThemeAttribute:@"font" inState:CPThemeStateBordered];
|
||||
[button setValue:[CPFont systemFontOfSize:12.0] forThemeAttribute:@"font" inState:CPThemeStateBordered];
|
||||
[button setValue:CGInsetMake(0.0, 0.0, 0.0, 20.0) forThemeAttribute:@"content-inset" inState:CPThemeStateBordered];
|
||||
[button setValue:bezelColor forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered];
|
||||
[button setValue:bezelColorSelected forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered | CPThemeStateSelected];
|
||||
@@ -493,7 +493,7 @@
|
||||
isVertical:NO]);
|
||||
|
||||
[button setValue:CPLeftTextAlignment forThemeAttribute:@"alignment" inState:CPThemeStateBordered];
|
||||
[button setValue:[CPFont boldSystemFontOfSize:12.0] forThemeAttribute:@"font" inState:CPThemeStateBordered];
|
||||
[button setValue:[CPFont systemFontOfSize:12.0] forThemeAttribute:@"font" inState:CPThemeStateBordered];
|
||||
[button setValue:CGInsetMake(0.0, 0.0, 0.0, 20.0) forThemeAttribute:@"content-inset" inState:CPThemeStateBordered];
|
||||
[button setValue:bezelColor forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered];
|
||||
[button setValue:bezelColorSelected forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered | CPThemeStateSelected];
|
||||
@@ -721,17 +721,54 @@
|
||||
|
||||
+ (CPButtonBar)themedButtonBar
|
||||
{
|
||||
var buttonBar = [[CPButtonBar alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 26.0)],
|
||||
color = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:
|
||||
[
|
||||
[_CPCibCustomResource imageResourceWithName:"buttonbar-bezel.png" size:CGSizeMake(1.0, 26.0)],
|
||||
[_CPCibCustomResource imageResourceWithName:"buttonbar-bezel.png" size:CGSizeMake(1.0, 26.0)],
|
||||
[_CPCibCustomResource imageResourceWithName:"buttonbar-bezel-right.png" size:CGSizeMake(13.0, 26.0)]
|
||||
]
|
||||
isVertical:NO]];
|
||||
var buttonBar = [[CPButtonBar alloc] initWithFrame:CGRectMake(0.0, 0.0, 147.0, 26.0)],
|
||||
color = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:"buttonbar-bezel.png" size:CGSizeMake(1.0, 26.0)]];
|
||||
|
||||
[buttonBar setHasResizeControl:YES];
|
||||
|
||||
[buttonBar setValue:color forThemeAttribute:@"bezel-color"];
|
||||
|
||||
|
||||
var resizeColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:"buttonbar-resize-control.png" size:CGSizeMake(5.0, 10.0)]];
|
||||
|
||||
[buttonBar setValue:CGSizeMake(5.0, 10.0) forThemeAttribute:@"resize-control-size"];
|
||||
[buttonBar setValue:CGInsetMake(9.0, 4.0, 7.0, 4.0) forThemeAttribute:@"resize-control-inset"];
|
||||
[buttonBar setValue:resizeColor forThemeAttribute:@"resize-control-color"];
|
||||
|
||||
var buttonBezelColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:
|
||||
[
|
||||
[_CPCibCustomResource imageResourceWithName:"buttonbar-button-bezel-left.png" size:CGSizeMake(2.0, 25.0)],
|
||||
[_CPCibCustomResource imageResourceWithName:"buttonbar-button-bezel-center.png" size:CGSizeMake(1.0, 25.0)],
|
||||
[_CPCibCustomResource imageResourceWithName:"buttonbar-button-bezel-right.png" size:CGSizeMake(2.0, 25.0)]
|
||||
]
|
||||
isVertical:NO]],
|
||||
|
||||
buttonBezelHighlightedColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:
|
||||
[
|
||||
[_CPCibCustomResource imageResourceWithName:"buttonbar-button-bezel-highlighted-left.png" size:CGSizeMake(2.0, 25.0)],
|
||||
[_CPCibCustomResource imageResourceWithName:"buttonbar-button-bezel-highlighted-center.png" size:CGSizeMake(1.0, 25.0)],
|
||||
[_CPCibCustomResource imageResourceWithName:"buttonbar-button-bezel-highlighted-right.png" size:CGSizeMake(2.0, 25.0)]
|
||||
]
|
||||
isVertical:NO]],
|
||||
|
||||
buttonBezelDisabledColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:
|
||||
[
|
||||
[_CPCibCustomResource imageResourceWithName:"buttonbar-button-bezel-disabled-left.png" size:CGSizeMake(2.0, 25.0)],
|
||||
[_CPCibCustomResource imageResourceWithName:"buttonbar-button-bezel-disabled-center.png" size:CGSizeMake(1.0, 25.0)],
|
||||
[_CPCibCustomResource imageResourceWithName:"buttonbar-button-bezel-disabled-right.png" size:CGSizeMake(2.0, 25.0)]
|
||||
]
|
||||
isVertical:NO]];
|
||||
|
||||
[buttonBar setValue:buttonBezelColor forThemeAttribute:@"button-bezel-color"];
|
||||
[buttonBar setValue:buttonBezelHighlightedColor forThemeAttribute:@"button-bezel-color" inState:CPThemeStateHighlighted];
|
||||
[buttonBar setValue:buttonBezelDisabledColor forThemeAttribute:@"button-bezel-color" inState:CPThemeStateDisabled];
|
||||
[buttonBar setValue:[CPColor blackColor] forThemeAttribute:@"button-text-color"];
|
||||
|
||||
var popup = [CPButtonBar actionPopupButton];
|
||||
[popup addItemWithTitle:"Item 1"];
|
||||
[popup addItemWithTitle:"Item 2"];
|
||||
|
||||
[buttonBar setButtons:[[CPButtonBar plusButton], [CPButtonBar minusButton], popup]];
|
||||
|
||||
return buttonBar;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ blendKitTask = framework ("BlendKit", function(blendKitTask)
|
||||
blendKitTask.setBuildPath(FILE.join($BUILD_DIR, $CONFIGURATION));
|
||||
|
||||
blendKitTask.setIdentifier("com.280n.BlendKit");
|
||||
blendKitTask.setVersion("0.8.0");
|
||||
blendKitTask.setVersion(getCappuccinoVersion());
|
||||
blendKitTask.setAuthor("280 North, Inc.");
|
||||
blendKitTask.setEmail("feedback @nospam@ 280north.com");
|
||||
blendKitTask.setSummary("BlendKit classes for Cappuccino");
|
||||
|
||||
@@ -5,13 +5,18 @@
|
||||
{
|
||||
}
|
||||
|
||||
- (void)_init
|
||||
{
|
||||
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 23.0))]];
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
{
|
||||
if (self = [super initWithFrame:aFrame])
|
||||
{
|
||||
[self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 23.0))]];
|
||||
[self _init];
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -20,16 +25,23 @@
|
||||
var context = [[CPGraphicsContext currentContext] graphicsPort];
|
||||
|
||||
CGContextSetStrokeColor(context, [CPColor colorWithHexString:@"dce0e2"]);
|
||||
|
||||
var points = [
|
||||
CGPointMake(aRect.origin.x, aRect.origin.y),
|
||||
CGPointMake(aRect.origin.x + aRect.size.width, aRect.origin.y),
|
||||
|
||||
|
||||
var points = [
|
||||
CGPointMake(aRect.origin.x, aRect.origin.y + 0.5),
|
||||
CGPointMake(aRect.origin.x, aRect.origin.y + aRect.size.height)
|
||||
];
|
||||
|
||||
|
||||
CGContextStrokeLineSegments(context, points, 2);
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
self = [super initWithCoder:aCoder];
|
||||
{
|
||||
[self _init];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -63,6 +63,7 @@ var HORIZONTAL_MARGIN = 3.0,
|
||||
|
||||
CPCellImagePosition _imagePosition;
|
||||
CPImageScaling _imageScaling;
|
||||
BOOL _shouldDimImage;
|
||||
|
||||
CPImage _image;
|
||||
CPString _text;
|
||||
@@ -211,6 +212,17 @@ var HORIZONTAL_MARGIN = 3.0,
|
||||
return _imageScaling;
|
||||
}
|
||||
|
||||
- (void)setDimsImage:(BOOL)shouldDim
|
||||
{
|
||||
var shouldDimImage = !!shouldDimImage;
|
||||
|
||||
if (_shouldDimImage !== shouldDimImage)
|
||||
{
|
||||
_shouldDimImage = shouldDim;
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setTextColor:(CPColor)aTextColor
|
||||
{
|
||||
if (_textColor === aTextColor)
|
||||
@@ -332,7 +344,8 @@ var HORIZONTAL_MARGIN = 3.0,
|
||||
hasDOMTextElement = !!_DOMTextElement;
|
||||
|
||||
// Create or destroy the DOM Text Element as necessary
|
||||
if (needsDOMTextElement !== hasDOMTextElement)
|
||||
if (needsDOMTextElement !== hasDOMTextElement)
|
||||
{
|
||||
if (hasDOMTextElement)
|
||||
{
|
||||
_DOMElement.removeChild(_DOMTextElement);
|
||||
@@ -361,6 +374,7 @@ var HORIZONTAL_MARGIN = 3.0,
|
||||
// We have to set all these values now.
|
||||
_flags |= _CPImageAndTextViewTextChangedFlag | _CPImageAndTextViewFontChangedFlag | _CPImageAndTextViewLineBreakModeChangedFlag;
|
||||
}
|
||||
}
|
||||
|
||||
var textStyle = hasDOMTextElement ? _DOMTextElement.style : nil;
|
||||
|
||||
@@ -369,6 +383,7 @@ var HORIZONTAL_MARGIN = 3.0,
|
||||
hasDOMTextShadowElement = !!_DOMTextShadowElement;
|
||||
|
||||
if (needsDOMTextShadowElement !== hasDOMTextShadowElement)
|
||||
{
|
||||
if (hasDOMTextShadowElement)
|
||||
{
|
||||
_DOMElement.removeChild(_DOMTextShadowElement);
|
||||
@@ -386,6 +401,7 @@ var HORIZONTAL_MARGIN = 3.0,
|
||||
shadowStyle.font = [_font ? _font : [CPFont systemFontOfSize:12.0] cssString];
|
||||
shadowStyle.position = "absolute";
|
||||
shadowStyle.whiteSpace = textStyle.whiteSpace;
|
||||
shadowStyle.wordWrap = textStyle.wordWrap;
|
||||
shadowStyle.color = [_textShadowColor cssString];
|
||||
|
||||
shadowStyle.zIndex = 150;
|
||||
@@ -394,7 +410,6 @@ var HORIZONTAL_MARGIN = 3.0,
|
||||
if (document.attachEvent)
|
||||
{
|
||||
shadowStyle.overflow = textStyle.overflow;
|
||||
shadowStyle.wordWrap = textStyle.wordWrap;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -408,6 +423,7 @@ var HORIZONTAL_MARGIN = 3.0,
|
||||
|
||||
_flags |= _CPImageAndTextViewTextChangedFlag; //sigh...
|
||||
}
|
||||
}
|
||||
|
||||
var shadowStyle = hasDOMTextShadowElement ? _DOMTextShadowElement.style : nil;
|
||||
|
||||
@@ -447,9 +463,7 @@ var HORIZONTAL_MARGIN = 3.0,
|
||||
case CPLineBreakByClipping: textStyle.overflow = "hidden";
|
||||
textStyle.textOverflow = "clip";
|
||||
textStyle.whiteSpace = "pre";
|
||||
|
||||
if (document.attachEvent)
|
||||
textStyle.wordWrap = "normal";
|
||||
textStyle.wordWrap = "normal";
|
||||
|
||||
break;
|
||||
|
||||
@@ -459,26 +473,23 @@ var HORIZONTAL_MARGIN = 3.0,
|
||||
case CPLineBreakByTruncatingTail: textStyle.textOverflow = "ellipsis";
|
||||
textStyle.whiteSpace = "nowrap";
|
||||
textStyle.overflow = "hidden";
|
||||
|
||||
if (document.attachEvent)
|
||||
textStyle.wordWrap = "normal";
|
||||
textStyle.wordWrap = "normal";
|
||||
|
||||
break;
|
||||
|
||||
case CPLineBreakByCharWrapping:
|
||||
case CPLineBreakByWordWrapping: if (document.attachEvent)
|
||||
{
|
||||
case CPLineBreakByWordWrapping: textStyle.wordWrap = "break-word";
|
||||
try {
|
||||
textStyle.whiteSpace = "pre";
|
||||
textStyle.wordWrap = "break-word";
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
textStyle.whiteSpace = "-o-pre-wrap";
|
||||
textStyle.whiteSpace = "-pre-wrap";
|
||||
textStyle.whiteSpace = "-moz-pre-wrap";
|
||||
textStyle.whiteSpace = "pre-wrap";
|
||||
}
|
||||
catch (e) {
|
||||
//internet explorer doesn't like these properties
|
||||
textStyle.whiteSpace = "pre";
|
||||
}
|
||||
|
||||
textStyle.overflow = "hidden";
|
||||
textStyle.textOverflow = "clip";
|
||||
@@ -490,7 +501,6 @@ var HORIZONTAL_MARGIN = 3.0,
|
||||
{
|
||||
if (document.attachEvent)
|
||||
{
|
||||
shadowStyle.wordWrap = textStyle.wordWrap;
|
||||
shadowStyle.overflow = textStyle.overflow;
|
||||
}
|
||||
else
|
||||
@@ -499,6 +509,7 @@ var HORIZONTAL_MARGIN = 3.0,
|
||||
shadowStyle.overflowY = textStyle.overflowY;
|
||||
}
|
||||
|
||||
shadowStyle.wordWrap = textStyle.wordWrap;
|
||||
shadowStyle.whiteSpace = textStyle.whiteSpace;
|
||||
shadowStyle.textOverflow = textStyle.textOverflow;
|
||||
}
|
||||
@@ -510,6 +521,7 @@ var HORIZONTAL_MARGIN = 3.0,
|
||||
|
||||
// Create or destroy DOM Image element
|
||||
if (needsDOMImageElement !== hasDOMImageElement)
|
||||
{
|
||||
if (hasDOMImageElement)
|
||||
{
|
||||
_DOMElement.removeChild(_DOMImageElement);
|
||||
@@ -539,8 +551,8 @@ var HORIZONTAL_MARGIN = 3.0,
|
||||
_DOMElement.appendChild(_DOMImageElement);
|
||||
|
||||
hasDOMImageElement = YES;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
var size = [self bounds].size,
|
||||
textRect = _CGRectMake(0.0, 0.0, size.width, size.height);
|
||||
@@ -572,67 +584,59 @@ var HORIZONTAL_MARGIN = 3.0,
|
||||
imageHeight *= scale;
|
||||
}
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
if (CPFeatureIsCompatible(CPOpacityRequiresFilterFeature))
|
||||
imageStyle.filter = @"alpha(opacity=" + _shouldDimImage ? 35 : 100 + ")";
|
||||
else
|
||||
imageStyle.opacity = _shouldDimImage ? 0.35 : 1.0;
|
||||
|
||||
_DOMImageElement.width = imageWidth;
|
||||
_DOMImageElement.height = imageHeight;
|
||||
imageStyle.width = imageWidth + "px";
|
||||
imageStyle.height = imageHeight + "px";
|
||||
#endif
|
||||
imageStyle.width = MAX(imageWidth, 0) + "px";
|
||||
imageStyle.height = MAX(imageHeight, 0) + "px";
|
||||
|
||||
if (_imagePosition === CPImageBelow)
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
imageStyle.left = FLOOR(centerX - imageWidth / 2.0) + "px";
|
||||
imageStyle.top = FLOOR(size.height - imageHeight) + "px";
|
||||
#endif
|
||||
|
||||
textRect.size.height = size.height - imageHeight - VERTICAL_MARGIN;
|
||||
}
|
||||
else if (_imagePosition === CPImageAbove)
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
CPDOMDisplayServerSetStyleLeftTop(_DOMImageElement, NULL, FLOOR(centerX - imageWidth / 2.0), 0);
|
||||
#endif
|
||||
|
||||
textRect.origin.y += imageHeight + VERTICAL_MARGIN;
|
||||
textRect.size.height = size.height - imageHeight - VERTICAL_MARGIN;
|
||||
}
|
||||
else if (_imagePosition === CPImageLeft)
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
imageStyle.top = FLOOR(centerY - imageHeight / 2.0) + "px";
|
||||
imageStyle.left = "0px";
|
||||
#endif
|
||||
|
||||
textRect.origin.x = imageWidth + HORIZONTAL_MARGIN;
|
||||
textRect.size.width -= imageWidth + HORIZONTAL_MARGIN;
|
||||
}
|
||||
else if (_imagePosition === CPImageRight)
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
imageStyle.top = FLOOR(centerY - imageHeight / 2.0) + "px";
|
||||
imageStyle.left = FLOOR(size.width - imageWidth) + "px";
|
||||
#endif
|
||||
|
||||
textRect.size.width -= imageWidth + HORIZONTAL_MARGIN;
|
||||
}
|
||||
else if (_imagePosition === CPImageOnly)
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
imageStyle.top = FLOOR(centerY - imageHeight / 2.0) + "px";
|
||||
imageStyle.left = FLOOR(centerX - imageWidth / 2.0) + "px";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
if (hasDOMTextElement)
|
||||
{
|
||||
var textRectX = _CGRectGetMinX(textRect),
|
||||
textRectY = _CGRectGetMinY(textRect),
|
||||
textRectWidth = _CGRectGetWidth(textRect),
|
||||
textRectHeight = _CGRectGetHeight(textRect);
|
||||
|
||||
|
||||
if (_verticalAlignment !== CPTopVerticalTextAlignment)
|
||||
{
|
||||
if (!_textSize)
|
||||
@@ -659,8 +663,8 @@ var HORIZONTAL_MARGIN = 3.0,
|
||||
|
||||
textStyle.top = ROUND(textRectY) + "px";
|
||||
textStyle.left = ROUND(textRectX) + "px";
|
||||
textStyle.width = ROUND(textRectWidth) + "px";
|
||||
textStyle.height = ROUND(textRectHeight) + "px";
|
||||
textStyle.width = MAX(ROUND(textRectWidth), 0) + "px";
|
||||
textStyle.height = MAX(ROUND(textRectHeight), 0) + "px";
|
||||
|
||||
if (shadowStyle)
|
||||
{
|
||||
@@ -669,8 +673,8 @@ var HORIZONTAL_MARGIN = 3.0,
|
||||
|
||||
shadowStyle.top = ROUND(textRectY + _textShadowOffset.height) + "px";
|
||||
shadowStyle.left = ROUND(textRectX + _textShadowOffset.width) + "px";
|
||||
shadowStyle.width = ROUND(textRectWidth) + "px";
|
||||
shadowStyle.height = ROUND(textRectHeight) + "px";
|
||||
shadowStyle.width = MAX(ROUND(textRectWidth), 0) + "px";
|
||||
shadowStyle.height = MAX(ROUND(textRectHeight), 0) + "px";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -8,7 +8,7 @@ new FileList("**/*").exclude("Jakefile").forEach(function(aFilename)
|
||||
if (!FILE.isFile(aFilename))
|
||||
return;
|
||||
|
||||
var buildFilename = FILE.join($BUILD_CONFIGURATION_DIR, "CommonJS", "cappuccino", aFilename);
|
||||
var buildFilename = FILE.join($BUILD_CJS_CAPPUCCINO, aFilename);
|
||||
|
||||
filedir (buildFilename, [aFilename], function ()
|
||||
{
|
||||
@@ -27,3 +27,7 @@ new FileList("**/*").exclude("Jakefile").forEach(function(aFilename)
|
||||
task ("build", buildFilename);
|
||||
CLOBBER.include(buildFilename);
|
||||
});
|
||||
|
||||
task ("build", function() {
|
||||
setPackageMetadata(FILE.join($BUILD_CJS_CAPPUCCINO, "package.json"));
|
||||
});
|
||||
|
||||
@@ -8,6 +8,9 @@ require("narwhal").ensureEngine("rhino");
|
||||
|
||||
var FILE = require("file");
|
||||
var OS = require("os");
|
||||
var UTIL = require("util");
|
||||
|
||||
var CACHEMANIFEST = require("objective-j/cache-manifest");
|
||||
|
||||
var stream = require("term").stream;
|
||||
var parser = new (require("args").Parser)();
|
||||
@@ -24,6 +27,10 @@ parser.option("-F", "--framework", "frameworks")
|
||||
.push()
|
||||
.help("Add a frameworks directory, relative to INPUT_PROJECT (default: ['Frameworks'])");
|
||||
|
||||
parser.option("-P", "--path", "paths")
|
||||
.push()
|
||||
.help("Add a path (relative to the application root) to inline.");
|
||||
|
||||
parser.option("-f", "--force", "force")
|
||||
.def(false)
|
||||
.set(true)
|
||||
@@ -34,6 +41,20 @@ parser.option("--index", "index")
|
||||
.set()
|
||||
.help("The root HTML file to modify (default: index.html)");
|
||||
|
||||
parser.option("-s", "--split", "number", "split")
|
||||
.natural()
|
||||
.def(0)
|
||||
.help("Split into multiple files");
|
||||
|
||||
parser.option("-c", "--compressor", "compressor")
|
||||
.def("shrinksafe")
|
||||
.set()
|
||||
.help("Select a compressor to use (closure-compiler, yuicompressor, shrinksafe), or \"none\" (default: shrinksafe)");
|
||||
|
||||
parser.option("--manifest", "manifest")
|
||||
.set(true)
|
||||
.help("Generate HTML5 cache manifest.");
|
||||
|
||||
parser.option("-v", "--verbose", "verbose")
|
||||
.def(false)
|
||||
.set(true)
|
||||
@@ -81,151 +102,240 @@ function main(args)
|
||||
|
||||
var flattener = new ObjectiveJFlattener(rootPath);
|
||||
|
||||
flattener.options = options;
|
||||
|
||||
flattener.setIncludePaths(frameworks);
|
||||
flattener.setEnvironments([environment, "ObjJ"]);
|
||||
|
||||
print("Loading application.");
|
||||
flattener.load(mainPath);
|
||||
flattener.finishLoading();
|
||||
|
||||
var rootResources = flattener.require("objective-j").StaticResource.rootResources();
|
||||
print("Loading default theme.");
|
||||
flattener.require("objective-j").objj_eval("("+(function() {
|
||||
var blend = [[CPThemeBlend alloc] initWithContentsOfURL:[[CPBundle bundleForClass:[CPApplication class]] pathForResource:[CPApplication defaultThemeName] + ".blend"]];
|
||||
[blend loadWithDelegate:nil];
|
||||
})+")")();
|
||||
|
||||
var root = rootResources["file:"];
|
||||
|
||||
// FIXME: shouldn't have to do this manually
|
||||
var components = rootPath.split("/").slice(0, -1);
|
||||
components[0] = "/";
|
||||
var node = root;
|
||||
while (components.length) {
|
||||
node = node.children()[components.shift()];
|
||||
}
|
||||
applicationRoot = node;
|
||||
|
||||
print(applicationRoot.toString());
|
||||
|
||||
var applicationJS = flattener.buildApplicationJS(applicationRoot);
|
||||
var applicationJSs = flattener.buildApplicationJS();
|
||||
|
||||
FILE.copyTree(rootPath, outputPath);
|
||||
|
||||
outputPath.join("Application.js").write(applicationJS);
|
||||
applicationJSs.forEach(function(applicationJS, n) {
|
||||
var name = "Application"+(n||"")+".js";
|
||||
if (options.compressor === "none") {
|
||||
print("skipping compression: " + name);
|
||||
} else {
|
||||
print("compressing: " + name);
|
||||
applicationJS = require("minify/"+options.compressor).compress(applicationJS, { charset : "UTF-8", useServer : true });
|
||||
}
|
||||
outputPath.join(name).write(applicationJS, { charset : "UTF-8" });
|
||||
});
|
||||
|
||||
rewriteMainHTML(outputPath.join(options.index));
|
||||
|
||||
if (options.manifest) {
|
||||
CACHEMANIFEST.generateManifest(outputPath, {
|
||||
index : outputPath.join(options.index),
|
||||
exclude : Object.keys(flattener.filesToCache).map(function(path) { return outputPath.join(path).toString(); })
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// ObjectiveJFlattener inherits from ObjectiveJRuntimeAnalyzer
|
||||
function ObjectiveJFlattener(rootPath) {
|
||||
ObjectiveJRuntimeAnalyzer.apply(this, arguments);
|
||||
|
||||
this.resourceBuffer = [];
|
||||
this.bundleBuffer = [];
|
||||
this.filesToCache = {};
|
||||
this.fileCacheBuffer = [];
|
||||
this.functionsBuffer = [];
|
||||
|
||||
this._outputBundles = {};
|
||||
}
|
||||
|
||||
ObjectiveJFlattener.prototype = Object.create(ObjectiveJRuntimeAnalyzer.prototype);
|
||||
|
||||
ObjectiveJFlattener.prototype.buildApplicationJS = function(applicationRoot) {
|
||||
this.serializeStaticResources(applicationRoot);
|
||||
this.serializeStaticFileExecutables();
|
||||
ObjectiveJFlattener.prototype.buildApplicationJS = function() {
|
||||
|
||||
var buffer = []
|
||||
this.setupFileCache();
|
||||
this.serializeFunctions();
|
||||
this.serializeFileCache();
|
||||
|
||||
buffer.push("(function(){");
|
||||
var additions = FILE.read(FILE.join(FILE.dirname(module.path), "..", "..", "cappuccino", "lib", "cappuccino", "objj-flatten-additions.js"), { charset:"UTF-8" });
|
||||
|
||||
buffer.push("var appURL = new CFURL('.', ObjectiveJ.pageURL);")
|
||||
var applicationJSs = [];
|
||||
|
||||
buffer.push(this.bundleBuffer.join("\n"));
|
||||
if (this.options.split === 0) {
|
||||
var buffer = [];
|
||||
buffer.push("var baseURL = new CFURL(\".\", ObjectiveJ.pageURL);");
|
||||
buffer.push(additions);
|
||||
buffer.push(this.fileCacheBuffer.join("\n"));
|
||||
buffer.push(this.functionsBuffer.join("\n"));
|
||||
buffer.push("ObjectiveJ.bootstrap();");
|
||||
applicationJSs.push(buffer.join("\n"));
|
||||
} else {
|
||||
var appFilesCount = this.options.split;
|
||||
|
||||
buffer.push("var nodeStack = [];");
|
||||
buffer.push("var applicationRoot = ObjectiveJ.StaticResource.resourceAtURL(appURL, true);");
|
||||
buffer.push("var currentNode = null;");
|
||||
buffer.push("var newNode;");
|
||||
var buffers = [];
|
||||
for (var i = 0; i <= appFilesCount; i++)
|
||||
buffers.push([]);
|
||||
|
||||
buffer.push(this.resourceBuffer.join("\n"));
|
||||
var chunks = this.fileCacheBuffer.concat(this.functionsBuffer).sort(function(chunkA, chunkB) {
|
||||
return chunkA.length - chunkB.length;
|
||||
});
|
||||
|
||||
buffer.push("})();");
|
||||
// try to equally distribute the chunks. could be better but good enough for now.
|
||||
var n = 0;
|
||||
while (chunks.length) {
|
||||
buffers[(n++ % appFilesCount) + 1].push(chunks.pop());
|
||||
}
|
||||
|
||||
buffer.push(this.functionsBuffer.join("\n"));
|
||||
buffers[0].push("var baseURL = new CFURL(\".\", ObjectiveJ.pageURL);");
|
||||
buffers[0].push(additions);
|
||||
|
||||
buffer.push("ObjectiveJ.bootstrap();");
|
||||
buffers[0].push("var appFilesCount = " + appFilesCount +";");
|
||||
buffers[0].push("for (var i = 1; i <= appFilesCount; i++) {");
|
||||
buffers[0].push(" var script = document.createElement(\"script\");");
|
||||
buffers[0].push(" script.src = \"Application\"+i+\".js\";");
|
||||
buffers[0].push(" script.charset = \"UTF-8\";");
|
||||
buffers[0].push(" script.onload = function() { if (--appFilesCount === 0) ObjectiveJ.bootstrap(); };");
|
||||
buffers[0].push(" document.getElementsByTagName(\"head\")[0].appendChild(script);");
|
||||
buffers[0].push("}");
|
||||
|
||||
return buffer.join("\n");
|
||||
buffers.forEach(function(buffer) {
|
||||
applicationJSs.push(buffer.join("\n"));
|
||||
});
|
||||
}
|
||||
|
||||
return applicationJSs;
|
||||
}
|
||||
|
||||
ObjectiveJFlattener.prototype.serializeStaticFileExecutables = function() {
|
||||
this.require("objective-j").FileExecutable.allFileExecutables().forEach(function(aFileExecutable) {
|
||||
var deps = aFileExecutable.fileDependencies().map(function(dependency) {
|
||||
return "new ObjectiveJ.FileDependency(new CFURL("+JSON.stringify(dependency.path())+"),"+JSON.stringify(dependency.isLocal())+")"
|
||||
}).join(",");
|
||||
ObjectiveJFlattener.prototype.serializeFunctions = function() {
|
||||
var inlineFunctions = true;//this.options.inlineFunctions;
|
||||
|
||||
var func = aFileExecutable._function.toString();
|
||||
// HACK
|
||||
func = func.replace(", require, exports, module, system, print, window", "");
|
||||
var outputFiles = {};
|
||||
|
||||
this.functionsBuffer.push("var path = "+JSON.stringify(this.rootPath.relative(aFileExecutable.path()).toString())+";");
|
||||
this.functionsBuffer.push("new ObjectiveJ.FileExecutable(path,"+
|
||||
"new ObjectiveJ.Executable(null, ["+deps+"], path, "+func+"));");
|
||||
var _cachedExecutableFunctions = {};
|
||||
|
||||
this.require("objective-j").FileExecutable.allFileExecutables().forEach(function(executable) {
|
||||
var path = executable.path();
|
||||
|
||||
if (inlineFunctions)
|
||||
{
|
||||
// stringify the function, replacing arguments
|
||||
var functionString = executable._function.toString().replace(", require, exports, module, system, print, window", ""); // HACK
|
||||
|
||||
var relative = this.rootPath.relative(path).toString();
|
||||
this.functionsBuffer.push("ObjectiveJ.FileExecutable._cacheFunction(new CFURL("+JSON.stringify(relative)+", baseURL),\n"+functionString+");");
|
||||
}
|
||||
|
||||
var bundle = this.context.global.CFBundle.bundleContainingURL(path);
|
||||
if (bundle && bundle.infoDictionary())
|
||||
{
|
||||
var executablePath = bundle.executablePath(),
|
||||
relativeToBundle = FILE.relative(FILE.join(bundle.path(), ""), path);
|
||||
|
||||
if (executablePath)
|
||||
{
|
||||
if (inlineFunctions)
|
||||
{
|
||||
// remove the code since we're inlining the functions
|
||||
executable._code = "alert("+JSON.stringify(relativeToBundle)+");";
|
||||
}
|
||||
|
||||
if (!outputFiles[executablePath])
|
||||
{
|
||||
outputFiles[executablePath] = [];
|
||||
outputFiles[executablePath].push("@STATIC;1.0;");
|
||||
}
|
||||
|
||||
var fileContents = executable.toMarkedString();
|
||||
|
||||
outputFiles[executablePath].push("p;" + relativeToBundle.length + ";" + relativeToBundle);
|
||||
outputFiles[executablePath].push("t;" + fileContents.length + ";" + fileContents);
|
||||
|
||||
// stream.print("Adding \0green(" + this.rootPath.relative(path) + "\0) to \0cyan(" + this.rootPath.relative(executablePath) + "\0)");
|
||||
}
|
||||
}
|
||||
else
|
||||
CPLog.warn("No bundle (or info dictionary for) " + rootPath.relative(path));
|
||||
}, this);
|
||||
|
||||
for (var executablePath in outputFiles)
|
||||
{
|
||||
var relative = this.rootPath.relative(executablePath).toString();
|
||||
var contents = outputFiles[executablePath].join("");
|
||||
this.filesToCache[relative] = contents;
|
||||
}
|
||||
}
|
||||
|
||||
ObjectiveJFlattener.prototype.serializeFileCache = function() {
|
||||
for (var relative in this.filesToCache) {
|
||||
var contents = this.filesToCache[relative];
|
||||
print("caching: " + relative + " => " + (contents == null ? 404 : 200));
|
||||
if (contents == null)
|
||||
this.fileCacheBuffer.push("CFHTTPRequest._cacheRequest(new CFURL("+JSON.stringify(relative)+", baseURL), 404);");
|
||||
else
|
||||
this.fileCacheBuffer.push("CFHTTPRequest._cacheRequest(new CFURL("+JSON.stringify(relative)+", baseURL), 200, {}, "+JSON.stringify(contents)+");");
|
||||
}
|
||||
}
|
||||
|
||||
ObjectiveJFlattener.prototype.setupFileCache = function() {
|
||||
var paths = {};
|
||||
|
||||
UTIL.update(paths, this.requestedURLs);
|
||||
|
||||
this.options.paths.forEach(function(relativePath) {
|
||||
paths[this.rootPath.join(relativePath)] = true;
|
||||
}, this);
|
||||
|
||||
Object.keys(paths).forEach(function(absolute) {
|
||||
var relative = this.rootPath.relative(absolute).toString();
|
||||
if (relative.indexOf("..") === 0)
|
||||
{
|
||||
print("skipping (parent of app root): " + absolute);
|
||||
return;
|
||||
}
|
||||
|
||||
if (FILE.isFile(absolute))
|
||||
{
|
||||
// if (this.options.maxCachedSize && FILE.size(absolute) > this.options.maxCachedSize)
|
||||
// {
|
||||
// print("skipping (larger than "+this.options.maxCachedSize+" bytes): " + absolute);
|
||||
// return;
|
||||
// }
|
||||
|
||||
var contents = FILE.read(absolute, { charset : "UTF-8" });
|
||||
this.filesToCache[relative] = contents;
|
||||
} else {
|
||||
this.filesToCache[relative] = null;
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
|
||||
ObjectiveJFlattener.prototype.serializeStaticResources = function(node, depth) {
|
||||
depth = depth || 0;
|
||||
|
||||
var bundle = this.context.global.CFBundle.bundleContainingURL(node.URL());
|
||||
if (!bundle) {
|
||||
stream.print("\0yellow(Warning:\0) No bundle for path: \0cyan("+node.URL()+"\0)");
|
||||
}
|
||||
else if (!this._outputBundles[bundle.path()]) {
|
||||
this._outputBundles[bundle.path()] = bundle;
|
||||
stream.print("Writing bundle: \0cyan("+bundle.path()+"\0)");
|
||||
print(bundle.infoDictionary())
|
||||
|
||||
var relative = this.rootPath.relative(bundle.path()).toString();
|
||||
this.bundleBuffer.push("var bundle = new CFBundle("+(relative ? JSON.stringify(relative) : "appURL")+");");
|
||||
this.bundleBuffer.push("bundle._loadStatus = " + (1<<4) + ";");
|
||||
if (bundle.infoDictionary()) {
|
||||
this.bundleBuffer.push("bundle._infoDictionary = CFPropertyList.propertyListFromString(" +
|
||||
JSON.stringify(CPPropertyListCreateData(bundle.infoDictionary()).rawString()) + ");");
|
||||
}
|
||||
}
|
||||
|
||||
// not the root node:
|
||||
if (depth > 0) {
|
||||
this.resourceBuffer.push("newNode = new ObjectiveJ.StaticResource(" +
|
||||
JSON.stringify(node.name()) +
|
||||
", currentNode, " +
|
||||
JSON.stringify(node.isDirectory()) + ", " +
|
||||
JSON.stringify(node.isResolved()) + ");");
|
||||
} else {
|
||||
this.resourceBuffer.push("newNode = applicationRoot;");
|
||||
}
|
||||
|
||||
// var contents = node.contents();
|
||||
// if (contents) {
|
||||
// this.resourceBuffer.push("newNode._contents = " + JSON.stringify(contents) + ";");
|
||||
// }
|
||||
|
||||
if (!node.children())
|
||||
return;
|
||||
|
||||
this.resourceBuffer.push("nodeStack.push(currentNode);");
|
||||
this.resourceBuffer.push("currentNode = newNode;");
|
||||
|
||||
var children = node.children();
|
||||
for (var name in children) {
|
||||
this.serializeStaticResources(children[name], depth+1);
|
||||
}
|
||||
|
||||
this.resourceBuffer.push("currentNode = nodeStack.pop();");
|
||||
}
|
||||
|
||||
// "$1" is the matching indentation
|
||||
var scriptTagsBefore = '$1<script type = "text/javascript">\n$1 OBJJ_AUTO_BOOTSTRAP = false;\n$1</script>';
|
||||
var scriptTagsAfter = '$1<script type = "text/javascript" src = "Application.js"></script>';
|
||||
var scriptTagsBefore =
|
||||
'$1<script type = "text/javascript">\n'+
|
||||
'$1 OBJJ_AUTO_BOOTSTRAP = false;\n'+
|
||||
'$1</script>';
|
||||
|
||||
var scriptTagsAfter =
|
||||
'$1<script type="text/javascript" src="Application.js" charset="UTF-8"></script>';
|
||||
|
||||
// enable CPLog:
|
||||
// scriptTagsAfter = '$1<script type="text/javascript">\n$1 CPLogRegister(CPLogConsole);\n$1</script>\n' + scriptTagsAfter;
|
||||
|
||||
function rewriteMainHTML(indexHTMLPath) {
|
||||
if (indexHTMLPath.isFile()) {
|
||||
var indexHTML = indexHTMLPath.read();
|
||||
var indexHTML = indexHTMLPath.read({ charset : "UTF-8" });
|
||||
|
||||
// inline the Application.js if it's smallish
|
||||
var applicationJSPath = indexHTMLPath.dirname().join("Application.js");
|
||||
if (applicationJSPath.size() < 10*1024) {
|
||||
// escape any dollar signs by replacing them with two
|
||||
// then indent by splitting/joining on newlines
|
||||
scriptTagsAfter =
|
||||
'$1<script type="text/javascript">\n'+
|
||||
'$1 ' + applicationJSPath.read({ charset : "UTF-8" }).replace(/\$/g, "$$$$").split("\n").join("\n$1 ")+'\n'+
|
||||
'$1</script>';
|
||||
}
|
||||
|
||||
// attempt to find Objective-J script tag and add ours
|
||||
var newIndexHTML = indexHTML.replace(/([ \t]+)<script[^>]+Objective-J\.js[^>]+>(?:\s*<\/script>)?/,
|
||||
@@ -233,7 +343,7 @@ function rewriteMainHTML(indexHTMLPath) {
|
||||
|
||||
if (newIndexHTML !== indexHTML) {
|
||||
stream.print("\0green(Modified: "+indexHTMLPath+".\0)");
|
||||
indexHTMLPath.write(newIndexHTML);
|
||||
indexHTMLPath.write(newIndexHTML, { charset : "UTF-8" });
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -10,6 +10,8 @@ require("narwhal").ensureEngine("rhino");
|
||||
var FILE = require("file");
|
||||
var OS = require("os");
|
||||
|
||||
var CACHEMANIFEST = require("objective-j/cache-manifest");
|
||||
|
||||
var stream = require("term").stream;
|
||||
var parser = new (require("args").Parser)();
|
||||
|
||||
@@ -31,11 +33,20 @@ parser.option("-f", "--force", "force")
|
||||
.set(true)
|
||||
.help("Force overwriting OUTPUT_PROJECT if it exists");
|
||||
|
||||
parser.option("--index", "index")
|
||||
.def("index.html")
|
||||
.set()
|
||||
.help("The root HTML file to modify (default: index.html) (NOTE: currently only used by '--manifest' option)");
|
||||
|
||||
parser.option("-p", "--pngcrush", "png")
|
||||
.def(false)
|
||||
.set(true)
|
||||
.help("Run pngcrush on all PNGs (pngcrush must be installed!)");
|
||||
|
||||
parser.option("--manifest", "manifest")
|
||||
.set(true)
|
||||
.help("Generate HTML5 cache manifest.");
|
||||
|
||||
parser.option("-v", "--verbose", "verbose")
|
||||
.def(false)
|
||||
.set(true)
|
||||
@@ -146,6 +157,12 @@ function press(rootPath, outputPath, options) {
|
||||
if (options.png) {
|
||||
pngcrushDirectory(outputPath);
|
||||
}
|
||||
|
||||
if (options.manifest) {
|
||||
CACHEMANIFEST.generateManifest(outputPath, {
|
||||
index : outputPath.join(options.index)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function pressEnvironment(rootPath, outputFiles, environment, options) {
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
var FILE = require("file");
|
||||
var sprintf = require("printf").sprintf;
|
||||
|
||||
var pkg = null;
|
||||
function getPackage() {
|
||||
if (!pkg)
|
||||
pkg = JSON.parse(FILE.path(module.path).dirname().dirname().join("package.json").read({ charset : "UTF-8" }));
|
||||
return pkg;
|
||||
}
|
||||
|
||||
exports.version = function() { return getPackage()["version"]; }
|
||||
exports.revision = function() { return getPackage()["cappuccino-revision"]; }
|
||||
exports.timestamp = function() { return new Date(getPackage()["cappuccino-timestamp"]); }
|
||||
|
||||
exports.fullVersionString = function() {
|
||||
return sprintf("cappuccino %s (%04d-%02d-%02d %s)",
|
||||
exports.version(),
|
||||
exports.timestamp().getUTCFullYear(),
|
||||
exports.timestamp().getUTCMonth()+1,
|
||||
exports.timestamp().getUTCDate(),
|
||||
exports.revision().slice(0,6)
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
var FILE = require("file");
|
||||
var OS = require("os");
|
||||
|
||||
var NATIVEHOST_SOURCE = FILE.path(module.path).dirname().dirname().dirname().join("support", "NativeHost.app");
|
||||
|
||||
exports.buildNativeHost = function(rootPath, buildNative, options) {
|
||||
options = options || {};
|
||||
options.index = options.index || "index.html";
|
||||
|
||||
rootPath = FILE.path(rootPath);
|
||||
buildNative = FILE.path(buildNative);
|
||||
|
||||
if (buildNative.exists())
|
||||
buildNative.rmtree();
|
||||
|
||||
buildNative.dirname().mkdirs();
|
||||
// FIXME: Narwhal doesn't preserve permissions
|
||||
// FILE.copyTree(NATIVEHOST_SOURCE, buildNative);
|
||||
OS.system(["cp", "-r", NATIVEHOST_SOURCE, buildNative]);
|
||||
FILE.chmod(buildNative.join("Contents", "MacOS", "NativeHost"), 0755);
|
||||
|
||||
var rootBaseName = rootPath.basename();
|
||||
var buildClientDirectory = buildNative.join("Contents", "Resources", rootBaseName);
|
||||
|
||||
FILE.mkdirs(FILE.dirname(buildClientDirectory));
|
||||
// FILE.copyTree(rootPath, buildClientDirectory);
|
||||
OS.system(["cp", "-r", rootPath, buildClientDirectory]);
|
||||
|
||||
var defaultBundleName = buildNative.basename().match(/^(.*)(\.app)?$/)[1];
|
||||
|
||||
function mergePlist(plist, path) {
|
||||
var otherPlist = CFPropertyList.readPropertyListFromFile(String(path));
|
||||
|
||||
otherPlist.keys().forEach(function(key) {
|
||||
var value = otherPlist.valueForKey(key);
|
||||
plist.setValueForKey(key, value);
|
||||
|
||||
if (key === "CPBundleName")
|
||||
plist.setValueForKey("CFBundleName", value);
|
||||
|
||||
if (key === "CFBundleIconFile") {
|
||||
var iconPath = rootPath.join("Resources", value);
|
||||
if (iconPath.isFile())
|
||||
iconPath.copy(buildNative.join("Contents", "Resources", value));
|
||||
else
|
||||
print("Warning: CFBundleIconFile references " + value + " but does not exist in the resources directory.");
|
||||
}
|
||||
|
||||
if (key === "CFBundleExecutable") {
|
||||
buildNative.join("Contents", "MacOS", "NativeHost").rename(value);
|
||||
// FIXME:
|
||||
FILE.chmod(buildNative.join("Contents", "MacOS", value), 0755);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
CFPropertyList.modifyPlist(buildNative.join("Contents", "Info.plist"), function(plist) {
|
||||
|
||||
plist.setValueForKey("CFBundleName", defaultBundleName);
|
||||
plist.setValueForKey("NHInitialResource", FILE.join(rootBaseName, options.index));
|
||||
|
||||
// merge Cappuccino plist
|
||||
var cappPlistPath = rootPath.join("Info.plist");
|
||||
if (cappPlistPath.isFile())
|
||||
mergePlist(plist, cappPlistPath);
|
||||
|
||||
if (options.extraPlistPath)
|
||||
mergePlist(plist, options.extraPlistPath);
|
||||
});
|
||||
}
|
||||
@@ -5,6 +5,8 @@ var Context = require("interpreter").Context;
|
||||
ObjectiveJRuntimeAnalyzer = function(rootPath)
|
||||
{
|
||||
this.rootPath = rootPath;
|
||||
this.rootURL = new CFURL(String(rootPath));
|
||||
|
||||
this.context = new Context();
|
||||
|
||||
this.scope = setupObjectiveJ(this.context);
|
||||
@@ -28,6 +30,19 @@ ObjectiveJRuntimeAnalyzer = function(rootPath)
|
||||
var url = this.executableURL();
|
||||
return url ? url.absoluteURL().path() : null;
|
||||
}
|
||||
|
||||
this.require("cappuccino/objj-flatten-additions");
|
||||
|
||||
if (!this.context.global.CFHTTPRequest._lookupCachedRequest)
|
||||
print("Warning: CFHTTPRequest._lookupCachedRequest. Need to import objj-flatten-additions module.");
|
||||
|
||||
var requestedURLs = this.requestedURLs = {};
|
||||
var _lookupCachedRequest = this.context.global.CFHTTPRequest._lookupCachedRequest;
|
||||
this.context.global.CFHTTPRequest._lookupCachedRequest = function(aURL) {
|
||||
var path = new CFURL(aURL, this.rootURL).absoluteURL().path();
|
||||
requestedURLs[path] = true;
|
||||
return _lookupCachedRequest.apply(null, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
ObjectiveJRuntimeAnalyzer.prototype.setIncludePaths = function(includePaths) {
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
|
||||
var URLCache = { };
|
||||
|
||||
var CFHTTPRequest_open = CFHTTPRequest.prototype.open;
|
||||
CFHTTPRequest.prototype.open = function(/*String*/ method, /*String*/ url, /*Boolean*/ async, /*String*/ user, /*String*/ password)
|
||||
{
|
||||
var cachedRequest = CFHTTPRequest._lookupCachedRequest(url);
|
||||
if (cachedRequest)
|
||||
{
|
||||
var self = this;
|
||||
this._nativeRequest = cachedRequest;
|
||||
this._nativeRequest.onreadystatechange = function()
|
||||
{
|
||||
ObjectiveJ.determineAndDispatchHTTPRequestEvents(self);
|
||||
};
|
||||
}
|
||||
return CFHTTPRequest_open.apply(this, arguments);
|
||||
}
|
||||
|
||||
CFHTTPRequest._cacheRequest = function(/*CFURL|String*/ aURL, /*Number*/ status, /*Object*/ headers, /*String*/ body)
|
||||
{
|
||||
URLCache[aURL] = new MockXMLHttpRequest(status, headers, body);
|
||||
}
|
||||
|
||||
CFHTTPRequest._lookupCachedRequest = function(/*CFURL|String*/ aURL)
|
||||
{
|
||||
return URLCache[aURL];
|
||||
}
|
||||
|
||||
function MockXMLHttpRequest(status, headers, body)
|
||||
{
|
||||
this.readyState = CFHTTPRequest.UninitializedState;
|
||||
this.status = status || 200;
|
||||
this.statusText = "";
|
||||
this.responseText = body || "";
|
||||
this._responseHeaders = headers || {};
|
||||
};
|
||||
MockXMLHttpRequest.prototype.open = function(method, url, async, user, password)
|
||||
{
|
||||
this.readyState = CFHTTPRequest.LoadingState;
|
||||
this.async = async;
|
||||
};
|
||||
MockXMLHttpRequest.prototype.send = function(body)
|
||||
{
|
||||
var self = this;
|
||||
self.responseText = self.responseText.toString();
|
||||
function complete() {
|
||||
for (self.readyState = CFHTTPRequest.LoadedState; self.readyState <= CFHTTPRequest.CompleteState; self.readyState++)
|
||||
self.onreadystatechange();
|
||||
}
|
||||
(self.async ? ObjectiveJ.Asynchronous(complete) : complete)();
|
||||
};
|
||||
MockXMLHttpRequest.prototype.onreadystatechange = function() {};
|
||||
MockXMLHttpRequest.prototype.abort = function() {};
|
||||
MockXMLHttpRequest.prototype.setRequestHeader = function(header, value) {};
|
||||
MockXMLHttpRequest.prototype.getAllResponseHeaders = function() { return this._responseHeaders; };
|
||||
MockXMLHttpRequest.prototype.getResponseHeader = function(header) { return this._responseHeaders[header]; };
|
||||
MockXMLHttpRequest.prototype.overrideMimeType = function(mimetype) {};
|
||||
@@ -4,7 +4,6 @@
|
||||
"description": "Cappuccino module",
|
||||
"keywords": ["objective-j", "objj", "objective j", "capp", "cappuccino"],
|
||||
"author": "280 North, Inc. (http://280north.com/)",
|
||||
"version": "0.8.0",
|
||||
"objj-frameworks": ["Frameworks"],
|
||||
"objj-debug-frameworks": ["Frameworks/Debug"],
|
||||
"contributors": [
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
- (id)initWithArray:(CPArray)anArray
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
|
||||
if (self)
|
||||
{
|
||||
_array = anArray;
|
||||
@@ -67,13 +67,13 @@
|
||||
- (id)initWithArray:(CPArray)anArray
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
|
||||
if (self)
|
||||
{
|
||||
_array = anArray;
|
||||
_index = [_array count];
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
|
||||
@end
|
||||
|
||||
/*!
|
||||
/*!
|
||||
@class CPArray
|
||||
@brief A mutable array backed by a JavaScript Array.
|
||||
@ingroup foundation
|
||||
@@ -145,10 +145,10 @@
|
||||
{
|
||||
var i = 2,
|
||||
array = [[self alloc] init],
|
||||
argument;
|
||||
count = arguments.length;
|
||||
|
||||
for(; i < arguments.length && (argument = arguments[i]) != nil; ++i)
|
||||
array.push(argument);
|
||||
for (; i < count; ++i)
|
||||
array.push(arguments[i]);
|
||||
|
||||
return array;
|
||||
}
|
||||
@@ -182,10 +182,10 @@
|
||||
- (id)initWithArray:(CPArray)anArray
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
|
||||
if (self)
|
||||
[self setArray:anArray];
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -203,22 +203,22 @@
|
||||
return [self initWithArray:anArray];
|
||||
|
||||
self = [super init];
|
||||
|
||||
|
||||
if (self)
|
||||
{
|
||||
var index = 0,
|
||||
count = [anArray count];
|
||||
|
||||
for(; index < count; ++index)
|
||||
|
||||
for (; index < count; ++index)
|
||||
{
|
||||
if (anArray[index].isa)
|
||||
self[index] = [anArray[index] copy];
|
||||
// Do a deep/shallow copy?
|
||||
else
|
||||
self[index] = anArray;
|
||||
self[index] = anArray[index];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -229,12 +229,12 @@
|
||||
{
|
||||
// The arguments array contains self and _cmd, so the first object is at position 2.
|
||||
var i = 2,
|
||||
argument;
|
||||
|
||||
for(; i < arguments.length && (argument = arguments[i]) != nil; ++i)
|
||||
push(argument);
|
||||
count = arguments.length;
|
||||
|
||||
return self;
|
||||
for (; i < count; ++i)
|
||||
push(arguments[i]);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -246,12 +246,12 @@
|
||||
- (id)initWithObjects:(id)objects count:(unsigned)aCount
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
|
||||
if (self)
|
||||
{
|
||||
var index = 0;
|
||||
|
||||
for(; index < aCount; ++index)
|
||||
|
||||
for (; index < aCount; ++index)
|
||||
push(objects[index]);
|
||||
}
|
||||
|
||||
@@ -278,97 +278,88 @@
|
||||
|
||||
/*!
|
||||
Returns the index of \c anObject in this array.
|
||||
If the object is \c nil or not in the array,
|
||||
If the object is not in the array,
|
||||
returns \c CPNotFound. It first attempts to find
|
||||
a match using \c -isEqual:, then \c ==.
|
||||
a match using \c -isEqual:, then \c ===.
|
||||
@param anObject the object to search for
|
||||
*/
|
||||
- (int)indexOfObject:(id)anObject
|
||||
{
|
||||
if (anObject === nil)
|
||||
return CPNotFound;
|
||||
|
||||
var i = 0,
|
||||
var i = 0,
|
||||
count = length;
|
||||
|
||||
// Only use -isEqual: if our object is a CPObject.
|
||||
if (anObject.isa)
|
||||
if (anObject && anObject.isa)
|
||||
{
|
||||
for(; i < count; ++i)
|
||||
if([self[i] isEqual:anObject])
|
||||
for (; i < count; ++i)
|
||||
if ([self[i] isEqual:anObject])
|
||||
return i;
|
||||
}
|
||||
// If indexOf exists, use it since it's probably
|
||||
// If indexOf exists, use it since it's probably
|
||||
// faster than anything we can implement.
|
||||
else if (self.indexOf)
|
||||
return indexOf(anObject);
|
||||
// Last resort, do a straight forward linear O(N) search.
|
||||
else
|
||||
for(; i < count; ++i)
|
||||
if(self[i] == anObject)
|
||||
for (; i < count; ++i)
|
||||
if (self[i] === anObject)
|
||||
return i;
|
||||
|
||||
|
||||
return CPNotFound;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the index of \c anObject in the array
|
||||
within \c aRange. It first attempts to find
|
||||
a match using \c -isEqual:, then \c ==.
|
||||
a match using \c -isEqual:, then \c ===.
|
||||
@param anObject the object to search for
|
||||
@param aRange the range to search within
|
||||
@return the index of the object, or \c CPNotFound if it was not found.
|
||||
*/
|
||||
- (int)indexOfObject:(id)anObject inRange:(CPRange)aRange
|
||||
{
|
||||
if (anObject === nil)
|
||||
return CPNotFound;
|
||||
|
||||
var i = aRange.location,
|
||||
var i = aRange.location,
|
||||
count = MIN(CPMaxRange(aRange), length);
|
||||
|
||||
|
||||
// Only use isEqual: if our object is a CPObject.
|
||||
if (anObject.isa)
|
||||
if (anObject && anObject.isa)
|
||||
{
|
||||
for(; i < count; ++i)
|
||||
if([self[i] isEqual:anObject])
|
||||
for (; i < count; ++i)
|
||||
if ([self[i] isEqual:anObject])
|
||||
return i;
|
||||
}
|
||||
// Last resort, do a straight forward linear O(N) search.
|
||||
else
|
||||
for(; i < count; ++i)
|
||||
if(self[i] == anObject)
|
||||
for (; i < count; ++i)
|
||||
if (self[i] === anObject)
|
||||
return i;
|
||||
|
||||
|
||||
return CPNotFound;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the index of \c anObject in the array. The test for equality is done using only \c ==.
|
||||
Returns the index of \c anObject in the array. The test for equality is done using only \c ===.
|
||||
@param anObject the object to search for
|
||||
@return the index of the object in the array. \c CPNotFound if the object is not in the array.
|
||||
*/
|
||||
- (int)indexOfObjectIdenticalTo:(id)anObject
|
||||
{
|
||||
if (anObject === nil)
|
||||
return CPNotFound;
|
||||
|
||||
// If indexOf exists, use it since it's probably
|
||||
// If indexOf exists, use it since it's probably
|
||||
// faster than anything we can implement.
|
||||
if (self.indexOf)
|
||||
return indexOf(anObject);
|
||||
|
||||
|
||||
// Last resort, do a straight forward linear O(N) search.
|
||||
else
|
||||
{
|
||||
var index = 0,
|
||||
var index = 0,
|
||||
count = length;
|
||||
|
||||
for(; index < count; ++index)
|
||||
if(self[index] === anObject)
|
||||
|
||||
for (; index < count; ++index)
|
||||
if (self[index] === anObject)
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
return CPNotFound;
|
||||
}
|
||||
|
||||
@@ -382,36 +373,33 @@
|
||||
*/
|
||||
- (int)indexOfObjectIdenticalTo:(id)anObject inRange:(CPRange)aRange
|
||||
{
|
||||
if (anObject === nil)
|
||||
return CPNotFound;
|
||||
|
||||
// If indexOf exists, use it since it's probably
|
||||
// If indexOf exists, use it since it's probably
|
||||
// faster than anything we can implement.
|
||||
if (self.indexOf)
|
||||
{
|
||||
var index = indexOf(anObject, aRange.location);
|
||||
|
||||
|
||||
if (CPLocationInRange(index, aRange))
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
// Last resort, do a straight forward linear O(N) search.
|
||||
else
|
||||
{
|
||||
var index = aRange.location,
|
||||
var index = aRange.location,
|
||||
count = MIN(CPMaxRange(aRange), length);
|
||||
|
||||
for(; index < count; ++index)
|
||||
if(self[index] == anObject)
|
||||
|
||||
for (; index < count; ++index)
|
||||
if (self[index] == anObject)
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
return CPNotFound;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the index of \c anObject in the array, which must be sorted in the same order as
|
||||
calling sortUsingSelector: with the selector passed to this method would result in.
|
||||
calling sortUsingSelector: with the selector passed to this method would result in.
|
||||
@param anObject the object to search for
|
||||
@param aSelector the comparison selector to call on each item in the list, the same
|
||||
selector should have been used to sort the array (or to maintain its sorted order).
|
||||
@@ -419,12 +407,12 @@
|
||||
*/
|
||||
- (unsigned)indexOfObject:(id)anObject sortedBySelector:(SEL)aSelector
|
||||
{
|
||||
return [self indexOfObject:anObject sortedByFunction: function(lhs, rhs) { objj_msgSend(lhs, aSelector, rhs); }];
|
||||
return [self indexOfObject:anObject sortedByFunction:function(lhs, rhs) { objj_msgSend(lhs, aSelector, rhs); }];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the index of \c anObject in the array, which must be sorted in the same order as
|
||||
calling sortUsingFunction: with the selector passed to this method would result in.
|
||||
calling sortUsingFunction: with the selector passed to this method would result in.
|
||||
The function will be called like so:
|
||||
<pre>
|
||||
aFunction(anObject, currentObjectInArrayForComparison)
|
||||
@@ -441,7 +429,7 @@
|
||||
|
||||
/*!
|
||||
Returns the index of \c anObject in the array, which must be sorted in the same order as
|
||||
calling sortUsingFunction: with the selector passed to this method would result in.
|
||||
calling sortUsingFunction: with the selector passed to this method would result in.
|
||||
The function will be called like so:
|
||||
<pre>
|
||||
aFunction(anObject, currentObjectInArrayForComparison, context)
|
||||
@@ -454,10 +442,23 @@
|
||||
*/
|
||||
- (unsigned)indexOfObject:(id)anObject sortedByFunction:(Function)aFunction context:(id)aContext
|
||||
{
|
||||
if (!aFunction || anObject === undefined)
|
||||
var result = [self _indexOfObject:anObject sortedByFunction:aFunction context:aContext];
|
||||
return result >= 0 ? result : CPNotFound;
|
||||
}
|
||||
|
||||
- (unsigned)_indexOfObject:(id)anObject sortedByFunction:(Function)aFunction context:(id)aContext
|
||||
{
|
||||
if (!aFunction)
|
||||
return CPNotFound;
|
||||
|
||||
var mid, c, first = 0, last = length - 1;
|
||||
if (length === 0)
|
||||
return -1;
|
||||
|
||||
var mid,
|
||||
c,
|
||||
first = 0,
|
||||
last = length - 1;
|
||||
|
||||
while (first <= last)
|
||||
{
|
||||
mid = FLOOR((first + last) / 2);
|
||||
@@ -476,12 +477,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
return CPNotFound;
|
||||
return -first - 1;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the index of \c anObject in the array, which must be sorted in the same order as
|
||||
calling sortUsingDescriptors: with the descriptors passed to this method would result in.
|
||||
calling sortUsingDescriptors: with the descriptors passed to this method would result in.
|
||||
@param anObject the object to search for
|
||||
@param descriptors the array of descriptors to use to compare each item in the array that we search. the same
|
||||
descriptors should have been used to sort the array (or to maintain its sorted order).
|
||||
@@ -496,7 +497,7 @@
|
||||
result = CPOrderedSame;
|
||||
|
||||
while (i < count)
|
||||
if((result = [descriptors[i++] compareObject:lhs withObject:rhs]) != CPOrderedSame)
|
||||
if ((result = [descriptors[i++] compareObject:lhs withObject:rhs]) != CPOrderedSame)
|
||||
return result;
|
||||
|
||||
return result;
|
||||
@@ -509,9 +510,10 @@
|
||||
- (id)lastObject
|
||||
{
|
||||
var count = [self count];
|
||||
|
||||
if (!count) return nil;
|
||||
|
||||
|
||||
if (!count)
|
||||
return nil;
|
||||
|
||||
return self[count - 1];
|
||||
}
|
||||
|
||||
@@ -537,7 +539,7 @@
|
||||
var index = CPNotFound,
|
||||
objects = [];
|
||||
|
||||
while((index = [indexes indexGreaterThanIndex:index]) !== CPNotFound)
|
||||
while ((index = [indexes indexGreaterThanIndex:index]) !== CPNotFound)
|
||||
[objects addObject:[self objectAtIndex:index]];
|
||||
|
||||
return objects;
|
||||
@@ -573,11 +575,11 @@
|
||||
{
|
||||
if (!aSelector)
|
||||
[CPException raise:CPInvalidArgumentException reason:"makeObjectsPerformSelector: 'aSelector' can't be nil"];
|
||||
|
||||
var index = 0,
|
||||
|
||||
var index = 0,
|
||||
count = length;
|
||||
|
||||
for(; index < count; ++index)
|
||||
|
||||
for (; index < count; ++index)
|
||||
objj_msgSend(self[index], aSelector);
|
||||
}
|
||||
|
||||
@@ -592,10 +594,10 @@
|
||||
if (!aSelector)
|
||||
[CPException raise:CPInvalidArgumentException reason:"makeObjectsPerformSelector:withObject 'aSelector' can't be nil"];
|
||||
|
||||
var index = 0,
|
||||
var index = 0,
|
||||
count = length;
|
||||
|
||||
for(; index < count; ++index)
|
||||
|
||||
for (; index < count; ++index)
|
||||
objj_msgSend(self[index], aSelector, anObject);
|
||||
}
|
||||
|
||||
@@ -608,7 +610,7 @@
|
||||
count = length,
|
||||
argumentsArray = [nil, aSelector].concat(objects || []);
|
||||
|
||||
for(; index < count; ++index)
|
||||
for (; index < count; ++index)
|
||||
{
|
||||
argumentsArray[0] = self[index];
|
||||
objj_msgSend.apply(this, argumentsArray);
|
||||
@@ -626,12 +628,12 @@
|
||||
{
|
||||
if (![anArray count] || ![self count])
|
||||
return nil;
|
||||
|
||||
|
||||
var i = 0,
|
||||
count = [self count];
|
||||
|
||||
for(; i < count; ++i)
|
||||
if([anArray containsObject:self[i]])
|
||||
for (; i < count; ++i)
|
||||
if ([anArray containsObject:self[i]])
|
||||
return self[i];
|
||||
|
||||
return nil;
|
||||
@@ -644,23 +646,23 @@
|
||||
{
|
||||
if (self === anArray)
|
||||
return YES;
|
||||
|
||||
if(length != anArray.length)
|
||||
|
||||
if (anArray === nil || length !== anArray.length)
|
||||
return NO;
|
||||
|
||||
|
||||
var index = 0,
|
||||
count = [self count];
|
||||
|
||||
for(; index < count; ++index)
|
||||
|
||||
for (; index < count; ++index)
|
||||
{
|
||||
var lhs = self[index],
|
||||
rhs = anArray[index];
|
||||
|
||||
|
||||
// If they're not equal, and either doesn't have an isa, or they're !isEqual (not isEqual)
|
||||
if (lhs !== rhs && (lhs && !lhs.isa || rhs && !rhs.isa || ![lhs isEqual:rhs]))
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@@ -668,8 +670,8 @@
|
||||
{
|
||||
if (self === anObject)
|
||||
return YES;
|
||||
|
||||
if(![anObject isKindOfClass:[CPArray class]])
|
||||
|
||||
if (![anObject isKindOfClass:[CPArray class]])
|
||||
return NO;
|
||||
|
||||
return [self isEqualToArray:anObject];
|
||||
@@ -684,14 +686,9 @@
|
||||
*/
|
||||
- (CPArray)arrayByAddingObject:(id)anObject
|
||||
{
|
||||
if (anObject === nil || anObject === undefined)
|
||||
[CPException raise:CPInvalidArgumentException
|
||||
reason:"arrayByAddingObject: object can't be nil"];
|
||||
|
||||
var array = [self copy];
|
||||
|
||||
array.push(anObject);
|
||||
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
@@ -704,17 +701,17 @@
|
||||
return slice(0).concat(anArray);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
- (CPArray)filteredArrayUsingPredicate:(CPPredicate)aPredicate
|
||||
{
|
||||
var i= 0,
|
||||
var i= 0,
|
||||
count = [self count],
|
||||
array = [CPArray array];
|
||||
|
||||
for(; i<count; ++i)
|
||||
if(aPredicate.evaluateWithObject(self[i]))
|
||||
|
||||
for (; i<count; ++i)
|
||||
if (aPredicate.evaluateWithObject(self[i]))
|
||||
array.push(self[i]);
|
||||
|
||||
|
||||
return array;
|
||||
}
|
||||
*/
|
||||
@@ -739,9 +736,9 @@
|
||||
- (CPArray)sortedArrayUsingDescriptors:(CPArray)descriptors
|
||||
{
|
||||
var sorted = [self copy];
|
||||
|
||||
|
||||
[sorted sortUsingDescriptors:descriptors];
|
||||
|
||||
|
||||
return sorted;
|
||||
}
|
||||
|
||||
@@ -764,9 +761,9 @@
|
||||
- (CPArray)sortedArrayUsingFunction:(Function)aFunction context:(id)aContext
|
||||
{
|
||||
var sorted = [self copy];
|
||||
|
||||
|
||||
[sorted sortUsingFunction:aFunction context:aContext];
|
||||
|
||||
|
||||
return sorted;
|
||||
}
|
||||
|
||||
@@ -777,7 +774,7 @@
|
||||
- (CPArray)sortedArrayUsingSelector:(SEL)aSelector
|
||||
{
|
||||
var sorted = [self copy]
|
||||
|
||||
|
||||
[sorted sortUsingSelector:aSelector];
|
||||
|
||||
return sorted;
|
||||
@@ -811,7 +808,7 @@
|
||||
count = [self count],
|
||||
description = '(';
|
||||
|
||||
for(; index < count; ++index)
|
||||
for (; index < count; ++index)
|
||||
{
|
||||
if (index === 0)
|
||||
description += '\n';
|
||||
@@ -843,11 +840,11 @@
|
||||
var index = 0,
|
||||
count = [self count],
|
||||
array = [];
|
||||
|
||||
for(; index < count; ++index)
|
||||
|
||||
for (; index < count; ++index)
|
||||
if (self[index].isa && [self[index] isKindOfClass:[CPString class]] && [filterTypes containsObject:[self[index] pathExtension]])
|
||||
array.push(self[index]);
|
||||
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
@@ -861,8 +858,8 @@
|
||||
{
|
||||
var i = 0,
|
||||
count = [self count];
|
||||
|
||||
for(; i < count; ++i)
|
||||
|
||||
for (; i < count; ++i)
|
||||
[self[i] setValue:aValue forKey:aKey];
|
||||
}
|
||||
|
||||
@@ -876,10 +873,10 @@
|
||||
var i = 0,
|
||||
count = [self count],
|
||||
array = [];
|
||||
|
||||
for(; i < count; ++i)
|
||||
|
||||
for (; i < count; ++i)
|
||||
array.push([self[i] valueForKey:aKey]);
|
||||
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
@@ -893,7 +890,7 @@
|
||||
{
|
||||
return slice(0);
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPArray(CPMutableArray)
|
||||
@@ -956,22 +953,44 @@
|
||||
{
|
||||
var indexesCount = [indexes count],
|
||||
objectsCount = [objects count];
|
||||
|
||||
if(indexesCount !== objectsCount)
|
||||
|
||||
if (indexesCount !== objectsCount)
|
||||
[CPException raise:CPRangeException reason:"the counts of the passed-in array (" + objectsCount + ") and index set (" + indexesCount + ") must be identical."];
|
||||
|
||||
|
||||
var lastIndex = [indexes lastIndex];
|
||||
|
||||
if(lastIndex >= [self count] + indexesCount)
|
||||
[CPException raise:CPRangeException reason:"the last index (" + lastIndex + ") must be less than the sum of the original count (" + [self count] + ") and the insertion count (" + indexesCount + ")."];
|
||||
|
||||
|
||||
if (lastIndex >= [self count] + indexesCount)
|
||||
[CPException raise:CPRangeException reason:"the last index (" + lastIndex + ") must be less than the sum of the original count (" + [self count] + ") and the insertion count (" + indexesCount + ")."];
|
||||
|
||||
var index = 0,
|
||||
currentIndex = [indexes firstIndex];
|
||||
|
||||
|
||||
for (; index < objectsCount; ++index, currentIndex = [indexes indexGreaterThanIndex:currentIndex])
|
||||
[self insertObject:objects[index] atIndex:currentIndex];
|
||||
}
|
||||
|
||||
- (unsigned)insertObject:(id)anObject inArraySortedByDescriptors:(CPArray)descriptors
|
||||
{
|
||||
var index = [self _indexOfObject:anObject sortedByFunction:function(lhs, rhs)
|
||||
{
|
||||
var i = 0,
|
||||
count = [descriptors count],
|
||||
result = CPOrderedSame;
|
||||
|
||||
while (i < count)
|
||||
if ((result = [descriptors[i++] compareObject:lhs withObject:rhs]) != CPOrderedSame)
|
||||
return result;
|
||||
|
||||
return result;
|
||||
} context:nil];
|
||||
|
||||
if (index < 0)
|
||||
index = -index - 1;
|
||||
|
||||
[self insertObject:anObject atIndex:index];
|
||||
return index;
|
||||
}
|
||||
|
||||
/*!
|
||||
Replaces the element at \c anIndex with \c anObject.
|
||||
The current element at position \c anIndex will be removed from the array.
|
||||
@@ -990,10 +1009,10 @@
|
||||
*/
|
||||
- (void)replaceObjectsAtIndexes:(CPIndexSet)anIndexSet withObjects:(CPArray)objects
|
||||
{
|
||||
var i = 0,
|
||||
var i = 0,
|
||||
index = [anIndexSet firstIndex];
|
||||
|
||||
while(index != CPNotFound)
|
||||
|
||||
while (index != CPNotFound)
|
||||
{
|
||||
[self replaceObjectAtIndex:index withObject:objects[i++]];
|
||||
index = [anIndexSet indexGreaterThanIndex:index];
|
||||
@@ -1034,8 +1053,9 @@
|
||||
*/
|
||||
- (void)setArray:(CPArray)anArray
|
||||
{
|
||||
if(self == anArray) return;
|
||||
|
||||
if (self == anArray)
|
||||
return;
|
||||
|
||||
splice.apply(self, [0, length].concat(anArray));
|
||||
}
|
||||
|
||||
@@ -1073,7 +1093,7 @@
|
||||
- (void)removeObject:(id)anObject inRange:(CPRange)aRange
|
||||
{
|
||||
var index;
|
||||
|
||||
|
||||
while ((index = [self indexOfObject:anObject inRange:aRange]) != CPNotFound)
|
||||
{
|
||||
[self removeObjectAtIndex:index];
|
||||
@@ -1097,7 +1117,7 @@
|
||||
- (void)removeObjectsAtIndexes:(CPIndexSet)anIndexSet
|
||||
{
|
||||
var index = [anIndexSet lastIndex];
|
||||
|
||||
|
||||
while (index != CPNotFound)
|
||||
{
|
||||
[self removeObjectAtIndex:index];
|
||||
@@ -1126,7 +1146,7 @@
|
||||
{
|
||||
var index,
|
||||
count = [self count];
|
||||
|
||||
|
||||
while ((index = [self indexOfObjectIdenticalTo:anObject inRange:aRange]) !== CPNotFound)
|
||||
{
|
||||
[self removeObjectAtIndex:index];
|
||||
@@ -1142,7 +1162,7 @@
|
||||
{
|
||||
var index = 0,
|
||||
count = [anArray count];
|
||||
|
||||
|
||||
for (; index < count; ++index)
|
||||
[self removeObject:anArray[index]];
|
||||
}
|
||||
@@ -1176,11 +1196,11 @@
|
||||
var i = 0,
|
||||
count = [descriptors count],
|
||||
result = CPOrderedSame;
|
||||
|
||||
while(i < count)
|
||||
if((result = [descriptors[i++] compareObject:lhs withObject:rhs]) != CPOrderedSame)
|
||||
|
||||
while (i < count)
|
||||
if ((result = [descriptors[i++] compareObject:lhs withObject:rhs]) != CPOrderedSame)
|
||||
return result;
|
||||
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -153,6 +153,12 @@
|
||||
continue;
|
||||
|
||||
var value = object[key];
|
||||
|
||||
if (value === null)
|
||||
{
|
||||
[dictionary setObject:[CPNull null] forKey:key];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (recursively)
|
||||
{
|
||||
@@ -521,6 +527,11 @@
|
||||
return self.toString();
|
||||
}
|
||||
|
||||
- (BOOL)containsKey:(id)aKey
|
||||
{
|
||||
var value = [self objectForKey:aKey];
|
||||
return ((value !== nil) && (value !== undefined));
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation CPDictionary (CPCoding)
|
||||
|
||||
@@ -739,7 +739,10 @@
|
||||
shifts = [];
|
||||
|
||||
for (; j < count; ++j)
|
||||
{
|
||||
[shifts addObject:_ranges[j]];
|
||||
_count -= _ranges[j].length;
|
||||
}
|
||||
|
||||
if ((j = i + 1) < count)
|
||||
{
|
||||
|
||||
@@ -56,7 +56,7 @@ CPJSONPCallbackReplacementString = @"${JSONP_CALLBACK}";
|
||||
|
||||
+ (CPJSONPConnection)connectionWithRequest:(CPURLRequest)aRequest callback:(CPString)callbackParameter delegate:(id)aDelegate
|
||||
{
|
||||
return [[[self class] alloc] initWithRequest:aRequest callback:callbackParameter delegate:aDelegate startImmediately:YES];;
|
||||
return [[[self class] alloc] initWithRequest:aRequest callback:callbackParameter delegate:aDelegate startImmediately:YES];
|
||||
}
|
||||
|
||||
- (id)initWithRequest:(CPURLRequest)aRequest callback:(CPString)aString delegate:(id)aDelegate
|
||||
@@ -88,7 +88,12 @@ CPJSONPCallbackReplacementString = @"${JSONP_CALLBACK}";
|
||||
{
|
||||
CPJSONPConnectionCallbacks["callback"+[self UID]] = function(data)
|
||||
{
|
||||
[_delegate connection:self didReceiveData:data];
|
||||
if ([_delegate respondsToSelector:@selector(connection:didReceiveData:)])
|
||||
[_delegate connection:self didReceiveData:data];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(connectionDidFinishLoading:)])
|
||||
[_delegate connectionDidFinishLoading:self];
|
||||
|
||||
[self removeScriptTag];
|
||||
|
||||
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
||||
@@ -118,7 +123,9 @@ CPJSONPCallbackReplacementString = @"${JSONP_CALLBACK}";
|
||||
}
|
||||
catch (exception)
|
||||
{
|
||||
[_delegate connection: self didFailWithError: exception];
|
||||
if ([_delegate respondsToSelector:@selector(connection:didFailWithError:)])
|
||||
[_delegate connection: self didFailWithError: exception];
|
||||
|
||||
[self removeScriptTag];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,5 +277,14 @@ CPUnknownUserInfoKey = @"CPUnknownUserInfoKey";
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPNull (KeyValueCoding)
|
||||
|
||||
- (id)valueForKey:(CPString)aKey
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@import "CPKeyValueObserving.j"
|
||||
@import "CPArray+KVO.j"
|
||||
|
||||
@@ -480,6 +480,12 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld,
|
||||
|
||||
- (void)willChangeValueForKey:(CPString)aKey
|
||||
{
|
||||
var superClass = [self class],
|
||||
methodSelector = @selector(willChangeValueForKey:),
|
||||
methodImp = class_getMethodImplementation(superClass, methodSelector);
|
||||
|
||||
methodImp(self, methodSelector, aKey);
|
||||
|
||||
if (!aKey)
|
||||
return;
|
||||
|
||||
@@ -490,6 +496,12 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld,
|
||||
|
||||
- (void)didChangeValueForKey:(CPString)aKey
|
||||
{
|
||||
var superClass = [self class],
|
||||
methodSelector = @selector(didChangeValueForKey:),
|
||||
methodImp = class_getMethodImplementation(superClass, methodSelector);
|
||||
|
||||
methodImp(self, methodSelector, aKey);
|
||||
|
||||
if (!aKey)
|
||||
return;
|
||||
|
||||
@@ -498,6 +510,12 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld,
|
||||
|
||||
- (void)willChange:(CPKeyValueChange)change valuesAtIndexes:(CPIndexSet)indexes forKey:(CPString)aKey
|
||||
{
|
||||
var superClass = [self class],
|
||||
methodSelector = @selector(willChange:valuesAtIndexes:forKey:),
|
||||
methodImp = class_getMethodImplementation(superClass, methodSelector);
|
||||
|
||||
methodImp(self, methodSelector, change, indexes, aKey);
|
||||
|
||||
if (!aKey)
|
||||
return;
|
||||
|
||||
@@ -508,6 +526,12 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld,
|
||||
|
||||
- (void)didChange:(CPKeyValueChange)change valuesAtIndexes:(CPIndexSet)indexes forKey:(CPString)aKey
|
||||
{
|
||||
var superClass = [self class],
|
||||
methodSelector = @selector(didChange:valuesAtIndexes:forKey:),
|
||||
methodImp = class_getMethodImplementation(superClass, methodSelector);
|
||||
|
||||
methodImp(self, methodSelector, change, indexes, aKey);
|
||||
|
||||
if (!aKey)
|
||||
return;
|
||||
|
||||
|
||||
@@ -163,9 +163,15 @@ var CPArrayClass = Ni
|
||||
@param data the data from which to read the graph
|
||||
@return the unarchived object
|
||||
*/
|
||||
+ (id)unarchiveObjectWithData:(CPData)data
|
||||
+ (id)unarchiveObjectWithData:(CPData)aData
|
||||
{
|
||||
var unarchiver = [[self alloc] initForReadingWithData:data],
|
||||
if (!aData)
|
||||
{
|
||||
CPLog.error("Null data passed to -[CPKeyedUnarchiver unarchiveObjectWithData:].");
|
||||
return nil;
|
||||
}
|
||||
|
||||
var unarchiver = [[self alloc] initForReadingWithData:aData],
|
||||
object = [unarchiver decodeObjectForKey:@"root"];
|
||||
|
||||
[unarchiver finishDecoding];
|
||||
@@ -200,7 +206,7 @@ var CPArrayClass = Ni
|
||||
- (CPDictionary)_decodeDictionaryOfObjectsForKey:(CPString)aKey
|
||||
{
|
||||
var object = _plistObject.valueForKey(aKey),
|
||||
objectClass = object && object.isa;
|
||||
objectClass = (object != nil) && object.isa;
|
||||
|
||||
if (objectClass === CPDictionaryClass || objectClass === CPMutableDictionaryClass)
|
||||
{
|
||||
@@ -315,7 +321,7 @@ var CPArrayClass = Ni
|
||||
- (id)decodeObjectForKey:(CPString)aKey
|
||||
{
|
||||
var object = _plistObject.valueForKey(aKey),
|
||||
objectClass = object && object.isa;
|
||||
objectClass = (object != nil) && object.isa;
|
||||
|
||||
if (objectClass === CPDictionaryClass || objectClass === CPMutableDictionaryClass)
|
||||
return _CPKeyedUnarchiverDecodeObjectAtIndex(self, object.valueForKey(_CPKeyedArchiverUIDKey));
|
||||
@@ -465,7 +471,7 @@ var _CPKeyedUnarchiverDecodeObjectAtIndex = function(self, anIndex)
|
||||
|
||||
self._plistObject = savedPlistObject;
|
||||
|
||||
if (processedObject != object)
|
||||
if (processedObject !== object)
|
||||
{
|
||||
if (self._delegateSelectors & _CPKeyedUnarchiverWillReplaceObjectWithObjectSelector)
|
||||
[self._delegate unarchiver:self willReplaceObject:object withObject:processedObject];
|
||||
@@ -519,7 +525,7 @@ var _CPKeyedUnarchiverDecodeObjectAtIndex = function(self, anIndex)
|
||||
|
||||
// If this object is a member of _CPKeyedArchiverValue, then we know
|
||||
// that it is a wrapper for a primitive JavaScript object.
|
||||
if (object.isa === _CPKeyedArchiverValueClass)
|
||||
if ((object != nil) && (object.isa === _CPKeyedArchiverValueClass))
|
||||
object = [object JSObject];
|
||||
|
||||
return object;
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
var CPNullSharedNull = nil;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
@class CPNull
|
||||
@ingroup foundation
|
||||
@brief An object representation of \c nil.
|
||||
@@ -41,7 +41,7 @@ var CPNullSharedNull = nil;
|
||||
{
|
||||
if (CPNullSharedNull)
|
||||
return CPNullSharedNull;
|
||||
|
||||
|
||||
return [super alloc];
|
||||
}*/
|
||||
/*!
|
||||
@@ -53,8 +53,27 @@ var CPNullSharedNull = nil;
|
||||
{
|
||||
if (!CPNullSharedNull)
|
||||
CPNullSharedNull = [[CPNull alloc] init];
|
||||
|
||||
|
||||
return CPNullSharedNull;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns CPNull null.
|
||||
@param aCoder the coder from which to do nothing
|
||||
@return [CPNull null]
|
||||
*/
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
return [CPNull null];
|
||||
}
|
||||
|
||||
/*!
|
||||
Writes out nothing to the specified coder.
|
||||
@param aCoder the coder to which nothing will
|
||||
be written
|
||||
*/
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
- (void)forwardInvocation:(CPInvocation)anInvocation
|
||||
{
|
||||
[CPException raise:CPInvalidArgumentException
|
||||
reason:@"-methodSignatureForSelector: called on abstract CPProxy class."];
|
||||
reason:@"-forwardInvocation: called on abstract CPProxy class."];
|
||||
}
|
||||
|
||||
// FIXME: This should be moved to the runtime?
|
||||
|
||||
@@ -157,6 +157,7 @@ var CPRunLoopLastNativeRunLoop = 0;
|
||||
CPDate _effectiveDate;
|
||||
|
||||
CPArray _orderedPerforms;
|
||||
int _runLoopInsuranceTimer;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -267,6 +268,17 @@ var CPRunLoopLastNativeRunLoop = 0;
|
||||
aTimer._lastNativeRunLoopsForModes = {};
|
||||
|
||||
aTimer._lastNativeRunLoopsForModes[aMode] = CPRunLoopLastNativeRunLoop;
|
||||
|
||||
|
||||
// FIXME: Hack for not doing this in CommonJS
|
||||
if ([CFBundle.environments() indexOfObject:("Browser")] !== CPNotFound)
|
||||
{
|
||||
if (!_runLoopInsuranceTimer)
|
||||
_runLoopInsuranceTimer = window.setNativeTimeout(function()
|
||||
{
|
||||
[self limitDateForMode:CPDefaultRunLoopMode];
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -277,9 +289,19 @@ var CPRunLoopLastNativeRunLoop = 0;
|
||||
//simple locking to try to prevent concurrent iterating over timers
|
||||
if (_runLoopLock)
|
||||
return;
|
||||
|
||||
|
||||
_runLoopLock = YES;
|
||||
|
||||
|
||||
// FIXME: Hack for not doing this in CommonJS
|
||||
if ([CFBundle.environments() indexOfObject:("Browser")] !== CPNotFound)
|
||||
{
|
||||
if (_runLoopInsuranceTimer)
|
||||
{
|
||||
window.clearNativeTimeout(_runLoopInsuranceTimer);
|
||||
_runLoopInsuranceTimer = nil;
|
||||
}
|
||||
}
|
||||
|
||||
var now = _effectiveDate ? [_effectiveDate laterDate:[CPDate date]] : [CPDate date],
|
||||
nextFireDate = nil,
|
||||
nextTimerFireDate = _nextTimerFireDatesForModes[aMode];
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
*
|
||||
* TODO: Needs to implement CPCoding, CPCopying.
|
||||
*/
|
||||
|
||||
|
||||
@import "CPObject.j"
|
||||
@import "CPArray.j"
|
||||
@import "CPNumber.j"
|
||||
@@ -79,7 +79,7 @@
|
||||
/*
|
||||
Creates and returns a set containing the objects in a given argument list.
|
||||
@param anObject The first object to add to the new set.
|
||||
@param ... A comma-separated list of objects, ending with nil, to add to the new set. If the same object appears more than once objects, it is added only once to the returned set.
|
||||
@param ... A comma-separated list of objects, ending with nil, to add to the new set. If the same object appears more than once objects, it is added only once to the returned set.
|
||||
*/
|
||||
+ (id)setWithObjects:(id)anObject, ...
|
||||
{
|
||||
@@ -89,7 +89,7 @@
|
||||
|
||||
for(; i < argLength && ((argument = arguments[i]) !== nil); ++i)
|
||||
[set addObject:argument];
|
||||
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
_count = 0;
|
||||
_contents = {};
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -121,21 +121,21 @@
|
||||
@param array An array of objects to add to the new set. If the same object appears more than once in array, it is represented only once in the returned set.
|
||||
*/
|
||||
- (id)initWithArray:(CPArray)anArray
|
||||
{
|
||||
{
|
||||
if (self = [self init])
|
||||
{
|
||||
var count = anArray.length;
|
||||
|
||||
|
||||
while (count--)
|
||||
[self addObject:anArray[count]];
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
Initializes a newly allocated set with members taken from the specified list of objects.
|
||||
@param objects A array of objects to add to the new set. If the same object appears more than once objects, it is added only once to the returned set.
|
||||
@param objects A array of objects to add to the new set. If the same object appears more than once objects, it is added only once to the returned set.
|
||||
@param count The number of objects from objects to add to the new set.
|
||||
*/
|
||||
- (id)initWithObjects:(id)objects count:(unsigned)count
|
||||
@@ -158,7 +158,7 @@
|
||||
for(; i < argLength && (argument = arguments[i]) != nil; ++i)
|
||||
[self addObject:argument];
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -179,9 +179,9 @@
|
||||
|
||||
if (!aSet)
|
||||
return self;
|
||||
|
||||
|
||||
var contents = aSet._contents;
|
||||
|
||||
|
||||
for (var property in contents)
|
||||
{
|
||||
if (contents.hasOwnProperty(property))
|
||||
@@ -192,7 +192,7 @@
|
||||
[self addObject:contents[property]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -202,13 +202,13 @@
|
||||
- (CPArray)allObjects
|
||||
{
|
||||
var array = [];
|
||||
|
||||
|
||||
for (var property in _contents)
|
||||
{
|
||||
if (_contents.hasOwnProperty(property))
|
||||
array.push(_contents[property]);
|
||||
}
|
||||
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@
|
||||
if (_contents.hasOwnProperty(property))
|
||||
return _contents[property];
|
||||
}
|
||||
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@@ -236,7 +236,7 @@
|
||||
|
||||
if (obj !== undefined && [obj isEqual:anObject])
|
||||
return YES;
|
||||
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
@@ -277,7 +277,7 @@
|
||||
@param set The set with which to compare the receiver.
|
||||
*/
|
||||
- (BOOL)isEqualToSet:(CPSet)set
|
||||
{
|
||||
{
|
||||
// If both are subsets of each other, they are equal
|
||||
return self === set || ([self count] === [set count] && [set isSubsetOfSet:self]);
|
||||
}
|
||||
@@ -295,7 +295,7 @@
|
||||
if (![set containsObject:items[i]])
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@@ -330,7 +330,7 @@
|
||||
{
|
||||
if ([self containsObject:object])
|
||||
return object;
|
||||
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@@ -467,6 +467,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (CPString)description
|
||||
{
|
||||
return @"{(" + [self allObjects].join(", ") + ")}";
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPSet (CPCopying)
|
||||
|
||||
@@ -664,6 +664,9 @@ var CPStringRegexSpecialCharacters = [
|
||||
*/
|
||||
- (CPString)pathExtension
|
||||
{
|
||||
if (lastIndexOf('.') === CPNotFound)
|
||||
return "";
|
||||
|
||||
return substr(lastIndexOf('.') + 1);
|
||||
}
|
||||
|
||||
@@ -699,6 +702,21 @@ var CPStringRegexSpecialCharacters = [
|
||||
return path;
|
||||
}
|
||||
|
||||
/*!
|
||||
Deletes the extension of a string.
|
||||
*/
|
||||
- (CPString)stringByDeletingPathExtension
|
||||
{
|
||||
var extension = [self pathExtension];
|
||||
if (extension === "")
|
||||
return self;
|
||||
|
||||
if (lastIndexOf('.') < 1)
|
||||
return self;
|
||||
|
||||
return substr(0, [self length] - (extension.length + 1));
|
||||
}
|
||||
|
||||
- (CPString)stringByStandardizingPath
|
||||
{
|
||||
return objj_standardize_path(self);
|
||||
|
||||
@@ -196,8 +196,8 @@ var CPURLURLStringKey = @"CPURLURLStringKey",
|
||||
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
return [self initWithURLString:[aCoder decodeObjectForKey:CPURLURLStringKey]
|
||||
baseURL:[aCoder decodeObjectForKey:CPURLBaseURLKey]];
|
||||
return [self initWithString:[aCoder decodeObjectForKey:CPURLURLStringKey]
|
||||
relativeToURL:[aCoder decodeObjectForKey:CPURLBaseURLKey]];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
|
||||
@@ -34,7 +34,7 @@ foundationTask = framework ("Foundation", function(foundationTask)
|
||||
foundationTask.setEmail("feedback @nospam@ 280north.com");
|
||||
foundationTask.setSummary("Foundation classes for Cappuccino");
|
||||
foundationTask.setIdentifier("com.280n.Foundation");
|
||||
foundationTask.setVersion("0.8.0");
|
||||
foundationTask.setVersion(getCappuccinoVersion());
|
||||
foundationTask.setLicense(BundleTask.License.LGPL_v2_1);
|
||||
foundationTask.setSources(new FileList("**/*.j"));
|
||||
foundationTask.setResources(new FileList("Resources/**/*"));
|
||||
|
||||
@@ -107,14 +107,16 @@ task ("documentation", function()
|
||||
|
||||
// Downloads
|
||||
|
||||
task ("downloads", ["starter_download", "tools_download"]);
|
||||
task ("downloads", ["starter_download"]);
|
||||
|
||||
$STARTER_README = FILE.join('Tools', 'READMEs', 'STARTER-README');
|
||||
$STARTER_BOOTSTRAP = 'bootstrap.sh';
|
||||
$STARTER_DOWNLOAD = FILE.join($BUILD_DIR, 'Cappuccino', 'Starter');
|
||||
$STARTER_DOWNLOAD_APPLICATION = FILE.join($STARTER_DOWNLOAD, 'NewApplication');
|
||||
$STARTER_DOWNLOAD_README = FILE.join($STARTER_DOWNLOAD, 'README');
|
||||
$STARTER_DOWNLOAD_BOOTSTRAP = FILE.join($STARTER_DOWNLOAD, 'bootstrap.sh');
|
||||
|
||||
task ("starter_download", [$STARTER_DOWNLOAD_APPLICATION, $STARTER_DOWNLOAD_README, "documentation"], function()
|
||||
task ("starter_download", [$STARTER_DOWNLOAD_APPLICATION, $STARTER_DOWNLOAD_README, $STARTER_DOWNLOAD_BOOTSTRAP, "documentation"], function()
|
||||
{
|
||||
if (FILE.exists($DOCUMENTATION_BUILD))
|
||||
{
|
||||
@@ -130,8 +132,8 @@ filedir ($STARTER_DOWNLOAD_APPLICATION, ["CommonJS"], function()
|
||||
|
||||
if (OS.system(["capp", "gen", $STARTER_DOWNLOAD_APPLICATION, "-t", "Application", "--noconfig"]))
|
||||
// FIXME: uncomment this: we get conversion errors
|
||||
//OS.exit(1); // rake abort if ($? != 0)
|
||||
{}
|
||||
OS.exit(1); // rake abort if ($? != 0)
|
||||
//{}
|
||||
// No tools means no objective-j gem
|
||||
// FILE.rm(FILE.join($STARTER_DOWNLOAD_APPLICATION, 'Rakefile'))
|
||||
});
|
||||
@@ -141,36 +143,11 @@ filedir ($STARTER_DOWNLOAD_README, [$STARTER_README], function()
|
||||
cp($STARTER_README, $STARTER_DOWNLOAD_README);
|
||||
});
|
||||
|
||||
$TOOLS_README = FILE.join('Tools', 'READMEs', 'TOOLS-README');
|
||||
$TOOLS_EDITORS = FILE.join('Tools', 'Editors');
|
||||
$TOOLS_INSTALLER = FILE.join('Tools', 'Install', 'install-tools');
|
||||
$TOOLS_DOWNLOAD = FILE.join($BUILD_DIR, 'Cappuccino', 'Tools');
|
||||
$TOOLS_DOWNLOAD_EDITORS = FILE.join($TOOLS_DOWNLOAD, 'Editors');
|
||||
$TOOLS_DOWNLOAD_README = FILE.join($TOOLS_DOWNLOAD, 'README');
|
||||
$TOOLS_DOWNLOAD_INSTALLER = FILE.join($TOOLS_DOWNLOAD, 'install-tools');
|
||||
$TOOLS_DOWNLOAD_COMMONJS = FILE.join($BUILD_DIR, "Cappuccino", "Tools", "CommonJS", "objective-j");
|
||||
|
||||
task ("tools_download", [$TOOLS_DOWNLOAD_EDITORS, $TOOLS_DOWNLOAD_README, $TOOLS_DOWNLOAD_INSTALLER, $TOOLS_DOWNLOAD_COMMONJS]);
|
||||
|
||||
filedir ($TOOLS_DOWNLOAD_EDITORS, [$TOOLS_EDITORS], function()
|
||||
filedir ($STARTER_DOWNLOAD_BOOTSTRAP, [$STARTER_BOOTSTRAP], function()
|
||||
{
|
||||
cp_r(FILE.join($TOOLS_EDITORS, '.'), $TOOLS_DOWNLOAD_EDITORS);
|
||||
});
|
||||
|
||||
filedir ($TOOLS_DOWNLOAD_README, [$TOOLS_README], function()
|
||||
{
|
||||
cp($TOOLS_README, $TOOLS_DOWNLOAD_README);
|
||||
});
|
||||
|
||||
filedir ($TOOLS_DOWNLOAD_INSTALLER, [$TOOLS_INSTALLER], function()
|
||||
{
|
||||
cp($TOOLS_INSTALLER, $TOOLS_DOWNLOAD_INSTALLER);
|
||||
});
|
||||
|
||||
filedir ($TOOLS_DOWNLOAD_COMMONJS, ["CommonJS"], function()
|
||||
{
|
||||
rm_rf($TOOLS_DOWNLOAD_COMMONJS);
|
||||
cp_r($COMMONJS_PRODUCT, $TOOLS_DOWNLOAD_COMMONJS);
|
||||
var bootstrap = FILE.read($STARTER_BOOTSTRAP, { charset : "UTF-8" }).replace('install_capp=""', 'install_capp="yes"');
|
||||
FILE.write($STARTER_DOWNLOAD_BOOTSTRAP, bootstrap, { charset : "UTF-8" });
|
||||
OS.system(["chmod", "+x", $STARTER_DOWNLOAD_BOOTSTRAP]);
|
||||
});
|
||||
|
||||
// Deployment
|
||||
@@ -233,21 +210,28 @@ task ("demos", function()
|
||||
{
|
||||
return this.name();
|
||||
}
|
||||
|
||||
|
||||
FILE.glob(FILE.join(demosDir, "demos", "**/Info.plist")).map(function(demoPath){
|
||||
return new Demo(FILE.dirname(demoPath))
|
||||
}).filter(function(demo){
|
||||
return !demo.excluded();
|
||||
}).forEach(function(demo)
|
||||
{
|
||||
var outputPath = FILE.join(demosDir, demo.name().replace(/\s/g, "-")+".zip");
|
||||
OS.system("cd "+OS.enquote(FILE.dirname(demo.path()))+"; zip -ry -8 "+OS.enquote(outputPath)+" "+OS.enquote(demo.path()));
|
||||
// copy frameworks into the demos
|
||||
cp_r(FILE.join($STARTER_DOWNLOAD_APPLICATION, "Frameworks"), FILE.join(demo.path(), "Frameworks"));
|
||||
rm_rf(FILE.join(demo.path(), "Frameworks", "Debug"));
|
||||
|
||||
var outputPath = demo.name().replace(/\s/g, "-")+".zip";
|
||||
OS.system("cd "+OS.enquote(FILE.dirname(demo.path()))+" && zip -ry -8 "+OS.enquote(outputPath)+" "+OS.enquote(FILE.basename(demo.path())));
|
||||
|
||||
// remove the frameworks
|
||||
rm_rf(FILE.join(demo.path(), "Frameworks"));
|
||||
});
|
||||
});
|
||||
|
||||
// Testing
|
||||
|
||||
task("test", ["build", "test-only"]);
|
||||
task("test", ["CommonJS", "test-only"]);
|
||||
|
||||
task("test-only", function()
|
||||
{
|
||||
@@ -280,21 +264,23 @@ task("push-objective-j", function() {
|
||||
function pushPackage(path, remote, branch)
|
||||
{
|
||||
branch = branch || "master";
|
||||
|
||||
|
||||
var pushPackagesPath = FILE.path(".push-package");
|
||||
|
||||
pushPackagesPath.mkdirs();
|
||||
|
||||
var packagePath = pushPackagesPath.join(remote.replace(/[^\w]/g, "_"));
|
||||
|
||||
stream.print("Pushing \0blue(" + path + "\0) to "+branch+" of \0blue(" + remote + "\0)");
|
||||
|
||||
FILE.mkdirs(".push-package");
|
||||
|
||||
var pushPackageDir = FILE.join(".push-package", remote.replace(/[^\w]/g, "_"));
|
||||
|
||||
if (FILE.exists(pushPackageDir))
|
||||
OS.system(buildCmd([["cd", pushPackageDir], ["git", "fetch"]]));
|
||||
if (packagePath.isDirectory())
|
||||
OS.system(buildCmd([["cd", packagePath], ["git", "fetch"]]));
|
||||
else
|
||||
OS.system(["git", "clone", remote, pushPackageDir]);
|
||||
OS.system(["git", "clone", remote, packagePath]);
|
||||
|
||||
if (OS.system(buildCmd([["cd", pushPackageDir], ["git", "checkout", "origin/"+branch]]))) {
|
||||
if (OS.system(buildCmd([["cd", packagePath], ["git", "checkout", "origin/"+branch]]))) {
|
||||
if (OS.system(buildCmd([
|
||||
["cd", pushPackageDir],
|
||||
["cd", packagePath],
|
||||
["git", "symbolic-ref", "HEAD", "refs/heads/"+branch],
|
||||
["rm", ".git/index"],
|
||||
["git", "clean", "-fdx"]
|
||||
@@ -302,20 +288,30 @@ function pushPackage(path, remote, branch)
|
||||
throw "pushPackage failed";
|
||||
}
|
||||
|
||||
if (OS.system("cd "+OS.enquote(pushPackageDir)+" && git rm --ignore-unmatch -r * && rm -rf *"))
|
||||
if (OS.system("cd "+OS.enquote(packagePath)+" && git rm --ignore-unmatch -r * && rm -rf *"))
|
||||
throw "pushPackage failed";
|
||||
if (OS.system("cp -R "+OS.enquote(path)+"/* "+OS.enquote(pushPackageDir)+"/."))
|
||||
if (OS.system("cp -R "+OS.enquote(path)+"/* "+OS.enquote(packagePath)+"/."))
|
||||
throw "pushPackage failed";
|
||||
|
||||
OS.system(buildCmd([
|
||||
["cd", pushPackageDir],
|
||||
var pkg = JSON.parse(packagePath.join("package.json").read({ charset : "UTF-8" }));
|
||||
|
||||
stream.print(" Version: \0purple(" + pkg["version"] + "\0)");
|
||||
stream.print(" Revision: \0purple(" + pkg["cappuccino-revision"] + "\0)");
|
||||
stream.print(" Timestamp: \0purple(" + pkg["cappuccino-timestamp"] + "\0)");
|
||||
|
||||
var cmd = [
|
||||
["cd", packagePath],
|
||||
["git", "add", "."],
|
||||
["git", "commit", "-m", "Pushed on " + new Date()]
|
||||
]));
|
||||
["git", "commit", "-m", "version="+pkg.version+"; revision="+pkg["cappuccino-revision"]+"; timestamp="+pkg["cappuccino-timestamp"]+";"]
|
||||
];
|
||||
if (pkg["cappuccino-revision"])
|
||||
cmd.push(["git", "tag", "rev-"+pkg["cappuccino-revision"].slice(0,6)]);
|
||||
|
||||
OS.system(buildCmd(cmd));
|
||||
|
||||
if (OS.system(buildCmd([
|
||||
["cd", pushPackageDir],
|
||||
["git", "push", "origin", "HEAD:"+branch]
|
||||
["cd", packagePath],
|
||||
["git", "push", "--tags", "origin", "HEAD:"+branch]
|
||||
])))
|
||||
throw "pushPackage failed";
|
||||
}
|
||||
|
||||
@@ -81,7 +81,36 @@ function resolveMainBundleURL()
|
||||
Executable.fileImporterForURL(mainBundleURL)(mainFileURL.lastPathComponent(), YES, function()
|
||||
{
|
||||
disableCFURLCaching();
|
||||
afterDocumentLoad(main);
|
||||
afterDocumentLoad(function()
|
||||
{
|
||||
var hashString = window.location.hash.substring(1),
|
||||
args = [];
|
||||
|
||||
if (hashString.length)
|
||||
{
|
||||
args = hashString.split("/");
|
||||
for (var i = 0, count = args.length; i < count; i++)
|
||||
args[i] = decodeURIComponent(args[i]);
|
||||
}
|
||||
|
||||
var namedArgsArray = window.location.search.substring(1).split("&"),
|
||||
namedArgs = new CFMutableDictionary();
|
||||
|
||||
for (var i = 0, count = namedArgsArray.length; i < count; i++)
|
||||
{
|
||||
var thisArg = namedArgsArray[i].split("=");
|
||||
|
||||
if (!thisArg[0])
|
||||
continue;
|
||||
|
||||
if (thisArg[1] == null)
|
||||
thisArg[1] = true;
|
||||
|
||||
namedArgs.setValueForKey(decodeURIComponent(thisArg[0]), decodeURIComponent(thisArg[1]));
|
||||
}
|
||||
|
||||
main(args, namedArgs);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ GLOBAL(CFBundle) = function(/*CFURL|String*/ aURL)
|
||||
this._resourcesDirectoryURL = new CFURL("Resources/", aURL);
|
||||
|
||||
this._staticResource = NULL;
|
||||
this._isValid = NO;
|
||||
|
||||
this._loadStatus = CFBundleUnloaded;
|
||||
this._loadRequests = [];
|
||||
@@ -58,34 +59,47 @@ GLOBAL(CFBundle) = function(/*CFURL|String*/ aURL)
|
||||
this._eventDispatcher = new EventDispatcher(this);
|
||||
}
|
||||
|
||||
DISPLAY_NAME(CFBundle);
|
||||
|
||||
CFBundle.environments = function()
|
||||
{
|
||||
// Passed in by GCC.
|
||||
return ENVIRONMENTS;
|
||||
}
|
||||
|
||||
DISPLAY_NAME(CFBundle.environments);
|
||||
|
||||
CFBundle.bundleContainingURL = function(/*CFURL|String*/ aURL)
|
||||
{
|
||||
aURL = new CFURL(".", makeAbsoluteURL(aURL));
|
||||
|
||||
while (aURL.path() !== "/")
|
||||
{
|
||||
var bundle = CFBundlesForURLStrings[aURL.absoluteString()];
|
||||
var previousURLString,
|
||||
URLString = aURL.absoluteString();
|
||||
|
||||
if (bundle)
|
||||
while (!previousURLString || previousURLString !== URLString)
|
||||
{
|
||||
var bundle = CFBundlesForURLStrings[URLString];
|
||||
|
||||
if (bundle && bundle._isValid)
|
||||
return bundle;
|
||||
|
||||
aURL = new CFURL("..", aURL);
|
||||
previousURLString = URLString;
|
||||
URLString = aURL.absoluteString();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DISPLAY_NAME(CFBundle.bundleContainingURL);
|
||||
|
||||
CFBundle.mainBundle = function()
|
||||
{
|
||||
return new CFBundle(mainBundleURL);
|
||||
}
|
||||
|
||||
DISPLAY_NAME(CFBundle.mainBundle);
|
||||
|
||||
function addClassToBundle(aClass, aBundle)
|
||||
{
|
||||
if (aBundle)
|
||||
@@ -97,16 +111,22 @@ CFBundle.bundleForClass = function(/*Class*/ aClass)
|
||||
return CFBundlesForClasses[aClass.name] || CFBundle.mainBundle();
|
||||
}
|
||||
|
||||
DISPLAY_NAME(CFBundle.bundleForClass);
|
||||
|
||||
CFBundle.prototype.bundleURL = function()
|
||||
{
|
||||
return this._bundleURL;
|
||||
}
|
||||
|
||||
DISPLAY_NAME(CFBundle.prototype.bundleURL);
|
||||
|
||||
CFBundle.prototype.resourcesDirectoryURL = function()
|
||||
{
|
||||
return this._resourcesDirectoryURL;
|
||||
}
|
||||
|
||||
DISPLAY_NAME(CFBundle.prototype.resourcesDirectoryURL);
|
||||
|
||||
CFBundle.prototype.resourceURL = function(/*String*/ aResourceName, /*String*/ aType, /*String*/ aSubDirectory)
|
||||
{
|
||||
if (aType)
|
||||
@@ -120,6 +140,8 @@ CFBundle.prototype.resourceURL = function(/*String*/ aResourceName, /*String*/ a
|
||||
return resourceURL.absoluteURL();
|
||||
}
|
||||
|
||||
DISPLAY_NAME(CFBundle.prototype.resourceURL);
|
||||
|
||||
CFBundle.prototype.mostEligibleEnvironmentURL = function()
|
||||
{
|
||||
if (this._mostEligibleEnvironmentURL === undefined)
|
||||
@@ -128,6 +150,8 @@ CFBundle.prototype.mostEligibleEnvironmentURL = function()
|
||||
return this._mostEligibleEnvironmentURL;
|
||||
}
|
||||
|
||||
DISPLAY_NAME(CFBundle.prototype.mostEligibleEnvironmentURL);
|
||||
|
||||
CFBundle.prototype.executableURL = function()
|
||||
{
|
||||
if (this._executableURL === undefined)
|
||||
@@ -143,16 +167,22 @@ CFBundle.prototype.executableURL = function()
|
||||
return this._executableURL;
|
||||
}
|
||||
|
||||
DISPLAY_NAME(CFBundle.prototype.executableURL);
|
||||
|
||||
CFBundle.prototype.infoDictionary = function()
|
||||
{
|
||||
return this._infoDictionary;
|
||||
}
|
||||
|
||||
DISPLAY_NAME(CFBundle.prototype.infoDictionary);
|
||||
|
||||
CFBundle.prototype.valueForInfoDictionaryKey = function(/*String*/ aKey)
|
||||
{
|
||||
return this._infoDictionary.valueForKey(aKey);
|
||||
}
|
||||
|
||||
DISPLAY_NAME(CFBundle.prototype.valueForInfoDictionaryKey);
|
||||
|
||||
CFBundle.prototype.hasSpritedImages = function()
|
||||
{
|
||||
var environments = this._infoDictionary.valueForKey("CPBundleEnvironmentsWithImageSprites") || [],
|
||||
@@ -166,11 +196,15 @@ CFBundle.prototype.hasSpritedImages = function()
|
||||
return NO;
|
||||
}
|
||||
|
||||
DISPLAY_NAME(CFBundle.prototype.hasSpritedImages);
|
||||
|
||||
CFBundle.prototype.environments = function()
|
||||
{
|
||||
return this._infoDictionary.valueForKey("CPBundleEnvironments") || ["ObjJ"];
|
||||
}
|
||||
|
||||
DISPLAY_NAME(CFBundle.prototype.environments);
|
||||
|
||||
CFBundle.prototype.mostEligibleEnvironment = function(/*Array*/ environments)
|
||||
{
|
||||
environments = environments || this.environments();
|
||||
@@ -194,11 +228,15 @@ CFBundle.prototype.mostEligibleEnvironment = function(/*Array*/ environments)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DISPLAY_NAME(CFBundle.prototype.mostEligibleEnvironment);
|
||||
|
||||
CFBundle.prototype.isLoading = function()
|
||||
{
|
||||
return this._loadStatus & CFBundleLoading;
|
||||
}
|
||||
|
||||
DISPLAY_NAME(CFBundle.prototype.isLoading);
|
||||
|
||||
CFBundle.prototype.load = function(/*BOOL*/ shouldExecute)
|
||||
{
|
||||
if (this._loadStatus !== CFBundleUnloaded)
|
||||
@@ -223,7 +261,13 @@ CFBundle.prototype.load = function(/*BOOL*/ shouldExecute)
|
||||
function onsuccess(/*Event*/ anEvent)
|
||||
{
|
||||
self._loadStatus &= ~CFBundleLoadingInfoPlist;
|
||||
self._infoDictionary = anEvent.request.responsePropertyList();
|
||||
|
||||
var infoDictionary = anEvent.request.responsePropertyList();
|
||||
|
||||
self._isValid = !!infoDictionary || CFBundle.mainBundle() === self;
|
||||
|
||||
if (infoDictionary)
|
||||
self._infoDictionary = infoDictionary;
|
||||
|
||||
if (!self._infoDictionary)
|
||||
{
|
||||
@@ -240,6 +284,7 @@ CFBundle.prototype.load = function(/*BOOL*/ shouldExecute)
|
||||
|
||||
function onfailure()
|
||||
{
|
||||
self._isValid = CFBundle.mainBundle() === self;
|
||||
self._loadStatus = CFBundleUnloaded;
|
||||
|
||||
finishBundleLoadingWithError(self, new Error("Could not load bundle at \"" + self.bundleURL() + "\""));
|
||||
@@ -249,6 +294,8 @@ CFBundle.prototype.load = function(/*BOOL*/ shouldExecute)
|
||||
});
|
||||
}
|
||||
|
||||
DISPLAY_NAME(CFBundle.prototype.load);
|
||||
|
||||
function finishBundleLoadingWithError(/*CFBundle*/ aBundle, /*Event*/ anError)
|
||||
{
|
||||
resolveStaticResource(aBundle._staticResource);
|
||||
@@ -390,12 +437,13 @@ function loadSpritedImagesForBundle(/*Bundle*/ aBundle, success, failure)
|
||||
CFTotalBytesLoaded += anEvent.request.responseText().length;
|
||||
decompileStaticFile(aBundle, anEvent.request.responseText(), spritedImagesURL);
|
||||
aBundle._loadStatus &= ~CFBundleLoadingSpritedImages;
|
||||
success();
|
||||
}
|
||||
catch(anException)
|
||||
{
|
||||
failure(anException);
|
||||
}
|
||||
|
||||
success();
|
||||
}, failure);
|
||||
}
|
||||
|
||||
@@ -514,11 +562,11 @@ function executeBundle(/*Bundle*/ aBundle, /*Function*/ aCallback)
|
||||
|
||||
else
|
||||
{
|
||||
executable.addEventListener("dependenciesload", function()
|
||||
executable.loadFileDependencies(function()
|
||||
{
|
||||
executeStaticResources(index);
|
||||
});
|
||||
executable.loadFileDependencies();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -615,16 +663,22 @@ CFBundle.prototype.addEventListener = function(/*String*/ anEventName, /*Functio
|
||||
this._eventDispatcher.addEventListener(anEventName, anEventListener);
|
||||
}
|
||||
|
||||
DISPLAY_NAME(CFBundle.prototype.addEventListener);
|
||||
|
||||
CFBundle.prototype.removeEventListener = function(/*String*/ anEventName, /*Function*/ anEventListener)
|
||||
{
|
||||
this._eventDispatcher.removeEventListener(anEventName, anEventListener);
|
||||
}
|
||||
|
||||
DISPLAY_NAME(CFBundle.prototype.removeEventListener);
|
||||
|
||||
CFBundle.prototype.onerror = function(/*Event*/ anEvent)
|
||||
{
|
||||
throw anEvent.error;
|
||||
}
|
||||
|
||||
DISPLAY_NAME(CFBundle.prototype.onerror);
|
||||
|
||||
CFBundle.prototype.bundlePath = function()
|
||||
{
|
||||
return this._bundleURL.absoluteURL().path();
|
||||
|
||||
@@ -92,15 +92,23 @@ if (!NativeRequest)
|
||||
|
||||
GLOBAL(CFHTTPRequest) = function()
|
||||
{
|
||||
this._isOpen = false;
|
||||
this._requestHeaders = {};
|
||||
this._mimeType = null;
|
||||
|
||||
this._eventDispatcher = new EventDispatcher(this);
|
||||
this._nativeRequest = new NativeRequest();
|
||||
|
||||
var self = this;
|
||||
|
||||
this._nativeRequest.onreadystatechange = function()
|
||||
this._stateChangeHandler = function()
|
||||
{
|
||||
determineAndDispatchHTTPRequestEvents(self);
|
||||
}
|
||||
|
||||
this._nativeRequest.onreadystatechange = this._stateChangeHandler;
|
||||
|
||||
if (CFHTTPRequest.AuthenticationDelegate !== nil)
|
||||
this._eventDispatcher.addEventListener("HTTP403", function(){CFHTTPRequest.AuthenticationDelegate(self)});
|
||||
}
|
||||
|
||||
CFHTTPRequest.UninitializedState = 0;
|
||||
@@ -109,6 +117,9 @@ CFHTTPRequest.LoadedState = 2;
|
||||
CFHTTPRequest.InteractiveState = 3;
|
||||
CFHTTPRequest.CompleteState = 4;
|
||||
|
||||
//override to forward all CFHTTPRequest authorization failures to a single function
|
||||
CFHTTPRequest.AuthenticationDelegate = nil;
|
||||
|
||||
CFHTTPRequest.prototype.status = function()
|
||||
{
|
||||
try
|
||||
@@ -177,7 +188,7 @@ CFHTTPRequest.prototype.responseText = function()
|
||||
|
||||
CFHTTPRequest.prototype.setRequestHeader = function(/*String*/ aHeader, /*Object*/ aValue)
|
||||
{
|
||||
return this._nativeRequest.setRequestHeader(aHeader, aValue);
|
||||
this._requestHeaders[aHeader] = aValue;
|
||||
}
|
||||
|
||||
CFHTTPRequest.prototype.getResponseHeader = function(/*String*/ aHeader)
|
||||
@@ -192,17 +203,40 @@ CFHTTPRequest.prototype.getAllResponseHeaders = function()
|
||||
|
||||
CFHTTPRequest.prototype.overrideMimeType = function(/*String*/ aMimeType)
|
||||
{
|
||||
if ("overrideMimeType" in this._nativeRequest)
|
||||
return this._nativeRequest.overrideMimeType(aMimeType);
|
||||
this._mimeType = aMimeType;
|
||||
}
|
||||
|
||||
CFHTTPRequest.prototype.open = function(/*...*/)
|
||||
CFHTTPRequest.prototype.open = function(/*String*/ aMethod, /*String*/ aURL, /*Boolean*/ isAsynchronous, /*String*/ aUser, /*String*/ aPassword)
|
||||
{
|
||||
return this._nativeRequest.open(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
|
||||
this._isOpen = true;
|
||||
this._URL = aURL;
|
||||
this._async = isAsynchronous;
|
||||
this._method = aMethod;
|
||||
this._user = aUser;
|
||||
this._password = aPassword;
|
||||
return this._nativeRequest.open(aMethod, aURL, isAsynchronous, aUser, aPassword);
|
||||
}
|
||||
|
||||
CFHTTPRequest.prototype.send = function(/*Object*/ aBody)
|
||||
{
|
||||
for (var i in this._requestHeaders)
|
||||
{
|
||||
if (this._requestHeaders.hasOwnProperty(i))
|
||||
this._nativeRequest.setRequestHeader(i, this._requestHeaders[i]);
|
||||
}
|
||||
|
||||
if (!this._isOpen)
|
||||
{
|
||||
delete this._nativeRequest.onreadystatechange;
|
||||
this._nativeRequest.open(this._method, this._URL, this._async, this._user, this._password);
|
||||
this._nativeRequest.onreadystatechange = this._stateChangeHandler;
|
||||
}
|
||||
|
||||
if (this._mimeType && "overrideMimeType" in this._nativeRequest)
|
||||
this._nativeRequest.overrideMimeType(this._mimeType);
|
||||
|
||||
this._isOpen = false;
|
||||
|
||||
try
|
||||
{
|
||||
return this._nativeRequest.send(aBody);
|
||||
@@ -216,6 +250,7 @@ CFHTTPRequest.prototype.send = function(/*Object*/ aBody)
|
||||
|
||||
CFHTTPRequest.prototype.abort = function()
|
||||
{
|
||||
this._isOpen = false;
|
||||
return this._nativeRequest.abort();
|
||||
}
|
||||
|
||||
@@ -236,61 +271,50 @@ function determineAndDispatchHTTPRequestEvents(/*CFHTTPRequest*/ aRequest)
|
||||
eventDispatcher.dispatchEvent({ type:"readystatechange", request:aRequest});
|
||||
|
||||
var nativeRequest = aRequest._nativeRequest,
|
||||
readyState = ["uninitialized", "loading", "loaded", "interactive", "complete"][aRequest.readyState()];
|
||||
readyStates = ["uninitialized", "loading", "loaded", "interactive", "complete"];
|
||||
|
||||
eventDispatcher.dispatchEvent({ type:readyState, request:aRequest});
|
||||
|
||||
if (readyState === "complete")
|
||||
if (readyStates[aRequest.readyState()] === "complete")
|
||||
{
|
||||
var status = "HTTP" + aRequest.status();
|
||||
|
||||
eventDispatcher.dispatchEvent({ type:status, request:aRequest });
|
||||
|
||||
var result = aRequest.success() ? "success" : "failure";
|
||||
|
||||
eventDispatcher.dispatchEvent({ type:result, request:aRequest });
|
||||
|
||||
eventDispatcher.dispatchEvent({ type:readyStates[aRequest.readyState()], request:aRequest});
|
||||
}
|
||||
else
|
||||
eventDispatcher.dispatchEvent({ type:readyStates[aRequest.readyState()], request:aRequest});
|
||||
}
|
||||
|
||||
function FileRequest(/*CFURL*/ aURL, onsuccess, onfailure)
|
||||
{
|
||||
#ifdef BROWSER
|
||||
var request = new CFHTTPRequest();
|
||||
|
||||
request.onsuccess = Asynchronous(onsuccess);
|
||||
request.onfailure = Asynchronous(onfailure);
|
||||
|
||||
if (aURL.pathExtension() === "plist")
|
||||
request.overrideMimeType("text/xml");
|
||||
|
||||
request.open("GET", aURL.absoluteString(), YES);
|
||||
if (exports.asyncLoader)
|
||||
{
|
||||
request.onsuccess = Asynchronous(onsuccess);
|
||||
request.onfailure = Asynchronous(onfailure);
|
||||
}
|
||||
else
|
||||
{
|
||||
request.onsuccess = onsuccess;
|
||||
request.onfailure = onfailure;
|
||||
}
|
||||
|
||||
request.open("GET", aURL.absoluteString(), exports.asyncLoader);
|
||||
request.send("");
|
||||
}
|
||||
|
||||
#ifdef BROWSER
|
||||
exports.asyncLoader = YES;
|
||||
#else
|
||||
var FILE = require("file"),
|
||||
filePath = aURL.absoluteURL().path();
|
||||
|
||||
if (!FILE.exists(filePath))
|
||||
return onfailure();
|
||||
|
||||
this._responseText = FILE.read(filePath, { charset:"UTF-8" });
|
||||
|
||||
onsuccess({ type:"success", request:this });
|
||||
exports.asyncLoader = NO;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef COMMONJS
|
||||
FileRequest.prototype.responseText = function()
|
||||
{
|
||||
return this._responseText;
|
||||
}
|
||||
|
||||
FileRequest.prototype.responseXML = function()
|
||||
{
|
||||
return new DOMParser().parseFromString(anXMLString, "text/xml");
|
||||
}
|
||||
|
||||
FileRequest.prototype.responsePropertyList = function()
|
||||
{
|
||||
return CFPropertyList.propertyListFromString(this.responseText());
|
||||
}
|
||||
#endif
|
||||
// FIXME: Get rid of these when we no longer need Mock requests in flatten.
|
||||
exports.Asynchronous = Asynchronous;
|
||||
exports.determineAndDispatchHTTPRequestEvents = determineAndDispatchHTTPRequestEvents;
|
||||
|
||||
@@ -91,6 +91,16 @@ CFPropertyList.writePropertyListToFile = function(/*CFPropertyList*/ aPropertyLi
|
||||
{
|
||||
return FILE.write(aFilePath, CFPropertyList.stringFromPropertyList(aPropertyList, aFormat), { charset:"UTF-8" });
|
||||
}
|
||||
CFPropertyList.modifyPlist = function(/*String*/ aFilePath, /*Function*/ aCallback, /*String*/ aFormat)
|
||||
{
|
||||
var string = FILE.read(aFilePath, { charset:"UTF-8" });
|
||||
var format = CFPropertyList.sniffedFormatOfString(string);
|
||||
var plist = CFPropertyList.propertyListFromString(string, format);
|
||||
|
||||
aCallback(plist);
|
||||
|
||||
CFPropertyList.writePropertyListToFile(plist, aFilePath, aFormat || format);
|
||||
}
|
||||
#endif
|
||||
|
||||
function serializePropertyList(/*CFPropertyList*/ aPropertyList, /*Object*/ serializers)
|
||||
|
||||
@@ -314,7 +314,7 @@ function resolveURL(aURL)
|
||||
resolvedPathComponents.splice(basePathComponents.length - 1, 1);
|
||||
|
||||
// If this doesn't start with a "..", then we're simply appending to already standardized paths.
|
||||
if (pathComponents.length && pathComponents[0] === "..")
|
||||
if (pathComponents.length && (pathComponents[0] === ".." || pathComponents[0] === "."))
|
||||
standardizePathComponents(resolvedPathComponents, YES);
|
||||
|
||||
resolvedParts.pathComponents = resolvedPathComponents;
|
||||
@@ -352,19 +352,26 @@ function standardizePathComponents(/*Array*/ pathComponents, /*BOOL*/ inPlace)
|
||||
var index = 0,
|
||||
resultIndex = 0,
|
||||
count = pathComponents.length,
|
||||
result = inPlace ? pathComponents : [];
|
||||
result = inPlace ? pathComponents : [],
|
||||
startsWithPeriod = NO;
|
||||
|
||||
for (; index < count; ++index)
|
||||
{
|
||||
var component = pathComponents[index];
|
||||
|
||||
if (component === "" || component === ".")
|
||||
if (component === "")
|
||||
continue;
|
||||
|
||||
if (component === ".")
|
||||
{
|
||||
startsWithPeriod = resultIndex === 0;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (component !== ".." || resultIndex === 0 || result[resultIndex - 1] === "..")
|
||||
{
|
||||
//if (resultIndex !== index)
|
||||
result[resultIndex] = component;
|
||||
result[resultIndex] = component;
|
||||
|
||||
resultIndex++;
|
||||
|
||||
@@ -375,6 +382,9 @@ function standardizePathComponents(/*Array*/ pathComponents, /*BOOL*/ inPlace)
|
||||
--resultIndex;
|
||||
}
|
||||
|
||||
if (startsWithPeriod && resultIndex === 0)
|
||||
result[resultIndex++] = ".";
|
||||
|
||||
result.length = resultIndex;
|
||||
|
||||
return result;
|
||||
@@ -505,10 +515,11 @@ CFURL.prototype.hasDirectoryPath = function()
|
||||
var lastPathComponent = this.lastPathComponent();
|
||||
|
||||
hasDirectoryPath = lastPathComponent === "." || lastPathComponent === "..";
|
||||
|
||||
this._hasDirectoryPath = hasDirectoryPath;
|
||||
}
|
||||
|
||||
return this._hasDirectoryPath;
|
||||
return hasDirectoryPath;
|
||||
}
|
||||
|
||||
DISPLAY_NAME(CFURL.prototype.hasDirectoryPath);
|
||||
@@ -646,7 +657,14 @@ CFURL.prototype.asDirectoryPathURL = function()
|
||||
if (this.hasDirectoryPath())
|
||||
return this;
|
||||
|
||||
return new CFURL(this.lastPathComponent() + "/", this);
|
||||
var lastPathComponent = this.lastPathComponent();
|
||||
|
||||
// We do this because on Windows the path may start with C: and be
|
||||
// misinterpreted as a scheme.
|
||||
if (lastPathComponent !== "/")
|
||||
lastPathComponent = "./" + lastPathComponent;
|
||||
|
||||
return new CFURL(lastPathComponent + "/", this);
|
||||
}
|
||||
|
||||
DISPLAY_NAME(CFURL.prototype.asDirectoryPathURL);
|
||||
|
||||
@@ -357,3 +357,10 @@ function _CPLogInitPopup(logWindow)
|
||||
}, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if COMMONJS
|
||||
CPLogDefault = CPLogPrint;
|
||||
#else
|
||||
CPLogDefault = (typeof window === "object" && window.console) ? CPLogConsole : CPLogPopup;
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
|
||||
var FILE = require("file");
|
||||
var sprintf = require("printf").sprintf;
|
||||
|
||||
var window = exports.window = require("browser/window");
|
||||
|
||||
if (system.engine === "rhino")
|
||||
@@ -7,7 +9,7 @@ if (system.engine === "rhino")
|
||||
window.__parent__ = null;
|
||||
window.__proto__ = global;
|
||||
}
|
||||
|
||||
|
||||
// setup OBJJ_HOME, OBJJ_INCLUDE_PATHS, etc
|
||||
window.OBJJ_HOME = exports.OBJJ_HOME = FILE.resolve(module.path, "..");
|
||||
|
||||
@@ -77,6 +79,12 @@ exports.run = function(args)
|
||||
// copy the args since we're going to modify them
|
||||
var argv = args.slice(1);
|
||||
|
||||
if (argv[0] === "--version")
|
||||
{
|
||||
print(exports.fullVersionString());
|
||||
return;
|
||||
}
|
||||
|
||||
while (argv.length && argv[0].indexOf('-I') === 0)
|
||||
OBJJ_INCLUDE_PATHS.unshift.apply(OBJJ_INCLUDE_PATHS, argv.shift().substr(2).split(':'));
|
||||
}
|
||||
@@ -140,37 +148,12 @@ exports.repl = function()
|
||||
}
|
||||
}
|
||||
|
||||
exports.objj_eval = function(/*String*/ aString)
|
||||
{
|
||||
// We need this while code still refers to window.
|
||||
Executable.setCommonJSArguments(require, exports, module, system, print, window);
|
||||
|
||||
var executable = exports.preprocess(aString, "", 0);
|
||||
|
||||
if (!executable.hasLoadedFileDependencies())
|
||||
executable.loadFileDependencies();
|
||||
|
||||
// A bit of a hack. Executable compiles the code itself into a function, but we want
|
||||
// the raw code to eval here.
|
||||
var code = executable._code;
|
||||
|
||||
// Not clear why these should be global, varing them doesn't seem to take effect with evaluateString.
|
||||
global.objj_executeFile = Executable.fileExecuterForURL(FILE.cwd());
|
||||
global.objj_importFile = Executable.fileImporterForURL(FILE.cwd());
|
||||
|
||||
if (typeof system !== "undefined" && system.engine === "rhino")
|
||||
return Packages.org.mozilla.javascript.Context.getCurrentContext().evaluateString(global, code, "objj_eval", 0, NULL);
|
||||
|
||||
return eval(code);
|
||||
}
|
||||
|
||||
Executable.setCommonJSParameters("require", "exports", "module", "system", "print", "window");
|
||||
|
||||
// creates a narwhal factory function in the objj module scope
|
||||
exports.make_narwhal_factory = function(path)
|
||||
{
|
||||
return function(require, exports, module, system, print)
|
||||
{
|
||||
Executable.setCommonJSParameters("require", "exports", "module", "system", "print", "window");
|
||||
Executable.setCommonJSArguments(require, exports, module, system, print, window);
|
||||
Executable.fileImporterForURL(FILE.dirname(path))(path, YES);
|
||||
}
|
||||
@@ -178,5 +161,32 @@ exports.make_narwhal_factory = function(path)
|
||||
|
||||
} // end "with"
|
||||
|
||||
var pkg = null;
|
||||
function getPackage() {
|
||||
if (!pkg)
|
||||
pkg = JSON.parse(FILE.path(module.path).dirname().dirname().join("package.json").read({ charset : "UTF-8" }));
|
||||
return pkg;
|
||||
}
|
||||
|
||||
exports.version = function() { return getPackage()["version"]; }
|
||||
exports.revision = function() { return getPackage()["cappuccino-revision"]; }
|
||||
exports.timestamp = function() { return new Date(getPackage()["cappuccino-timestamp"]); }
|
||||
|
||||
exports.fullVersionString = function() {
|
||||
return sprintf("objective-j %s (%04d-%02d-%02d %s)",
|
||||
exports.version(),
|
||||
exports.timestamp().getUTCFullYear(),
|
||||
exports.timestamp().getUTCMonth()+1,
|
||||
exports.timestamp().getUTCDate(),
|
||||
exports.revision().slice(0,6)
|
||||
);
|
||||
}
|
||||
|
||||
global.ObjectiveJ = {};
|
||||
|
||||
for (key in exports)
|
||||
if (Object.prototype.hasOwnProperty.call(exports, key))
|
||||
global.ObjectiveJ[key] = exports[key];
|
||||
|
||||
if (require.main == module.id)
|
||||
exports.run(system.args);
|
||||
|
||||