Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
16a70c5c8e | ||
|
|
b78eddd878 | ||
|
|
203942d123 | ||
|
|
5957e71967 | ||
|
|
fdf47eb84e | ||
|
|
6963b37f61 | ||
|
|
379c5294c2 | ||
|
|
fb27f86126 | ||
|
|
133dd39485 | ||
|
|
d50cbb02e6 | ||
|
|
30695e4110 | ||
|
|
3e79d8324d | ||
|
|
71de04787d | ||
|
|
81332fa57e | ||
|
|
191a02a89b | ||
|
|
f4ae6c450b | ||
|
|
f2c53c9f52 | ||
|
|
090fcab8c6 | ||
|
|
d3836c2a52 | ||
|
|
ea8c29356d | ||
|
|
6a942630e4 | ||
|
|
2aa806e52a | ||
|
|
04f1b61534 | ||
|
|
b6119a763e | ||
|
|
0876fd6db9 | ||
|
|
3d106c0716 | ||
|
|
c390b19d4b | ||
|
|
6a735ecda9 | ||
|
|
aada884cff | ||
|
|
b62789bb18 | ||
|
|
eafec339f1 | ||
|
|
ef326dbbb4 | ||
|
|
4bbbcb15f1 | ||
|
|
92cb69b623 | ||
|
|
18ea086ffc | ||
|
|
40b04b7956 | ||
|
|
38dc125fc2 | ||
|
|
378df68995 | ||
|
|
ec330a1090 | ||
|
|
f07543045a | ||
|
|
4458884048 | ||
|
|
7245fb99a6 | ||
|
|
5d27661354 | ||
|
|
b33b2df778 | ||
|
|
d2f27408a5 | ||
|
|
235b323658 | ||
|
|
54c3cc0187 | ||
|
|
59cc590b51 | ||
|
|
66a87c472b | ||
|
|
688aed72cb | ||
|
|
6310733881 | ||
|
|
3fe505b8e5 | ||
|
|
00915083d4 | ||
|
|
4e1ecbef72 | ||
|
|
e4f6214005 | ||
|
|
ed98a44116 | ||
|
|
50d36e76ac | ||
|
|
818bf475f2 | ||
|
|
47afb96c4c | ||
|
|
467dc3c2d5 | ||
|
|
7e3079add6 | ||
|
|
9796f5d5d7 | ||
|
|
37323b811c | ||
|
|
8720a952b0 | ||
|
|
bf4724d401 | ||
|
|
c73e2e1a91 | ||
|
|
630cd121a6 | ||
|
|
5d88ffbe66 | ||
|
|
bd5aa1c959 | ||
|
|
c65bfd22a2 | ||
|
|
e656e0561b | ||
|
|
ddbba22533 | ||
|
|
91b5596034 | ||
|
|
e0185a0eff | ||
|
|
2fe8845842 | ||
|
|
c02128a1fd | ||
|
|
27ad98e160 | ||
|
|
fc746db70f | ||
|
|
6a6256bdb4 | ||
|
|
5a0cfc1595 | ||
|
|
32107ab650 | ||
|
|
494f615aaa | ||
|
|
5c2ebd546c | ||
|
|
72b8ed2faf | ||
|
|
6b8c85df7c | ||
|
|
cce4e3ded8 | ||
|
|
0240c648aa | ||
|
|
6019ff9107 | ||
|
|
c4ee83e4c1 | ||
|
|
61b0cbb1af | ||
|
|
af30e96b7b | ||
|
|
b7bdec189a | ||
|
|
2a27a87ae6 | ||
|
|
31ac84f683 | ||
|
|
c41defe864 | ||
|
|
6bc109f7fc | ||
|
|
2d603df83c | ||
|
|
dcf440396d | ||
|
|
1dc10440b7 | ||
|
|
0ef2557ec3 | ||
|
|
05e69c85c7 | ||
|
|
9c6476615d | ||
|
|
b393d0597f | ||
|
|
f69e2e8d8f | ||
|
|
5fd470acea | ||
|
|
28e660c295 | ||
|
|
9a76b4451f | ||
|
|
b50f955cfd | ||
|
|
76b5682234 | ||
|
|
4aa4f1a62a | ||
|
|
7ae14e9eb5 | ||
|
|
bfe03a8874 | ||
|
|
66b6b44f86 | ||
|
|
b70018bd80 | ||
|
|
a302fdfb8f | ||
|
|
bb9e1a830d | ||
|
|
9b7f8ec31e | ||
|
|
17b40fcb9d |
@@ -94,4 +94,3 @@
|
||||
@import "CPWebView.j"
|
||||
@import "CPWindow.j"
|
||||
@import "CPWindowController.j"
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
@class CPAccordionView
|
||||
|
||||
<p>CPAccordionView provides a container for CPAccordionViewItem objects and manages layout state
|
||||
for all sublayout items.</p>
|
||||
for all sub-layout items.</p>
|
||||
|
||||
<strong>Example</strong><br />
|
||||
<pre>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* Copyright 2008, Jake MacMullin.
|
||||
*
|
||||
* 11/10/2008 Ross Boucher
|
||||
* - Make it conform to style guidelines, general cleanup and ehancements
|
||||
* - Make it conform to style guidelines, general cleanup and enhancements
|
||||
* 11/10/2010 Antoine Mercadal
|
||||
* - Enhancements, better compliance with Cocoa API
|
||||
*
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
@import <Foundation/CPObject.j>
|
||||
@import <Foundation/CPTimer.j>
|
||||
|
||||
@import "CAMediaTimingFunction.j"
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ CPRunContinuesResponse = -1002;
|
||||
@ingroup appkit
|
||||
@class CPApplication
|
||||
|
||||
CPApplication is THE way to start up the Cappucino framework for your application to use.
|
||||
CPApplication is THE way to start up the Cappuccino framework for your application to use.
|
||||
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:
|
||||
@@ -90,7 +90,6 @@ CPRunContinuesResponse = -1002;
|
||||
CPWindow _previousKeyWindow;
|
||||
CPWindow _previousMainWindow;
|
||||
|
||||
CPMenu _mainMenu;
|
||||
CPDocumentController _documentController;
|
||||
|
||||
CPModalSession _currentSession;
|
||||
@@ -293,11 +292,21 @@ CPRunContinuesResponse = -1002;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the applications icon image. This image is used in the default "About" window.
|
||||
By default this value is pulled from the CPApplicationIcon key in your info.plist file.
|
||||
|
||||
@param anImage - The image to set.
|
||||
*/
|
||||
- (void)setApplicationIconImage:(CPImage)anImage
|
||||
{
|
||||
_applicationIconImage = anImage;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the application icon image. By default this is pulled from the CPApplicationIcon key of info.plist.
|
||||
@return CPImage - Your application icon image.
|
||||
*/
|
||||
- (CPImage)applicationIconImage
|
||||
{
|
||||
if (_applicationIconImage)
|
||||
@@ -310,11 +319,38 @@ CPRunContinuesResponse = -1002;
|
||||
return _applicationIconImage;
|
||||
}
|
||||
|
||||
/*!
|
||||
Opens the standard about panel with no options.
|
||||
*/
|
||||
- (void)orderFrontStandardAboutPanel:(id)sender
|
||||
{
|
||||
[self orderFrontStandardAboutPanelWithOptions:nil];
|
||||
}
|
||||
|
||||
/*!
|
||||
Opens the standard about panel. This method takes a single argument \c options.
|
||||
Options is a dictionary that can contain any of the following keys:
|
||||
<pre>
|
||||
ApplicationName - The name of your application.
|
||||
ApplicationIcon - Application icon image.
|
||||
Version - The full version of your application
|
||||
ApplicationVersion - The shorter version number of your application.
|
||||
Copyright - Human readable copyright information.
|
||||
</pre>
|
||||
|
||||
If you choose not the include any of the above keys, they will default
|
||||
to the following respective keys in your info.plist file.
|
||||
|
||||
<pre>
|
||||
CPBundleName
|
||||
CPApplicationIcon (through a call to -applicationIconImage, see documentation for that method for more details)
|
||||
CPBundleVersion
|
||||
CPBundleShortVersionString
|
||||
CPHumanReadableCopyright
|
||||
</pre>
|
||||
|
||||
@param options - A dictionary with the aboe listed keys. You can pass nil to default to your plist values.
|
||||
*/
|
||||
- (void)orderFrontStandardAboutPanelWithOptions:(CPDictionary)options
|
||||
{
|
||||
if (!_aboutPanel)
|
||||
@@ -530,7 +566,7 @@ CPRunContinuesResponse = -1002;
|
||||
- (BOOL)_handleKeyEquivalent:(CPEvent)anEvent
|
||||
{
|
||||
return [[self keyWindow] performKeyEquivalent:anEvent] ||
|
||||
[_mainMenu performKeyEquivalent:anEvent];
|
||||
[[self mainMenu] performKeyEquivalent:anEvent];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -574,6 +610,10 @@ CPRunContinuesResponse = -1002;
|
||||
[[anEvent window] sendEvent:anEvent];
|
||||
}
|
||||
|
||||
/*!
|
||||
If the delegate responds to the given selector it will call the method on the delegate,
|
||||
otherwise the method will be passed to CPResponder.
|
||||
*/
|
||||
- (void)doCommandBySelector:(SEL)aSelector
|
||||
{
|
||||
if ([_delegate respondsToSelector:aSelector])
|
||||
@@ -637,7 +677,7 @@ CPRunContinuesResponse = -1002;
|
||||
*/
|
||||
- (CPMenu)mainMenu
|
||||
{
|
||||
return _mainMenu;
|
||||
return [self menu];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -645,21 +685,30 @@ CPRunContinuesResponse = -1002;
|
||||
@param aMenu the menu to set for the application
|
||||
*/
|
||||
- (void)setMainMenu:(CPMenu)aMenu
|
||||
{
|
||||
[self setMenu:aMenu];
|
||||
}
|
||||
|
||||
- (void)setMenu:(CPMenu)aMenu
|
||||
{
|
||||
if ([aMenu _menuName] === "CPMainMenu")
|
||||
{
|
||||
if (_mainMenu === aMenu)
|
||||
if ([self menu] === aMenu)
|
||||
return;
|
||||
|
||||
_mainMenu = aMenu;
|
||||
[super setMenu:aMenu];
|
||||
|
||||
if ([CPPlatform supportsNativeMainMenu])
|
||||
window.cpSetMainMenu(_mainMenu);
|
||||
window.cpSetMainMenu([self menu]);
|
||||
}
|
||||
else
|
||||
[aMenu _setMenuName:@"CPMainMenu"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Opens the shared color panel.
|
||||
@param aSender
|
||||
*/
|
||||
- (void)orderFrontColorPanel:(id)aSender
|
||||
{
|
||||
[[CPColorPanel sharedColorPanel] orderFront:self];
|
||||
@@ -828,16 +877,38 @@ CPRunContinuesResponse = -1002;
|
||||
return nil;
|
||||
}
|
||||
|
||||
/*!
|
||||
Fires a callback function when an event matching a given mask occurs.
|
||||
@param aCallback - A js function to be fired.
|
||||
@prarm aMask - An event mask for the next event.
|
||||
@param anExpiration - The date for which this callback expires (not implemented).
|
||||
@param inMode (not implemented).
|
||||
@param shouldDequeue (not implemented).
|
||||
*/
|
||||
- (void)setCallback:(Function)aCallback forNextEventMatchingMask:(unsigned int)aMask untilDate:(CPDate)anExpiration inMode:(CPString)aMode dequeue:(BOOL)shouldDequeue
|
||||
{
|
||||
_eventListeners.push(_CPEventListenerMake(aMask, aCallback));
|
||||
}
|
||||
|
||||
- (CPEvent)setTarget:(id)aTarget selector:(SEL)aSelector forNextEventMatchingMask:(unsigned int)aMask untilDate:(CPDate)anExpiration inMode:(CPString)aMode dequeue:(BOOL)shouldDequeue
|
||||
/*!
|
||||
Assigns a target and action for the next event matching a given event mask.
|
||||
The callback method called will be passed the CPEvent when it fires.
|
||||
|
||||
@param aTarget - The target object for the callback.
|
||||
@param aSelector - The selector which should be called on the target object.
|
||||
@param aMask - The mask for a given event which should trigger the callback.
|
||||
@param anExpiration - The date for which the callback expires (not implemented).
|
||||
@param aMode (not implemented).
|
||||
@param shouldDequeue (not implemented).
|
||||
*/
|
||||
- (void)setTarget:(id)aTarget selector:(SEL)aSelector forNextEventMatchingMask:(unsigned int)aMask untilDate:(CPDate)anExpiration inMode:(CPString)aMode dequeue:(BOOL)shouldDequeue
|
||||
{
|
||||
_eventListeners.push(_CPEventListenerMake(aMask, function (anEvent) { objj_msgSend(aTarget, aSelector, anEvent); }));
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the last event recieved by your application.
|
||||
*/
|
||||
- (CPEvent)currentEvent
|
||||
{
|
||||
return _currentEvent;
|
||||
@@ -867,6 +938,19 @@ CPRunContinuesResponse = -1002;
|
||||
[aWindow _attachSheet:aSheet modalDelegate:aModalDelegate didEndSelector:aDidEndSelector contextInfo:aContextInfo];
|
||||
}
|
||||
|
||||
/*!
|
||||
Ends a sheet modal.
|
||||
The following are predefined return codes:
|
||||
|
||||
<pre>
|
||||
CPRunStoppedResponse
|
||||
CPRunAbortedResponse
|
||||
CPRunContinuesResponse
|
||||
</pre>
|
||||
|
||||
@param sheet - The window object (sheet) to dismiss.
|
||||
@param returnCode - The return code to send to the delegate. You can use one of the return codes above or a custom value that you define.
|
||||
*/
|
||||
- (void)endSheet:(CPWindow)sheet returnCode:(int)returnCode
|
||||
{
|
||||
var count = [_windows count];
|
||||
@@ -885,11 +969,31 @@ CPRunContinuesResponse = -1002;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Ends a sheet and sends the return code "0".
|
||||
@param sheet - The CPWindow object (sheet) that should be dismissed.
|
||||
*/
|
||||
- (void)endSheet:(CPWindow)sheet
|
||||
{
|
||||
// FIX ME: this is wrong: by Cocoa this should be: CPRunStoppedResponse.
|
||||
[self endSheet:sheet returnCode:0];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns and array of slash seperated arugments to your application.
|
||||
These values are pulled from your window location hash.
|
||||
|
||||
For exampled if your application loaded:
|
||||
<pre>
|
||||
index.html#280north/cappuccino/issues
|
||||
</pre>
|
||||
The follow array would be returned:
|
||||
<pre>
|
||||
["280north", "cappuccino", "issues"]
|
||||
</pre>
|
||||
|
||||
@return CPArray - The array of arguments.
|
||||
*/
|
||||
- (CPArray)arguments
|
||||
{
|
||||
if (_fullArgsString !== window.location.hash)
|
||||
@@ -898,6 +1002,22 @@ CPRunContinuesResponse = -1002;
|
||||
return _args;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the arguments of your application.
|
||||
That is, set the slash seperated values of an array as the window location hash.
|
||||
|
||||
For example if you pass an array:
|
||||
<pre>
|
||||
["280north", "cappuccino", "issues"]
|
||||
</pre>
|
||||
|
||||
The new window location would be
|
||||
<pre>
|
||||
index.html#280north/cappuccino/issues
|
||||
</pre>
|
||||
|
||||
@param args - An array of arguments.
|
||||
*/
|
||||
- (void)setArguments:(CPArray)args
|
||||
{
|
||||
if (!args || args.length == 0)
|
||||
@@ -939,6 +1059,23 @@ CPRunContinuesResponse = -1002;
|
||||
_args = [];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a dictionary of the window location named arguments.
|
||||
For example if your location was:
|
||||
<pre>
|
||||
index.html?owner=280north&repo=cappuccino&type=issues
|
||||
</pre>
|
||||
|
||||
a CPDictionary with the keys:
|
||||
<pre>
|
||||
owner, repo, type
|
||||
</pre>
|
||||
and respective values:
|
||||
<pre>
|
||||
280north, cappuccino, issues
|
||||
</pre>
|
||||
Will be returned.
|
||||
*/
|
||||
- (CPDictionary)namedArguments
|
||||
{
|
||||
return _namedArgs;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
/*
|
||||
* CPArrayController.j
|
||||
* AppKit
|
||||
@@ -29,7 +27,14 @@
|
||||
@import "CPObjectController.j"
|
||||
@import "CPKeyValueBinding.j"
|
||||
|
||||
/*!
|
||||
|
||||
@class CPArrayController
|
||||
|
||||
CPArrayController is a bindings compatible class that manages an array.
|
||||
CPArrayController also provides selection management and sorting capabilities.
|
||||
|
||||
*/
|
||||
@implementation CPArrayController : CPObjectController
|
||||
{
|
||||
BOOL _avoidsEmptySelection;
|
||||
@@ -39,10 +44,12 @@
|
||||
BOOL _selectsInsertedObjects;
|
||||
BOOL _alwaysUsesMultipleValuesMarker;
|
||||
|
||||
id _selectionIndexes;
|
||||
id _sortDescriptors;
|
||||
id _filterPredicate;
|
||||
id _arrangedObjects;
|
||||
BOOL _automaticallyRearrangesObjects; // FIXME: Not in use
|
||||
|
||||
CPIndexSet _selectionIndexes;
|
||||
CPArray _sortDescriptors;
|
||||
CPPredicate _filterPredicate;
|
||||
CPArray _arrangedObjects;
|
||||
}
|
||||
|
||||
+ (void)initialize
|
||||
@@ -102,54 +109,168 @@
|
||||
return [CPSet setWithObjects:"selectionIndexes"];
|
||||
}
|
||||
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self)
|
||||
{
|
||||
_sortDescriptors = [CPArray array];
|
||||
_selectionIndexes = [CPIndexSet indexSet];
|
||||
_preservesSelection = YES;
|
||||
_selectsInsertedObjects = YES;
|
||||
_avoidsEmptySelection = YES;
|
||||
_clearsFilterPredicateOnInsertion = YES;
|
||||
_alwaysUsesMultipleValuesMarker = NO;
|
||||
_automaticallyRearrangesObjects = NO;
|
||||
|
||||
_filterRestrictsInsertion = YES; // FIXME: Not in use
|
||||
|
||||
[self _init];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)_init
|
||||
{
|
||||
_sortDescriptors = [CPArray array];
|
||||
_filterPredicate = nil;
|
||||
_selectionIndexes = [CPIndexSet indexSet];
|
||||
_arrangedObjects = nil;
|
||||
}
|
||||
|
||||
- (void)prepareContent
|
||||
{
|
||||
[self _setContentArray:[[self newObject]]];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns YES if the selection should try to be preserved when the content changes, otherwise NO.
|
||||
@return BOOL YES if the selection is preserved, otherwise NO.
|
||||
*/
|
||||
- (BOOL)preservesSelection
|
||||
{
|
||||
return _preservesSelection;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets whether the selection is kept when the content changes.
|
||||
|
||||
@param BOOL aFlag - YES if the selection should be kept, otherwise NO.
|
||||
*/
|
||||
- (void)setPreservesSelection:(BOOL)value
|
||||
{
|
||||
_preservesSelection = value;
|
||||
}
|
||||
|
||||
/*!
|
||||
@return BOOL - Returns YES if new objects are automatically selected, otherwise NO.
|
||||
*/
|
||||
- (BOOL)selectsInsertedObjects
|
||||
{
|
||||
return _selectsInsertedObjects;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets whether the controller will automatically select objects as they are inserted.
|
||||
@return BOOL - YES if new objects are selected, otherwise NO.
|
||||
*/
|
||||
- (void)setSelectsInsertedObjects:(BOOL)value
|
||||
{
|
||||
_selectsInsertedObjects = value;
|
||||
}
|
||||
|
||||
/*!
|
||||
@return BOOL - YES if the controller should try to avoid an empty selection otherwise NO.
|
||||
*/
|
||||
- (BOOL)avoidsEmptySelection
|
||||
{
|
||||
return _avoidsEmptySelection;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets whether the controller should try to avoid an empty selection.
|
||||
@param BOOL aFlag - YES if the receiver should attempt to avoid an empty selection, otherwise NO.
|
||||
*/
|
||||
- (void)setAvoidsEmptySelection:(BOOL)value
|
||||
{
|
||||
_avoidsEmptySelection = value;
|
||||
}
|
||||
|
||||
/*!
|
||||
Whether the receiver will clear its filter predicate when a new object is inserted.
|
||||
|
||||
@return BOOL YES if the receiver clears filter predicates on insert
|
||||
*/
|
||||
- (BOOL)clearsFilterPredicateOnInsertion
|
||||
{
|
||||
return _clearsFilterPredicateOnInsertion;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets whether the receiver should clear its filter predicate when a new object is inserted.
|
||||
|
||||
@param BOOL YES if the receiver should clear filter predicates on insert
|
||||
*/
|
||||
- (void)setClearsFilterPredicateOnInsertion:(BOOL)aFlag
|
||||
{
|
||||
_clearsFilterPredicateOnInsertion = aFlag;
|
||||
}
|
||||
|
||||
/*!
|
||||
Whether the receiver will always return the multiple values marker when multiple
|
||||
items are selected, even if the items have the same value.
|
||||
|
||||
@return BOOL YES if the receiver always uses the multiple values marker
|
||||
*/
|
||||
- (BOOL)alwaysUsesMultipleValuesMarker
|
||||
{
|
||||
return _alwaysUsesMultipleValuesMarker;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets whether the receiver should always return the multiple values marker when multiple
|
||||
items are selected, even if the items have the same value.
|
||||
|
||||
@param BOOL aFlag YES if the receiver should always use the multiple values marker
|
||||
*/
|
||||
- (void)setAlwaysUsesMultipleValuesMarker:(BOOL)aFlag
|
||||
{
|
||||
_alwaysUsesMultipleValuesMarker = aFlag;
|
||||
}
|
||||
|
||||
/*!
|
||||
Whether the receiver will rearrange its contents automatically whenever the sort
|
||||
descriptors or filter predicates are changed.
|
||||
|
||||
NOTE: not yet implemented. Cappuccino always act as if this value was YES.
|
||||
|
||||
@return BOOL YES if the receiver will automatically rearrange its content on new sort
|
||||
descriptors or filter predicates
|
||||
*/
|
||||
- (BOOL)automaticallyRearrangesObjects
|
||||
{
|
||||
return _automaticallyRearrangesObjects;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets whether the receiver should rearrange its contents automatically whenever the sort
|
||||
descriptors or filter predicates are changed.
|
||||
|
||||
NOTE: not yet implemented. Cappuccino always act as if this value was YES.
|
||||
|
||||
@param BOOL YES if the receiver should automatically rearrange its content on new sort
|
||||
descriptors or filter predicates
|
||||
*/
|
||||
- (void)setAutomaticallyRearrangesObjects:(BOOL)aFlag
|
||||
{
|
||||
_automaticallyRearrangesObjects = aFlag;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the controller's content object.
|
||||
|
||||
@param id value - the content object of the controller.
|
||||
*/
|
||||
- (void)setContent:(id)value
|
||||
{
|
||||
if (value === nil)
|
||||
@@ -185,7 +306,7 @@
|
||||
// We need to be in control of when notifications fire.
|
||||
_contentObject = value;
|
||||
|
||||
if (_clearsFilterPredicateOnInsertion)
|
||||
if (_clearsFilterPredicateOnInsertion && _filterPredicate != nil)
|
||||
[self __setFilterPredicate:nil]; // Causes a _rearrangeObjects.
|
||||
else
|
||||
[self _rearrangeObjects];
|
||||
@@ -199,32 +320,53 @@
|
||||
[self didChangeValueForKey:@"filterPredicate"];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)_setContentArray:(id)anArray
|
||||
{
|
||||
[self setContent:anArray];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)_setContentSet:(id)aSet
|
||||
{
|
||||
[self setContent:[aSet allObjects]];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the content array of the controller.
|
||||
@return id the content array of the receiver
|
||||
*/
|
||||
- (id)contentArray
|
||||
{
|
||||
return [self content];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the content of the receiver as a CPSet.
|
||||
|
||||
@return id - the content of the controller as a set.
|
||||
*/
|
||||
- (id)contentSet
|
||||
{
|
||||
return [CPSet setWithArray:[self content]];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sorts and filters a given array and returns it.
|
||||
|
||||
@param CPArray anArray - an array of objects.
|
||||
@return CPArray - the array of sorted objects.
|
||||
*/
|
||||
- (CPArray)arrangeObjects:(CPArray)objects
|
||||
{
|
||||
var filterPredicate = [self filterPredicate],
|
||||
sortDescriptors = [self sortDescriptors];
|
||||
|
||||
if (filterPredicate && sortDescriptors)
|
||||
if (filterPredicate && [sortDescriptors count] > 0)
|
||||
{
|
||||
var sortedObjects = [objects filteredArrayUsingPredicate:filterPredicate];
|
||||
[sortedObjects sortUsingDescriptors:sortDescriptors];
|
||||
@@ -232,12 +374,15 @@
|
||||
}
|
||||
else if (filterPredicate)
|
||||
return [objects filteredArrayUsingPredicate:filterPredicate];
|
||||
else if (sortDescriptors)
|
||||
else if ([sortDescriptors count] > 0)
|
||||
return [objects sortedArrayUsingDescriptors:sortDescriptors];
|
||||
|
||||
return [objects copy];
|
||||
}
|
||||
|
||||
/*!
|
||||
Triggers the filtering of the objects in the controller.
|
||||
*/
|
||||
- (void)rearrangeObjects
|
||||
{
|
||||
[self willChangeValueForKey:@"arrangedObjects"];
|
||||
@@ -271,24 +416,40 @@
|
||||
[self __setSelectionIndexes:oldSelectionIndexes];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)__setArrangedObjects:(id)value
|
||||
{
|
||||
if (_arrangedObjects === value)
|
||||
return;
|
||||
|
||||
_arrangedObjects = [[_CPObservableArray alloc] initWithArray:value];
|
||||
_arrangedObjects = [[_CPObservableArray alloc] initWithArray:value];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns an array of the controller's objects sorted and filtered.
|
||||
@return - array of objects
|
||||
*/
|
||||
- (id)arrangedObjects
|
||||
{
|
||||
return _arrangedObjects;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the receiver's array of sort descriptors.
|
||||
@return CPArray an array of sort descriptors
|
||||
*/
|
||||
- (CPArray)sortDescriptors
|
||||
{
|
||||
return _sortDescriptors;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the sort descriptors for the controller.
|
||||
|
||||
@param CPArray descriptors - the new sort descriptors.
|
||||
*/
|
||||
- (void)setSortDescriptors:(CPArray)value
|
||||
{
|
||||
if (_sortDescriptors === value)
|
||||
@@ -300,11 +461,23 @@
|
||||
[self _rearrangeObjects];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the predicate used by the controller to filter the contents of the receiver.
|
||||
If no predicate is set nil is returned.
|
||||
|
||||
@return CPPredicate the predicate used by the controller
|
||||
*/
|
||||
- (CPPredicate)filterPredicate
|
||||
{
|
||||
return _filterPredicate;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the predicate for the controller to filter the content.
|
||||
Passing nil will remove an existing prediate.
|
||||
|
||||
@param CPPrediate aPredicate - the new predicate.
|
||||
*/
|
||||
- (void)setFilterPredicate:(CPPredicate)value
|
||||
{
|
||||
[self __setFilterPredicate:value];
|
||||
@@ -325,28 +498,52 @@
|
||||
[self _rearrangeObjects];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a BOOL indicating whether the receiver always returns the multiple values marker when multiple objects are selected.
|
||||
@return BOOL YES is the controller always uses multiple value markers, otherwise NO.
|
||||
*/
|
||||
- (BOOL)alwaysUsesMultipleValuesMarker
|
||||
{
|
||||
return _alwaysUsesMultipleValuesMarker;
|
||||
}
|
||||
|
||||
//Selection
|
||||
|
||||
/*!
|
||||
Returns the index of the first object in the controller's selection.
|
||||
@return unsigned - Index of the first selected object.
|
||||
*/
|
||||
- (unsigned)selectionIndex
|
||||
{
|
||||
return [_selectionIndexes firstIndex];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the selected index
|
||||
|
||||
@param unsigned anIndex - the new index to select
|
||||
@return BOOL - Returns YES if the selection was changed, otherwise NO.
|
||||
*/
|
||||
- (BOOL)setSelectionIndex:(unsigned)index
|
||||
{
|
||||
return [self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns an index set of the selected indexes.
|
||||
|
||||
@return CPIndexSet - The selected indexes.
|
||||
*/
|
||||
- (CPIndexSet)selectionIndexes
|
||||
{
|
||||
return _selectionIndexes;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the selection indexes of the controller.
|
||||
|
||||
@param CPIndexSet indexes - the indexes to select
|
||||
@return BOOL - Returns YES if the selection changed, otherwise NO.
|
||||
*/
|
||||
- (BOOL)setSelectionIndexes:(CPIndexSet)indexes
|
||||
{
|
||||
[self _selectionWillChange]
|
||||
@@ -400,6 +597,10 @@
|
||||
return YES;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns an array of the selected objects.
|
||||
@return CPArray - the selected objects.
|
||||
*/
|
||||
- (CPArray)selectedObjects
|
||||
{
|
||||
var objects = [[self arrangedObjects] objectsAtIndexes:[self selectionIndexes]];
|
||||
@@ -407,6 +608,12 @@
|
||||
return [_CPObservableArray arrayWithArray:(objects || [])];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the selected objects of the controller.
|
||||
|
||||
@param CPArray anArray - the objects to select
|
||||
@return BOOL - Returns YES if the selection was changed, otherwise NO.
|
||||
*/
|
||||
- (BOOL)setSelectedObjects:(CPArray)objects
|
||||
{
|
||||
[self willChangeValueForKey:@"selectionIndexes"];
|
||||
@@ -441,12 +648,20 @@
|
||||
}
|
||||
|
||||
//Moving selection
|
||||
/*!
|
||||
Returns YES if the previous object, relative to the current selection, in the controller's content array can be selected.
|
||||
|
||||
@return BOOL - YES if the object can be selected, otherwise NO.
|
||||
*/
|
||||
- (BOOL)canSelectPrevious
|
||||
{
|
||||
return [[self selectionIndexes] firstIndex] > 0
|
||||
}
|
||||
|
||||
/*!
|
||||
Selects the previous object, relative to the current selection, in the controllers arranged content.
|
||||
@param id sender - the sender of the message.
|
||||
*/
|
||||
- (void)selectPrevious:(id)sender
|
||||
{
|
||||
var index = [[self selectionIndexes] firstIndex] - 1;
|
||||
@@ -455,11 +670,20 @@
|
||||
[self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns YES if the next object, relative to the current selection, in the controller's content array can be selected.
|
||||
|
||||
@return BOOL - YES if the object can be selected, otherwise NO.
|
||||
*/
|
||||
- (BOOL)canSelectNext
|
||||
{
|
||||
return [[self selectionIndexes] firstIndex] < [[self arrangedObjects] count] - 1;
|
||||
}
|
||||
|
||||
/*!
|
||||
Selects the next object, relative to the current selection, in the controllers arranged content.
|
||||
@param id sender - the sender of the message.
|
||||
*/
|
||||
- (void)selectNext:(id)sender
|
||||
{
|
||||
var index = [[self selectionIndexes] firstIndex] + 1;
|
||||
@@ -470,6 +694,11 @@
|
||||
|
||||
//Add/Remove
|
||||
|
||||
/*!
|
||||
Adds object to the receiver's content collection and the arranged objects array.
|
||||
|
||||
@param id anObject - the object to add the controller.
|
||||
*/
|
||||
- (void)addObject:(id)object
|
||||
{
|
||||
if (![self canAdd])
|
||||
@@ -503,6 +732,12 @@
|
||||
[self didChangeValueForKey:@"filterPredicate"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Adds an object at a given index to the receiver's collection.
|
||||
|
||||
@param id anObject - The object to add to the collection.
|
||||
@param int anIndex - The index to insert the object at.
|
||||
*/
|
||||
- (void)insertObject:(id)anObject atArrangedObjectIndex:(int)anIndex
|
||||
{
|
||||
if (![self canAdd])
|
||||
@@ -534,6 +769,11 @@
|
||||
[self didChangeValueForKey:@"filterPredicate"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Removes a given object from the receiver's collection.
|
||||
|
||||
@param id anObject - The object to remove from the collection.
|
||||
*/
|
||||
- (void)removeObject:(id)object
|
||||
{
|
||||
[self willChangeValueForKey:@"content"];
|
||||
@@ -552,6 +792,11 @@
|
||||
[self didChangeValueForKey:@"content"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates and adds a new object to the receiver's content and arranged objects.
|
||||
|
||||
@param id sender - The sender of the message.
|
||||
*/
|
||||
- (void)add:(id)sender
|
||||
{
|
||||
if (![self canAdd])
|
||||
@@ -560,6 +805,10 @@
|
||||
[self insert:sender];
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a new object and inserts it into the receiver's content array.
|
||||
@param id sender - The sender of the message.
|
||||
*/
|
||||
- (void)insert:(id)sender
|
||||
{
|
||||
if (![self canInsert])
|
||||
@@ -570,17 +819,29 @@
|
||||
[self addObject:newObject];
|
||||
}
|
||||
|
||||
/*!
|
||||
Removes the controller's selected objects from the controller's collection.
|
||||
@param id sender - The sender of the message.
|
||||
*/
|
||||
- (void)remove:(id)sender
|
||||
{
|
||||
[self removeObjects:[[self arrangedObjects] objectsAtIndexes:[self selectionIndexes]]];
|
||||
}
|
||||
|
||||
/*!
|
||||
Removes the objects at the specified indexes in the controller's arranged objects from the content array.
|
||||
@param CPIndexSet indexes - indexes of the objects to remove.
|
||||
*/
|
||||
- (void)removeObjectsAtArrangedObjectIndexes:(CPIndexSet)indexes
|
||||
{
|
||||
[self _removeObjects:[[self arrangedObjects] objectsAtIndexes:indexes]];
|
||||
}
|
||||
|
||||
/*!
|
||||
Adds an array of objects to the controller's collection.
|
||||
|
||||
@param CPArray anArray - The array of objects to add to the collection.
|
||||
*/
|
||||
- (void)addObjects:(CPArray)objects
|
||||
{
|
||||
if (![self canAdd])
|
||||
@@ -595,11 +856,18 @@
|
||||
[self setContent:contentArray];
|
||||
}
|
||||
|
||||
/*!
|
||||
Removes an array of objects from the collection.
|
||||
@param CPArray anArray - The array of objects to remove
|
||||
*/
|
||||
- (void)removeObjects:(CPArray)objects
|
||||
{
|
||||
[self _removeObjects:objects];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)_removeObjects:(CPArray)objects
|
||||
{
|
||||
[self willChangeValueForKey:@"content"];
|
||||
@@ -631,6 +899,10 @@
|
||||
[self didChangeValueForKey:@"content"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a BOOL indicating whether an object can be inserted into the controller's collection.
|
||||
@return BOOL - YES if an object can be inserted, otherwise NO.
|
||||
*/
|
||||
- (BOOL)canInsert
|
||||
{
|
||||
return [self isEditable];
|
||||
@@ -643,7 +915,8 @@ var CPArrayControllerAvoidsEmptySelection = @"CPArrayControllerAvoid
|
||||
CPArrayControllerFilterRestrictsInsertion = @"CPArrayControllerFilterRestrictsInsertion",
|
||||
CPArrayControllerPreservesSelection = @"CPArrayControllerPreservesSelection",
|
||||
CPArrayControllerSelectsInsertedObjects = @"CPArrayControllerSelectsInsertedObjects",
|
||||
CPArrayControllerAlwaysUsesMultipleValuesMarker = @"CPArrayControllerAlwaysUsesMultipleValuesMarker";
|
||||
CPArrayControllerAlwaysUsesMultipleValuesMarker = @"CPArrayControllerAlwaysUsesMultipleValuesMarker",
|
||||
CPArrayControllerAutomaticallyRearrangesObjects = @"CPArrayControllerAutomaticallyRearrangesObjects";
|
||||
|
||||
@implementation CPArrayController (CPCoding)
|
||||
|
||||
@@ -659,6 +932,8 @@ var CPArrayControllerAvoidsEmptySelection = @"CPArrayControllerAvoid
|
||||
_preservesSelection = [aCoder decodeBoolForKey:CPArrayControllerPreservesSelection];
|
||||
_selectsInsertedObjects = [aCoder decodeBoolForKey:CPArrayControllerSelectsInsertedObjects];
|
||||
_alwaysUsesMultipleValuesMarker = [aCoder decodeBoolForKey:CPArrayControllerAlwaysUsesMultipleValuesMarker];
|
||||
_automaticallyRearrangesObjects = [aCoder decodeBoolForKey:CPArrayControllerAutomaticallyRearrangesObjects];
|
||||
_sortDescriptors = [CPArray array];
|
||||
|
||||
if (![self content] && [self automaticallyPreparesContent])
|
||||
[self prepareContent];
|
||||
@@ -679,6 +954,7 @@ var CPArrayControllerAvoidsEmptySelection = @"CPArrayControllerAvoid
|
||||
[aCoder encodeBool:_preservesSelection forKey:CPArrayControllerPreservesSelection];
|
||||
[aCoder encodeBool:_selectsInsertedObjects forKey:CPArrayControllerSelectsInsertedObjects];
|
||||
[aCoder encodeBool:_alwaysUsesMultipleValuesMarker forKey:CPArrayControllerAlwaysUsesMultipleValuesMarker];
|
||||
[aCoder encodeBool:_automaticallyRearrangesObjects forKey:CPArrayControllerAutomaticallyRearrangesObjects];
|
||||
}
|
||||
|
||||
- (void)awakeFromCib
|
||||
|
||||
@@ -38,7 +38,7 @@ var DefaultLineWidth = 1.0;
|
||||
@class CPBezierPath
|
||||
|
||||
A CPBezierPath allows you to create paths for drawing to the screen using a simpler API than CoreGraphics.
|
||||
Paths can form any shape, including regular polgyons like squares and triangles; circles, arcs; or complex
|
||||
Paths can form any shape, including regular polygons like squares and triangles; circles, arcs; or complex
|
||||
line segments.
|
||||
|
||||
A path can be stroked and filled using the relevant method. The currently active fill and stroke color will
|
||||
|
||||
@@ -235,8 +235,8 @@ CPGrooveBorder = 3;
|
||||
switch (_boxType)
|
||||
{
|
||||
case CPBoxSeparator:
|
||||
// NSBox does not include a horitontal flag for the seperator type. We have to determine
|
||||
// the type of seperator to draw by the width and height of the frame.
|
||||
// NSBox does not include a horizontal flag for the separator type. We have to determine
|
||||
// the type of separator to draw by the width and height of the frame.
|
||||
if (CGRectGetWidth(bounds) === 5.0)
|
||||
return [self _drawVerticalSeperatorInRect:bounds];
|
||||
else if (CGRectGetHeight(bounds) === 5.0)
|
||||
|
||||
@@ -83,42 +83,47 @@
|
||||
{
|
||||
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:CPThemeStateSelectedDataView];
|
||||
[_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];
|
||||
[self _init];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)_init
|
||||
{
|
||||
_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:CPThemeStateSelectedDataView];
|
||||
[_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];
|
||||
}
|
||||
|
||||
- (void)setPrototypeView:(CPView)aPrototypeView
|
||||
{
|
||||
_prototypeView = [CPKeyedUnarchiver unarchiveObjectWithData:
|
||||
@@ -650,6 +655,53 @@
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPBrowser (CPCoding)
|
||||
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
self = [super initWithCoder:aCoder];
|
||||
|
||||
if (self)
|
||||
{
|
||||
[self _init];
|
||||
|
||||
_allowsEmptySelection = [aCoder decodeBoolForKey:@"CPBrowserAllowsEmptySelectionKey"];
|
||||
_allowsMultipleSelection = [aCoder decodeBoolForKey:@"CPBrowserAllowsMultipleSelectionKey"];
|
||||
_prototypeView = [aCoder decodeObjectForKey:@"CPBrowserPrototypeViewKey"];
|
||||
_rowHeight = [aCoder decodeFloatForKey:@"CPBrowserRowHeightKey"];
|
||||
_imageWidth = [aCoder decodeFloatForKey:@"CPBrowserImageWidthKey"];
|
||||
_minColumnWidth = [aCoder decodeFloatForKey:@"CPBrowserMinColumnWidthKey"];
|
||||
_columnWidths = [aCoder decodeObjectForKey:@"CPBrowserColumnWidthsKey"];
|
||||
|
||||
[self setDelegate:[aCoder decodeObjectForKey:@"CPBrowserDelegateKey"]];
|
||||
[self setAutohidesScroller:[aCoder decodeBoolForKey:@"CPBrowserAutohidesScrollerKey"]];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
// Don't encode the subviews, they're transient and will be recreated from data.
|
||||
var actualSubviews = _subviews;
|
||||
_subviews = [];
|
||||
[super encodeWithCoder:aCoder];
|
||||
_subviews = actualSubviews;
|
||||
|
||||
[aCoder encodeBool:[self autohidesScroller] forKey:@"CPBrowserAutohidesScrollerKey"];
|
||||
[aCoder encodeBool:_allowsEmptySelection forKey:@"CPBrowserAllowsEmptySelectionKey"];
|
||||
[aCoder encodeBool:_allowsMultipleSelection forKey:@"CPBrowserAllowsMultipleSelectionKey"];
|
||||
[aCoder encodeObject:_delegate forKey:@"CPBrowserDelegateKey"];
|
||||
[aCoder encodeObject:_prototypeView forKey:@"CPBrowserPrototypeViewKey"];
|
||||
[aCoder encodeFloat:_rowHeight forKey:@"CPBrowserRowHeightKey"];
|
||||
[aCoder encodeFloat:_imageWidth forKey:@"CPBrowserImageWidthKey"];
|
||||
[aCoder encodeFloat:_minColumnWidth forKey:@"CPBrowserMinColumnWidthKey"];
|
||||
[aCoder encodeObject:_columnWidths forKey:@"CPBrowserColumnWidthsKey"];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
var _CPBrowserResizeControlBackgroundImage = nil;
|
||||
|
||||
@implementation _CPBrowserResizeControl : CPView
|
||||
|
||||
@@ -125,7 +125,7 @@ var cachedBlackColor,
|
||||
}
|
||||
|
||||
/*!
|
||||
@deprecated in favor of colorWithWhite:apha:
|
||||
@deprecated in favor of colorWithWhite:alpha:
|
||||
|
||||
Creates a new color object with \c white for the RGB components.
|
||||
For the alpha component, a value of 1.0 is opaque, and 0.0 means completely transparent.
|
||||
|
||||
@@ -57,7 +57,7 @@ CPJavascriptRemedialKeySupport = 1 << 16;
|
||||
CPJavaScriptShadowFeature = 1 << 20;
|
||||
|
||||
CPJavaScriptNegativeMouseWheelValues = 1 << 22;
|
||||
CPJavaScriptMouseWheelValues_8_15 = 1 << 23
|
||||
CPJavaScriptMouseWheelValues_8_15 = 1 << 23;
|
||||
|
||||
CPOpacityRequiresFilterFeature = 1 << 24;
|
||||
|
||||
|
||||
@@ -43,21 +43,21 @@ CPLineBreakByTruncatingHead = 3;
|
||||
CPLineBreakByTruncatingTail = 4;
|
||||
CPLineBreakByTruncatingMiddle = 5;
|
||||
|
||||
CPTopVerticalTextAlignment = 1,
|
||||
CPCenterVerticalTextAlignment = 2,
|
||||
CPTopVerticalTextAlignment = 1;
|
||||
CPCenterVerticalTextAlignment = 2;
|
||||
CPBottomVerticalTextAlignment = 3;
|
||||
|
||||
CPScaleProportionally = 0;
|
||||
CPScaleToFit = 1;
|
||||
CPScaleNone = 2;
|
||||
CPScaleProportionally = 0;
|
||||
CPScaleToFit = 1;
|
||||
CPScaleNone = 2;
|
||||
|
||||
CPNoImage = 0;
|
||||
CPImageOnly = 1;
|
||||
CPImageLeft = 2;
|
||||
CPImageRight = 3;
|
||||
CPImageBelow = 4;
|
||||
CPImageAbove = 5;
|
||||
CPImageOverlaps = 6;
|
||||
CPNoImage = 0;
|
||||
CPImageOnly = 1;
|
||||
CPImageLeft = 2;
|
||||
CPImageRight = 3;
|
||||
CPImageBelow = 4;
|
||||
CPImageAbove = 5;
|
||||
CPImageOverlaps = 6;
|
||||
|
||||
CPOnState = 1;
|
||||
CPOffState = 0;
|
||||
@@ -72,7 +72,7 @@ CPControlTextDidBeginEditingNotification = "CPControlTextDidBeginEditingNotif
|
||||
CPControlTextDidChangeNotification = "CPControlTextDidChangeNotification";
|
||||
CPControlTextDidEndEditingNotification = "CPControlTextDidEndEditingNotification";
|
||||
|
||||
var CPControlBlackColor = [CPColor blackColor];
|
||||
var CPControlBlackColor = [CPColor blackColor];
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@@ -171,7 +171,8 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the receiver's target action
|
||||
Sets the receiver's target action.
|
||||
|
||||
@param anAction Sets the action message that gets sent to the target.
|
||||
*/
|
||||
- (void)setAction:(SEL)anAction
|
||||
@@ -180,7 +181,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the receiver's target action
|
||||
Returns the receiver's target action.
|
||||
*/
|
||||
- (SEL)action
|
||||
{
|
||||
@@ -189,6 +190,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
|
||||
/*!
|
||||
Sets the receiver's target. The target receives action messages from the receiver.
|
||||
|
||||
@param aTarget the object that will receive the message specified by action
|
||||
*/
|
||||
- (void)setTarget:(id)aTarget
|
||||
@@ -206,6 +208,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
|
||||
/*!
|
||||
Causes \c anAction to be sent to \c anObject.
|
||||
|
||||
@param anAction the action to send
|
||||
@param anObject the object to which the action will be sent
|
||||
*/
|
||||
@@ -226,6 +229,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
|
||||
/*!
|
||||
Sets the tooltip for the receiver.
|
||||
|
||||
@param aToolTip the tooltip
|
||||
*/
|
||||
/*
|
||||
@@ -262,7 +266,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
|
||||
/*!
|
||||
Sets whether the cell can continuously send its action messages.
|
||||
*/
|
||||
*/
|
||||
- (void)setContinuous:(BOOL)flag
|
||||
{
|
||||
// Some subclasses should redefine this with CPLeftMouseDraggedMask
|
||||
@@ -272,6 +276,9 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
_sendActionOn &= ~CPPeriodicMask;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns YES if the receiver tracks the mouse outside the frame, otherwise NO.
|
||||
*/
|
||||
- (BOOL)tracksMouseOutsideOfFrame
|
||||
{
|
||||
return NO;
|
||||
@@ -334,6 +341,11 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
Perform a click on the receiver.
|
||||
|
||||
@param sender - The sender object
|
||||
*/
|
||||
- (void)performClick:(id)sender
|
||||
{
|
||||
if (![self isEnabled])
|
||||
@@ -356,11 +368,18 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Fired when the button timer finished, usually after the user hits enter.
|
||||
*/
|
||||
- (void)unhighlightButtonTimerDidFinish:(id)sender
|
||||
{
|
||||
[self highlight:NO];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the mask of modifier keys held down when the user clicked.
|
||||
*/
|
||||
- (unsigned)mouseDownFlags
|
||||
{
|
||||
return _trackingMouseDownFlags;
|
||||
@@ -411,7 +430,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the receiver's object value
|
||||
Returns the receiver's object value.
|
||||
*/
|
||||
- (id)objectValue
|
||||
{
|
||||
@@ -419,7 +438,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
}
|
||||
|
||||
/*!
|
||||
Set's the receiver's object value
|
||||
Sets the receiver's object value.
|
||||
*/
|
||||
- (void)setObjectValue:(id)anObject
|
||||
{
|
||||
@@ -430,7 +449,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the receiver's float value
|
||||
Returns the receiver's float value.
|
||||
*/
|
||||
- (float)floatValue
|
||||
{
|
||||
@@ -439,7 +458,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the receiver's float value
|
||||
Sets the receiver's float value.
|
||||
*/
|
||||
- (void)setFloatValue:(float)aValue
|
||||
{
|
||||
@@ -447,7 +466,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the receiver's double value
|
||||
Returns the receiver's double value.
|
||||
*/
|
||||
- (double)doubleValue
|
||||
{
|
||||
@@ -456,7 +475,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
}
|
||||
|
||||
/*!
|
||||
Set's the receiver's double value
|
||||
Sets the receiver's double value.
|
||||
*/
|
||||
- (void)setDoubleValue:(double)anObject
|
||||
{
|
||||
@@ -464,7 +483,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the receiver's int value
|
||||
Returns the receiver's int value.
|
||||
*/
|
||||
- (int)intValue
|
||||
{
|
||||
@@ -473,7 +492,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
}
|
||||
|
||||
/*!
|
||||
Set's the receiver's int value
|
||||
Sets the receiver's int value.
|
||||
*/
|
||||
- (void)setIntValue:(int)anObject
|
||||
{
|
||||
@@ -481,7 +500,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the receiver's int value
|
||||
Returns the receiver's int value.
|
||||
*/
|
||||
- (int)integerValue
|
||||
{
|
||||
@@ -490,7 +509,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
}
|
||||
|
||||
/*!
|
||||
Set's the receiver's int value
|
||||
Sets the receiver's int value.
|
||||
*/
|
||||
- (void)setIntegerValue:(int)anObject
|
||||
{
|
||||
@@ -498,7 +517,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the receiver's string value
|
||||
Returns the receiver's string value.
|
||||
*/
|
||||
- (CPString)stringValue
|
||||
{
|
||||
@@ -506,7 +525,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
}
|
||||
|
||||
/*!
|
||||
Set's the receiver's string value
|
||||
Sets the receiver's string value.
|
||||
*/
|
||||
- (void)setStringValue:(CPString)anObject
|
||||
{
|
||||
@@ -582,96 +601,199 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidEndEditingNotification object:self userInfo:[CPDictionary dictionaryWithObject:[note object] forKey:"CPFieldEditor"]];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the text alignment of the control.
|
||||
|
||||
<pre>
|
||||
CPLeftTextAlignment
|
||||
CPCenterTextAlignment
|
||||
CPRightTextAlignment
|
||||
CPJustifiedTextAlignment
|
||||
CPNaturalTextAlignment
|
||||
</pre>
|
||||
*/
|
||||
- (void)setAlignment:(CPTextAlignment)alignment
|
||||
{
|
||||
[self setValue:alignment forThemeAttribute:@"alignment"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the text alignment of the control.
|
||||
*/
|
||||
- (CPTextAlignment)alignment
|
||||
{
|
||||
return [self valueForThemeAttribute:@"alignment"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the vertical text alignment of the control.
|
||||
|
||||
<pre>
|
||||
CPTopVerticalTextAlignment
|
||||
CPCenterVerticalTextAlignment
|
||||
CPBottomVerticalTextAlignment
|
||||
</pre>
|
||||
*/
|
||||
- (void)setVerticalAlignment:(CPTextVerticalAlignment)alignment
|
||||
{
|
||||
[self setValue:alignment forThemeAttribute:@"vertical-alignment"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the vertical text alignment of the receiver.
|
||||
*/
|
||||
- (CPTextVerticalAlignment)verticalAlignment
|
||||
{
|
||||
return [self valueForThemeAttribute:@"vertical-alignment"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the line break mode of the receiver.
|
||||
|
||||
<pre>
|
||||
CPLineBreakByWordWrapping
|
||||
CPLineBreakByCharWrapping
|
||||
CPLineBreakByClipping
|
||||
CPLineBreakByTruncatingHead
|
||||
CPLineBreakByTruncatingTail
|
||||
CPLineBreakByTruncatingMiddle
|
||||
</pre>
|
||||
*/
|
||||
- (void)setLineBreakMode:(CPLineBreakMode)mode
|
||||
{
|
||||
[self setValue:mode forThemeAttribute:@"line-break-mode"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the line break mode of the control.
|
||||
*/
|
||||
- (CPLineBreakMode)lineBreakMode
|
||||
{
|
||||
return [self valueForThemeAttribute:@"line-break-mode"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the text color of the receiver.
|
||||
|
||||
@param aColor - A CPColor object.
|
||||
*/
|
||||
- (void)setTextColor:(CPColor)aColor
|
||||
{
|
||||
[self setValue:aColor forThemeAttribute:@"text-color"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the text color of the receiver.
|
||||
*/
|
||||
- (CPColor)textColor
|
||||
{
|
||||
return [self valueForThemeAttribute:@"text-color"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the shadow color of the text for the receiver.
|
||||
*/
|
||||
- (void)setTextShadowColor:(CPColor)aColor
|
||||
{
|
||||
[self setValue:aColor forThemeAttribute:@"text-shadow-color"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the shadow color of the text for the control.
|
||||
*/
|
||||
- (CPColor)textShadowColor
|
||||
{
|
||||
return [self valueForThemeAttribute:@"text-shadow-color"];
|
||||
}
|
||||
|
||||
- (void)setTextShadowOffset:(float)offset
|
||||
/*!
|
||||
Sets the shadow offset for the text.
|
||||
|
||||
@param offset - a CGSize with the x and y offsets.
|
||||
*/
|
||||
- (void)setTextShadowOffset:(CGSize)offset
|
||||
{
|
||||
[self setValue:offset forThemeAttribute:@"text-shadow-offset"];
|
||||
}
|
||||
|
||||
- (float)textShadowOffset
|
||||
/*!
|
||||
Returns the text shadow offset of the receiver.
|
||||
*/
|
||||
- (CGSize)textShadowOffset
|
||||
{
|
||||
return [self valueForThemeAttribute:@"text-shadow-offset"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the font of the control.
|
||||
*/
|
||||
- (void)setFont:(CPFont)aFont
|
||||
{
|
||||
[self setValue:aFont forThemeAttribute:@"font"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the font of the control.
|
||||
*/
|
||||
- (CPFont)font
|
||||
{
|
||||
return [self valueForThemeAttribute:@"font"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the image position of the control.
|
||||
|
||||
<pre>
|
||||
CPNoImage
|
||||
CPImageOnly
|
||||
CPImageLeft
|
||||
CPImageRight
|
||||
CPImageBelow
|
||||
CPImageAbove
|
||||
CPImageOverlaps
|
||||
</pre>
|
||||
*/
|
||||
- (void)setImagePosition:(CPCellImagePosition)position
|
||||
{
|
||||
[self setValue:position forThemeAttribute:@"image-position"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the image position of the receiver.
|
||||
*/
|
||||
- (CPCellImagePosition)imagePosition
|
||||
{
|
||||
return [self valueForThemeAttribute:@"image-position"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the image scaling of the control.
|
||||
|
||||
<pre>
|
||||
CPScaleProportionally
|
||||
CPScaleToFit
|
||||
CPScaleNone
|
||||
</pre>
|
||||
*/
|
||||
- (void)setImageScaling:(CPImageScaling)scaling
|
||||
{
|
||||
[self setValue:scaling forThemeAttribute:@"image-scaling"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the image scaling of the control.
|
||||
*/
|
||||
- (CPImageScaling)imageScaling
|
||||
{
|
||||
return [self valueForThemeAttribute:@"image-scaling"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the enabled status of the control.
|
||||
Controls that are not enabled can not be used by the user and obtain the CPThemeStateDisabled theme state.
|
||||
|
||||
@param BOOL - YES if the control should be enabled, otherwise NO.
|
||||
*/
|
||||
- (void)setEnabled:(BOOL)isEnabled
|
||||
{
|
||||
if (isEnabled)
|
||||
@@ -680,16 +802,29 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
[self setThemeState:CPThemeStateDisabled];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns YES if the receiver is enabled, otherwise NO.
|
||||
*/
|
||||
- (BOOL)isEnabled
|
||||
{
|
||||
return ![self hasThemeState:CPThemeStateDisabled];
|
||||
}
|
||||
|
||||
/*!
|
||||
Highlights the receiver.
|
||||
|
||||
@param BOOL - YES if the receiver should be highlighted, otherwise NO.
|
||||
*/
|
||||
- (void)highlight:(BOOL)shouldHighlight
|
||||
{
|
||||
[self setHighlighted:shouldHighlight];
|
||||
}
|
||||
|
||||
/*!
|
||||
Highlights the receiver.
|
||||
|
||||
@param BOOL - YES if the receiver should be highlighted, otherwise NO.
|
||||
*/
|
||||
- (void)setHighlighted:(BOOL)isHighlighted
|
||||
{
|
||||
if (isHighlighted)
|
||||
@@ -698,6 +833,9 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
[self unsetThemeState:CPThemeStateHighlighted];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns YES if the control is highlighted, otherwise NO.
|
||||
*/
|
||||
- (BOOL)isHighlighted
|
||||
{
|
||||
return [self hasThemeState:CPThemeStateHighlighted];
|
||||
@@ -721,6 +859,7 @@ var __Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
|
||||
|
||||
/*
|
||||
Initializes the control by unarchiving it from a coder.
|
||||
|
||||
@param aCoder the coder from which to unarchive the control
|
||||
@return the initialized control
|
||||
*/
|
||||
@@ -744,6 +883,7 @@ var __Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
|
||||
|
||||
/*
|
||||
Archives the control to the provided coder.
|
||||
|
||||
@param aCoder the coder to which the control will be archived.
|
||||
*/
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
@@ -753,8 +893,10 @@ var __Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
|
||||
if (_sendsActionOnEndEditing)
|
||||
[aCoder encodeBool:_sendsActionOnEndEditing forKey:CPControlSendsActionOnEndEditingKey];
|
||||
|
||||
if (_value !== nil)
|
||||
[aCoder encodeObject:_value forKey:CPControlValueKey];
|
||||
var objectValue = [self objectValue];
|
||||
|
||||
if (objectValue !== nil)
|
||||
[aCoder encodeObject:objectValue forKey:CPControlValueKey];
|
||||
|
||||
if (_target !== nil)
|
||||
[aCoder encodeConditionalObject:_target forKey:CPControlTargetKey];
|
||||
|
||||
@@ -88,7 +88,7 @@ var CPDocumentUntitledCount = 0;
|
||||
@class CPDocument
|
||||
|
||||
CPDocument is used to represent a document/file in a Cappuccino application.
|
||||
In a document-based application, generally multiple documents are open simutaneously
|
||||
In a document-based application, generally multiple documents are open simultaneously
|
||||
(multiple text documents, slide presentations, spreadsheets, etc.), and multiple
|
||||
CPDocuments should be used to represent this.
|
||||
*/
|
||||
@@ -208,7 +208,7 @@ var CPDocumentUntitledCount = 0;
|
||||
throws an exception.
|
||||
@param aType the format of the data
|
||||
@param anError not used
|
||||
@throws CPUnsupportedMethodException if this method hasn't been overriden by the subclass
|
||||
@throws CPUnsupportedMethodException if this method hasn't been overridden by the subclass
|
||||
@return the document data
|
||||
*/
|
||||
- (CPData)dataOfType:(CPString)aType error:({CPError})anError
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
@import <Foundation/CPBundle.j>
|
||||
|
||||
@import "CPDocument.j"
|
||||
@import "CPOpenPanel.j";
|
||||
@import "CPOpenPanel.j"
|
||||
|
||||
|
||||
var CPSharedDocumentController = nil;
|
||||
@@ -177,7 +177,7 @@ var CPSharedDocumentController = nil;
|
||||
@param aType the document type
|
||||
@param aDelegate the delegate to notify
|
||||
@param aSelector the selector to notify with
|
||||
@param aContextInfo the context infomration passed to the delegate
|
||||
@param aContextInfo the context information passed to the delegate
|
||||
*/
|
||||
- (CPDocument)makeDocumentWithContentsOfURL:(CPURL)anAbsoluteURL ofType:(CPString)aType delegate:(id)aDelegate didReadSelector:(SEL)aSelector contextInfo:(id)aContextInfo
|
||||
{
|
||||
|
||||
@@ -28,13 +28,13 @@
|
||||
@import "CPWindow.j"
|
||||
|
||||
|
||||
CPDragOperationNone = 0,
|
||||
CPDragOperationCopy = 1 << 1,
|
||||
CPDragOperationLink = 1 << 1,
|
||||
CPDragOperationGeneric = 1 << 2,
|
||||
CPDragOperationPrivate = 1 << 3,
|
||||
CPDragOperationMove = 1 << 4,
|
||||
CPDragOperationDelete = 1 << 5,
|
||||
CPDragOperationNone = 0;
|
||||
CPDragOperationCopy = 1 << 1;
|
||||
CPDragOperationLink = 1 << 1;
|
||||
CPDragOperationGeneric = 1 << 2;
|
||||
CPDragOperationPrivate = 1 << 3;
|
||||
CPDragOperationMove = 1 << 4;
|
||||
CPDragOperationDelete = 1 << 5;
|
||||
CPDragOperationEvery = -1;
|
||||
|
||||
#define DRAGGING_WINDOW(anObject) ([anObject isKindOfClass:[CPWindow class]] ? anObject : [anObject window])
|
||||
|
||||
@@ -161,21 +161,21 @@ CPEscapeFunctionKey = "\u001B";
|
||||
CPSpaceFunctionKey = "\u0020";
|
||||
|
||||
|
||||
CPDOMEventDoubleClick = "dblclick",
|
||||
CPDOMEventMouseDown = "mousedown",
|
||||
CPDOMEventMouseUp = "mouseup",
|
||||
CPDOMEventMouseMoved = "mousemove",
|
||||
CPDOMEventMouseDragged = "mousedrag",
|
||||
CPDOMEventKeyUp = "keyup",
|
||||
CPDOMEventKeyDown = "keydown",
|
||||
CPDOMEventKeyPress = "keypress";
|
||||
CPDOMEventCopy = "copy";
|
||||
CPDOMEventPaste = "paste";
|
||||
CPDOMEventScrollWheel = "mousewheel";
|
||||
CPDOMEventTouchStart = "touchstart";
|
||||
CPDOMEventTouchMove = "touchmove";
|
||||
CPDOMEventTouchEnd = "touchend";
|
||||
CPDOMEventTouchCancel = "touchcancel";
|
||||
CPDOMEventDoubleClick = "dblclick";
|
||||
CPDOMEventMouseDown = "mousedown";
|
||||
CPDOMEventMouseUp = "mouseup";
|
||||
CPDOMEventMouseMoved = "mousemove";
|
||||
CPDOMEventMouseDragged = "mousedrag";
|
||||
CPDOMEventKeyUp = "keyup";
|
||||
CPDOMEventKeyDown = "keydown";
|
||||
CPDOMEventKeyPress = "keypress";
|
||||
CPDOMEventCopy = "copy";
|
||||
CPDOMEventPaste = "paste";
|
||||
CPDOMEventScrollWheel = "mousewheel";
|
||||
CPDOMEventTouchStart = "touchstart";
|
||||
CPDOMEventTouchMove = "touchmove";
|
||||
CPDOMEventTouchEnd = "touchend";
|
||||
CPDOMEventTouchCancel = "touchcancel";
|
||||
|
||||
var _CPEventPeriodicEventPeriod = 0,
|
||||
_CPEventPeriodicEventTimer = nil,
|
||||
@@ -211,6 +211,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
|
||||
/*!
|
||||
Creates a new keyboard event.
|
||||
|
||||
@param anEventType the event type. Must be one of CPKeyDown, CPKeyUp or CPFlagsChanged
|
||||
@param aPoint the location of the cursor in the window specified by \c aWindowNumber
|
||||
@param modifierFlags a bitwise combination of the modifiers specified in the CPEvent globals
|
||||
@@ -235,7 +236,8 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a new mouse event
|
||||
Creates a new mouse event.
|
||||
|
||||
@param anEventType the event type
|
||||
@param aPoint the location of the cursor in the window specified by \c aWindowNumber
|
||||
@param modifierFlags a bitwise combination of the modifiers specified in the CPEvent globals
|
||||
@@ -257,7 +259,8 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a new custom event
|
||||
Creates a new custom event.
|
||||
|
||||
@param anEventType the event type. Must be one of CPAppKitDefined, CPSystemDefined, CPApplicationDefined or CPPeriodic
|
||||
@param aLocation the location of the cursor in the window specified by \c aWindowNumber
|
||||
@param modifierFlags a bitwise combination of the modifiers specified in the CPEvent globals
|
||||
@@ -349,10 +352,10 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
|
||||
/*!
|
||||
Returns the location of the mouse (for mouse events).
|
||||
If this is not a mouse event, it returns \c nil.
|
||||
If \c window returns \c nil, then
|
||||
the mouse coordinates will be based on the screen coordinates.
|
||||
If the receiver is not a mouse event, it returns \c nil.
|
||||
If \c window returns \c nil, then the mouse coordinates will be based on the screen coordinates.
|
||||
Otherwise, the coordinates are relative to the window's coordinates.
|
||||
|
||||
@return the location of the mouse, or \c nil for non-mouse events.
|
||||
*/
|
||||
- (CGPoint)locationInWindow
|
||||
@@ -372,7 +375,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns event information as a bit mask
|
||||
Returns event information as a bit mask.
|
||||
*/
|
||||
- (unsigned)modifierFlags
|
||||
{
|
||||
@@ -380,7 +383,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the time the event occurred
|
||||
Returns the time the event occurred.
|
||||
*/
|
||||
- (CPTimeInterval)timestamp
|
||||
{
|
||||
@@ -396,7 +399,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the event's associated window
|
||||
Returns the event's associated window.
|
||||
*/
|
||||
- (CPWindow)window
|
||||
{
|
||||
@@ -427,7 +430,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the number of clicks that caused this event. (mouse only)
|
||||
Returns the number of clicks that caused this event (mouse only).
|
||||
*/
|
||||
- (int)clickCount
|
||||
{
|
||||
@@ -435,7 +438,8 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the characters associated with this event (keyboard only)
|
||||
Returns the characters associated with this event (keyboard only).
|
||||
|
||||
@throws CPInternalInconsistencyException if this method is called on a non-key event
|
||||
*/
|
||||
- (CPString)characters
|
||||
@@ -445,6 +449,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
|
||||
/*!
|
||||
Returns the character ignoring any modifiers (except shift).
|
||||
|
||||
@throws CPInternalInconsistencyException if this method is called on a non-key event
|
||||
*/
|
||||
- (CPString)charactersIgnoringModifiers
|
||||
@@ -454,6 +459,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
|
||||
/*!
|
||||
Returns \c YES if the keyboard event was caused by the key being held down.
|
||||
|
||||
@throws CPInternalInconsistencyException if this method is called on a non-key event
|
||||
*/
|
||||
- (BOOL)isARepeat
|
||||
@@ -463,6 +469,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
|
||||
/*!
|
||||
Returns the key's key code.
|
||||
|
||||
@throws CPInternalInconsistencyException if this method is called on a non-key event
|
||||
*/
|
||||
- (unsigned short)keyCode
|
||||
@@ -495,7 +502,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
return _DOMEvent;
|
||||
}
|
||||
|
||||
// Getting Scroll Wheel Event Infomration
|
||||
// Getting Scroll Wheel Event Information
|
||||
/*!
|
||||
Returns the change in the x-axis for a mouse event.
|
||||
*/
|
||||
@@ -586,7 +593,8 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
}
|
||||
|
||||
/*!
|
||||
Gene rates periodic events every \c aPeriod seconds.
|
||||
Generates periodic events every \c aPeriod seconds.
|
||||
|
||||
@param aDelay the number of seconds before the first event
|
||||
@param aPeriod the length of time in seconds between successive events
|
||||
*/
|
||||
@@ -599,7 +607,7 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
}
|
||||
|
||||
/*!
|
||||
Stops the periodic events from being generated
|
||||
Stops the periodic events from being generated.
|
||||
*/
|
||||
+ (void)stopPeriodicEvents
|
||||
{
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
@import "CGContext.j"
|
||||
|
||||
|
||||
var CPGraphicsContextCurrent = nil;
|
||||
var CPGraphicsContextCurrent = nil;
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
|
||||
@@ -52,7 +52,7 @@ var _CPMenuBarVisible = NO,
|
||||
@class CPMenu
|
||||
|
||||
Menus provide the user with a list of actions and/or submenus. Submenus themselves are full fledged menus
|
||||
and so a heirarchical structure appears.
|
||||
and so a hierarchical structure appears.
|
||||
*/
|
||||
@implementation CPMenu : CPObject
|
||||
{
|
||||
@@ -80,6 +80,9 @@ var _CPMenuBarVisible = NO,
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
if (self !== CPMenu)
|
||||
return;
|
||||
|
||||
[[self class] setMenuBarAttributes:[CPDictionary dictionary]];
|
||||
}
|
||||
|
||||
@@ -274,22 +277,7 @@ var _CPMenuBarVisible = NO,
|
||||
*/
|
||||
- (void)insertItem:(CPMenuItem)aMenuItem atIndex:(unsigned)anIndex
|
||||
{
|
||||
var menu = [aMenuItem menu];
|
||||
|
||||
if (menu)
|
||||
if (menu !== self)
|
||||
[CPException raise:CPInternalInconsistencyException reason:@"Attempted to insert item into menu that was already in another menu."];
|
||||
else
|
||||
return;
|
||||
|
||||
[aMenuItem setMenu:self];
|
||||
[_items insertObject:aMenuItem atIndex:anIndex];
|
||||
|
||||
[[CPNotificationCenter defaultCenter]
|
||||
postNotificationName:CPMenuDidAddItemNotification
|
||||
object:self
|
||||
userInfo:[CPDictionary dictionaryWithObject:anIndex forKey:@"CPMenuItemIndex"]];
|
||||
|
||||
[self insertObject:aMenuItem inItemsAtIndex:anIndex];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -346,16 +334,7 @@ var _CPMenuBarVisible = NO,
|
||||
*/
|
||||
- (void)removeItemAtIndex:(unsigned)anIndex
|
||||
{
|
||||
if (anIndex < 0 || anIndex >= _items.length)
|
||||
return;
|
||||
|
||||
[_items[anIndex] setMenu:nil];
|
||||
[_items removeObjectAtIndex:anIndex];
|
||||
|
||||
[[CPNotificationCenter defaultCenter]
|
||||
postNotificationName:CPMenuDidRemoveItemNotification
|
||||
object:self
|
||||
userInfo:[CPDictionary dictionaryWithObject:anIndex forKey:@"CPMenuItemIndex"]];
|
||||
[self removeObjectFromItemsAtIndex:anIndex];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -364,9 +343,11 @@ var _CPMenuBarVisible = NO,
|
||||
*/
|
||||
- (void)itemChanged:(CPMenuItem)aMenuItem
|
||||
{
|
||||
if ([aMenuItem menu] != self)
|
||||
if ([aMenuItem menu] !== self)
|
||||
return;
|
||||
|
||||
[aMenuItem setValue:[aMenuItem valueForKey:@"changeCount"] + 1 forKey:@"changeCount"];
|
||||
|
||||
[[CPNotificationCenter defaultCenter]
|
||||
postNotificationName:CPMenuDidChangeItemNotification
|
||||
object:self
|
||||
@@ -1035,6 +1016,61 @@ var _CPMenuBarVisible = NO,
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPMenu (CPKeyValueCoding)
|
||||
|
||||
- (CPUInteger)countOfItems
|
||||
{
|
||||
return [_items count];
|
||||
}
|
||||
|
||||
- (CPMenuItem)objectInItemsAtIndex:(CPUInteger)anIndex
|
||||
{
|
||||
return [_items objectAtIndex:anIndex];
|
||||
}
|
||||
|
||||
- (CPArray)itemsAtIndexes:(CPIndexSet)indexes
|
||||
{
|
||||
return [_items objectsAtIndexes:indexes];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPMenu (CPKeyValueObserving)
|
||||
|
||||
- (void)insertObject:(CPMenuItem)aMenuItem inItemsAtIndex:(CPUInteger)anIndex
|
||||
{
|
||||
var menu = [aMenuItem menu];
|
||||
|
||||
if (menu)
|
||||
if (menu !== self)
|
||||
[CPException raise:CPInternalInconsistencyException reason:@"Attempted to insert item into menu that was already in another menu."];
|
||||
else
|
||||
return;
|
||||
|
||||
[aMenuItem setMenu:self];
|
||||
[_items insertObject:aMenuItem atIndex:anIndex];
|
||||
|
||||
[[CPNotificationCenter defaultCenter]
|
||||
postNotificationName:CPMenuDidAddItemNotification
|
||||
object:self
|
||||
userInfo:[CPDictionary dictionaryWithObject:anIndex forKey:@"CPMenuItemIndex"]];
|
||||
}
|
||||
|
||||
- (void)removeObjectFromItemsAtIndex:(CPUInteger)anIndex
|
||||
{
|
||||
if (anIndex < 0 || anIndex >= [_items count])
|
||||
return;
|
||||
|
||||
[[_items objectAtIndex:anIndex] setMenu:nil];
|
||||
[_items removeObjectAtIndex:anIndex];
|
||||
|
||||
[[CPNotificationCenter defaultCenter]
|
||||
postNotificationName:CPMenuDidRemoveItemNotification
|
||||
object:self
|
||||
userInfo:[CPDictionary dictionaryWithObject:anIndex forKey:@"CPMenuItemIndex"]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var CPMenuTitleKey = @"CPMenuTitleKey",
|
||||
CPMenuNameKey = @"CPMenuNameKey",
|
||||
|
||||
@@ -77,6 +77,8 @@
|
||||
id _representedObject;
|
||||
CPView _view;
|
||||
|
||||
int _changeCount;
|
||||
|
||||
_CPMenuItemView _menuItemView;
|
||||
}
|
||||
|
||||
@@ -98,12 +100,14 @@
|
||||
|
||||
if (self)
|
||||
{
|
||||
_changeCount = 0;
|
||||
_isSeparator = NO;
|
||||
|
||||
_title = aTitle;
|
||||
_action = anAction;
|
||||
|
||||
_isEnabled = YES;
|
||||
_isHidden = NO;
|
||||
|
||||
_tag = 0;
|
||||
_state = CPOffState;
|
||||
@@ -445,7 +449,7 @@ CPOffState
|
||||
return _mixedStateImage;
|
||||
}
|
||||
|
||||
// Managing Subemenus
|
||||
// Managing Submenus
|
||||
/*!
|
||||
Sets the submenu for this item
|
||||
@param aMenu the submenu
|
||||
@@ -644,7 +648,7 @@ CPControlKeyMask
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the title of the menu item and the mnemonic character. The mnemonic chracter should be preceded by an '&'.
|
||||
Sets the title of the menu item and the mnemonic character. The mnemonic character should be preceded by an '&'.
|
||||
@param aTitle the title string with a denoted mnemonic
|
||||
*/
|
||||
- (void)setTitleWithMnemonicLocation:(CPString)aTitle
|
||||
@@ -890,6 +894,7 @@ var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
|
||||
|
||||
if (self)
|
||||
{
|
||||
_changeCount = 0;
|
||||
_isSeparator = [aCoder containsValueForKey:CPMenuItemIsSeparatorKey] && [aCoder decodeBoolForKey:CPMenuItemIsSeparatorKey];
|
||||
|
||||
_title = [aCoder decodeObjectForKey:CPMenuItemTitleKey];
|
||||
|
||||
@@ -34,7 +34,6 @@ var _CPMenuItemSelectionColor = nil,
|
||||
BOOL _isDirty;
|
||||
BOOL _showsStateColumn;
|
||||
|
||||
CPImageView _stateView;
|
||||
_CPImageAndTextView _imageAndTextView;
|
||||
CPView _submenuView;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,16 @@
|
||||
|
||||
@import "CPController.j"
|
||||
|
||||
/*!
|
||||
@class
|
||||
|
||||
CPObjectController is a bindings-compatible controller class.
|
||||
Properties of the content object of an object of this class can be bound to user interface elements to change and access their values.
|
||||
|
||||
The content of an CPObjectController instance is an CPMutableDictionary object by default.
|
||||
This allows a single CPObjectController instance to be used to manage several properties accessed by key value paths.
|
||||
The default content object class can be changed by calling setObjectClass:, which a subclass must override.
|
||||
*/
|
||||
@implementation CPObjectController : CPController
|
||||
{
|
||||
id _contentObject;
|
||||
@@ -53,11 +62,20 @@
|
||||
return [CPSet setWithObjects:"editable", "selection"];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (id)init
|
||||
{
|
||||
return [self initWithContent:nil];
|
||||
}
|
||||
|
||||
/*!
|
||||
Inits and returns a CPObjectController object with the given content.
|
||||
|
||||
@param id aContent - The object the controller will use.
|
||||
@return id the CPObjectConroller instance.
|
||||
*/
|
||||
- (id)initWithContent:(id)aContent
|
||||
{
|
||||
if (self = [super init])
|
||||
@@ -72,11 +90,19 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the controller's content object.
|
||||
@return id - The content object of the controller.
|
||||
*/
|
||||
- (id)content
|
||||
{
|
||||
return _contentObject;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the content object for the controller.
|
||||
@param id aContent - The new content object for the controller.
|
||||
*/
|
||||
- (void)setContent:(id)aContent
|
||||
{
|
||||
[self willChangeValueForKey:@"contentObject"];
|
||||
@@ -88,51 +114,91 @@
|
||||
[self _selectionDidChange];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)_setContentObject:(id)aContent
|
||||
{
|
||||
[self setContent:aContent];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (id)_contentObject
|
||||
{
|
||||
return [self content];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets whether the controller automatically creates and inserts new content objects automatically when loading from a cib file.
|
||||
If you pass YES and the controller uses prepareContent to create the content object.
|
||||
The default is NO.
|
||||
|
||||
@param BOOL shouldAutomaticallyPrepareContent - YES if the content should be prepared, otherwise NO.
|
||||
*/
|
||||
- (void)setAutomaticallyPreparesContent:(BOOL)shouldAutomaticallyPrepareContent
|
||||
{
|
||||
_automaticallyPreparesContent = shouldAutomaticallyPrepareContent;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns if the controller prepares the content automatically.
|
||||
@return BOOL - YES if the content is prepared, otherwise NO.
|
||||
*/
|
||||
- (BOOL)automaticallyPreparesContent
|
||||
{
|
||||
return _automaticallyPreparesContent;
|
||||
}
|
||||
|
||||
/*!
|
||||
Overridden by a subclass that require control over the creation of new objects.
|
||||
*/
|
||||
- (void)prepareContent
|
||||
{
|
||||
[self setContent:[self newObject]];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the object class when creating new objects.
|
||||
@param Class - the class of new objects that will be created.
|
||||
*/
|
||||
- (void)setObjectClass:(Class)aClass
|
||||
{
|
||||
_objectClass = aClass;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the class of what new objects will be when they are created.
|
||||
|
||||
@return Class - The class of new objects.
|
||||
*/
|
||||
- (Class)objectClass
|
||||
{
|
||||
return _objectClass;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (id)_defaultNewObject
|
||||
{
|
||||
return [[[self objectClass] alloc] init];
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates and returns a new object of the appropriate class.
|
||||
@return id - The object created.
|
||||
*/
|
||||
- (id)newObject
|
||||
{
|
||||
return [self _defaultNewObject];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the controller's content object.
|
||||
@param id anObject - The object to set for the controller.
|
||||
*/
|
||||
- (void)addObject:(id)anObject
|
||||
{
|
||||
[self setContent:anObject];
|
||||
@@ -141,6 +207,10 @@
|
||||
[[binderClass getBinding:@"contentObject" forObject:self] reverseSetValueFor:@"contentObject"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Removes a given object from the controller.
|
||||
@param id anObject - The object to remove from the receiver.
|
||||
*/
|
||||
- (void)removeObject:(id)anObject
|
||||
{
|
||||
if ([self content] === anObject)
|
||||
@@ -150,54 +220,87 @@
|
||||
[[binderClass getBinding:@"contentObject" forObject:self] reverseSetValueFor:@"contentObject"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates and adds a sets the object as the controller's content.
|
||||
@param id aSender - The sender of the message.
|
||||
*/
|
||||
- (void)add:(id)aSender
|
||||
{
|
||||
// FIXME: This should happen on the next run loop?
|
||||
[self addObject:[self newObject]];
|
||||
}
|
||||
|
||||
/*!
|
||||
@return BOOL - YES if you can added to the controller using add:
|
||||
*/
|
||||
- (BOOL)canAdd
|
||||
{
|
||||
return [self isEditable];
|
||||
}
|
||||
|
||||
/*!
|
||||
Removes the content object from the controller.
|
||||
@param id aSender - The sender of the message.
|
||||
*/
|
||||
- (void)remove:(id)aSender
|
||||
{
|
||||
// FIXME: This should happen on the next run loop?
|
||||
[self removeObject:[self content]];
|
||||
}
|
||||
|
||||
/*!
|
||||
@return BOOL - Returns YES if you can remove the controller's content using remove:
|
||||
*/
|
||||
- (BOOL)canRemove
|
||||
{
|
||||
return [self isEditable] && [[self selectedObjects] count];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets whether the controller allows for the editing of the content.
|
||||
@param BOOL shouldBeEditable - YES if the content should be editable, otherwise NO.
|
||||
*/
|
||||
- (void)setEditable:(BOOL)shouldBeEditable
|
||||
{
|
||||
_isEditable = shouldBeEditable;
|
||||
}
|
||||
|
||||
/*!
|
||||
@return BOOL - Returns YES if the content of the controller is editable, otherwise NO.
|
||||
*/
|
||||
- (BOOL)isEditable
|
||||
{
|
||||
return _isEditable;
|
||||
}
|
||||
|
||||
/*!
|
||||
@return CPArray - Returns an array of all objects to be affected by editing.
|
||||
*/
|
||||
- (CPArray)selectedObjects
|
||||
{
|
||||
return [[_CPObservableArray alloc] initWithArray:[_contentObject]];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a proxy object representing the controller's selection.
|
||||
*/
|
||||
- (id)selection
|
||||
{
|
||||
return _selection;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)_selectionWillChange
|
||||
{
|
||||
[_selection controllerWillChange];
|
||||
[self willChangeValueForKey:@"selection"];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)_selectionDidChange
|
||||
{
|
||||
if (_selection === undefined || _selection === nil)
|
||||
@@ -207,6 +310,9 @@
|
||||
[self didChangeValueForKey:@"selection"];
|
||||
}
|
||||
|
||||
/*!
|
||||
@return id - Returns the keys which are being observed.
|
||||
*/
|
||||
- (id)observedKeys
|
||||
{
|
||||
return _observedKeys;
|
||||
|
||||
@@ -75,15 +75,24 @@ var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_
|
||||
|
||||
CPOutlineViewDropOnItemIndex = -1;
|
||||
|
||||
var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
|
||||
CPOutlineViewCoalesceSelectionNotificationStateOn = 1,
|
||||
CPOutlineViewCoalesceSelectionNotificationStateDid = 2;
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPOutlineView
|
||||
|
||||
CPOutlineView is a subclass of CPTableView that inherates the row and column format to display hierarchial data.
|
||||
The outlineview adds the ability to expand and collapse items. This is useful for browsing a tree like structure such as directories or a filesystem.
|
||||
CPOutlineView is a subclass of CPTableView that inherits the row and
|
||||
column format to display hierarchical data. The outlineview adds the
|
||||
ability to expand and collapse items. This is useful for browsing a tree
|
||||
like structure such as directories or a filesystem.
|
||||
|
||||
Like the tableview, an outlineview uses a data source to supply its data. For this reason you must implement a couple data source methods (documented in setDataSource:)
|
||||
Like the tableview, an outlineview uses a data source to supply its data.
|
||||
For this reason you must implement a couple data source methods
|
||||
(documented in setDataSource:).
|
||||
|
||||
Theme states for custom data views are documented in CPTableView.
|
||||
*/
|
||||
@implementation CPOutlineView : CPTableView
|
||||
{
|
||||
@@ -113,6 +122,8 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
CPInteger _retargedChildIndex;
|
||||
CPTimer _dragHoverTimer;
|
||||
id _dropItem;
|
||||
|
||||
BOOL _coalesceSelectionNotificationState;
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
@@ -121,7 +132,6 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
|
||||
if (self)
|
||||
{
|
||||
|
||||
_selectionHighlightStyle = CPTableViewSelectionHighlightStyleSourceList;
|
||||
|
||||
// The root item has weight "0", thus represents the weight solely of its descendants.
|
||||
@@ -150,8 +160,10 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
return self;
|
||||
}
|
||||
/*!
|
||||
In addition to standard delegation, the outline view also supports data source delegation. This method sets the data source object.
|
||||
Just like the TableView you have CPTableColumns but instead of rows you deal with items.
|
||||
<pre>
|
||||
In addition to standard delegation, the outline view also supports data
|
||||
source delegation. This method sets the data source object. Just like the
|
||||
TableView you have CPTableColumns but instead of rows you deal with items.
|
||||
|
||||
You must implement these data source methods:
|
||||
|
||||
@@ -177,10 +189,11 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
|
||||
Sorting:
|
||||
- (void)outlineView:(CPOutlineView)outlineView sortDescriptorsDidChange:(CPArray)oldDescriptors;
|
||||
The outlineview will call this method if you click the tableheader. You should sort the datasource based off of the new sort descriptors and reload the data
|
||||
The outlineview will call this method if you click the table header. You should sort the datasource based off of the new sort descriptors and reload the data
|
||||
|
||||
Drag and Drop:
|
||||
In order for the outlineview to recieve drops dont forget to first register the tableview for drag types like you do with every other view
|
||||
In order for the outlineview to receive drops don't forget to first
|
||||
register the tableview for drag types like you do with every other view
|
||||
|
||||
- (BOOL)outlineView:(CPOutlineView)outlineView acceptDrop:(id < CPDraggingInfo >)info item:(id)item childIndex:(CPInteger)index;
|
||||
Return YES if the operation was successful otherwise return NO.
|
||||
@@ -188,14 +201,14 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
To get this data use the draggingPasteboard method on the CPDraggingInfo object.
|
||||
|
||||
- (CPDragOperation)outlineView:(CPOutlineView)outlineView validateDrop:(id < CPDraggingInfo >)info proposedItem:(id)item proposedChildIndex:(CPInteger)index;
|
||||
Return the drag operation (move, copy, etc) that should be performaned if a registered drag type is over the tableview
|
||||
Return the drag operation (move, copy, etc) that should be performed if a registered drag type is over the tableview
|
||||
The data source can retarget a drop if you want by calling -(void)setDropItem:(id)anItem dropChildIndex:(int)anIndex;
|
||||
|
||||
- (BOOL)outlineView:(CPOutlineView)outlineView writeItems:(CPArray)items toPasteboard:(CPPasteboard)pboard;
|
||||
Returns YES if the drop operation is allowed otherwise NO.
|
||||
This method is invoked by the outlineview after a drag should begin, but before it is started. If you dont want the drag to being return NO.
|
||||
This method is invoked by the outlineview after a drag should begin, but before it is started. If you don't want the drag to being return NO.
|
||||
If you want the drag to begin you should return YES and place the drag data on the pboard.
|
||||
|
||||
</pre>
|
||||
*/
|
||||
- (void)setDataSource:(id)aDataSource
|
||||
{
|
||||
@@ -252,6 +265,7 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
|
||||
/*!
|
||||
Returns the datasource object.
|
||||
|
||||
@return id - The data source object
|
||||
*/
|
||||
- (id)dataSource
|
||||
@@ -280,7 +294,7 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
}
|
||||
|
||||
/*!
|
||||
Used to find if an item is already expanded.
|
||||
Used to find if an item is already expanded.
|
||||
|
||||
@param anItem - the item you are interest in.
|
||||
|
||||
@@ -300,7 +314,7 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
}
|
||||
|
||||
/*!
|
||||
Expends a given item.
|
||||
Expands a given item.
|
||||
|
||||
@param anItem - the item to expand.
|
||||
*/
|
||||
@@ -327,14 +341,31 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
if (!itemInfo)
|
||||
return;
|
||||
|
||||
// to prevent items which are already expanded from firing notifications
|
||||
// When shouldExpandChildren is YES, we need to make sure we're collecting
|
||||
// selection notifications so that exactly one IsChanging and one
|
||||
// DidChange is sent as needed, for the totality of the operation.
|
||||
var isTopLevel = NO;
|
||||
if (!_coalesceSelectionNotificationState)
|
||||
{
|
||||
isTopLevel = YES;
|
||||
_coalesceSelectionNotificationState = CPOutlineViewCoalesceSelectionNotificationStateOn;
|
||||
}
|
||||
|
||||
// To prevent items which are already expanded from firing notifications.
|
||||
if (!itemInfo.isExpanded)
|
||||
{
|
||||
[self _noteItemWillExpand:anItem];
|
||||
|
||||
var previousRowCount = [self numberOfRows];
|
||||
|
||||
itemInfo.isExpanded = YES;
|
||||
// XXX Shouldn't the items reload before the notification is sent?
|
||||
[self _noteItemDidExpand:anItem];
|
||||
[self reloadItem:anItem reloadChildren:YES];
|
||||
|
||||
// Shift selection indexes below so that the same items remain selected.
|
||||
var newRowCount = [_outlineViewDataSource outlineView:self numberOfChildrenOfItem:anItem];
|
||||
if (newRowCount)
|
||||
var rowCountDelta = [self numberOfRows] - previousRowCount;
|
||||
if (rowCountDelta)
|
||||
{
|
||||
var selection = [self selectedRowIndexes],
|
||||
expandIndex = [self rowForItem:anItem] + 1;
|
||||
@@ -342,14 +373,10 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
if ([selection intersectsIndexesInRange:CPMakeRange(expandIndex, _itemsForRows.length)])
|
||||
{
|
||||
[self _noteSelectionIsChanging];
|
||||
[selection shiftIndexesStartingAtIndex:expandIndex by:newRowCount];
|
||||
[self _setSelectedRowIndexes:selection];
|
||||
[selection shiftIndexesStartingAtIndex:expandIndex by:rowCountDelta];
|
||||
[self _setSelectedRowIndexes:selection]; // _noteSelectionDidChange will be suppressed.
|
||||
}
|
||||
}
|
||||
|
||||
itemInfo.isExpanded = YES;
|
||||
[self _noteItemDidExpand:anItem];
|
||||
[self reloadItem:anItem reloadChildren:YES];
|
||||
}
|
||||
|
||||
if (shouldExpandChildren)
|
||||
@@ -360,6 +387,14 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
while (childIndex--)
|
||||
[self expandItem:children[childIndex] expandChildren:YES];
|
||||
}
|
||||
|
||||
if (isTopLevel)
|
||||
{
|
||||
var r = _coalesceSelectionNotificationState;
|
||||
_coalesceSelectionNotificationState = CPOutlineViewCoalesceSelectionNotificationStateOff;
|
||||
if (r === CPOutlineViewCoalesceSelectionNotificationStateDid)
|
||||
[self _noteSelectionDidChange];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -380,6 +415,9 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
if (!itemInfo.isExpanded)
|
||||
return;
|
||||
|
||||
// Don't spam notifications.
|
||||
_coalesceSelectionNotificationState = CPOutlineViewCoalesceSelectionNotificationStateOn;
|
||||
|
||||
[self _noteItemWillCollapse:anItem];
|
||||
// Update selections:
|
||||
// * Deselect items inside the collapsed item.
|
||||
@@ -392,39 +430,38 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
collapseEndIndex++;
|
||||
|
||||
var collapseRange = CPMakeRange(collapseTopIndex + 1, collapseEndIndex - collapseTopIndex);
|
||||
|
||||
if (collapseRange.length)
|
||||
{
|
||||
var selection = [self selectedRowIndexes],
|
||||
didChange = NO;
|
||||
var selection = [self selectedRowIndexes];
|
||||
|
||||
if ([selection intersectsIndexesInRange:collapseRange])
|
||||
{
|
||||
[selection removeIndexesInRange:collapseRange];
|
||||
[self _noteSelectionIsChanging];
|
||||
didChange = YES;
|
||||
// Will call _noteSelectionDidChange
|
||||
[self _setSelectedRowIndexes:selection];
|
||||
[selection removeIndexesInRange:collapseRange];
|
||||
[self _setSelectedRowIndexes:selection]; // _noteSelectionDidChange will be suppressed.
|
||||
}
|
||||
|
||||
// Shift any selected rows below upwards.
|
||||
if ([selection intersectsIndexesInRange:CPMakeRange(collapseEndIndex + 1, _itemsForRows.length)])
|
||||
{
|
||||
// Notify if that wasn't already done above.
|
||||
if (!didChange)
|
||||
[self _noteSelectionIsChanging];
|
||||
didChange = YES;
|
||||
|
||||
[self _noteSelectionIsChanging];
|
||||
[selection shiftIndexesStartingAtIndex:collapseEndIndex + 1 by:-collapseRange.length];
|
||||
[self _setSelectedRowIndexes:selection]; // _noteSelectionDidChange will be suppressed.
|
||||
}
|
||||
|
||||
if (didChange)
|
||||
[self _setSelectedRowIndexes:selection];
|
||||
}
|
||||
itemInfo.isExpanded = NO;
|
||||
|
||||
// XXX Shouldn't the items reload before the notification is sent?
|
||||
[self _noteItemDidCollapse:anItem];
|
||||
|
||||
[self reloadItem:anItem reloadChildren:YES];
|
||||
|
||||
// Send selection notifications only after the items have loaded so that
|
||||
// the new selection is consistent with the actual rows for any observers.
|
||||
var r = _coalesceSelectionNotificationState;
|
||||
_coalesceSelectionNotificationState = CPOutlineViewCoalesceSelectionNotificationStateOff;
|
||||
if (r === CPOutlineViewCoalesceSelectionNotificationStateDid)
|
||||
[self _noteSelectionDidChange];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -456,7 +493,7 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
/*!
|
||||
Returns the item at a given row index. If no item exists nil is returned.
|
||||
|
||||
@param aRow - The rown index you want to find the item at.
|
||||
@param aRow - The row index you want to find the item at.
|
||||
@return id - The item at a given index.
|
||||
*/
|
||||
- (id)itemAtRow:(CPInteger)aRow
|
||||
@@ -484,7 +521,8 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the table column you want to display the disclosure button in.
|
||||
Sets the table column you want to display the disclosure button in. If you
|
||||
do not want an outline column pass nil.
|
||||
|
||||
@param aTableColumn - The CPTableColumn you want to use for hierarchical data.
|
||||
*/
|
||||
@@ -510,7 +548,9 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the indentation level of a given item. If the item is nil (the top level root item) CPNotFound is returned. Indentation levels are zero based, thus items that are not indented return 0.
|
||||
Returns the indentation level of a given item. If the item is nil (the top
|
||||
level root item) CPNotFound is returned. Indentation levels are zero
|
||||
based, thus items that are not indented return 0.
|
||||
|
||||
@param anItem - The item you want the indentation level for.
|
||||
@return int - the indentation level of anItem.
|
||||
@@ -529,9 +569,10 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the indentation level for a given row. If the row is invalid CPNotFound is returned. Rows that are nto indented return 0.
|
||||
Returns the indentation level for a given row. If the row is invalid
|
||||
CPNotFound is returned. Rows that are not indented return 0.
|
||||
|
||||
@param aRow - the row of the reciever
|
||||
@param aRow - the row of the receiver
|
||||
@return int - the indentation level of aRow.
|
||||
*/
|
||||
- (CPInteger)levelForRow:(CPInteger)aRow
|
||||
@@ -566,7 +607,9 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the layout behaviour of disclosure button. If you pass NO the disclosure button will always align itself to the left of the outline column.
|
||||
Sets the layout behavior of disclosure button. If you pass NO the
|
||||
disclosure button will always align itself to the left of the outline
|
||||
column.
|
||||
|
||||
@param indentationMarkerShouldFollowDataView - Pass YES if the disclosure control should be indented along with the dataview, otherwise NO.
|
||||
*/
|
||||
@@ -582,9 +625,11 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the layout behaviour of the disclosure buttons.
|
||||
Returns the layout behavior of the disclosure buttons.
|
||||
|
||||
@return BOOL - YES if the disclosure control indents itself with the dataview, otherwise NO if the control is always aligned to the left of the outline column
|
||||
@return BOOL - YES if the disclosure control indents itself with the
|
||||
dataview, otherwise NO if the control is always aligned to the left of
|
||||
the outline column
|
||||
*/
|
||||
- (BOOL)indentationMarkerFollowsDataView
|
||||
{
|
||||
@@ -594,8 +639,9 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
/*!
|
||||
Returns the parent item for a given item. If the item is a top level root object nil is returned.
|
||||
|
||||
@param anItem - The item of the reciver.
|
||||
@return id - The parent item of anItem. If no parent exists (the item is a root item) nil is returned.
|
||||
@param anItem - The item of the receiver.
|
||||
@return id - The parent item of anItem. If no parent exists (the item is a
|
||||
root item) nil is returned.
|
||||
*/
|
||||
- (id)parentForItem:(id)anItem
|
||||
{
|
||||
@@ -619,7 +665,7 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
/*!
|
||||
@ignore
|
||||
|
||||
Returns the frame of the dataview at the row given for the outline column
|
||||
Returns the frame of the dataview at the row given for the outline column.
|
||||
*/
|
||||
- (CGRect)_frameOfOutlineDataViewAtRow:(CPInteger)aRow
|
||||
{
|
||||
@@ -634,11 +680,11 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the frame of the disclosure button for the outline column.
|
||||
If the item is not expandable a CGZeroRect is returned.
|
||||
Subclasses can return a CGZeroRect to prevent the disclosure control from being displayed.
|
||||
Returns the frame of the disclosure button for the outline column. If the
|
||||
item is not expandable a CGZeroRect is returned. Subclasses can return a
|
||||
CGZeroRect to prevent the disclosure control from being displayed.
|
||||
|
||||
@param aRow - The row of the reciever
|
||||
@param aRow - The row of the receiver
|
||||
@return CGRect - The rect of the disclosure button at aRow.
|
||||
*/
|
||||
- (CGRect)frameOfOutlineDisclosureControlAtRow:(CPInteger)aRow
|
||||
@@ -654,7 +700,7 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Select or deselect rows, this is overridden because we need to change the color or the outline control
|
||||
Select or deselect rows, this is overridden because we need to change the color or the outline control.
|
||||
*/
|
||||
- (void)_performSelection:(BOOL)select forRow:(CPInteger)rowIndex context:(id)context
|
||||
{
|
||||
@@ -667,6 +713,7 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
}
|
||||
|
||||
/*!
|
||||
<pre>
|
||||
Sets the delegate for the outlineview.
|
||||
|
||||
The following methods can be implemented:
|
||||
@@ -679,7 +726,7 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
Called when the user resizes a column in the outlineview.
|
||||
|
||||
- (void)outlineViewItemDidCollapse:(CPNotification)notification;
|
||||
Called when the user collapses an item in teh outlineview.
|
||||
Called when the user collapses an item in the outlineview.
|
||||
|
||||
- (void)outlineViewItemDidExpand:(CPNotification)notification;
|
||||
Called when the user expands an item in the outlineview.
|
||||
@@ -726,7 +773,14 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
Implement this to indicate whether a given item should be rendered using the group item style.
|
||||
Return YES if the item is a group item, otherwise NO.
|
||||
|
||||
@param aDelegate - the delegate object you wish to set for the reciever.
|
||||
Variable Item Heights
|
||||
- (int)outlineView:(CPOutlineView)outlineView heightOfRowByItem:(id)anItem;
|
||||
Implement this method to get custom heights of rows based on the item.
|
||||
This delegate method will be passed your 'item' object and expects you to return an integer height.
|
||||
NOTE: this should only be implemented if rows will be different heights, if you want to set a height for ALL of your rows see -setRowHeight:
|
||||
|
||||
@param aDelegate - the delegate object you wish to set for the receiver.
|
||||
<pre>
|
||||
*/
|
||||
- (void)setDelegate:(id)aDelegate
|
||||
{
|
||||
@@ -899,8 +953,9 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the prototype of the disclosure control. This is used if you want to set a special type of button, instead of the default triangle.
|
||||
The control must implement CPCoding.
|
||||
Sets the prototype of the disclosure control. This is used if you want to
|
||||
set a special type of button, instead of the default triangle. The control
|
||||
must implement CPCoding.
|
||||
|
||||
@param aControl - the control to be used to expand and collapse items.
|
||||
*/
|
||||
@@ -910,7 +965,7 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
_disclosureControlData = nil;
|
||||
_disclosureControlQueue = [];
|
||||
|
||||
// fIXME: reall?
|
||||
// fIXME: really?
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
@@ -922,9 +977,37 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
[self reloadItem:nil reloadChildren:YES];
|
||||
}
|
||||
|
||||
/*!
|
||||
Adds a new table column to the receiver. If this is the first column added
|
||||
it will automatically be set to the outline column.
|
||||
|
||||
Also see -setOutlineTableColumn:.
|
||||
|
||||
NOTE: This behavior deviates from cocoa slightly.
|
||||
|
||||
@param CPTableColumn aTableColumn - The table column to add.
|
||||
*/
|
||||
- (void)addTableColumn:(CPTableColumn)aTableColumn
|
||||
{
|
||||
[super addTableColumn:aTableColumn];
|
||||
|
||||
if ([self numberOfColumns] === 1)
|
||||
_outlineTableColumn = aTableColumn;
|
||||
}
|
||||
/*!
|
||||
@ignore
|
||||
We overide this because we need a special behaviour for the outline column
|
||||
*/
|
||||
- (void)removeTableColumn:(CPTableColumn)aTableColumn
|
||||
{
|
||||
if (aTableColumn === [self outlineTableColumn])
|
||||
CPLog("CPOutlineView cannot remove outlineTableColumn with removeTableColumn:. User setOutlineTableColumn: instead.");
|
||||
else
|
||||
[super removeTableColumn:aTableColumn];
|
||||
}
|
||||
/*!
|
||||
@ignore
|
||||
We override this because we need a special behavior for the outline
|
||||
column.
|
||||
*/
|
||||
- (CGRect)frameOfDataViewAtColumn:(CPInteger)aColumn row:(CPInteger)aRow
|
||||
{
|
||||
@@ -938,7 +1021,7 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
we need to offset the dataview and add the dislosure triangle
|
||||
We need to offset the dataview and add the disclosure triangle.
|
||||
*/
|
||||
- (CPView)_dragViewForColumn:(int)theColumnIndex event:(CPEvent)theDragEvent offset:(CPPointPointer)theDragViewOffset
|
||||
{
|
||||
@@ -998,9 +1081,15 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
|
||||
/*!
|
||||
Retargets the drop item for the outlineview.
|
||||
To specify a drop on theItem, you specify item as theItem and index as CPOutlineViewDropOnItemIndex.
|
||||
To specify a drop between child 1 and 2 of theItem, you specify item as theItem and index as 2.
|
||||
To specify a drop on an item that can't be expanded theItem, you specify item as someOutlineItem and index as CPOutlineViewDropOnItemIndex.
|
||||
|
||||
To specify a drop on theItem, you specify item as theItem and index as
|
||||
CPOutlineViewDropOnItemIndex.
|
||||
|
||||
To specify a drop between child 1 and 2 of theItem, you specify item as
|
||||
theItem and index as 2.
|
||||
|
||||
To specify a drop on an item that can't be expanded theItem, you specify
|
||||
item as someOutlineItem and index as CPOutlineViewDropOnItemIndex.
|
||||
|
||||
@param theItem - The item you want to retarget the drop on.
|
||||
@param theIndex - The index of the child item you want to retarget the drop between. Pass CPOutlineViewDropOnItemIndex if you want to drop on theItem.
|
||||
@@ -1110,7 +1199,7 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
We need to move the disclosure control too
|
||||
We need to move the disclosure control too.
|
||||
*/
|
||||
- (void)_layoutDataViewsInRows:(CPIndexSet)rows columns:(CPIndexSet)columns
|
||||
{
|
||||
@@ -1277,10 +1366,16 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
*/
|
||||
- (void)_noteSelectionIsChanging
|
||||
{
|
||||
[[CPNotificationCenter defaultCenter]
|
||||
postNotificationName:CPOutlineViewSelectionIsChangingNotification
|
||||
object:self
|
||||
userInfo:nil];
|
||||
if (!_coalesceSelectionNotificationState || _coalesceSelectionNotificationState === CPOutlineViewCoalesceSelectionNotificationStateOn)
|
||||
{
|
||||
[[CPNotificationCenter defaultCenter]
|
||||
postNotificationName:CPOutlineViewSelectionIsChangingNotification
|
||||
object:self
|
||||
userInfo:nil];
|
||||
}
|
||||
|
||||
if (_coalesceSelectionNotificationState === CPOutlineViewCoalesceSelectionNotificationStateOn)
|
||||
_coalesceSelectionNotificationState = CPOutlineViewCoalesceSelectionNotificationStateDid;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1288,10 +1383,16 @@ CPOutlineViewDropOnItemIndex = -1;
|
||||
*/
|
||||
- (void)_noteSelectionDidChange
|
||||
{
|
||||
[[CPNotificationCenter defaultCenter]
|
||||
postNotificationName:CPOutlineViewSelectionDidChangeNotification
|
||||
object:self
|
||||
userInfo:nil];
|
||||
if (!_coalesceSelectionNotificationState)
|
||||
{
|
||||
[[CPNotificationCenter defaultCenter]
|
||||
postNotificationName:CPOutlineViewSelectionDidChangeNotification
|
||||
object:self
|
||||
userInfo:nil];
|
||||
}
|
||||
|
||||
if (_coalesceSelectionNotificationState === CPOutlineViewCoalesceSelectionNotificationStateOn)
|
||||
_coalesceSelectionNotificationState = CPOutlineViewCoalesceSelectionNotificationStateDid;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1651,13 +1752,13 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
|
||||
return NO;
|
||||
}
|
||||
|
||||
/*- (float)tableView:(CPTableView)theTableView heightOfRow:(int)theRow
|
||||
- (float)tableView:(CPTableView)theTableView heightOfRow:(int)theRow
|
||||
{
|
||||
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_heightOfRowByItem_))
|
||||
return [_outlineView._outlineViewDelegate outlineView:_outlineView heightOfRowByItem:[_outlineView itemAtRow:theRow]];
|
||||
|
||||
return [theTableView rowHeight];
|
||||
}*/
|
||||
}
|
||||
|
||||
- (void)tableView:(CPTableView)aTableView willDisplayView:(id)aView forTableColumn:(CPTableColumn)aTableColumn row:(int)aRowIndex
|
||||
{
|
||||
@@ -1787,7 +1888,14 @@ var CPOutlineViewIndentationPerLevelKey = @"CPOutlineViewIndentationPerLevelKey"
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
// Make sure we don't encode our internal delegate and data source.
|
||||
var internalDelegate = _delegate,
|
||||
internalDataSource = _dataSource;
|
||||
_delegate = nil;
|
||||
_dataSource = nil;
|
||||
[super encodeWithCoder:aCoder];
|
||||
_delegate = internalDelegate;
|
||||
_dataSource = internalDataSource;
|
||||
|
||||
[aCoder encodeObject:_outlineTableColumn forKey:CPOutlineViewOutlineTableColumnKey];
|
||||
[aCoder encodeFloat:_indentationPerLevel forKey:CPOutlineViewIndentationPerLevelKey];
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
CPOKButton = 1;
|
||||
CPCancelButton = 0;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPPanel
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
@import "CPMenuItem.j"
|
||||
|
||||
|
||||
var VISIBLE_MARGIN = 7.0;
|
||||
var VISIBLE_MARGIN = 7.0;
|
||||
|
||||
CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
|
||||
@@ -38,10 +38,8 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
*/
|
||||
@implementation CPPopUpButton : CPButton
|
||||
{
|
||||
int _selectedIndex;
|
||||
CPUInteger _selectedIndex;
|
||||
CPRectEdge _preferredEdge;
|
||||
|
||||
CPMenu _menu;
|
||||
}
|
||||
|
||||
+ (CPString)defaultThemeClass
|
||||
@@ -49,9 +47,19 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
return "popup-button";
|
||||
}
|
||||
|
||||
+ (CPSet)keyPathsForValuesAffectingSelectedIndex
|
||||
{
|
||||
return [CPSet setWithObject:@"objectValue"];
|
||||
}
|
||||
|
||||
+ (CPSet)keyPathsForValuesAffectingSelectedTag
|
||||
{
|
||||
return [CPSet setWithObject:@"selectedIndex"];
|
||||
return [CPSet setWithObject:@"objectValue"];
|
||||
}
|
||||
|
||||
+ (CPSet)keyPathsForValuesAffectingSelectedItem
|
||||
{
|
||||
return [CPSet setWithObject:@"objectValue"];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -66,7 +74,8 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
|
||||
if (self)
|
||||
{
|
||||
_selectedIndex = CPNotFound;
|
||||
[self selectItemAtIndex:CPNotFound];
|
||||
|
||||
_preferredEdge = CPMaxYEdge;
|
||||
|
||||
[self setValue:CPImageLeft forThemeAttribute:@"image-position"];
|
||||
@@ -76,6 +85,14 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
[self setMenu:[[CPMenu alloc] initWithTitle:@""]];
|
||||
|
||||
[self setPullsDown:shouldPullDown];
|
||||
|
||||
var options = CPKeyValueObservingOptionNew |
|
||||
CPKeyValueObservingOptionOld;/* |
|
||||
CPKeyValueObservingOptionInitial;
|
||||
*/
|
||||
[self addObserver:self forKeyPath:@"menu.items" options:options context:nil];
|
||||
[self addObserver:self forKeyPath:@"_firstItem.changeCount" options:options context:nil];
|
||||
[self addObserver:self forKeyPath:@"selectedItem.changeCount" options:options context:nil];
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -90,6 +107,9 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
|
||||
/*!
|
||||
Specifies whether the object is a pull-down or a pop-up menu.
|
||||
If the button pulls down the menu items represent actions, not states.
|
||||
So the text in the button will NOT change when the user selects something different.
|
||||
|
||||
@param shouldPullDown \c YES makes the pop-up button
|
||||
a pull-down menu. \c NO makes it a pop-up menu.
|
||||
*/
|
||||
@@ -103,7 +123,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
if (!changed)
|
||||
return;
|
||||
|
||||
var items = [_menu itemArray];
|
||||
var items = [[self menu] itemArray];
|
||||
|
||||
if ([items count] <= 0)
|
||||
return;
|
||||
@@ -128,21 +148,21 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
*/
|
||||
- (void)addItem:(CPMenuItem)anItem
|
||||
{
|
||||
[_menu addItem:anItem];
|
||||
[[self menu] addItem:anItem];
|
||||
}
|
||||
|
||||
/*!
|
||||
Adds a new menu item with the specified title.
|
||||
@param the new menu item's tite
|
||||
@param the new menu item's title
|
||||
*/
|
||||
- (void)addItemWithTitle:(CPString)aTitle
|
||||
{
|
||||
[_menu addItemWithTitle:aTitle action:NULL keyEquivalent:nil];
|
||||
[[self menu] addItemWithTitle:aTitle action:NULL keyEquivalent:nil];
|
||||
}
|
||||
|
||||
/*!
|
||||
Adds multiple new menu items with the titles specified in the provided array.
|
||||
@param titles an arry of names for the new items
|
||||
@param titles an array of names for the new items
|
||||
*/
|
||||
- (void)addItemsWithTitles:(CPArray)titles
|
||||
{
|
||||
@@ -155,7 +175,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
|
||||
/*!
|
||||
Inserts a new item with the specified title and index location.
|
||||
@param aTitle the new itme's title
|
||||
@param aTitle the new item's title
|
||||
@param anIndex the item's index in the menu
|
||||
*/
|
||||
- (void)insertItemWithTitle:(CPString)aTitle atIndex:(int)anIndex
|
||||
@@ -167,7 +187,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
if ([items[count] title] == aTitle)
|
||||
[self removeItemAtIndex:count];
|
||||
|
||||
[_menu insertItemWithTitle:aTitle action:NULL keyEquivalent:nil atIndex:anIndex];
|
||||
[[self menu] insertItemWithTitle:aTitle action:NULL keyEquivalent:nil atIndex:anIndex];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -175,10 +195,11 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
*/
|
||||
- (void)removeAllItems
|
||||
{
|
||||
var count = [_menu numberOfItems];
|
||||
var menu = [self menu],
|
||||
count = [menu numberOfItems];
|
||||
|
||||
while (count--)
|
||||
[_menu removeItemAtIndex:0];
|
||||
[menu removeItemAtIndex:0];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -197,7 +218,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
*/
|
||||
- (void)removeItemAtIndex:(int)anIndex
|
||||
{
|
||||
[_menu removeItemAtIndex:anIndex];
|
||||
[[self menu] removeItemAtIndex:anIndex];
|
||||
[self synchronizeTitleAndSelectedItem];
|
||||
}
|
||||
|
||||
@@ -207,10 +228,12 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
*/
|
||||
- (CPMenuItem)selectedItem
|
||||
{
|
||||
if (_selectedIndex < 0 || _selectedIndex > [self numberOfItems] - 1)
|
||||
var indexOfSelectedItem = [self indexOfSelectedItem];
|
||||
|
||||
if (indexOfSelectedItem < 0 || indexOfSelectedItem > [self numberOfItems] - 1)
|
||||
return nil;
|
||||
|
||||
return [_menu itemAtIndex:_selectedIndex];
|
||||
return [[self menu] itemAtIndex:indexOfSelectedItem];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -229,15 +252,6 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
return _selectedIndex;
|
||||
}
|
||||
|
||||
// For us, CPNumber is toll-free bridged to Number, so just return the selected index.
|
||||
/*!
|
||||
Returns the selected item's index. If no item is selected, it returns CPNotFound.
|
||||
*/
|
||||
- (id)objectValue
|
||||
{
|
||||
return _selectedIndex;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
@@ -268,24 +282,48 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
Selects the item at the specified index
|
||||
@param anIndex the index of the item to select
|
||||
*/
|
||||
- (void)selectItemAtIndex:(int)anIndex
|
||||
- (void)selectItemAtIndex:(CPUInteger)anIndex
|
||||
{
|
||||
if (_selectedIndex == anIndex)
|
||||
[self setObjectValue:anIndex];
|
||||
}
|
||||
|
||||
- (void)setSelectedIndex:(CPUInteger)anIndex
|
||||
{
|
||||
[self setObjectValue:anIndex];
|
||||
}
|
||||
|
||||
- (CPUInteger)selectedIndex
|
||||
{
|
||||
return [self objectValue];
|
||||
}
|
||||
|
||||
/*!
|
||||
Selects the item at the specified index
|
||||
@param anIndex the index of the item to select
|
||||
*/
|
||||
- (void)setObjectValue:(int)anIndex
|
||||
{
|
||||
var indexOfSelectedItem = [self objectValue];
|
||||
|
||||
anIndex = parseInt(+anIndex, 10);
|
||||
|
||||
if (indexOfSelectedItem === anIndex)
|
||||
return;
|
||||
|
||||
[self willChangeValueForKey:@"selectedIndex"];
|
||||
|
||||
if (_selectedIndex >= 0 && ![self pullsDown])
|
||||
if (indexOfSelectedItem >= 0 && ![self pullsDown])
|
||||
[[self selectedItem] setState:CPOffState];
|
||||
|
||||
_selectedIndex = anIndex;
|
||||
|
||||
if (_selectedIndex >= 0 && ![self pullsDown])
|
||||
if (indexOfSelectedItem >= 0 && ![self pullsDown])
|
||||
[[self selectedItem] setState:CPOnState];
|
||||
|
||||
[self synchronizeTitleAndSelectedItem];
|
||||
}
|
||||
|
||||
[self didChangeValueForKey:@"selectedIndex"];
|
||||
- (id)objectValue
|
||||
{
|
||||
return _selectedIndex;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -306,84 +344,14 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
[self selectItemAtIndex:[self indexOfItemWithTitle:aTitle]];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the object for the selected item. If no item is selected, then this method has no effect.
|
||||
@param the object set for the selected item
|
||||
*/
|
||||
- (void)setObjectValue:(id)aValue
|
||||
{
|
||||
[self selectItemAtIndex:[aValue intValue]];
|
||||
}
|
||||
|
||||
// Getting Menu Items
|
||||
/*!
|
||||
Returns the button's menu of items.
|
||||
*/
|
||||
- (CPMenu)menu
|
||||
{
|
||||
return _menu;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the menu for the button
|
||||
*/
|
||||
- (void)setMenu:(CPMenu)aMenu
|
||||
{
|
||||
if (_menu === aMenu)
|
||||
return;
|
||||
|
||||
var defaultCenter = [CPNotificationCenter defaultCenter];
|
||||
|
||||
if (_menu)
|
||||
{
|
||||
[defaultCenter
|
||||
removeObserver:self
|
||||
name:CPMenuDidAddItemNotification
|
||||
object:_menu];
|
||||
|
||||
[defaultCenter
|
||||
removeObserver:self
|
||||
name:CPMenuDidChangeItemNotification
|
||||
object:_menu];
|
||||
|
||||
[defaultCenter
|
||||
removeObserver:self
|
||||
name:CPMenuDidRemoveItemNotification
|
||||
object:_menu];
|
||||
}
|
||||
|
||||
_menu = aMenu;
|
||||
|
||||
if (_menu)
|
||||
{
|
||||
[defaultCenter
|
||||
addObserver:self
|
||||
selector:@selector(menuDidAddItem:)
|
||||
name:CPMenuDidAddItemNotification
|
||||
object:_menu];
|
||||
|
||||
[defaultCenter
|
||||
addObserver:self
|
||||
selector:@selector(menuDidChangeItem:)
|
||||
name:CPMenuDidChangeItemNotification
|
||||
object:_menu];
|
||||
|
||||
[defaultCenter
|
||||
addObserver:self
|
||||
selector:@selector(menuDidRemoveItem:)
|
||||
name:CPMenuDidRemoveItemNotification
|
||||
object:_menu];
|
||||
}
|
||||
|
||||
[self synchronizeTitleAndSelectedItem];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a count of the number of items in the button's menu.
|
||||
*/
|
||||
- (int)numberOfItems
|
||||
{
|
||||
return [_menu numberOfItems];
|
||||
return [[self menu] numberOfItems];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -391,7 +359,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
*/
|
||||
- (CPArray)itemArray
|
||||
{
|
||||
return [_menu itemArray];
|
||||
return [[self menu] itemArray];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -400,7 +368,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
*/
|
||||
- (CPMenuItem)itemAtIndex:(unsigned)anIndex
|
||||
{
|
||||
return [_menu itemAtIndex:anIndex];
|
||||
return [[self menu] itemAtIndex:anIndex];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -409,7 +377,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
*/
|
||||
- (CPString)itemTitleAtIndex:(unsigned)anIndex
|
||||
{
|
||||
return [[_menu itemAtIndex:anIndex] title];
|
||||
return [[[self menu] itemAtIndex:anIndex] title];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -434,7 +402,9 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
*/
|
||||
- (CPMenuItem)itemWithTitle:(CPString)aTitle
|
||||
{
|
||||
return [_menu itemAtIndex:[_menu indexOfItemWithTitle:aTitle]];
|
||||
var menu = [self menu];
|
||||
|
||||
return [menu itemAtIndex:[menu indexOfItemWithTitle:aTitle]];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -442,7 +412,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
*/
|
||||
- (CPMenuItem)lastItem
|
||||
{
|
||||
return [[_menu itemArray] lastObject];
|
||||
return [[[self menu] itemArray] lastObject];
|
||||
}
|
||||
|
||||
// Getting the Indices of Menu Items
|
||||
@@ -452,7 +422,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
*/
|
||||
- (int)indexOfItem:(CPMenuItem)aMenuItem
|
||||
{
|
||||
return [_menu indexOfItem:aMenuItem];
|
||||
return [[self menu] indexOfItem:aMenuItem];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -461,16 +431,16 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
*/
|
||||
- (int)indexOfItemWithTag:(int)aTag
|
||||
{
|
||||
return [_menu indexOfItemWithTag:aTag];
|
||||
return [[self menu] indexOfItemWithTag:aTag];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the index of the item with the specified title or CPNotFound.
|
||||
@param aTitle the item's titel
|
||||
@param aTitle the item's title
|
||||
*/
|
||||
- (int)indexOfItemWithTitle:(CPString)aTitle
|
||||
{
|
||||
return [_menu indexOfItemWithTitle:aTitle];
|
||||
return [[self menu] indexOfItemWithTitle:aTitle];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -481,7 +451,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
*/
|
||||
- (int)indexOfItemWithRepresentedObject:(id)anObject
|
||||
{
|
||||
return [_menu indexOfItemWithRepresentedObject:anObject];
|
||||
return [[self menu] indexOfItemWithRepresentedObject:anObject];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -493,7 +463,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
*/
|
||||
- (int)indexOfItemWithTarget:(id)aTarget action:(SEL)anAction
|
||||
{
|
||||
return [_menu indexOfItemWithTarget:aTarget action:anAction];
|
||||
return [[self menu] indexOfItemWithTarget:aTarget action:anAction];
|
||||
}
|
||||
|
||||
// Setting the Cell Edge to Pop out in Restricted Situations
|
||||
@@ -508,7 +478,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the preffered edge of the button to display the
|
||||
Sets the preferred edge of the button to display the
|
||||
pop-up when there is a limited amount of screen space.
|
||||
By default, the pop-up should draw on top of the button.
|
||||
*/
|
||||
@@ -529,7 +499,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
|
||||
if ([self pullsDown])
|
||||
{
|
||||
var items = [_menu itemArray];
|
||||
var items = [[self menu] itemArray];
|
||||
|
||||
if ([items count] <= 0)
|
||||
[self addItemWithTitle:aTitle];
|
||||
@@ -577,7 +547,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
|
||||
if ([self pullsDown])
|
||||
{
|
||||
var items = [_menu itemArray];
|
||||
var items = [[self menu] itemArray];
|
||||
|
||||
if ([items count] > 0)
|
||||
item = items[0];
|
||||
@@ -589,73 +559,117 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
[super setTitle:[item title]];
|
||||
}
|
||||
|
||||
//
|
||||
/*!
|
||||
Called when the menu has a new item added to it.
|
||||
@param aNotification information about the event
|
||||
*/
|
||||
- (void)menuDidAddItem:(CPNotification)aNotification
|
||||
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)changes context:(id)aContext
|
||||
{
|
||||
var index = [[aNotification userInfo] objectForKey:@"CPMenuItemIndex"];
|
||||
var pullsDown = [self pullsDown];
|
||||
|
||||
if (_selectedIndex < 0)
|
||||
[self selectItemAtIndex:0];
|
||||
|
||||
else if (index == _selectedIndex)
|
||||
if (!pullsDown && aKeyPath === @"selectedItem.changeCount" ||
|
||||
pullsDown && (aKeyPath === @"_firstItem" || aKeyPath === @"_firstItem.changeCount"))
|
||||
[self synchronizeTitleAndSelectedItem];
|
||||
|
||||
else if (index < _selectedIndex)
|
||||
++_selectedIndex;
|
||||
|
||||
if (index == 0 && [self pullsDown])
|
||||
// FIXME: This is due to a bug in KVO, we should never get it for "menu".
|
||||
if (aKeyPath === @"menu")
|
||||
{
|
||||
var items = [_menu itemArray];
|
||||
aKeyPath = @"menu.items";
|
||||
|
||||
[items[0] setHidden:YES];
|
||||
|
||||
if (items.length > 0)
|
||||
[items[1] setHidden:NO];
|
||||
[changes setObject:CPKeyValueChangeSetting forKey:CPKeyValueChangeKindKey];
|
||||
[changes setObject:[[self menu] itemArray] forKey:CPKeyValueChangeNewKey];
|
||||
}
|
||||
|
||||
var item = [_menu itemArray][index],
|
||||
action = [item action];
|
||||
|
||||
if (!action || (action === @selector(_popUpItemAction:)))
|
||||
if (aKeyPath === @"menu.items")
|
||||
{
|
||||
[item setTarget:self];
|
||||
[item setAction:@selector(_popUpItemAction:)];
|
||||
var changeKind = [changes objectForKey:CPKeyValueChangeKindKey],
|
||||
indexOfSelectedItem = [self indexOfSelectedItem];
|
||||
|
||||
if (changeKind === CPKeyValueChangeRemoval)
|
||||
{
|
||||
var index = CPNotFound,
|
||||
indexes = [changes objectForKey:CPKeyValueChangeIndexesKey];
|
||||
|
||||
if ([indexes containsIndex:0] && [self pullsDown])
|
||||
[self _firstItemDidChange];
|
||||
|
||||
// See whether the index has changed, despite the actual item not changing.
|
||||
while ((index = [indexes indexGreaterThanIndex:index]) !== CPNotFound &&
|
||||
index <= indexOfSelectedItem)
|
||||
--indexOfSelectedItem;
|
||||
|
||||
[self selectItemAtIndex:indexOfSelectedItem];
|
||||
}
|
||||
|
||||
else if (changeKind === CPKeyValueChangeReplacement)
|
||||
{
|
||||
var indexes = [changes objectForKey:CPKeyValueChangeIndexesKey];
|
||||
|
||||
if (pullsDown && [indexes containsIndex:0] ||
|
||||
!pullsDown && [indexes containsIndex:indexOfSelectedItem])
|
||||
[self synchronizeTitleAndSelectedItem];
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// No matter what, we want to prepare the new items.
|
||||
var newItems = [changes objectForKey:CPKeyValueChangeNewKey];
|
||||
|
||||
[newItems enumerateObjectsUsingBlock:function(aMenuItem)
|
||||
{
|
||||
var action = [aMenuItem action];
|
||||
|
||||
if (!action)
|
||||
[aMenuItem setAction:action = @selector(_popUpItemAction:)];
|
||||
|
||||
if (action === @selector(_popUpItemAction:))
|
||||
[aMenuItem setTarget:self];
|
||||
}];
|
||||
|
||||
if (changeKind === CPKeyValueChangeSetting)
|
||||
{
|
||||
[self _firstItemDidChange];
|
||||
|
||||
[self selectItemAtIndex:CPNotFound];
|
||||
[self selectItemAtIndex:MIN([newItems count] - 1, indexOfSelectedItem)];
|
||||
}
|
||||
|
||||
else //if (changeKind === CPKeyValueChangeInsertion)
|
||||
{
|
||||
var indexes = [changes objectForKey:CPKeyValueChangeIndexesKey];
|
||||
|
||||
if ([self pullsDown] && [indexes containsIndex:0])
|
||||
{
|
||||
[self _firstItemDidChange];
|
||||
|
||||
if ([self numberOfItems] > 1)
|
||||
{
|
||||
var index = CPNotFound,
|
||||
originalIndex = 0;
|
||||
|
||||
while ((index = [indexes indexGreaterThanIndex:index]) !== CPNotFound &&
|
||||
index <= originalIndex)
|
||||
++originalIndex;
|
||||
|
||||
[[self itemAtIndex:originalIndex] setHidden:NO];
|
||||
}
|
||||
}
|
||||
|
||||
if (indexOfSelectedItem < 0)
|
||||
[self selectItemAtIndex:0];
|
||||
|
||||
else
|
||||
{
|
||||
var index = CPNotFound;
|
||||
|
||||
// See whether the index has changed, despite the actual item not changing.
|
||||
while ((index = [indexes indexGreaterThanIndex:index]) !== CPNotFound &&
|
||||
index <= indexOfSelectedItem)
|
||||
++indexOfSelectedItem;
|
||||
|
||||
[self selectItemAtIndex:indexOfSelectedItem];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Called when a menu item has changed.
|
||||
@param aNotification information about the event
|
||||
*/
|
||||
- (void)menuDidChangeItem:(CPNotification)aNotification
|
||||
{
|
||||
var index = [[aNotification userInfo] objectForKey:@"CPMenuItemIndex"];
|
||||
|
||||
if ([self pullsDown] && index != 0)
|
||||
return;
|
||||
|
||||
if (![self pullsDown] && index != _selectedIndex)
|
||||
return;
|
||||
|
||||
[self synchronizeTitleAndSelectedItem];
|
||||
}
|
||||
|
||||
/*!
|
||||
Called when an item was removed from the menu.
|
||||
@param aNotification information about the event
|
||||
*/
|
||||
- (void)menuDidRemoveItem:(CPNotification)aNotification
|
||||
{
|
||||
var numberOfItems = [self numberOfItems];
|
||||
|
||||
if (numberOfItems <= _selectedIndex && numberOfItems > 0)
|
||||
[self selectItemAtIndex:numberOfItems - 1];
|
||||
else
|
||||
[self synchronizeTitleAndSelectedItem];
|
||||
// [super observeValueForKeyPath:aKeyPath ofObject:anObject change:changes context:aContext];
|
||||
}
|
||||
|
||||
- (void)mouseDown:(CPEvent)anEvent
|
||||
@@ -727,7 +741,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
|
||||
- (void)rightMouseDown:(CPEvent)anEvent
|
||||
{
|
||||
// Disable standard CPView behaviour which incorrectly displays the menu as a 'context menu'.
|
||||
// Disable standard CPView behavior which incorrectly displays the menu as a 'context menu'.
|
||||
}
|
||||
|
||||
- (void)_popUpItemAction:(id)aSender
|
||||
@@ -735,6 +749,22 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
[self sendAction:[self action] to:[self target]];
|
||||
}
|
||||
|
||||
- (void)_firstItemDidChange
|
||||
{
|
||||
[self willChangeValueForKey:@"_firstItem"];
|
||||
[self didChangeValueForKey:@"_firstItem"];
|
||||
|
||||
[[self _firstItem] setHidden:YES];
|
||||
}
|
||||
|
||||
- (CPMenuItem)_firstItem
|
||||
{
|
||||
if ([self numberOfItems] <= 0)
|
||||
return nil;
|
||||
|
||||
return [[self menu] itemAtIndex:0];
|
||||
}
|
||||
|
||||
- (void)takeValueFromKeyPath:(CPString)aKeyPath ofObjects:(CPArray)objects
|
||||
{
|
||||
var count = objects.length,
|
||||
@@ -744,19 +774,14 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
[self setEnabled:YES];
|
||||
|
||||
while (count-- > 1)
|
||||
{
|
||||
if (value !== [objects[count] valueForKeyPath:aKeyPath])
|
||||
{
|
||||
[[self selectedItem] setState:CPOffState];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
|
||||
CPPopUpButtonSelectedIndexKey = @"CPPopUpButtonSelectedIndexKey",
|
||||
CPPopUpButtonPullsDownKey = @"CPPopUpButtonPullsDownKey";
|
||||
var DEPRECATED_CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
|
||||
DEPRECATED_CPPopUpButtonSelectedIndexKey = @"CPPopUpButtonSelectedIndexKey";
|
||||
|
||||
@implementation CPPopUpButton (CPCoding)
|
||||
/*!
|
||||
@@ -772,27 +797,30 @@ var CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey",
|
||||
|
||||
if (self)
|
||||
{
|
||||
// Nothing is currently selected
|
||||
_selectedIndex = -1;
|
||||
// FIXME: (or not?) _title is nulled in - [CPButton initWithCoder:],
|
||||
// so we need to do this again.
|
||||
[self synchronizeTitleAndSelectedItem];
|
||||
|
||||
[self setMenu:[aCoder decodeObjectForKey:CPPopUpButtonMenuKey]];
|
||||
[self selectItemAtIndex:[aCoder decodeObjectForKey:CPPopUpButtonSelectedIndexKey]];
|
||||
// FIXME: Remove deprecation leniency for 1.0
|
||||
if ([aCoder containsValueForKey:DEPRECATED_CPPopUpButtonMenuKey])
|
||||
{
|
||||
CPLog.warn(self + " was encoded with an older version of Cappuccino. Please nib2cib the original nib again or open and re-save in Atlas.");
|
||||
|
||||
[self setMenu:[aCoder decodeObjectForKey:DEPRECATED_CPPopUpButtonMenuKey]];
|
||||
[self setObjectValue:[aCoder decodeObjectForKey:DEPRECATED_CPPopUpButtonSelectedIndexKey]];
|
||||
}
|
||||
|
||||
var options = CPKeyValueObservingOptionNew |
|
||||
CPKeyValueObservingOptionOld;/* |
|
||||
CPKeyValueObservingOptionInitial;
|
||||
*/
|
||||
|
||||
[self addObserver:self forKeyPath:@"menu.items" options:options context:nil];
|
||||
[self addObserver:self forKeyPath:@"_firstItem.changeCount" options:options context:nil];
|
||||
[self addObserver:self forKeyPath:@"selectedItem.changeCount" options:options context:nil];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/*!
|
||||
Encodes the data of the pop-up button into a coder
|
||||
@param aCoder the coder to which the data
|
||||
will be written
|
||||
*/
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
[super encodeWithCoder:aCoder];
|
||||
|
||||
[aCoder encodeObject:_menu forKey:CPPopUpButtonMenuKey];
|
||||
[aCoder encodeInt:_selectedIndex forKey:CPPopUpButtonSelectedIndexKey];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -120,7 +120,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
|
||||
|
||||
CPProgressIndicatorStyleSizes = [];
|
||||
|
||||
// Bar Sttyle
|
||||
// Bar Style
|
||||
var prefixes = [
|
||||
CPProgressIndicatorClassName + @"BezelBorder" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorBarStyle],
|
||||
CPProgressIndicatorClassName + @"Bar" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorBarStyle],
|
||||
@@ -290,7 +290,7 @@ var CPProgressIndicatorSpinningStyleColors = nil,
|
||||
}
|
||||
|
||||
/*
|
||||
Not yet impemented.
|
||||
Not yet implemented.
|
||||
*/
|
||||
- (CPControlTint)controlTint
|
||||
{
|
||||
|
||||
@@ -358,8 +358,8 @@ var CPResponderNextResponderKey = @"CPResponderNextResponderKey",
|
||||
|
||||
if (self)
|
||||
{
|
||||
_nextResponder = [aCoder decodeObjectForKey:CPResponderNextResponderKey];
|
||||
_menu = [aCoder decodeObjectForKey:CPResponderMenuKey];
|
||||
[self setNextResponder:[aCoder decodeObjectForKey:CPResponderNextResponderKey]];
|
||||
[self setMenu:[aCoder decodeObjectForKey:CPResponderMenuKey]];
|
||||
}
|
||||
|
||||
return self;
|
||||
|
||||
@@ -506,7 +506,7 @@
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets whether the scroll view hides its scoll bars when not needed.
|
||||
Sets whether the scroll view hides its scroll bars when not needed.
|
||||
@param autohidesScrollers \c YES causes the scroll bars
|
||||
to be hidden when not needed.
|
||||
*/
|
||||
@@ -796,7 +796,7 @@
|
||||
|
||||
/*!
|
||||
Sets the vertical page scroll amount.
|
||||
@param aPageScroll the new vertcal page scroll amount
|
||||
@param aPageScroll the new vertical page scroll amount
|
||||
*/
|
||||
- (void)setVerticalPageScroll:(float)aPageScroll
|
||||
{
|
||||
|
||||
@@ -181,7 +181,7 @@ var RECENT_SEARCH_PREFIX = @" ";
|
||||
[_cancelButton setFrame:[self cancelButtonRectForBounds:[self bounds]]];
|
||||
[_cancelButton setAutoresizingMask:CPViewMinXMargin];
|
||||
[_cancelButton setTarget:self];
|
||||
[_cancelButton setAction:@selector(_searchFieldCancel:)];
|
||||
[_cancelButton setAction:@selector(cancelOperation:)];
|
||||
[self _updateCancelButtonVisibility];
|
||||
[self addSubview:_cancelButton];
|
||||
}
|
||||
@@ -209,7 +209,7 @@ var RECENT_SEARCH_PREFIX = @" ";
|
||||
[button setAlternateImage:CPSearchFieldCancelPressedImage];
|
||||
[button setAutoresizingMask:CPViewMinXMargin];
|
||||
[button setTarget:self];
|
||||
[button setAction:@selector(_searchFieldCancel:)];
|
||||
[button setAction:@selector(cancelOperation:)];
|
||||
}
|
||||
|
||||
// Custom Layout
|
||||
@@ -677,7 +677,7 @@ var RECENT_SEARCH_PREFIX = @" ";
|
||||
[_partialStringTimer invalidate];
|
||||
}
|
||||
|
||||
- (void)_searchFieldCancel:(id)sender
|
||||
- (void)cancelOperation:(id)sender
|
||||
{
|
||||
[self setObjectValue:@""];
|
||||
[self _sendPartialString];
|
||||
|
||||
@@ -361,9 +361,9 @@ CPSegmentSwitchTrackingMomentary = 2;
|
||||
}
|
||||
|
||||
/*!
|
||||
Enables/diables the specified segment.
|
||||
Enables/disables the specified segment.
|
||||
@param isEnabled \c YES enables the segment
|
||||
@param aSegment the segment to enable/disble
|
||||
@param aSegment the segment to enable/disable
|
||||
@throws CPRangeException if \c aSegment is out of bounds
|
||||
*/
|
||||
- (void)setEnabled:(BOOL)isEnabled forSegment:(unsigned)aSegment
|
||||
|
||||
@@ -384,7 +384,7 @@ CPCircularSlider = 1;
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
shoudl we have _continuous?
|
||||
should we have _continuous?
|
||||
*/
|
||||
- (void)setContinuous:(BOOL)flag
|
||||
{
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
|
||||
- (id)initView
|
||||
{
|
||||
aFrame = CGRectMake(0, 0, CPColorPickerViewWidth, CPColorPickerViewHeight);
|
||||
aFrame = CGRectMake(0, 0, CPColorPickerViewWidth, CPColorPickerViewHeight);
|
||||
|
||||
_contentView = [[CPView alloc] initWithFrame:aFrame];
|
||||
[_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
|
||||
@@ -240,7 +240,7 @@
|
||||
return (mode == CPSliderColorPickerMode) ? YES : NO;
|
||||
}
|
||||
|
||||
-(void)sliderChanged:(id)sender
|
||||
- (void)sliderChanged:(id)sender
|
||||
{
|
||||
var newColor,
|
||||
colorPanel = [self colorPanel],
|
||||
@@ -274,7 +274,7 @@
|
||||
[colorPanel setColor: newColor];
|
||||
}
|
||||
|
||||
-(void)setColor:(CPColor)aColor
|
||||
- (void)setColor:(CPColor)aColor
|
||||
{
|
||||
[self updateRGBSliders: aColor];
|
||||
[self updateHSBSliders: aColor];
|
||||
@@ -282,7 +282,7 @@
|
||||
[self updateLabels];
|
||||
}
|
||||
|
||||
-(void)updateHSBSliders:(CPColor)aColor
|
||||
- (void)updateHSBSliders:(CPColor)aColor
|
||||
{
|
||||
var hsb = [aColor hsbComponents];
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ CPSoundPlayBackStatePause = 2;
|
||||
Initialize with the sound contents of the URL represented by aFile.
|
||||
|
||||
@param aFile CPString the path of the sound
|
||||
@param byRef ignored (Cocoa compatibibility)
|
||||
@param byRef ignored (Cocoa compatibility)
|
||||
*/
|
||||
- (id)initWithContentsOfFile:(CPString)aFile byReference:(BOOL)byRef
|
||||
{
|
||||
@@ -94,7 +94,7 @@ CPSoundPlayBackStatePause = 2;
|
||||
Initialize with the sound contents of the file located at aURL.
|
||||
|
||||
@param aURL CPURL containing the URL of the sound
|
||||
@param byRef ignored (Cocoa compatibibility)
|
||||
@param byRef ignored (Cocoa compatibility)
|
||||
*/
|
||||
- (id)initWithContentsOfURL:(CPURL)aURL byReference:(BOOL)byRef
|
||||
{
|
||||
@@ -105,7 +105,7 @@ CPSoundPlayBackStatePause = 2;
|
||||
Initialize with the sound contents of someData.
|
||||
|
||||
@param someData CPData containing the sound
|
||||
@param byRef ignored (Cocoa compatibibility)
|
||||
@param byRef ignored (Cocoa compatibility)
|
||||
*/
|
||||
- (id)initWithData:(CPData)someData
|
||||
{
|
||||
|
||||
@@ -33,6 +33,14 @@ var CPSplitViewHorizontalImage = nil,
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPSplitView
|
||||
|
||||
CPSplitView is a view that allows you to stack several subviews vertically or horizontally. The user is given divider to resize the subviews.
|
||||
The divider indices are zero-based. So the divider on the top (or left for vertical dividers) will be index 0.
|
||||
|
||||
CPSplitView can be supplied a delegate to provide control over the resizing of the splitview and subviews. Those methods are documented in setDelegate:
|
||||
|
||||
CPSplitView will add dividers for each subview you add. So just like adding subviews to a CPView you should call addSubview: to add new resizable subviews in your splitview.
|
||||
*/
|
||||
|
||||
@implementation CPSplitView : CPView
|
||||
@@ -96,16 +104,28 @@ var CPSplitViewHorizontalImage = nil,
|
||||
return self;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the thickness of the divider.
|
||||
@return float - the thickness of the divider.
|
||||
*/
|
||||
- (float)dividerThickness
|
||||
{
|
||||
return [self currentValueForThemeAttribute:[self isPaneSplitter] ? @"pane-divider-thickness" : @"divider-thickness"];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns YES if the dividers are vertical, otherwise NO.
|
||||
@return YES if vertical, otherwise NO.
|
||||
*/
|
||||
- (BOOL)isVertical
|
||||
{
|
||||
return _isVertical;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets if the splitview dividers are vertical.
|
||||
@param shouldBeVertical - YES if the splitview dividers should be vertical, otherwise NO.
|
||||
*/
|
||||
- (void)setVertical:(BOOL)shouldBeVertical
|
||||
{
|
||||
if (![self _setVertical:shouldBeVertical])
|
||||
@@ -147,11 +167,21 @@ var CPSplitViewHorizontalImage = nil,
|
||||
return changed;
|
||||
}
|
||||
|
||||
/*!
|
||||
Use to find if the divider is a larger pane splitter.
|
||||
|
||||
@return BOOL - YES if the dividers are the larger pane splitters. Otherwise NO.
|
||||
*/
|
||||
- (BOOL)isPaneSplitter
|
||||
{
|
||||
return _isPaneSplitter;
|
||||
}
|
||||
|
||||
/*!
|
||||
Used to set if the split view dividers should be the larger pane splitter.
|
||||
|
||||
@param shouldBePaneSplitter - YES if the dividers should be the thicker pane splitter, otherwise NO.
|
||||
*/
|
||||
- (void)setIsPaneSplitter:(BOOL)shouldBePaneSplitter
|
||||
{
|
||||
if (_isPaneSplitter == shouldBePaneSplitter)
|
||||
@@ -173,11 +203,22 @@ var CPSplitViewHorizontalImage = nil,
|
||||
_needsResizeSubviews = YES;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns YES if the supplied subview is collapsed, otherwise NO.
|
||||
@param aSubview - the subview you are interested in.
|
||||
@return BOOL - YES if the subview is collapsed, otherwise NO.
|
||||
*/
|
||||
- (BOOL)isSubviewCollapsed:(CPView)subview
|
||||
{
|
||||
return [subview frame].size[_sizeComponent] < 1 ? YES : NO;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the CGRect of the divider at a given index.
|
||||
|
||||
@param int - The index of a divider.
|
||||
@return CGRect - The rect of a divider.
|
||||
*/
|
||||
- (CGRect)rectOfDividerAtIndex:(int)aDivider
|
||||
{
|
||||
var frame = [_subviews[aDivider] frame],
|
||||
@@ -191,6 +232,12 @@ var CPSplitViewHorizontalImage = nil,
|
||||
return rect;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the rect of the divider which the user is able to drag to resize.
|
||||
|
||||
@param int - The index of the divider.
|
||||
@return CGRect - The rect the user can drag.
|
||||
*/
|
||||
- (CGRect)effectiveRectOfDividerAtIndex:(int)aDivider
|
||||
{
|
||||
var realRect = [self rectOfDividerAtIndex:aDivider],
|
||||
@@ -212,7 +259,10 @@ var CPSplitViewHorizontalImage = nil,
|
||||
[self drawDividerInRect:[self rectOfDividerAtIndex:count]];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Draws the divider at a given rect.
|
||||
@param aRect - the rect of the divider to draw.
|
||||
*/
|
||||
- (void)drawDividerInRect:(CGRect)aRect
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
@@ -485,6 +535,11 @@ var CPSplitViewHorizontalImage = nil,
|
||||
[[CPCursor arrowCursor] set];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the maximum possible position of a divider at a given index.
|
||||
@param the index of the divider.
|
||||
@return float - the max possible position.
|
||||
*/
|
||||
- (float)maxPossiblePositionOfDividerAtIndex:(int)dividerIndex
|
||||
{
|
||||
var frame = [_subviews[dividerIndex + 1] frame];
|
||||
@@ -495,6 +550,11 @@ var CPSplitViewHorizontalImage = nil,
|
||||
return [self frame].size[_sizeComponent] - [self dividerThickness];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the minimum possible position of a divider at a given index.
|
||||
@param the index of the divider.
|
||||
@return float - the min possible position.
|
||||
*/
|
||||
- (float)minPossiblePositionOfDividerAtIndex:(int)dividerIndex
|
||||
{
|
||||
if (dividerIndex > 0)
|
||||
@@ -535,6 +595,11 @@ var CPSplitViewHorizontalImage = nil,
|
||||
return realPosition;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the position of a divider at a given index.
|
||||
@param position - The float value of the position to place the divider.
|
||||
@param dividerIndex - The index of the divider to position.
|
||||
*/
|
||||
- (void)setPosition:(float)position ofDividerAtIndex:(int)dividerIndex
|
||||
{
|
||||
[self _adjustSubviewsWithCalculatedSize];
|
||||
@@ -644,6 +709,48 @@ var CPSplitViewHorizontalImage = nil,
|
||||
[self _postNotificationDidResize];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the delegate of the receiver.
|
||||
Possible delegate methods to implement are listed below.
|
||||
|
||||
<pre>
|
||||
- (void)splitViewDidResizeSubviews:(CPSplitView)aSplitView;
|
||||
Notifies the delegate when the subviews have resized.
|
||||
|
||||
- (void)splitViewWillResizeSubviews:(CPSplitView)aSplitView;
|
||||
Notifies the delegate when the subviews will be resized.
|
||||
|
||||
- (CGRect)splitView:(CPSplitView)aSplitView effectiveRect:(CGRect)aRect forDrawnRect:(CGRect)aDrawnRect ofDividerAtIndex:(int)aDividerIndex;
|
||||
Lets the delegate specify a different rect for which the user can drag the splitView divider.
|
||||
|
||||
- (CGRect)splitView:(CPSplitView)aSplitView additionalEffectiveRectOfDividerAtIndex:(int)indexOfDivider;
|
||||
Lets the delegate specify an additional rect for which the user can drag the splitview divider.
|
||||
|
||||
- (BOOL)splitView:(CPSplitView)aSplitView canCollapseSubview:(CPView)aSubview;
|
||||
Notifies the delegate that the splitview is about to be collapsed. This usually happens when the user
|
||||
Double clicks on the divider. Return YES if the subview can be collapsed, otherwise NO.
|
||||
|
||||
- (BOOL)splitView:(CPSplitView)aSplitView shouldCollapseSubview:(CPView)aSubview;
|
||||
Notifies the delegate that the splitview is about to be collapsed. This usually happens when the user
|
||||
Double clicks on the divider. Return YES if the subview should be collapsed, otherwise NO.
|
||||
|
||||
- (float)splitView:(CPSplitView)aSpiltView constrainSplitPosition:(float)proposedPosition ofSubviewAt:(int)subviewIndex;
|
||||
Allows the delegate to constrain the subview beings resized. This method is called continuously as the user resizes the divider.
|
||||
For example if the subview needs to have a width which is a multiple of a certain number you could return that multiple with this method.
|
||||
|
||||
- (float)splitView:(CPSplitView)aSplitView constrainMinCoordinate:(float)proposedMin ofSubviewAt:(int)subviewIndex;
|
||||
Allows the delegate to constrain the minimum position of a subview.
|
||||
|
||||
- (float)splitView:(CPSplitView)aSplitView constrainMaxCoordinate:(float)proposedMax ofSubviewAt:(int)subviewIndex;
|
||||
Allows the delegate to constrain the maximum position of a subview.
|
||||
|
||||
- (void)splitView:(CPSplitView)aSplitView resizeSubviewsWithOldSize:(CGSize)oldSize;
|
||||
Allows the splitview to specify a custom resizing behavior. This is called when the splitview is resized.
|
||||
The sum of the views and the sum of the dividers should be equal to the size of the splitview.
|
||||
</pre>
|
||||
|
||||
@param delegate - The delegate of the splitview.
|
||||
*/
|
||||
- (void)setDelegate:(id)delegate
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(splitViewDidResizeSubviews:)])
|
||||
@@ -676,6 +783,9 @@ var CPSplitViewHorizontalImage = nil,
|
||||
|
||||
This method will automatically configure the hasResizeControl and resizeControlIsLeftAligned
|
||||
parameters of the button bar, and will override any currently set values.
|
||||
|
||||
@param CPButtonBar - The supplied button bar.
|
||||
@param unsigned int - The divider index the button bar will be assigned to.
|
||||
*/
|
||||
- (void)setButtonBar:(CPButtonBar)aButtonBar forDividerAtIndex:(unsigned)dividerIndex
|
||||
{
|
||||
@@ -741,7 +851,7 @@ var CPSplitViewDelegateKey = "CPSplitViewDelegateKey",
|
||||
|
||||
_buttonBars = [aCoder decodeObjectForKey:CPSplitViewButtonBarsKey] || [];
|
||||
|
||||
_delegate = [aCoder decodeObjectForKey:CPSplitViewDelegateKey];
|
||||
[self setDelegate:[aCoder decodeObjectForKey:CPSplitViewDelegateKey]];
|
||||
|
||||
_isPaneSplitter = [aCoder decodeBoolForKey:CPSplitViewIsPaneSplitterKey];
|
||||
[self _setVertical:[aCoder decodeBoolForKey:CPSplitViewIsVerticalKey]];
|
||||
|
||||
@@ -152,7 +152,7 @@ var CPStepperButtonsSize = CPSizeMake(19, 13);
|
||||
}
|
||||
|
||||
/*! set the current value of the stepper
|
||||
@param aValue a float contaning the value
|
||||
@param aValue a float containing the value
|
||||
*/
|
||||
- (void)setDoubleValue:(float)aValue
|
||||
{
|
||||
|
||||
@@ -85,7 +85,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
|
||||
|
||||
[self _updateItems];
|
||||
[self _repositionTabs];
|
||||
|
||||
|
||||
[aTabViewItem _setTabView:self];
|
||||
|
||||
if (_delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector)
|
||||
@@ -110,7 +110,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
|
||||
|
||||
[self _updateItems];
|
||||
[self _repositionTabs];
|
||||
|
||||
|
||||
[aTabViewItem _setTabView:nil];
|
||||
|
||||
if (_delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector)
|
||||
|
||||
@@ -145,8 +145,8 @@ CPPressedTab = 2;
|
||||
|
||||
// Assigning an Auxiliary View
|
||||
/*!
|
||||
Sets the tab's auxillary view.
|
||||
@param anAuxillaryView the new auxillary view
|
||||
Sets the tab's auxiliary view.
|
||||
@param anAuxiliaryView the new auxiliary view
|
||||
*/
|
||||
- (void)setAuxiliaryView:(CPView)anAuxiliaryView
|
||||
{
|
||||
@@ -154,7 +154,7 @@ CPPressedTab = 2;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the tab's auxillary view
|
||||
Returns the tab's auxiliary view
|
||||
*/
|
||||
- (CPView)auxiliaryView
|
||||
{
|
||||
|
||||
@@ -37,9 +37,12 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
@class CPTableColumn
|
||||
|
||||
A CPTableColumn contains a dataview to display for its column of the CPTableView.
|
||||
A CPTableColumn determines its own size constrains and resizing behaviour.
|
||||
A CPTableColumn determines its own size constrains and resizing behavior.
|
||||
|
||||
The default dataview is a CPTextField but you can set it to any view you'd like. See -setDataView:
|
||||
The default dataview is a CPTextField but you can set it to any view you'd like. See -setDataView: for documentation including theme states.
|
||||
|
||||
To customize the text of the column header you can simply call setStringValue: on the headerview of a table column.
|
||||
For example: [[myTableColumn headerView] setStringValue:"My Title"];
|
||||
*/
|
||||
@implementation CPTableColumn : CPObject
|
||||
{
|
||||
@@ -62,11 +65,6 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
BOOL _disableResizingPosting @accessors(property=disableResizingPosting);
|
||||
}
|
||||
|
||||
+ (Class)_binderClassForBinding:(CPString)theBinding
|
||||
{
|
||||
return [CPBinder class];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
@@ -197,7 +195,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the minimum width of the column.
|
||||
Sets the minimum width of the column.
|
||||
Default value is 10.
|
||||
*/
|
||||
- (void)setMinWidth:(float)aMinWidth
|
||||
@@ -225,7 +223,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the maximum width of the table column.
|
||||
Sets the maximum width of the table column.
|
||||
Default value is: 1000000
|
||||
*/
|
||||
- (void)setMaxWidth:(float)aMaxWidth
|
||||
@@ -253,13 +251,15 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the resizing mask of the column.
|
||||
By default the column can be resized automatically with the tableview and manaully by the user
|
||||
<pre>
|
||||
Set the resizing mask of the column.
|
||||
By default the column can be resized automatically with the tableview and manually by the user
|
||||
|
||||
Possible masking values are:
|
||||
CPTableColumnNoResizing
|
||||
CPTableColumnAutoresizingMask
|
||||
CPTableColumnUserResizingMask
|
||||
</pre>
|
||||
*/
|
||||
- (void)setResizingMask:(unsigned)aResizingMask
|
||||
{
|
||||
@@ -276,7 +276,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sizes the column to fix the column header text.
|
||||
Sizes the column to fix the column header text.
|
||||
*/
|
||||
- (void)sizeToFit
|
||||
{
|
||||
@@ -294,7 +294,12 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
|
||||
/*!
|
||||
Sets the header view for the column.
|
||||
The headerview handles the display of sort indicators, text, etc
|
||||
The headerview handles the display of sort indicators, text, etc.
|
||||
|
||||
If you do not want a headerview for you table you should call setHeaderView: on your CPTableView instance.
|
||||
Passing nil here will throw an exception.
|
||||
|
||||
In order to customize the text of the column header see - (CPView)headerView;
|
||||
*/
|
||||
- (void)setHeaderView:(CPView)aView
|
||||
{
|
||||
@@ -310,7 +315,10 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the headerview for the column
|
||||
Returns the headerview for the column.
|
||||
|
||||
In order to change the text of the headerview for a column you should call setStringValue: on the headerview.
|
||||
For example: [[myTableColumn headerView] setStringValue:"My Column"];
|
||||
*/
|
||||
- (CPView)headerView
|
||||
{
|
||||
@@ -318,11 +326,19 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
}
|
||||
|
||||
/*!
|
||||
<pre>
|
||||
This method sets the "prototype" view which will be used to create all table cells in this column.
|
||||
|
||||
It creates a snapshot of aView, using keyed archiving, which is then copied over and over for each
|
||||
individual cell that is shown. As a result, changes made after calling this method won't be reflected.
|
||||
|
||||
When you set a dataview and it is added to the tableview the theme state will be set to CPThemeStateTableDataView
|
||||
When the dataview becomes selected the theme state will be set to CPThemeStateSelectedDataView.
|
||||
|
||||
If the dataview shows up in a group row of the tableview the theme state will be set to CPThemeStateGroupRow.
|
||||
|
||||
You should overide setThemeState: and unsetThemeState: to handle these theme state changes in your dataview.
|
||||
|
||||
Example:
|
||||
|
||||
[tableColumn setDataView:someView]; // snapshot taken
|
||||
@@ -333,7 +349,37 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
[someView setSomething:x];
|
||||
[tableColumn setDataView:someView];
|
||||
|
||||
REMEMBER: you should implement CPKeyedArchiving otherwise you might see unexpected results
|
||||
REMEMBER: you should implement CPKeyedArchiving otherwise you might see unexpected results.
|
||||
This is done by adding the following methods to your class:
|
||||
- (id)initWithCoder(CPCoder)aCoder;
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder;
|
||||
|
||||
Example:
|
||||
Say you have two instance variables in your object that need to be set up each time an object is create.
|
||||
We will call these instance variables "image" and "text".
|
||||
Your CPCoding methods will look like the following:
|
||||
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
self = [super initWithCoder:aCoder];
|
||||
|
||||
if (self)
|
||||
{
|
||||
image = [aCoder decodeObjectForKey:"MyDataViewImage"];
|
||||
text = [aCoder decodeObjectForKey:"MyDataViewText"];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
[super encodeWithCoder:aCoder];
|
||||
|
||||
[aCoder encodeObject:image forKey:"MyDataViewImage"];
|
||||
[aCoder encodeObject:text forKey:"MyDataViewText"];
|
||||
}
|
||||
</pre>
|
||||
*/
|
||||
- (void)setDataView:(CPView)aView
|
||||
{
|
||||
@@ -355,7 +401,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
Returns the CPView object used by the CPTableView to draw values for the receiver.
|
||||
|
||||
By default, this method just calls dataView. Subclassers can override if they need to
|
||||
potentially use different cells for different rows. Subclasses should expect this method
|
||||
potentially use different "cells" or dataViews for different rows. Subclasses should expect this method
|
||||
to be invoked with row equal to -1 in cases where no actual row is involved but the table
|
||||
view needs to get some generic cell info.
|
||||
*/
|
||||
@@ -392,7 +438,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
|
||||
//Setting the Identifier
|
||||
|
||||
/*
|
||||
/*!
|
||||
Sets the receiver identifier to anIdentifier.
|
||||
*/
|
||||
- (void)setIdentifier:(id)anIdentifier
|
||||
@@ -400,7 +446,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
_identifier = anIdentifier;
|
||||
}
|
||||
|
||||
/*
|
||||
/*!
|
||||
Returns the object used by the data source to identify the attribute corresponding to the receiver.
|
||||
*/
|
||||
- (id)identifier
|
||||
@@ -410,7 +456,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
|
||||
//Controlling Editability
|
||||
|
||||
/*
|
||||
/*!
|
||||
Controls whether the user can edit cells in the receiver by double-clicking them.
|
||||
*/
|
||||
- (void)setEditable:(BOOL)shouldBeEditable
|
||||
@@ -418,7 +464,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
_isEditable = shouldBeEditable;
|
||||
}
|
||||
|
||||
/*
|
||||
/*!
|
||||
Returns YES if the user can edit cells associated with the receiver by double-clicking the
|
||||
column in the NSTableView, NO otherwise.
|
||||
*/
|
||||
@@ -428,7 +474,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the sort descriptor prototype for the column.
|
||||
Sets the sort descriptor prototype for the column.
|
||||
*/
|
||||
- (void)setSortDescriptorPrototype:(CPSortDescriptor)aSortDescriptor
|
||||
{
|
||||
@@ -444,7 +490,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
}
|
||||
|
||||
/*!
|
||||
If NO the tablecolumn will no longer be visisble in the tableview
|
||||
If NO the tablecolumn will no longer be visible in the tableview
|
||||
If YES the tablecolumn will be visible in the tableview.
|
||||
*/
|
||||
- (void)setHidden:(BOOL)shouldBeHidden
|
||||
@@ -469,7 +515,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
|
||||
//Setting Tool Tips
|
||||
|
||||
/*
|
||||
/*!
|
||||
Sets the tooltip string that is displayed when the cursor pauses over the
|
||||
header cell of the receiver.
|
||||
*/
|
||||
@@ -501,7 +547,40 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPTableColumnValueBinder : CPBinder
|
||||
{
|
||||
}
|
||||
|
||||
- (void)setValueFor:(CPString)aBinding
|
||||
{
|
||||
var tableView = [_source tableView],
|
||||
column = [[tableView tableColumns] indexOfObjectIdenticalTo:_source],
|
||||
rowIndexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [tableView numberOfRows])],
|
||||
columnIndexes = [CPIndexSet indexSetWithIndex:column];
|
||||
|
||||
[tableView reloadDataForRowIndexes:rowIndexes columnIndexes:columnIndexes];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPTableColumn (Bindings)
|
||||
|
||||
+ (id)_binderClassForBinding:(CPString)aBinding
|
||||
{
|
||||
if (aBinding == CPValueBinding)
|
||||
return [CPTableColumnValueBinder class];
|
||||
|
||||
return [super _binderClassForBinding:aBinding];
|
||||
}
|
||||
|
||||
/*!
|
||||
Binds the receiver to an object.
|
||||
|
||||
@param CPString aBinding - The binding you wish to make. Typically CPValueBinding.
|
||||
@param id anObject - The object to bind the receiver to.
|
||||
@param CPString aKeyPath - The key path you wish to bind the receiver to.
|
||||
@param CPDictionary options - A dictionary of options for the binding. This parameter is optional, pass nil if you do not wish to use it.
|
||||
*/
|
||||
- (void)bind:(CPString)aBinding toObject:(id)anObject withKeyPath:(CPString)aKeyPath options:(CPDictionary)options
|
||||
{
|
||||
[super bind:aBinding toObject:anObject withKeyPath:aKeyPath options:options];
|
||||
@@ -510,6 +589,9 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
[[self tableView] _establishBindingsIfUnbound:anObject];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)prepareDataView:(CPView)aDataView forRow:(unsigned)aRow
|
||||
{
|
||||
var bindingsDictionary = [CPBinder allBindingsForObject:self],
|
||||
@@ -561,11 +643,6 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
// return nil;
|
||||
//}
|
||||
|
||||
- (void)setValue:(CPArray)content
|
||||
{
|
||||
[[self tableView] reloadData];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
|
||||
@@ -581,6 +658,9 @@ var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
|
||||
|
||||
@implementation CPTableColumn (CPCoding)
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
self = [super init];
|
||||
@@ -608,6 +688,9 @@ var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
|
||||
return self;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
[aCoder encodeObject:_identifier forKey:CPTableColumnIdentifierKey];
|
||||
@@ -629,31 +712,45 @@ var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
|
||||
@end
|
||||
|
||||
@implementation CPTableColumn (NSInCompatibility)
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)setHeaderCell:(CPView)aView
|
||||
{
|
||||
[CPException raise:CPUnsupportedMethodException
|
||||
reason:@"setHeaderCell: is not supported. Use -setHeaderView:aView instead."];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (CPView)headerCell
|
||||
{
|
||||
[CPException raise:CPUnsupportedMethodException
|
||||
reason:@"headCell is not supported. Use -headerView instead."];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)setDataCell:(CPView)aView
|
||||
{
|
||||
[CPException raise:CPUnsupportedMethodException
|
||||
reason:@"setDataCell: is not supported. Use -setDataView:aView instead."];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (CPView)dataCell
|
||||
{
|
||||
[CPException raise:CPUnsupportedMethodException
|
||||
reason:@"dataCell is not supported. Use -dataView instead."];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (id)dataCellForRow:(int)row
|
||||
{
|
||||
[CPException raise:CPUnsupportedMethodException
|
||||
|
||||
@@ -604,7 +604,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
|
||||
|
||||
[headerView setFrame:frame];
|
||||
|
||||
if([headerView superview] != self)
|
||||
if ([headerView superview] != self)
|
||||
[self addSubview:headerView];
|
||||
}
|
||||
|
||||
|
||||
@@ -147,7 +147,9 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
All delegate and data source methods are documented in the setDataSource: and setDelegate: methods.
|
||||
|
||||
If you want to display something other than just text in the table you should call setDataView: on CPColumn. More documentation in that class.
|
||||
If you want to display something other than just text in the table you should call setDataView: on a CPTableColumn object. More documentation in that class including theme states.
|
||||
|
||||
Note: CPTableView does not contain its own scrollview. You should be sure you place the tableview in a CPScrollView on your own.
|
||||
*/
|
||||
@implementation CPTableView : CPControl
|
||||
{
|
||||
@@ -315,7 +317,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
FIX ME: we have a lot of redundent init stuff in initWithFrame: and initWithCoder: we should move it all into here.
|
||||
FIX ME: we have a lot of redundant init stuff in initWithFrame: and initWithCoder: we should move it all into here.
|
||||
we should do a full audit of all the initializers before 1.0
|
||||
*/
|
||||
- (void)_init
|
||||
@@ -378,15 +380,16 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
}
|
||||
|
||||
/*!
|
||||
<pre>
|
||||
Sets the receiver's data source to a given object.
|
||||
The data source implements various methods for handeling the tableview's data when bindings are not used.
|
||||
The data source implements various methods for handling the tableview's data when bindings are not used.
|
||||
|
||||
Methonds include:
|
||||
Methods include:
|
||||
- (int)numberOfRowsInTableView:(CPTableView)aTableView;
|
||||
Returns the number of rows in the tableview
|
||||
|
||||
- (id)tableView:(CPTableView)aTableView objectValueForTableColumn:(CPTableColumn)aColumn row:(int)aRowIndex;
|
||||
Returns the object value for each dataview. Each dataview will be sent a setObjectValue: method which will contai
|
||||
Returns the object value for each dataview. Each dataview will be sent a setObjectValue: method which will contain
|
||||
the object you return from this datasource method.
|
||||
|
||||
Editing:
|
||||
@@ -398,15 +401,15 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
The tableview will call this method if you click the tableheader. You should sort the datasource based off of the new sort descriptors and reload the data
|
||||
|
||||
Drag and Drop:
|
||||
In order for the tableview to recieve drops dont forget to first register the tableview for drag types like you do with every other view
|
||||
In order for the tableview to receive drops don't forget to first register the tableview for drag types like you do with every other view
|
||||
|
||||
- (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(CPDraggingInfo)info proposedRow:(int)row proposedDropOperation:(CPTableViewDropOperation)operation;
|
||||
Return the drag operation (move, copy, etc) that should be performaned if a registered drag type is over the tableview
|
||||
Return the drag operation (move, copy, etc) that should be performed if a registered drag type is over the tableview
|
||||
The data source can retarget a drop if you want by calling -(void)setDropRow:(int)aRow dropOperation:(CPTableViewDropOperation)anOperation;
|
||||
|
||||
- (BOOL)tableView:(CPTableView)aTableView writeRowsWithIndexes:(CPIndexSet)rowIndexes toPasteboard:(CPPasteboard)pboard;
|
||||
Returns YES if the drop operation is allowed otherwise NO.
|
||||
This method is invoked by the tabeview after a drag should begin, but before it is started. If you dont want the drag to being return NO.
|
||||
This method is invoked by the tableview after a drag should begin, but before it is started. If you don't want the drag to being return NO.
|
||||
If you want the drag to begin you should return YES and place the drag data on the pboard.
|
||||
|
||||
- (BOOL)tableView:(CPTableView)aTableView acceptDrop:(CPDraggingInfo)info row:(int)row dropOperation:(CPTableViewDropOperation)operation;
|
||||
@@ -416,7 +419,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
- (CPArray)tableView:(CPTableView)aTableView namesOfPromisedFilesDroppedAtDestination:(CPURL)dropDestination forDraggedRowsWithIndexes:(CPIndexSet)indexSet;
|
||||
NOT YET IMPLEMENTED
|
||||
|
||||
</pre>
|
||||
@param anObject The data source for the receiver. This object must implement numberOfRowsInTableView: and tableView:objectValueForTableColumn:row:
|
||||
*/
|
||||
- (void)setDataSource:(id)aDataSource
|
||||
@@ -576,6 +579,11 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
_allowsMultipleSelection = !!shouldAllowMultipleSelection;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns YES if the tableview is allowed to have multiple selections, otherwise NO.
|
||||
|
||||
@return BOOL - YES if the tableview is allowed to have multiple selections otherwise NO.
|
||||
*/
|
||||
- (BOOL)allowsMultipleSelection
|
||||
{
|
||||
return _allowsMultipleSelection;
|
||||
@@ -622,7 +630,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
Sets the width and height between dataviews.
|
||||
This value is (3.0, 2.0) by default.
|
||||
|
||||
@param aSize a CGSize object that degined the space between the cells
|
||||
@param aSize a CGSize object that defines the space between the cells
|
||||
*/
|
||||
- (void)setIntercellSpacing:(CGSize)aSize
|
||||
{
|
||||
@@ -701,7 +709,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the colors for the rows as they alternate. The number of colors can be arbitrary. By deafult these colors are white and light blue.
|
||||
Sets the colors for the rows as they alternate. The number of colors can be arbitrary. By default these colors are white and light blue.
|
||||
@param anArray an array of CPColors
|
||||
*/
|
||||
|
||||
@@ -722,11 +730,13 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
/*!
|
||||
Returns an enumerated value for the selection highlight style.
|
||||
<pre>
|
||||
|
||||
Valid values are:
|
||||
CPTableViewSelectionHighlightStyleNone
|
||||
CPTableViewSelectionHighlightStyleRegular
|
||||
CPTableViewSelectionHighlightStyleSourceList
|
||||
</pre>
|
||||
*/
|
||||
- (unsigned)selectionHighlightStyle
|
||||
{
|
||||
@@ -734,6 +744,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
}
|
||||
|
||||
/*!
|
||||
<pre>
|
||||
Sets the selection highlight style to an enumerated value.
|
||||
This value can also affect the way the tableview draws feedback when the user is dragging.
|
||||
|
||||
@@ -741,6 +752,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
CPTableViewSelectionHighlightStyleNone
|
||||
CPTableViewSelectionHighlightStyleRegular
|
||||
CPTableViewSelectionHighlightStyleSourceList
|
||||
</pre>
|
||||
*/
|
||||
- (void)setSelectionHighlightStyle:(unsigned)aSelectionHighlightStyle
|
||||
{
|
||||
@@ -778,12 +790,14 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
}
|
||||
|
||||
/*!
|
||||
<pre>
|
||||
Sets the highlight gradient for a row or column selection
|
||||
This is specific to the
|
||||
@param aDictionary a CPDictionary expects three keys to be set:
|
||||
CPSourceListGradient which is a CGGradient
|
||||
CPSourceListTopLineColor which is a CPColor
|
||||
CPSourceListBottomLineColor which is a CPColor
|
||||
</pre>
|
||||
*/
|
||||
- (void)setSelectionGradientColors:(CPDictionary)aDictionary
|
||||
{
|
||||
@@ -793,10 +807,12 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
}
|
||||
|
||||
/*!
|
||||
<pre>
|
||||
Returns a dictionary of containing the keys:
|
||||
CPSourceListGradient
|
||||
CPSourceListTopLineColor
|
||||
CPSourceListBottomLineColor
|
||||
</pre>
|
||||
*/
|
||||
- (CPDictionary)selectionGradientColors
|
||||
{
|
||||
@@ -861,6 +877,17 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
else
|
||||
_dirtyTableColumnRangeIndex = MIN(NUMBER_OF_COLUMNS() - 1, _dirtyTableColumnRangeIndex);
|
||||
|
||||
if ([[self sortDescriptors] count] > 0)
|
||||
{
|
||||
var mainSortDescriptor = [[self sortDescriptors] objectAtIndex:0];
|
||||
|
||||
if (aTableColumn === [self _tableColumnForSortDescriptor:mainSortDescriptor])
|
||||
{
|
||||
var image = [mainSortDescriptor ascending] ? [self _tableHeaderSortImage] : [self _tableHeaderReverseSortImage];
|
||||
[self setIndicatorImage:image inTableColumn:aTableColumn];
|
||||
}
|
||||
}
|
||||
|
||||
[self tile];
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
@@ -900,7 +927,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Interally used to set a column that will be dragged
|
||||
Internally used to set a column that will be dragged
|
||||
*/
|
||||
- (void)_setDraggedColumn:(CPTableColumn)aColumn
|
||||
{
|
||||
@@ -1372,7 +1399,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
*/
|
||||
- (void)editColumn:(CPInteger)columnIndex row:(CPInteger)rowIndex withEvent:(CPEvent)theEvent select:(BOOL)flag
|
||||
{
|
||||
// FIX ME: Cocoa documenation says all this should be called in THIS method:
|
||||
// FIX ME: Cocoa documentation says all this should be called in THIS method:
|
||||
// sets up the field editor, and sends selectWithFrame:inView:editor:delegate:start:length: and editWithFrame:inView:editor:delegate:event: to the field editor's NSCell object with the NSTableView as the text delegate.
|
||||
|
||||
if (![self isRowSelected:rowIndex])
|
||||
@@ -1384,6 +1411,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
// TODO Do something with flag.
|
||||
|
||||
_editingCellIndex = CGPointMake(columnIndex, rowIndex);
|
||||
_editingCellIndex._shouldSelect = flag;
|
||||
|
||||
[self reloadDataForRowIndexes:[CPIndexSet indexSetWithIndex:rowIndex]
|
||||
columnIndexes:[CPIndexSet indexSetWithIndex:columnIndex]];
|
||||
}
|
||||
@@ -1433,7 +1462,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the headerview for the receiver. The headerview contains column headerviews for each table column
|
||||
Returns the headerview for the receiver. The headerview contains column headerviews for each table column.
|
||||
*/
|
||||
- (CPView)headerView
|
||||
{
|
||||
@@ -1442,8 +1471,11 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
|
||||
/*!
|
||||
Sets the headerview for the tableview. This is the container view for the table column header views
|
||||
Sets the headerview for the tableview. This is the container view for the table column header views.
|
||||
This view also handles events for resizing and dragging.
|
||||
|
||||
If you don't want your tableview to have a headerview you should pass nil. (also see setCornerView:)
|
||||
If you're looking to customize the header text of a column see CPTableColumn's -(CPView)headerView; method.
|
||||
*/
|
||||
- (void)setHeaderView:(CPView)aHeaderView
|
||||
{
|
||||
@@ -1887,7 +1919,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
i = 0;
|
||||
|
||||
// find resizable columns
|
||||
// FIX ME: we could cache resizableColumns after this loop and reuse it durring the resize
|
||||
// FIX ME: we could cache resizableColumns after this loop and reuse it during the resize
|
||||
for (; i < count; i++)
|
||||
{
|
||||
var tableColumn = _tableColumns[i];
|
||||
@@ -1924,9 +1956,17 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now that we've reached the end we know there are likely rounding errors
|
||||
// so we should size the last resized to fit
|
||||
var delta = superviewWidth - _CGRectGetMaxX([self rectOfColumn:[self numberOfColumns] - 1]),
|
||||
newSize = [item width] + delta;
|
||||
|
||||
[item _tryToResizeToWidth:newSize];
|
||||
}
|
||||
|
||||
/*!
|
||||
<pre>
|
||||
Sets the column autoresizing style of the receiver to a given style.
|
||||
|
||||
@param aStyle the column autoresizing style for the receiver. Valid values are:
|
||||
@@ -1934,6 +1974,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
CPTableViewUniformColumnAutoresizingStyle
|
||||
CPTableViewLastColumnOnlyAutoresizingStyle
|
||||
CPTableViewFirstColumnOnlyAutoresizingStyle
|
||||
</pre>
|
||||
*/
|
||||
- (void)setColumnAutoresizingStyle:(unsigned)style
|
||||
{
|
||||
@@ -2002,9 +2043,13 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
if (hangingSelections > 0)
|
||||
{
|
||||
|
||||
var previousSelectionCount = [_selectedRowIndexes count];
|
||||
[_selectedRowIndexes removeIndexesInRange:CPMakeRange(_numberOfRows, hangingSelections)];
|
||||
|
||||
if (![_selectedRowIndexes containsIndex:[self selectedRow]])
|
||||
_lastSelectedRow = CPNotFound;
|
||||
|
||||
// For optimal performance, only send a notification if indices were actually removed.
|
||||
if (previousSelectionCount > [_selectedRowIndexes count])
|
||||
[self _noteSelectionDidChange];
|
||||
@@ -2233,13 +2278,14 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
|
||||
/*!
|
||||
<pre>
|
||||
Sets the delegate of the receiver. The delegate can implement the following methods:
|
||||
Displaying Cells
|
||||
- (void)tableView:(CPTableView)aTableView willDisplayView:(id)aView forTableColumn:(CPTableColumn)aTableColumn row:(int)rowIndex;
|
||||
Called when the tableview is about to display a dataview
|
||||
|
||||
- (BOOL)tableView:(CPTableView)tableView isGroupRow:(int)row;
|
||||
Group rows are a way to seperate a groups of data in a tableview. Return YES if the given row is a group row, otherwise NO.
|
||||
Group rows are a way to separate a groups of data in a tableview. Return YES if the given row is a group row, otherwise NO.
|
||||
|
||||
Editing Cells
|
||||
- (BOOL)tableView:(CPTableView)aTableView shouldEditTableColumn:(CPTableColumn)aTableColumn row:(int)rowIndex;
|
||||
@@ -2264,7 +2310,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
NOTE: this is only called via user interaction
|
||||
|
||||
- (void)tableViewSelectionIsChanging:(CPNotification)aNotification
|
||||
Inform the delegate that the tableview is in the process of chaning the selection.
|
||||
Inform the delegate that the tableview is in the process of chaining the selection.
|
||||
This usually happens when the user is dragging their mouse across rows.
|
||||
NOTE: this is only called via user interaction
|
||||
|
||||
@@ -2278,7 +2324,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
Return YES if the column at a given index should move to a new column index, otherwise NO.
|
||||
|
||||
- (void)tableView:(CPTableView)tableView didDragTableColumn:(CPTableColumn)tableColumn;
|
||||
Notifies the delegate that the tableview drag occured. This is send on mouse up.
|
||||
Notifies the delegate that the tableview drag occurred. This is send on mouse up.
|
||||
|
||||
- (void)tableViewColumnDidMove:(CPNotification)aNotification;
|
||||
Notifies the delegate that a tablecolumn was moved by the user.
|
||||
@@ -2299,6 +2345,11 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
Called when the user right clicks on the tableview. -1 is passed for the row or column if the user doesn't right click on a real row or column
|
||||
Return a CPMenu that should be displayed if the user right clicks. If you do not implement this the tableview will just call super on menuForEvent
|
||||
|
||||
Delete Key
|
||||
- (void)tableViewDeleteKeyPressed:(CPTableView)aTableView;
|
||||
Called when the user presses the delete key. Many times you will want to delete data (or prompt for deletion) when the user hids the delete key.
|
||||
Your delegate can implement this method to avoid subclassing the tableview to add this behaviour.
|
||||
</pre>
|
||||
@param aDelegate the delegate object for the tableview.
|
||||
|
||||
*/
|
||||
@@ -2639,7 +2690,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
@param dragRows an index set with the dragged row indexes
|
||||
@param theTableColumns an array of the table columns which are being dragged
|
||||
@param dragEvent the event which initiated the drag
|
||||
@param offset a point at wihch to set the drag image to be offset from the cursor
|
||||
@param offset a point at which to set the drag image to be offset from the cursor
|
||||
|
||||
@return CPImage an image to use for the drag feedback
|
||||
*/
|
||||
@@ -2649,12 +2700,14 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
}
|
||||
|
||||
/*!
|
||||
Computes and returns a view to use for dragging
|
||||
Computes and returns a view to use for dragging. By default this is a slightly transparent copy of the dataviews which are being dragged.
|
||||
You can override this in a subclass to show different dragging feedback. Additionally you can return nil from this method and implement:
|
||||
- (CPImage)dragImageForRowsWithIndexes:tableColumns:event:offset: - if you want to return a simple image.
|
||||
|
||||
@param dragRows an index set with the dragged row indexes
|
||||
@param theTableColumns an array of the table columns which are being dragged
|
||||
@param dragEvent the event which initiated the drag
|
||||
@param offset a point at wihch to set the drag image to be offset from the cursor
|
||||
@param offset a point at which to set the drag image to be offset from the cursor
|
||||
|
||||
@return CPView a view used as the dragging feedback
|
||||
*/
|
||||
@@ -2747,12 +2800,12 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the default operation mask for the drag behaviour of the table view.
|
||||
Sets the default operation mask for the drag behavior of the table view.
|
||||
NOTE: isLocal is not implemented.
|
||||
*/
|
||||
- (void)setDraggingSourceOperationMask:(CPDragOperation)mask forLocal:(BOOL)isLocal
|
||||
{
|
||||
//ignoral local for the time being since only one capp app can run at a time...
|
||||
//ignore local for the time being since only one capp app can run at a time...
|
||||
_dragOperationDefaultMask = mask;
|
||||
}
|
||||
|
||||
@@ -2778,11 +2831,15 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
}
|
||||
|
||||
/*!
|
||||
<pre>
|
||||
Sets the feedback style for when the table is the destination of a drag operation.
|
||||
This style is used to determine how the tableview looks when it is the receiver of a drag and drop operation.
|
||||
|
||||
Can be:
|
||||
CPTableViewDraggingDestinationFeedbackStyleNone
|
||||
CPTableViewDraggingDestinationFeedbackStyleRegular
|
||||
CPTableViewDraggingDestinationFeedbackStyleSourceList
|
||||
</pre>
|
||||
*/
|
||||
- (void)setDraggingDestinationFeedbackStyle:(CPTableViewDraggingDestinationFeedbackStyle)aStyle
|
||||
{
|
||||
@@ -2791,12 +2848,14 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
}
|
||||
|
||||
/*!
|
||||
<pre>
|
||||
Returns the tableview dragging destination feedback style.
|
||||
|
||||
Can be:
|
||||
CPTableViewDraggingDestinationFeedbackStyleNone
|
||||
CPTableViewDraggingDestinationFeedbackStyleRegular
|
||||
CPTableViewDraggingDestinationFeedbackStyleSourceList
|
||||
</pre>
|
||||
*/
|
||||
- (CPTableViewDraggingDestinationFeedbackStyle)draggingDestinationFeedbackStyle
|
||||
{
|
||||
@@ -2846,7 +2905,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
/*!
|
||||
Sets the table view's CPSortDescriptors objects in an array.
|
||||
|
||||
@param sortDescriptors an array of sort descritors.
|
||||
@param sortDescriptors an array of sort descriptors.
|
||||
*/
|
||||
- (void)setSortDescriptors:(CPArray)sortDescriptors
|
||||
{
|
||||
@@ -2883,6 +2942,9 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
[self setIndicatorImage:image inTableColumn:newColumn];
|
||||
|
||||
[self _sendDataSourceSortDescriptorsDidChange:oldSortDescriptors];
|
||||
|
||||
var binderClass = [[self class] _binderClassForBinding:@"sortDescriptors"];
|
||||
[[binderClass getBinding:@"sortDescriptors" forObject:self] reverseSetValueFor:@"sortDescriptors"];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -3126,6 +3188,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
else
|
||||
[dataView unsetThemeState:CPThemeStateSelectedDataView];
|
||||
|
||||
// FIX ME: for performance reasons we might consider diverging from cocoa and moving this to the reloadData method
|
||||
if (_implementedDelegateMethods & CPTableViewDelegate_tableView_isGroupRow_)
|
||||
{
|
||||
if ([_delegate tableView:self isGroupRow:row])
|
||||
@@ -3152,15 +3215,13 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
if (isButton || (_editingCellIndex && _editingCellIndex.x === column && _editingCellIndex.y === row))
|
||||
{
|
||||
if (!isButton)
|
||||
_editingCellIndex = undefined;
|
||||
|
||||
if (isTextField)
|
||||
{
|
||||
[dataView setEditable:YES];
|
||||
[dataView setSendsActionOnEndEditing:YES];
|
||||
[dataView setSelectable:YES];
|
||||
[dataView selectText:nil];
|
||||
[dataView setBezeled:YES];
|
||||
[dataView setDelegate:self];
|
||||
}
|
||||
|
||||
@@ -3218,6 +3279,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
*/
|
||||
- (void)_commitDataViewObjectValue:(id)sender
|
||||
{
|
||||
_editingCellIndex = nil;
|
||||
|
||||
[_dataSource tableView:self setObjectValue:[sender objectValue] forTableColumn:sender.tableViewEditedColumnObj row:sender.tableViewEditedRowIndex];
|
||||
|
||||
if ([sender respondsToSelector:@selector(setEditable:)])
|
||||
@@ -3226,7 +3289,14 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
if ([sender respondsToSelector:@selector(setSelectable:)])
|
||||
[sender setSelectable:NO];
|
||||
|
||||
if ([sender isKindOfClass:[CPTextField class]])
|
||||
[sender setBezeled:NO];
|
||||
|
||||
[self reloadDataForRowIndexes:[CPIndexSet indexSetWithIndex:sender.tableViewEditedRowIndex]
|
||||
columnIndexes:[CPIndexSet indexSetWithIndex:[_tableColumns indexOfObject:sender.tableViewEditedColumnObj]]];
|
||||
|
||||
[[self window] makeFirstResponder:self];
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -3243,6 +3313,11 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
if ([dataView respondsToSelector:@selector(setSelectable:)])
|
||||
[dataView setSelectable:NO];
|
||||
|
||||
if ([dataView isKindOfClass:[CPTextField class]])
|
||||
[dataView setBezeled:NO];
|
||||
|
||||
_editingCellIndex = nil;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -3350,6 +3425,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
/*!
|
||||
Draws the background in a given clip rect.
|
||||
This method should only be overridden if you want something other than a solid color or alternating row colors.
|
||||
NOTE: this method should not be called directly, instead use setNeedsDisplay:
|
||||
*/
|
||||
- (void)drawBackgroundInClipRect:(CGRect)aRect
|
||||
{
|
||||
@@ -3403,6 +3480,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
/*!
|
||||
Draws the grid for the tableview based on the set grid mask in a given clip rect.
|
||||
NOTE: this method should not be called directly, instead use setNeedsDisplay:
|
||||
*/
|
||||
- (void)drawGridInClipRect:(CGRect)aRect
|
||||
{
|
||||
@@ -3478,6 +3556,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
/*!
|
||||
Draws the selection with the set selection highlight style in a given clip rect.
|
||||
You can change the highlight style to a source list style gradient in setSelectionHighlightStyle:
|
||||
NOTE: this method should not be called directly, instead use setNeedsDisplay:
|
||||
*/
|
||||
- (void)highlightSelectionInClipRect:(CGRect)aRect
|
||||
{
|
||||
@@ -3528,7 +3608,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
var normalSelectionHighlightColor = [self selectionHighlightColor];
|
||||
|
||||
// dont do these lookups if there are no group rows
|
||||
// don't do these lookups if there are no group rows
|
||||
if ([_groupRows count])
|
||||
{
|
||||
var topGroupLineColor = [CPColor colorWithCalibratedWhite:212.0 / 255.0 alpha:1.0],
|
||||
@@ -3566,15 +3646,15 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
CGContextClosePath(context);
|
||||
|
||||
CGContextBeginPath(context);
|
||||
CGContextMoveToPoint(context, minX, minY);
|
||||
CGContextAddLineToPoint(context, maxX, minY);
|
||||
CGContextMoveToPoint(context, minX, minY + .5);
|
||||
CGContextAddLineToPoint(context, maxX, minY + .5);
|
||||
CGContextClosePath(context);
|
||||
CGContextSetStrokeColor(context, (shouldUseGroupGradient) ? topGroupLineColor : topLineColor);
|
||||
CGContextStrokePath(context);
|
||||
|
||||
CGContextBeginPath(context);
|
||||
CGContextMoveToPoint(context, minX, maxY);
|
||||
CGContextAddLineToPoint(context, maxX, maxY - 1);
|
||||
CGContextMoveToPoint(context, minX, maxY - .5);
|
||||
CGContextAddLineToPoint(context, maxX, maxY - .5);
|
||||
CGContextClosePath(context);
|
||||
CGContextSetStrokeColor(context, (shouldUseGroupGradient) ? bottomGroupLineColor : bottomLineColor);
|
||||
CGContextStrokePath(context);
|
||||
@@ -3712,7 +3792,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
*/
|
||||
- (void)drawRow:(CPInteger)row clipRect:(CGRect)rect
|
||||
{
|
||||
// This method does currently nothing in cappuccino. Can be overriden by subclasses.
|
||||
// This method does currently nothing in cappuccino. Can be overridden by subclasses.
|
||||
|
||||
}
|
||||
|
||||
@@ -3800,7 +3880,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
{
|
||||
var row = [self rowAtPoint:aPoint];
|
||||
|
||||
//if the user clicks outside a row then deslect everything
|
||||
//if the user clicks outside a row then deselect everything
|
||||
if (row < 0 && _allowsEmptySelection)
|
||||
[self selectRowIndexes:[CPIndexSet indexSet] byExtendingSelection:NO];
|
||||
|
||||
@@ -3890,7 +3970,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
tableColumns = [_tableColumns objectsAtIndexes:_exposedColumns];
|
||||
|
||||
// We deviate from the default Cocoa implementation here by asking for a view in stead of an image
|
||||
// We support both, but the view prefered over the image because we can mimic the rows we are dragging
|
||||
// We support both, but the view preferred over the image because we can mimic the rows we are dragging
|
||||
// by re-creating the data views for the dragged rows
|
||||
var view = [self dragViewForRowsWithIndexes:_draggedRowIndexes
|
||||
tableColumns:tableColumns
|
||||
@@ -4048,6 +4128,9 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
[self _draggingEnded];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)_draggingEnded
|
||||
{
|
||||
_retargetedDropOperation = nil;
|
||||
@@ -4055,6 +4138,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
_draggedRowIndexes = [CPIndexSet indexSet];
|
||||
[_dropOperationFeedbackView removeFromSuperview];
|
||||
}
|
||||
|
||||
/*
|
||||
@ignore
|
||||
*/
|
||||
@@ -4368,7 +4452,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
var character = [anEvent charactersIgnoringModifiers],
|
||||
modifierFlags = [anEvent modifierFlags];
|
||||
|
||||
// Check for the key events manually, as opossed to waiting for CPWindow to sent the actual actio message
|
||||
// Check for the key events manually, as opposed to waiting for CPWindow to sent the actual action message
|
||||
// in _processKeyboardUIKey:, because we might not want to handle the arrow events.
|
||||
if (character === CPUpArrowFunctionKey || character === CPDownArrowFunctionKey)
|
||||
{
|
||||
@@ -4394,7 +4478,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Selection behaviour depends on two things:
|
||||
Selection behavior depends on two things:
|
||||
_lastSelectedRow and the anchored selection (the last row selected by itself)
|
||||
*/
|
||||
- (void)_moveSelectionWithEvent:(CPEvent)theEvent upward:(BOOL)shouldGoUpward
|
||||
|
||||
@@ -486,11 +486,15 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
#if PLATFORM(DOM)
|
||||
|
||||
var string = [self stringValue],
|
||||
element = [self _inputElement];
|
||||
element = [self _inputElement],
|
||||
font = [self currentValueForThemeAttribute:@"font"];
|
||||
|
||||
// generate the font metric
|
||||
[font _getMetrics];
|
||||
|
||||
element.value = string;
|
||||
element.style.color = [[self currentValueForThemeAttribute:@"text-color"] cssString];
|
||||
element.style.font = [[self currentValueForThemeAttribute:@"font"] cssString];
|
||||
element.style.font = [font cssString];
|
||||
element.style.zIndex = 1000;
|
||||
|
||||
switch ([self alignment])
|
||||
@@ -502,12 +506,32 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
default: element.style.textAlign = "left";
|
||||
}
|
||||
|
||||
var contentRect = [self contentRectForBounds:[self bounds]];
|
||||
var contentRect = [self contentRectForBounds:[self bounds]],
|
||||
verticalAlign = [self currentValueForThemeAttribute:"vertical-alignment"];
|
||||
|
||||
element.style.top = _CGRectGetMinY(contentRect) + "px";
|
||||
switch (verticalAlign)
|
||||
{
|
||||
case CPTopVerticalTextAlignment:
|
||||
var topPoint = (_CGRectGetMinY(contentRect) + 1) + "px"; // for the same reason we have a -1 for the left, we also have a + 1 here
|
||||
break;
|
||||
|
||||
case CPCenterVerticalTextAlignment:
|
||||
var topPoint = (_CGRectGetMidY(contentRect) - (font._lineHeight / 2) + 1) + "px";
|
||||
break;
|
||||
|
||||
case CPBottomVerticalTextAlignment:
|
||||
var topPoint = (_CGRectGetMaxY(contentRect) - font._lineHeight) + "px";
|
||||
break;
|
||||
|
||||
default:
|
||||
var topPoint = (_CGRectGetMinY(contentRect) + 1) + "px";
|
||||
break;
|
||||
}
|
||||
|
||||
element.style.top = topPoint;
|
||||
element.style.left = (_CGRectGetMinX(contentRect) - 1) + "px"; // why -1?
|
||||
element.style.width = _CGRectGetWidth(contentRect) + "px";
|
||||
element.style.height = _CGRectGetHeight(contentRect) + "px";
|
||||
element.style.height = font._lineHeight + "px"; // private ivar for the line height of the DOM text at this particular size
|
||||
|
||||
_DOMElement.appendChild(element);
|
||||
|
||||
@@ -561,7 +585,9 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
[self _setStringValue:element.value];
|
||||
|
||||
CPTextFieldInputResigning = YES;
|
||||
element.blur();
|
||||
|
||||
if (CPTextFieldInputIsActive)
|
||||
element.blur();
|
||||
|
||||
if (!CPTextFieldInputDidBlur)
|
||||
CPTextFieldBlurFunction();
|
||||
@@ -679,30 +705,87 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
- (void)keyDown:(CPEvent)anEvent
|
||||
{
|
||||
var characters = [anEvent characters];
|
||||
// Treat \r and \n the same. See issue #710.
|
||||
if (characters === CPNewlineCharacter || characters === CPCarriageReturnCharacter)
|
||||
{
|
||||
// selectText: has a side effect - it can change first responder of the window
|
||||
// we have to prevent such behaviour inside this method because target should be able to change first responder after receiving action.
|
||||
[self selectText:nil];
|
||||
if ([anEvent _couldBeKeyEquivalent] && [self performKeyEquivalent:anEvent])
|
||||
return;
|
||||
|
||||
if (_isEditing)
|
||||
{
|
||||
_isEditing = NO;
|
||||
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:nil]];
|
||||
}
|
||||
// CPTextField uses an HTML input element to take the input so we need to
|
||||
// propagate the dom event so the element is updated. This has to be done
|
||||
// before interpretKeyEvents: though so individual commands have a chance
|
||||
// to override this (escape to clear the text in a search field for example).
|
||||
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
|
||||
|
||||
[self sendAction:[self action] to:[self target]];
|
||||
|
||||
[[[self window] platformWindow] _propagateCurrentDOMEvent:NO];
|
||||
}
|
||||
else
|
||||
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
|
||||
[self interpretKeyEvents:[anEvent]];
|
||||
|
||||
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
||||
}
|
||||
|
||||
/*!
|
||||
Invoke the action specified by aSelector on the current responder.
|
||||
|
||||
This is implemented by CPResponder and by default it passes any unrecognized
|
||||
actions on to the next responder but text fields apparently aren't supposed
|
||||
to do that according to this documentation by Apple:
|
||||
|
||||
http://developer.apple.com/mac/library/documentation/cocoa/reference/NSTextInputClient_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/NSTextInputClient/doCommandBySelector:
|
||||
*/
|
||||
- (void)doCommandBySelector:(SEL)aSelector
|
||||
{
|
||||
if ([self respondsToSelector:aSelector])
|
||||
[self performSelector:aSelector];
|
||||
}
|
||||
|
||||
- (void)insertNewline:(id)sender
|
||||
{
|
||||
if (_isEditing)
|
||||
{
|
||||
_isEditing = NO;
|
||||
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:nil]];
|
||||
}
|
||||
|
||||
[self sendAction:[self action] to:[self target]];
|
||||
[self selectText:nil];
|
||||
|
||||
[[[self window] platformWindow] _propagateCurrentDOMEvent:NO];
|
||||
}
|
||||
|
||||
- (void)insertNewlineIgnoringFieldEditor:(id)sender
|
||||
{
|
||||
var oldValue = [self stringValue];
|
||||
|
||||
[self _inputElement].value += CPNewlineCharacter;
|
||||
[self _setStringValue:[self _inputElement].value];
|
||||
|
||||
if (oldValue !== [self stringValue])
|
||||
{
|
||||
if (!_isEditing)
|
||||
{
|
||||
_isEditing = YES;
|
||||
[self textDidBeginEditing:[CPNotification notificationWithName:CPControlTextDidBeginEditingNotification object:self userInfo:nil]];
|
||||
}
|
||||
|
||||
[self textDidChange:[CPNotification notificationWithName:CPControlTextDidChangeNotification object:self userInfo:nil]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)insertTabIgnoringFieldEditor:(id)sender
|
||||
{
|
||||
var oldValue = [self stringValue];
|
||||
|
||||
[self _inputElement].value += CPTabCharacter;
|
||||
[self _setStringValue:[self _inputElement].value];
|
||||
|
||||
if (oldValue !== [self stringValue])
|
||||
{
|
||||
if (!_isEditing)
|
||||
{
|
||||
_isEditing = YES;
|
||||
[self textDidBeginEditing:[CPNotification notificationWithName:CPControlTextDidBeginEditingNotification object:self userInfo:nil]];
|
||||
}
|
||||
|
||||
[self textDidChange:[CPNotification notificationWithName:CPControlTextDidChangeNotification object:self userInfo:nil]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)textDidBlur:(CPNotification)note
|
||||
{
|
||||
// this looks to prevent false propagation of notifications for other objects
|
||||
@@ -1018,8 +1101,15 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
- (void)deleteBackward:(id)sender
|
||||
{
|
||||
var selectedRange = [self selectedRange],
|
||||
stringValue = [self stringValue],
|
||||
var selectedRange = [self selectedRange];
|
||||
|
||||
if (selectedRange.length < 2)
|
||||
return;
|
||||
|
||||
selectedRange.location += 1;
|
||||
selectedRange.length -= 1;
|
||||
|
||||
var stringValue = [self stringValue],
|
||||
newValue = [stringValue stringByReplacingCharactersInRange:selectedRange withString:""];
|
||||
|
||||
[self setStringValue:newValue];
|
||||
|
||||
@@ -179,7 +179,7 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
token = [self _inputElement].value;
|
||||
|
||||
// Make sure the user typed an actual token to prevent the previous token from being emptied
|
||||
// If the input area is empty, we want to fallback to the normal behaviour, resigning first responder or select the next or previous key view
|
||||
// If the input area is empty, we want to fallback to the normal behavior, resigning first responder or select the next or previous key view
|
||||
if (!token || token === @"")
|
||||
{
|
||||
if (DOMEvent && DOMEvent.keyCode === CPTabKeyCode)
|
||||
@@ -198,7 +198,7 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
var objectValue = [self objectValue];
|
||||
|
||||
// Remove the uncompleted token and add the token string.
|
||||
// Explicitely remove the last object because the array contains strings and removeObject uses isEqual to compare objects
|
||||
// Explicitly remove the last object because the array contains strings and removeObject uses isEqual to compare objects
|
||||
if (shouldRemoveLastObject)
|
||||
[objectValue removeObjectAtIndex:_selectedRange.location];
|
||||
|
||||
@@ -455,7 +455,7 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
- (CPArray)_tokens
|
||||
{
|
||||
// We return super here because objectValue uses this method
|
||||
// If we called self we would loop infinitly
|
||||
// If we called self we would loop infinitely
|
||||
return [super objectValue];
|
||||
}
|
||||
|
||||
@@ -633,7 +633,7 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
|
||||
CPTokenFieldTextDidChangeValue = [CPTokenFieldInputOwner stringValue];
|
||||
|
||||
// Update the selectedIndex if necesary
|
||||
// Update the selectedIndex if necessary
|
||||
var index = [[CPTokenFieldInputOwner autocompleteView] selectedRow];
|
||||
|
||||
if (aDOMEvent.keyCode === CPUpArrowKeyCode)
|
||||
@@ -665,7 +665,7 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
aDOMEvent.stopPropagation();
|
||||
aDOMEvent.cancelBubble = true;
|
||||
|
||||
// Only resign first responder if we weren't autocompleting
|
||||
// Only resign first responder if we weren't auto-completing
|
||||
if (![CPTokenFieldInputOwner hasThemeState:CPThemeStateAutoCompleting])
|
||||
{
|
||||
if (aDOMEvent && aDOMEvent.keyCode === CPReturnKeyCode)
|
||||
@@ -1129,7 +1129,7 @@ var CPThemeStateAutoCompleting = @"CPThemeStateAutoCompleting",
|
||||
return [];
|
||||
}
|
||||
|
||||
// // Alows the delegate to provide a string to be displayed as a proxy for the given represented object.
|
||||
// // Allows the delegate to provide a string to be displayed as a proxy for the given represented object.
|
||||
// // If you return nil or do not implement this method, then representedObject is displayed as the string.
|
||||
- (CPString)tokenField:(CPTokenField)tokenField displayStringForRepresentedObject:(id)representedObject
|
||||
{
|
||||
|
||||
@@ -50,8 +50,8 @@ CPToolbarDisplayModeIconOnly = 2;
|
||||
*/
|
||||
CPToolbarDisplayModeLabelOnly = 3;
|
||||
|
||||
var CPToolbarsByIdentifier = nil;
|
||||
var CPToolbarConfigurationsByIdentifier = nil;
|
||||
var CPToolbarsByIdentifier = nil,
|
||||
CPToolbarConfigurationsByIdentifier = nil;
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@@ -464,7 +464,7 @@ var CPToolbarIdentifierKey = @"CPToolbarIdentifierKey",
|
||||
// Because we don't know if a delegate will be set later (it is optional
|
||||
// as of OS X 10.5), we need to call -_reloadToolbarItems here.
|
||||
// In order to load any toolbar items that may have been configured in the
|
||||
// Cib. Unfortunatelly this means that if there is a delegate
|
||||
// Cib. Unfortunately this means that if there is a delegate
|
||||
// specified, it will be read later and the resulting call to -setDelegate:
|
||||
// will cause -_reloadToolbarItems] to run again :-(
|
||||
// FIXME: Can we make this better?
|
||||
|
||||
@@ -705,7 +705,7 @@ var CPViewFlags = { },
|
||||
Sets the frame size of the receiver to the dimensions and origin of the provided rectangle in the coordinate system
|
||||
of the superview. The method also posts an CPViewFrameDidChangeNotification to the notification
|
||||
center if the receiver is configured to do so. If the frame is the same as the current frame, the method simply
|
||||
returns (and no notificaion is posted).
|
||||
returns (and no notification is posted).
|
||||
@param aFrame the rectangle specifying the new origin and size of the receiver
|
||||
*/
|
||||
- (void)setFrame:(CGRect)aFrame
|
||||
@@ -1735,7 +1735,7 @@ setBoundsOrigin:
|
||||
@param aLocation the lower-left corner coordinate of \c anImage
|
||||
@param mouseOffset the distance from the \c -mouseDown: location and the current location
|
||||
@param anEvent the \c -mouseDown: that triggered the drag
|
||||
@param aPastebaord the pasteboard that holds the drag data
|
||||
@param aPasteboard the pasteboard that holds the drag data
|
||||
@param aSourceObject the drag operation controller
|
||||
@param slideBack Whether the image should 'slide back' if the drag is rejected
|
||||
*/
|
||||
@@ -1750,7 +1750,7 @@ setBoundsOrigin:
|
||||
@param aLocation the top-left corner coordinate of \c aView
|
||||
@param mouseOffset the distance from the \c -mouseDown: location and the current location
|
||||
@param anEvent the \c -mouseDown: that triggered the drag
|
||||
@param aPastebaord the pasteboard that holds the drag data
|
||||
@param aPasteboard the pasteboard that holds the drag data
|
||||
@param aSourceObject the drag operation controller
|
||||
@param slideBack Whether the view should 'slide back' if the drag is rejected
|
||||
*/
|
||||
@@ -2100,7 +2100,7 @@ setBoundsOrigin:
|
||||
|
||||
/*!
|
||||
Scrolls the clip view to a specified point
|
||||
@param the clip view to scoll
|
||||
@param the clip view to scroll
|
||||
@param the point to scroll to
|
||||
*/
|
||||
- (void)scrollClipView:(CPClipView)aClipView toPoint:(CGPoint)aPoint
|
||||
|
||||
@@ -31,11 +31,41 @@ CPViewAnimationEffectKey = @"CPViewAnimationEffectKey";
|
||||
CPViewAnimationFadeInEffect = @"CPViewAnimationFadeInEffect";
|
||||
CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOutEffect";
|
||||
|
||||
/*!
|
||||
@class CPViewAnimation
|
||||
|
||||
CPViewAnimation is a subclass of CPAnimation that makes it easy to do
|
||||
basic animations on views.
|
||||
*/
|
||||
|
||||
@implementation CPViewAnimation : CPAnimation
|
||||
{
|
||||
CPArray _viewAnimations;
|
||||
}
|
||||
|
||||
/*!
|
||||
Designated initializer.
|
||||
|
||||
This method takes an array of CPDictionaries. Each dictionary should
|
||||
contain values for the following keys:
|
||||
|
||||
<pre>
|
||||
CPViewAnimationTargetKey - (Required) The view to animate.
|
||||
CPViewAnimationStartFrameKey - (Optional) The start frame of the target.
|
||||
CPViewAnimationEndFrameKey - (Optional) The end frame of the target.
|
||||
CPViewAnimationEffectKey - (Optional) a fade effect to use for the animation.
|
||||
</pre>
|
||||
|
||||
For example:
|
||||
<pre>
|
||||
var animation = [CPDictionary dictionaryWithObjects:[myViewToAnimate, aStartFrame, anEndFrame, CPViewAnimationFadeInEffect]
|
||||
forKeys:[CPViewAnimationTargetKey, CPViewAnimationStartFrameKey, CPViewAnimationEndFrameKey, CPViewAnimationEffectKey]];
|
||||
</pre>
|
||||
|
||||
If you pass nil instead of an array of dictionaries you should later call setViewAnimations:.
|
||||
|
||||
@param viewAnimations - An array of CPDictionaries for each animation.
|
||||
*/
|
||||
- (id)initWithViewAnimations:(CPArray)viewAnimations
|
||||
{
|
||||
if (self = [super initWithDuration:0.5 animationCurve:CPAnimationLinear])
|
||||
@@ -181,6 +211,11 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOutEffect";
|
||||
return _viewAnimations;
|
||||
}
|
||||
|
||||
/*!
|
||||
Takes an array of CPDictionaries as documented in initWithViewAnimations:.
|
||||
|
||||
@param viewAnimations - An array of dictionaries describing the animation.
|
||||
*/
|
||||
- (void)setViewAnimations:(CPArray)viewAnimations
|
||||
{
|
||||
if (viewAnimations != _viewAnimations)
|
||||
|
||||
@@ -163,7 +163,7 @@ var CPViewControllerCachedCibs;
|
||||
if (_view === nil && [cibOwner isKindOfClass:[CPDocument class]])
|
||||
[self setView:[cibOwner valueForKey:@"view"]];
|
||||
|
||||
if (!_view)
|
||||
if (!_view)
|
||||
{
|
||||
var reason = [CPString stringWithFormat:@"View for %@ could not be loaded from Cib or no view specified. Override loadView to load the view manually.", self];
|
||||
|
||||
@@ -182,13 +182,13 @@ var CPViewControllerCachedCibs;
|
||||
|
||||
|
||||
/*!
|
||||
This method is called after the view controller has loaded its associated views into memory.
|
||||
This method is called regardless of whether the views were stored in a nib file or created programmatically in the loadView method.
|
||||
This method is called after the view controller has loaded its associated views into memory.
|
||||
This method is called regardless of whether the views were stored in a nib file or created programmatically in the loadView method.
|
||||
This method is most commonly used to perform additional initialization steps on views that are loaded from cib files.
|
||||
*/
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -43,6 +43,16 @@ CPWebViewScrollNative = 2;
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
|
||||
@class CPWebView
|
||||
|
||||
CPWebView is a class which allows you to display arbitrary HTML or embed a
|
||||
webpage inside your application.
|
||||
|
||||
It's important to note that the same origin policy applies to this view.
|
||||
That is, if the web page being displayed is not located in the same origin
|
||||
(protocol, domain, and port) as the application, you will have limited
|
||||
control over the view and no access to its contents.
|
||||
*/
|
||||
|
||||
@implementation CPWebView : CPView
|
||||
@@ -236,6 +246,10 @@ CPWebViewScrollNative = 2;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the scroll mode of the receiver. Valid options are
|
||||
CPWebViewScrollAppKit and CPWebViewScrollNative.
|
||||
*/
|
||||
- (void)setScrollMode:(int)aScrollMode
|
||||
{
|
||||
if (_scrollMode == aScrollMode)
|
||||
@@ -277,11 +291,22 @@ CPWebViewScrollNative = 2;
|
||||
parent.appendChild(_iframe);
|
||||
}
|
||||
|
||||
/*!
|
||||
Loads a string of HTML into the webview.
|
||||
|
||||
@param CPString - The string to load.
|
||||
*/
|
||||
- (void)loadHTMLString:(CPString)aString
|
||||
{
|
||||
[self loadHTMLString:aString baseURL:nil];
|
||||
}
|
||||
|
||||
/*!
|
||||
Loads a string of HTML into the webview.
|
||||
|
||||
@param CPString - The string to load.
|
||||
@param CPURL - The base url of the string. (not implemented)
|
||||
*/
|
||||
- (void)loadHTMLString:(CPString)aString baseURL:(CPURL)URL
|
||||
{
|
||||
// FIXME: do something with baseURL?
|
||||
@@ -365,11 +390,21 @@ CPWebViewScrollNative = 2;
|
||||
[_frameLoadDelegate webView:self didFinishLoadForFrame:nil]; // FIXME: give this a frame somehow?
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the URL of the main frame.
|
||||
|
||||
@return CPString - The URL of the main frame.
|
||||
*/
|
||||
- (CPString)mainFrameURL
|
||||
{
|
||||
return _mainFrameURL;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the URL of the main frame.
|
||||
|
||||
@param CPString - the url to set.
|
||||
*/
|
||||
- (void)setMainFrameURL:(CPString)URLString
|
||||
{
|
||||
if (_mainFrameURL)
|
||||
@@ -380,6 +415,11 @@ CPWebViewScrollNative = 2;
|
||||
[self _loadMainFrameURL];
|
||||
}
|
||||
|
||||
/*!
|
||||
Tells the webview to navigate to the previous page.
|
||||
|
||||
@return BOOL - YES if the receiver was able to go back, otherwise NO.
|
||||
*/
|
||||
- (BOOL)goBack
|
||||
{
|
||||
if (_backwardStack.length > 0)
|
||||
@@ -396,6 +436,11 @@ CPWebViewScrollNative = 2;
|
||||
return NO;
|
||||
}
|
||||
|
||||
/*!
|
||||
Tells the receiver to go forward in page history.
|
||||
|
||||
@return - YES if the receiver was able to go forward, otherwise NO.
|
||||
*/
|
||||
- (BOOL)goForward
|
||||
{
|
||||
if (_forwardStack.length > 0)
|
||||
@@ -412,11 +457,23 @@ CPWebViewScrollNative = 2;
|
||||
return NO;
|
||||
}
|
||||
|
||||
/*!
|
||||
Checks to see if the webview has a history stack you can navigate back
|
||||
through.
|
||||
|
||||
@return BOOL - YES if the receiver can navigate backward through history, otherwise NO.
|
||||
*/
|
||||
- (BOOL)canGoBack
|
||||
{
|
||||
return (_backwardStack.length > 0);
|
||||
}
|
||||
|
||||
/*!
|
||||
Checks to see if the webview has a history stack you can navigate forward
|
||||
through.
|
||||
|
||||
@return BOOL - YES if the receiver can navigate forward through history, otherwise NO.
|
||||
*/
|
||||
- (BOOL)canGoForward
|
||||
{
|
||||
return (_forwardStack.length > 0);
|
||||
@@ -428,16 +485,30 @@ CPWebViewScrollNative = 2;
|
||||
return { back: _backwardStack, forward: _forwardStack };
|
||||
}
|
||||
|
||||
/*!
|
||||
Closes the webview by unloading the webpage. The webview will no longer
|
||||
respond to load requests or delegate methods once this is called.
|
||||
*/
|
||||
- (void)close
|
||||
{
|
||||
_iframe.parentNode.removeChild(_iframe);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the window object of the webview.
|
||||
|
||||
@return DOMWindow - The window object.
|
||||
*/
|
||||
- (DOMWindow)DOMWindow
|
||||
{
|
||||
return (_iframe.contentDocument && _iframe.contentDocument.defaultView) || _iframe.contentWindow;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the root Object of the webview as a CPWebScriptObject.
|
||||
|
||||
@return CPWebScriptObject - the Object of the webview.
|
||||
*/
|
||||
- (CPWebScriptObject)windowScriptObject
|
||||
{
|
||||
var win = [self DOMWindow];
|
||||
@@ -451,17 +522,37 @@ CPWebViewScrollNative = 2;
|
||||
return _wso;
|
||||
}
|
||||
|
||||
/*!
|
||||
Evaluates a javascript string in the webview and returns the result of
|
||||
that evaluation as a string.
|
||||
|
||||
@param script - A string of javascript.
|
||||
@return CPString - The result of the evaluation.
|
||||
*/
|
||||
- (CPString)stringByEvaluatingJavaScriptFromString:(CPString)script
|
||||
{
|
||||
var result = [self objectByEvaluatingJavaScriptFromString:script];
|
||||
return result ? String(result) : nil;
|
||||
}
|
||||
|
||||
/*!
|
||||
Evaluates a string of javascript in the webview and returns the result.
|
||||
|
||||
@param script - A string of javascript.
|
||||
@return JSObject - A JSObject resulting from the evaluation.
|
||||
*/
|
||||
- (JSObject)objectByEvaluatingJavaScriptFromString:(CPString)script
|
||||
{
|
||||
return [[self windowScriptObject] evaluateWebScript:script];
|
||||
}
|
||||
|
||||
/*!
|
||||
Gets the computed style for an element.
|
||||
|
||||
@param DOMElement - An Element.
|
||||
@param pseudoElement - A pseudoElement.
|
||||
@return DOMCSSStyleDeclaration - The computed style for an element.
|
||||
*/
|
||||
- (DOMCSSStyleDeclaration)computedStyleForElement:(DOMElement)element pseudoElement:(CPString)pseudoElement
|
||||
{
|
||||
var win = [[self windowScriptObject] window];
|
||||
@@ -474,47 +565,85 @@ CPWebViewScrollNative = 2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
@return BOOL - YES if the webview draws its own background, otherwise NO.
|
||||
*/
|
||||
- (BOOL)drawsBackground
|
||||
{
|
||||
return _iframe.style.backgroundColor != "";
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets whether the webview draws its own background.
|
||||
|
||||
@param BOOL - YES if the webview should draw its background, otherwise NO.
|
||||
*/
|
||||
- (void)setDrawsBackground:(BOOL)drawsBackround
|
||||
{
|
||||
_iframe.style.backgroundColor = drawsBackround ? "white" : "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
// IBActions
|
||||
|
||||
- (IBAction)takeStringURLFrom:(id)sender
|
||||
/*!
|
||||
Used with the target/action mechanism to automatically set the webviews
|
||||
mainFrameURL to the senders stringValue.
|
||||
|
||||
@param sender - the sender of the action. Should respond to -stringValue.
|
||||
*/
|
||||
- (@action)takeStringURLFrom:(id)sender
|
||||
{
|
||||
[self setMainFrameURL:[sender stringValue]];
|
||||
}
|
||||
|
||||
- (IBAction)goBack:(id)sender
|
||||
/*!
|
||||
Same as -goBack but takes a sender as a param.
|
||||
|
||||
@param sender - the sender of the action.
|
||||
*/
|
||||
- (@action)goBack:(id)sender
|
||||
{
|
||||
[self goBack];
|
||||
}
|
||||
|
||||
- (IBAction)goForward:(id)sender
|
||||
/*!
|
||||
Same as -goForward but takes a sender as a param.
|
||||
|
||||
@param sender - the sender of the action.
|
||||
*/
|
||||
- (@action)goForward:(id)sender
|
||||
{
|
||||
[self goForward];
|
||||
}
|
||||
|
||||
- (IBAction)stopLoading:(id)sender
|
||||
/*!
|
||||
Stops loading the webview. (not yet implemented)
|
||||
|
||||
@param sender - the sender of the action.
|
||||
*/
|
||||
- (@action)stopLoading:(id)sender
|
||||
{
|
||||
// FIXME: what to do?
|
||||
}
|
||||
|
||||
- (IBAction)reload:(id)sender
|
||||
/*!
|
||||
Reloads the webview.
|
||||
|
||||
@param sender - the sender of the action.
|
||||
*/
|
||||
- (@action)reload:(id)sender
|
||||
{
|
||||
[self _loadMainFrameURL];
|
||||
}
|
||||
|
||||
- (IBAction)print:(id)sender
|
||||
/*!
|
||||
Tells the webview to print. If the webview is unable to print due to
|
||||
browser restrictions the user is alerted to print from the file menu.
|
||||
|
||||
@param sender - the sender of the receiver.
|
||||
*/
|
||||
- (@action)print:(id)sender
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -574,12 +703,19 @@ CPWebViewScrollNative = 2;
|
||||
|
||||
@end
|
||||
|
||||
/*!
|
||||
@class CPWebScriptObject
|
||||
|
||||
A CPWebScriptObject is an Objective-J wrapper around a scripting object.
|
||||
*/
|
||||
@implementation CPWebScriptObject : CPObject
|
||||
{
|
||||
Window _window;
|
||||
}
|
||||
|
||||
/*!
|
||||
Initializes the scripting object with the scripting Window object.
|
||||
*/
|
||||
- (id)initWithWindow:(Window)aWindow
|
||||
{
|
||||
if (self = [super init])
|
||||
@@ -589,6 +725,12 @@ CPWebViewScrollNative = 2;
|
||||
return self;
|
||||
}
|
||||
|
||||
/*!
|
||||
Call a method with arguments on the receiver.
|
||||
|
||||
@param methodName - The method that should be called.
|
||||
@param args - An array of arguments to pass to the method call.
|
||||
*/
|
||||
- (id)callWebScriptMethod:(CPString)methodName withArguments:(CPArray)args
|
||||
{
|
||||
// Would using "with" be better here?
|
||||
@@ -602,15 +744,25 @@ CPWebViewScrollNative = 2;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/*!
|
||||
Evaluates a string of javascript and returns the result.
|
||||
|
||||
@param script - The script to run.
|
||||
@return - The result of the evaluation, which may be 'undefined'.
|
||||
*/
|
||||
- (id)evaluateWebScript:(CPString)script
|
||||
{
|
||||
try {
|
||||
return _window.eval(script);
|
||||
} catch (e) {
|
||||
// FIX ME: if we fail inside here, shouldn't we return an exception?
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the receivers Window object.
|
||||
*/
|
||||
- (Window)window
|
||||
{
|
||||
return _window;
|
||||
@@ -623,6 +775,7 @@ CPWebViewScrollNative = 2;
|
||||
|
||||
/*!
|
||||
Initializes the web view from the data in a coder.
|
||||
|
||||
@param aCoder the coder from which to read the data
|
||||
@return the initialized web view
|
||||
*/
|
||||
@@ -650,6 +803,7 @@ CPWebViewScrollNative = 2;
|
||||
|
||||
/*!
|
||||
Writes out the web view's instance information to a coder.
|
||||
|
||||
@param aCoder the coder to which to write the data
|
||||
*/
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
|
||||
@@ -539,6 +539,12 @@ CPTexturedBackgroundWindowMask
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the receiver as a full platform window. If you pass YES the CPWindow instance will fill the entire browser content area,
|
||||
otherwise the CPWindow will be a window inside of your browser window which the user can drag around, and resize (if you allow).
|
||||
|
||||
@param BOOL - YES if the window should fill the browser window, otherwise NO.
|
||||
*/
|
||||
- (void)setFullPlatformWindow:(BOOL)shouldBeFullPlatformWindow
|
||||
{
|
||||
if (![_platformWindow supportsFullPlatformWindows])
|
||||
@@ -579,6 +585,9 @@ CPTexturedBackgroundWindowMask
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@return BOOL - YES if the CPWindow fills the browser window, otherwise NO.
|
||||
*/
|
||||
- (BOOL)isFullPlatformWindow
|
||||
{
|
||||
return _isFullPlatformWindow;
|
||||
@@ -594,6 +603,18 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
/*!
|
||||
Returns the frame rectangle used by a window.
|
||||
Style masks include:
|
||||
<pre>
|
||||
CPBorderlessWindowMask
|
||||
CPTitledWindowMask
|
||||
CPClosableWindowMask
|
||||
CPMiniaturizableWindowMask (NOTE: only available in NativeHost)
|
||||
CPResizableWindowMask
|
||||
CPTexturedBackgroundWindowMask
|
||||
CPBorderlessBridgeWindowMask
|
||||
CPHUDBackgroundWindowMask
|
||||
</pre>
|
||||
|
||||
@param aContentRect the content rectangle of the window
|
||||
@param aStyleMask the style mask of the window
|
||||
@return the matching window's frame rectangle
|
||||
@@ -635,7 +656,7 @@ CPTexturedBackgroundWindowMask
|
||||
the resize operation, and redraw itself if necessary.
|
||||
@param aFrame the new size and location for the window
|
||||
@param shouldDisplay whether the window should redraw its views
|
||||
@param shouldAnimate whether the window resize should be animated
|
||||
@param shouldAnimate whether the window resize should be animated.
|
||||
*/
|
||||
- (void)_setClippedFrame:(CGRect)aFrame display:(BOOL)shouldDisplay animate:(BOOL)shouldAnimate
|
||||
{
|
||||
@@ -644,6 +665,13 @@ CPTexturedBackgroundWindowMask
|
||||
[self setFrame:aFrame display:shouldDisplay animate:shouldAnimate];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the frame of the window.
|
||||
|
||||
@param aFrame - A CGRect of the new frame for the receiver.
|
||||
@param shouldDisplay - YES if the window should call setNeedsDisplay otherwise NO.
|
||||
@param shouldAnimate - YES if the window should animate to it's new size and position, otherwise NO.
|
||||
*/
|
||||
- (void)setFrame:(CGRect)aFrame display:(BOOL)shouldDisplay animate:(BOOL)shouldAnimate
|
||||
{
|
||||
aFrame = _CGRectMakeCopy(aFrame);
|
||||
@@ -721,6 +749,11 @@ CPTexturedBackgroundWindowMask
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the window's frame rect.
|
||||
@param aFrame - The new CGRect of the window.
|
||||
@param shouldDisplay - YES if the window should call setNeedsDisplay: otherwise NO.
|
||||
*/
|
||||
- (void)setFrame:(CGRect)aFrame display:(BOOL)shouldDisplay
|
||||
{
|
||||
[self _setClippedFrame:aFrame display:shouldDisplay animate:NO];
|
||||
@@ -728,6 +761,7 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
/*!
|
||||
Sets the window's frame rectangle
|
||||
@param aFrame - The CGRect of the windows new frame
|
||||
*/
|
||||
- (void)setFrame:(CGRect)aFrame
|
||||
{
|
||||
@@ -1111,6 +1145,17 @@ CPTexturedBackgroundWindowMask
|
||||
[self _updateShadow];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the shadow style of the receiver.
|
||||
Values are:
|
||||
<pre>
|
||||
CPWindowShadowStyleStandard
|
||||
CPWindowShadowStyleMenu
|
||||
CPWindowShadowStylePanel
|
||||
</pre>
|
||||
|
||||
@param aStyle - The new shadow style of the receiver.
|
||||
*/
|
||||
- (void)setShadowStyle:(unsigned)aStyle
|
||||
{
|
||||
_shadowStyle = aStyle;
|
||||
@@ -1631,7 +1676,7 @@ CPTexturedBackgroundWindowMask
|
||||
@param aLocation the lower-left corner coordinate of \c anImage
|
||||
@param mouseOffset the distance from the \c -mouseDown: location and the current location
|
||||
@param anEvent the \c -mouseDown: that triggered the drag
|
||||
@param aPastebaord the pasteboard that holds the drag data
|
||||
@param aPasteboard the pasteboard that holds the drag data
|
||||
@param aSourceObject the drag operation controller
|
||||
@param slideBack Whether the image should 'slide back' if the drag is rejected
|
||||
*/
|
||||
@@ -1668,7 +1713,7 @@ CPTexturedBackgroundWindowMask
|
||||
@param aLocation the lower-left corner coordinate of \c aView
|
||||
@param mouseOffset the distance from the \c -mouseDown: location and the current location
|
||||
@param anEvent the \c -mouseDown: that triggered the drag
|
||||
@param aPastebaord the pasteboard that holds the drag data
|
||||
@param aPasteboard the pasteboard that holds the drag data
|
||||
@param aSourceObject the drag operation controller
|
||||
@param slideBack Whether the view should 'slide back' if the drag is rejected
|
||||
*/
|
||||
@@ -1819,7 +1864,7 @@ CPTexturedBackgroundWindowMask
|
||||
}
|
||||
|
||||
/*!
|
||||
Restores a mimized window to it's original size.
|
||||
Restores a minimized window to it's original size.
|
||||
*/
|
||||
- (void)deminiaturize:(id)sender
|
||||
{
|
||||
@@ -2448,16 +2493,31 @@ CPTexturedBackgroundWindowMask
|
||||
[self makeFirstResponder:[aView previousValidKeyView]];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the default button for the window.
|
||||
Note: this method is deprecated use setDefaultButton: instead.
|
||||
@param aButton - The button that should become default.
|
||||
*/
|
||||
- (void)setDefaultButtonCell:(CPButton)aButton
|
||||
{
|
||||
[self setDefaultButton:aButton];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the default button of the receiver.
|
||||
NOTE: This method is deprecated. Use defaultButton instead.
|
||||
*/
|
||||
- (CPButton)defaultButtonCell
|
||||
{
|
||||
return [self defaultButton];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the default button for the window.
|
||||
This is equivalent to setting the the key equivalent of the button to "return".
|
||||
Additionally this will turn your button blue (with the Aristo theme).
|
||||
@param aButton - The button that should become default.
|
||||
*/
|
||||
- (void)setDefaultButton:(CPButton)aButton
|
||||
{
|
||||
if (_defaultButton === aButton)
|
||||
@@ -2472,26 +2532,43 @@ CPTexturedBackgroundWindowMask
|
||||
[_defaultButton setKeyEquivalent:CPCarriageReturnCharacter];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the default button of the receiver.
|
||||
*/
|
||||
- (CPButton)defaultButton
|
||||
{
|
||||
return _defaultButton;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the default button key equivalent to "return".
|
||||
*/
|
||||
- (void)enableKeyEquivalentForDefaultButton
|
||||
{
|
||||
_defaultButtonEnabled = YES;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the default button key equivalent to "return".
|
||||
NOTE: this method is deprecated. Use enableKeyEquivalentForDefaultButton instead.
|
||||
*/
|
||||
- (void)enableKeyEquivalentForDefaultButtonCell
|
||||
{
|
||||
[self enableKeyEquivalentForDefaultButton];
|
||||
}
|
||||
|
||||
/*!
|
||||
Removes the key equivalent for the default button.
|
||||
*/
|
||||
- (void)disableKeyEquivalentForDefaultButton
|
||||
{
|
||||
_defaultButtonEnabled = NO;
|
||||
}
|
||||
|
||||
/*!
|
||||
Removes the key equivalent for the default button.
|
||||
Note: this method is deprecated. Use disableKeyEquivalentForDefaultButton instead.
|
||||
*/
|
||||
- (void)disableKeyEquivalentForDefaultButtonCell
|
||||
{
|
||||
[self disableKeyEquivalentForDefaultButton];
|
||||
@@ -2603,16 +2680,25 @@ var keyViewComparator = function(lhs, rhs, context)
|
||||
return _autoresizingMask;
|
||||
}
|
||||
|
||||
/*!
|
||||
Converts aPoint from the window coordinate system to the global coordinate system.
|
||||
*/
|
||||
- (CGPoint)convertBaseToGlobal:(CGPoint)aPoint
|
||||
{
|
||||
return [CPPlatform isBrowser] ? [self convertBaseToPlatformWindow:aPoint] : [self convertBaseToScreen:aPoint];
|
||||
}
|
||||
|
||||
/*!
|
||||
Converts aPoint from the global coordinate system to the window coordinate system.
|
||||
*/
|
||||
- (CGPoint)convertGlobalToBase:(CGPoint)aPoint
|
||||
{
|
||||
return [CPPlatform isBrowser] ? [self convertPlatformWindowToBase:aPoint] : [self convertScreenToBase:aPoint];
|
||||
}
|
||||
|
||||
/*!
|
||||
Converts aPoint from the window coordinate system to the coordinate system of the parent platform window.
|
||||
*/
|
||||
- (CGPoint)convertBaseToPlatformWindow:(CGPoint)aPoint
|
||||
{
|
||||
if ([self _sharesChromeWithPlatformWindow])
|
||||
@@ -2623,6 +2709,9 @@ var keyViewComparator = function(lhs, rhs, context)
|
||||
return _CGPointMake(aPoint.x + origin.x, aPoint.y + origin.y);
|
||||
}
|
||||
|
||||
/*!
|
||||
Converts aPoint from the parent platform window coordinate system to the windows coordinate system.
|
||||
*/
|
||||
- (CGPoint)convertPlatformWindowToBase:(CGPoint)aPoint
|
||||
{
|
||||
if ([self _sharesChromeWithPlatformWindow])
|
||||
@@ -2712,12 +2801,19 @@ var keyViewComparator = function(lhs, rhs, context)
|
||||
@end
|
||||
|
||||
@implementation CPWindow (Deprecated)
|
||||
|
||||
/*!
|
||||
Sets the CPWindow to fill the whole browser window.
|
||||
NOTE: this method has been deprecated in favor of setFullPlatformWindow:
|
||||
*/
|
||||
- (void)setFullBridge:(BOOL)shouldBeFullBridge
|
||||
{
|
||||
[self setFullPlatformWindow:shouldBeFullBridge];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns YES if the window fills the full browser window, otherwise NO.
|
||||
NOTE: this method has been deprecated in favor of isFullPlatformWindow.
|
||||
*/
|
||||
- (BOOL)isFullBridge
|
||||
{
|
||||
return [self isFullPlatformWindow];
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
/*!
|
||||
Initializes the controller with a window.
|
||||
@param aWindow the window to control
|
||||
@return the initialzed window controller
|
||||
@return the initialized window controller
|
||||
*/
|
||||
- (id)initWithWindow:(CPWindow)aWindow
|
||||
{
|
||||
@@ -82,7 +82,7 @@
|
||||
}
|
||||
|
||||
/*!
|
||||
Initializes the controller with a Capppuccino Interface Builder name.
|
||||
Initializes the controller with a Cappuccino Interface Builder name.
|
||||
@param aWindowCibName the cib name of the window to control
|
||||
@return the initialized window controller
|
||||
*/
|
||||
|
||||
@@ -84,7 +84,7 @@ var _CPCibCustomViewClassNameKey = @"_CPCibCustomViewClassNameKey";
|
||||
{
|
||||
#if DEBUG
|
||||
CPLog("Unknown class \"" + _className + "\" in cib file, using CPView instead.");
|
||||
#endif
|
||||
#endif
|
||||
theClass = [CPView class];
|
||||
}
|
||||
|
||||
@@ -97,16 +97,16 @@ var _CPCibCustomViewClassNameKey = @"_CPCibCustomViewClassNameKey";
|
||||
}
|
||||
|
||||
var view = [[theClass alloc] initWithFrame:[self frame]];
|
||||
|
||||
|
||||
if (view)
|
||||
{
|
||||
[view setBounds:[self bounds]];
|
||||
|
||||
|
||||
// Since the object replacement logic hasn't had a chance to kick in yet, we need to do it manually:
|
||||
var subviews = [self subviews],
|
||||
index = 0,
|
||||
count = subviews.length;
|
||||
|
||||
|
||||
for (; index < count; ++index)
|
||||
[view addSubview:subviews[index]];
|
||||
|
||||
@@ -116,7 +116,7 @@ var _CPCibCustomViewClassNameKey = @"_CPCibCustomViewClassNameKey";
|
||||
[view setHitTests:[self hitTests]];
|
||||
[view setHidden:[self isHidden]];
|
||||
[view setAlphaValue:[self alphaValue]];
|
||||
|
||||
|
||||
[_superview replaceSubview:self with:view];
|
||||
|
||||
[view setBackgroundColor:[self backgroundColor]];
|
||||
|
||||
@@ -12,15 +12,15 @@
|
||||
- (id)initForReadingWithData:(CPData)data bundle:(CPBundle)aBundle awakenCustomResources:(BOOL)shouldAwakenCustomResources
|
||||
{
|
||||
self = [super initForReadingWithData:data];
|
||||
|
||||
|
||||
if (self)
|
||||
{
|
||||
_bundle = aBundle;
|
||||
_awakenCustomResources = shouldAwakenCustomResources;
|
||||
|
||||
|
||||
[self setDelegate:self];
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,19 +5,19 @@
|
||||
@import "CPWindow.j"
|
||||
|
||||
|
||||
var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemplateMinSizeKey",
|
||||
_CPCibWindowTemplateMaxSizeKey = @"_CPCibWindowTemplateMaxSizeKey",
|
||||
|
||||
_CPCibWindowTemplateViewClassKey = @"_CPCibWindowTemplateViewClassKey",
|
||||
_CPCibWindowTemplateWindowClassKey = @"_CPCibWindowTemplateWindowClassKey",
|
||||
|
||||
_CPCibWindowTemplateWindowRectKey = @"_CPCibWindowTemplateWindowRectKey",
|
||||
_CPCibWindowTemplateWindowStyleMaskKey = @"_CPCibWindowTempatStyleMaskKey",
|
||||
_CPCibWindowTemplateWindowTitleKey = @"_CPCibWindowTemplateWindowTitleKey",
|
||||
_CPCibWindowTemplateWindowViewKey = @"_CPCibWindowTemplateWindowViewKey",
|
||||
var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemplateMinSizeKey",
|
||||
_CPCibWindowTemplateMaxSizeKey = @"_CPCibWindowTemplateMaxSizeKey",
|
||||
|
||||
_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop = @"_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop";
|
||||
_CPCibWindowTemplateWindowIsFullPlatformWindowKey = @"_CPCibWindowTemplateWindowIsFullPlatformWindowKey";
|
||||
_CPCibWindowTemplateViewClassKey = @"_CPCibWindowTemplateViewClassKey",
|
||||
_CPCibWindowTemplateWindowClassKey = @"_CPCibWindowTemplateWindowClassKey",
|
||||
|
||||
_CPCibWindowTemplateWindowRectKey = @"_CPCibWindowTemplateWindowRectKey",
|
||||
_CPCibWindowTemplateWindowStyleMaskKey = @"_CPCibWindowTempatStyleMaskKey",
|
||||
_CPCibWindowTemplateWindowTitleKey = @"_CPCibWindowTemplateWindowTitleKey",
|
||||
_CPCibWindowTemplateWindowViewKey = @"_CPCibWindowTemplateWindowViewKey",
|
||||
|
||||
_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop = @"_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop",
|
||||
_CPCibWindowTemplateWindowIsFullPlatformWindowKey = @"_CPCibWindowTemplateWindowIsFullPlatformWindowKey";
|
||||
|
||||
@implementation _CPCibWindowTemplate : CPObject
|
||||
{
|
||||
@@ -60,27 +60,27 @@ var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemplateMinS
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
|
||||
if (self)
|
||||
{
|
||||
if ([aCoder containsValueForKey:_CPCibWindowTemplateMinSizeKey])
|
||||
_minSize = [aCoder decodeSizeForKey:_CPCibWindowTemplateMinSizeKey];
|
||||
if ([aCoder containsValueForKey:_CPCibWindowTemplateMaxSizeKey])
|
||||
_maxSize = [aCoder decodeSizeForKey:_CPCibWindowTemplateMaxSizeKey];
|
||||
|
||||
|
||||
_viewClass = [aCoder decodeObjectForKey:_CPCibWindowTemplateViewClassKey];
|
||||
|
||||
|
||||
_windowClass = [aCoder decodeObjectForKey:_CPCibWindowTemplateWindowClassKey];
|
||||
_windowRect = [aCoder decodeRectForKey:_CPCibWindowTemplateWindowRectKey];
|
||||
_windowStyleMask = [aCoder decodeIntForKey:_CPCibWindowTemplateWindowStyleMaskKey];
|
||||
|
||||
|
||||
_windowTitle = [aCoder decodeObjectForKey:_CPCibWindowTemplateWindowTitleKey];
|
||||
_windowView = [aCoder decodeObjectForKey:_CPCibWindowTemplateWindowViewKey];
|
||||
|
||||
_windowAutorecalculatesKeyViewLoop = !![aCoder decodeObjectForKey:_CPCibWindowTemplateWindowAutorecalculatesKeyViewLoop];
|
||||
_windowIsFullPlatformWindow = !![aCoder decodeObjectForKey:_CPCibWindowTemplateWindowIsFullPlatformWindowKey];
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -90,13 +90,13 @@ var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemplateMinS
|
||||
[aCoder encodeSize:_minSize forKey:_CPCibWindowTemplateMinSizeKey];
|
||||
if (_maxSize)
|
||||
[aCoder encodeSize:_maxSize forKey:_CPCibWindowTemplateMaxSizeKey];
|
||||
|
||||
|
||||
[aCoder encodeObject:_viewClass forKey:_CPCibWindowTemplateViewClassKey];
|
||||
|
||||
|
||||
[aCoder encodeObject:_windowClass forKey:_CPCibWindowTemplateWindowClassKey];
|
||||
[aCoder encodeRect:_windowRect forKey:_CPCibWindowTemplateWindowRectKey];
|
||||
[aCoder encodeInt:_windowStyleMask forKey:_CPCibWindowTemplateWindowStyleMaskKey];
|
||||
|
||||
|
||||
[aCoder encodeObject:_windowTitle forKey:_CPCibWindowTemplateWindowTitleKey];
|
||||
[aCoder encodeObject:_windowView forKey:_CPCibWindowTemplateWindowViewKey];
|
||||
|
||||
@@ -126,13 +126,13 @@ var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemplateMinS
|
||||
- (id)_cibInstantiate
|
||||
{
|
||||
var windowClass = CPClassFromString([self windowClass]);
|
||||
|
||||
|
||||
/* if (!windowClass)
|
||||
[NSException raise:NSInvalidArgumentException format:@"Unable to locate NSWindow class %@, using NSWindow",_windowClass];
|
||||
class=[NSWindow class];*/
|
||||
|
||||
|
||||
var theWindow = [[windowClass alloc] initWithContentRect:_windowRect styleMask:_windowStyleMask];
|
||||
|
||||
|
||||
if (_minSize)
|
||||
[theWindow setMinSize:_minSize];
|
||||
if (_maxSize)
|
||||
@@ -147,7 +147,7 @@ var _CPCibWindowTemplateMinSizeKey = @"_CPCibWindowTemplateMinS
|
||||
[theWindow setContentView:_windowView];
|
||||
|
||||
[_windowView setAutoresizesSubviews:YES];
|
||||
|
||||
|
||||
if ([_viewClass isKindOfClass:[CPToolbar class]])
|
||||
{
|
||||
[theWindow setToolbar:_viewClass];
|
||||
|
||||
@@ -64,54 +64,54 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
@implementation CALayer : CPObject
|
||||
{
|
||||
// Modifying the Layer Geometry
|
||||
|
||||
|
||||
CGRect _frame;
|
||||
CGRect _bounds;
|
||||
CGPoint _position;
|
||||
unsigned _zPosition;
|
||||
CGPoint _anchorPoint;
|
||||
|
||||
|
||||
CGAffineTransform _affineTransform;
|
||||
CGAffineTransform _sublayerTransform;
|
||||
CGAffineTransform _sublayerTransformForSublayers;
|
||||
|
||||
|
||||
CGRect _backingStoreFrame;
|
||||
CGRect _standardBackingStoreFrame;
|
||||
|
||||
|
||||
BOOL _hasSublayerTransform;
|
||||
BOOL _hasCustomBackingStoreFrame;
|
||||
|
||||
|
||||
// Style Attributes
|
||||
|
||||
|
||||
float _opacity;
|
||||
BOOL _isHidden;
|
||||
CPColor _backgroundColor;
|
||||
|
||||
|
||||
// Managing Layer Hierarchy
|
||||
|
||||
|
||||
CALayer _superlayer;
|
||||
CPMutableArray _sublayers;
|
||||
|
||||
// Updating Layer Display
|
||||
|
||||
|
||||
unsigned _runLoopUpdateMask;
|
||||
BOOL _needsDisplayOnBoundsChange;
|
||||
|
||||
// Modifying the Delegate
|
||||
|
||||
|
||||
id _delegate;
|
||||
|
||||
|
||||
BOOL _delegateRespondsToDisplayLayerSelector;
|
||||
BOOL _delegateRespondsToDrawLayerInContextSelector;
|
||||
|
||||
|
||||
// DOM Implementation
|
||||
|
||||
|
||||
DOMElement _DOMElement;
|
||||
DOMElement _DOMContentsElement;
|
||||
id _contents;
|
||||
CGContext _context;
|
||||
CPView _owningView;
|
||||
|
||||
|
||||
CGAffineTransform _transformToLayer;
|
||||
CGAffineTransform _transformFromLayer;
|
||||
}
|
||||
@@ -130,14 +130,14 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
|
||||
if (self)
|
||||
{
|
||||
_frame = CGRectMakeZero();
|
||||
|
||||
|
||||
_backingStoreFrame = CGRectMakeZero();
|
||||
_standardBackingStoreFrame = CGRectMakeZero();
|
||||
|
||||
|
||||
_bounds = CGRectMakeZero();
|
||||
_position = CGPointMakeZero();
|
||||
_zPosition = 0.0;
|
||||
@@ -147,15 +147,15 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
|
||||
_transformToLayer = CGAffineTransformMakeIdentity(); // FIXME? does it matter?
|
||||
_transformFromLayer = CGAffineTransformMakeIdentity();
|
||||
|
||||
|
||||
_opacity = 1.0;
|
||||
_isHidden = NO;
|
||||
_masksToBounds = NO;
|
||||
|
||||
|
||||
_sublayers = [];
|
||||
|
||||
|
||||
_DOMElement = document.createElement("div");
|
||||
|
||||
|
||||
_DOMElement.style.overflow = "visible";
|
||||
_DOMElement.style.position = "absolute";
|
||||
_DOMElement.style.visibility = "visible";
|
||||
@@ -165,7 +165,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
_DOMElement.style.width = "0px";
|
||||
_DOMElement.style.height = "0px";
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -182,20 +182,20 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
var oldOrigin = _bounds.origin;
|
||||
|
||||
_bounds = _CGRectMakeCopy(aBounds);
|
||||
|
||||
|
||||
if (_hasSublayerTransform)
|
||||
_CALayerUpdateSublayerTransformForSublayers(self);
|
||||
|
||||
|
||||
// _hasSublayerTransform == true will handle this for us.
|
||||
/*else if (!CGPointEqualToPoint(_bounds.origin, oldOrigin))
|
||||
{
|
||||
var index = _sublayers.length;
|
||||
|
||||
|
||||
// FIXME: This should climb the layer tree down.
|
||||
while (index--)
|
||||
_CALayerRecalculateGeometry(_sublayers[index], CALayerGeometryPositionMask);
|
||||
}*/
|
||||
|
||||
|
||||
_CALayerRecalculateGeometry(self, CALayerGeometryBoundsMask);
|
||||
}
|
||||
|
||||
@@ -215,9 +215,9 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
{
|
||||
if (CGPointEqualToPoint(_position, aPosition))
|
||||
return;
|
||||
|
||||
|
||||
_position = _CGPointMakeCopy(aPosition);
|
||||
|
||||
|
||||
_CALayerRecalculateGeometry(self, CALayerGeometryPositionMask);
|
||||
}
|
||||
|
||||
@@ -237,9 +237,9 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
{
|
||||
if (_zPosition == aZPosition)
|
||||
return;
|
||||
|
||||
|
||||
_zPosition = aZPosition;
|
||||
|
||||
|
||||
[self registerRunLoopUpdateWithMask:CALayerZPositionUpdateMask];
|
||||
}
|
||||
|
||||
@@ -252,18 +252,18 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
anAnchorPoint = _CGPointMakeCopy(anAnchorPoint);
|
||||
anAnchorPoint.x = MIN(1.0, MAX(0.0, anAnchorPoint.x));
|
||||
anAnchorPoint.y = MIN(1.0, MAX(0.0, anAnchorPoint.y));
|
||||
|
||||
|
||||
if (CGPointEqualToPoint(_anchorPoint, anAnchorPoint))
|
||||
return;
|
||||
|
||||
|
||||
_anchorPoint = anAnchorPoint;
|
||||
|
||||
|
||||
if (_hasSublayerTransform)
|
||||
_CALayerUpdateSublayerTransformForSublayers(self);
|
||||
|
||||
if (_owningView)
|
||||
_position = CGPointMake(_CGRectGetWidth(_bounds) * _anchorPoint.x, _CGRectGetHeight(_bounds) * _anchorPoint.y);
|
||||
|
||||
|
||||
_CALayerRecalculateGeometry(self, CALayerGeometryAnchorPointMask);
|
||||
}
|
||||
|
||||
@@ -283,9 +283,9 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
{
|
||||
if (CGAffineTransformEqualToTransform(_affineTransform, anAffineTransform))
|
||||
return;
|
||||
|
||||
|
||||
_affineTransform = _CGAffineTransformMakeCopy(anAffineTransform);
|
||||
|
||||
|
||||
_CALayerRecalculateGeometry(self, CALayerGeometryAffineTransformMask);
|
||||
}
|
||||
|
||||
@@ -307,16 +307,16 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
return;
|
||||
|
||||
var hadSublayerTransform = _hasSublayerTransform;
|
||||
|
||||
|
||||
_sublayerTransform = _CGAffineTransformMakeCopy(anAffineTransform);
|
||||
_hasSublayerTransform = !_CGAffineTransformIsIdentity(_sublayerTransform);
|
||||
|
||||
|
||||
if (_hasSublayerTransform)
|
||||
{
|
||||
_CALayerUpdateSublayerTransformForSublayers(self);
|
||||
|
||||
var index = _sublayers.length;
|
||||
|
||||
|
||||
// FIXME: This should climb the layer tree down.
|
||||
while (index--)
|
||||
_CALayerRecalculateGeometry(_sublayers[index], CALayerGeometryParentSublayerTransformMask);
|
||||
@@ -353,23 +353,23 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
/*!
|
||||
Returns the layer's frame.
|
||||
|
||||
The frame defines the bounding box of the layer: the smallest
|
||||
possible rectangle that could fit this layer after transform
|
||||
The frame defines the bounding box of the layer: the smallest
|
||||
possible rectangle that could fit this layer after transform
|
||||
properties are applied in superlayer coordinates.
|
||||
*/
|
||||
- (CGRect)frame
|
||||
{
|
||||
if (!_frame)
|
||||
_frame = [self convertRect:_bounds toLayer:_superlayer];
|
||||
|
||||
|
||||
return _frame;
|
||||
}
|
||||
|
||||
/*!
|
||||
The Backing Store Frame specifies the frame of the actual backing
|
||||
store used to contain this layer. Naturally, by default it is the
|
||||
same as the frame, however, users can specify their own custom
|
||||
Backing Store Frame in order to speed up certain operations, such as
|
||||
store used to contain this layer. Naturally, by default it is the
|
||||
same as the frame, however, users can specify their own custom
|
||||
Backing Store Frame in order to speed up certain operations, such as
|
||||
live transformation.
|
||||
@return the backing store frame
|
||||
*/
|
||||
@@ -385,7 +385,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
- (void)setBackingStoreFrame:(CGRect)aFrame
|
||||
{
|
||||
_hasCustomBackingStoreFrame = (aFrame != nil);
|
||||
|
||||
|
||||
if (aFrame == nil)
|
||||
aFrame = CGRectMakeCopy(_standardBackingStoreFrame);
|
||||
else
|
||||
@@ -393,23 +393,23 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
if (_superlayer)
|
||||
{
|
||||
aFrame = [_superlayer convertRect:aFrame toLayer:nil];
|
||||
|
||||
|
||||
var bounds = [_superlayer bounds],
|
||||
frame = [_superlayer convertRect:bounds toLayer:nil];
|
||||
|
||||
|
||||
aFrame.origin.x -= _CGRectGetMinX(frame);
|
||||
aFrame.origin.y -= _CGRectGetMinY(frame);
|
||||
}
|
||||
else
|
||||
aFrame = CGRectMakeCopy(aFrame);
|
||||
}
|
||||
|
||||
|
||||
if (!CGPointEqualToPoint(_backingStoreFrame.origin, aFrame.origin))
|
||||
[self registerRunLoopUpdateWithMask:CALayerFrameOriginUpdateMask];
|
||||
|
||||
|
||||
if (!CGSizeEqualToSize(_backingStoreFrame.size, aFrame.size))
|
||||
[self registerRunLoopUpdateWithMask:CALayerFrameSizeUpdateMask];
|
||||
|
||||
|
||||
_backingStoreFrame = aFrame;
|
||||
}
|
||||
|
||||
@@ -431,9 +431,9 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
{
|
||||
if (_contents == contents)
|
||||
return;
|
||||
|
||||
|
||||
_contents = contents;
|
||||
|
||||
|
||||
[self composite];
|
||||
}
|
||||
|
||||
@@ -445,26 +445,26 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
{
|
||||
if (USE_BUFFER && !_contents || !_context)
|
||||
return;
|
||||
|
||||
|
||||
CGContextClearRect(_context, _CGRectMake(0.0, 0.0, _CGRectGetWidth(_backingStoreFrame), _CGRectGetHeight(_backingStoreFrame)));
|
||||
|
||||
|
||||
// Recomposite
|
||||
var transform = _transformFromLayer;
|
||||
|
||||
|
||||
if (_superlayer)
|
||||
{
|
||||
var superlayerTransform = _CALayerGetTransform(_superlayer, nil),
|
||||
superlayerOrigin = CGPointApplyAffineTransform(_superlayer._bounds.origin, superlayerTransform);
|
||||
|
||||
|
||||
transform = CGAffineTransformConcat(transform, superlayerTransform);
|
||||
|
||||
|
||||
transform.tx -= superlayerOrigin.x;
|
||||
transform.ty -= superlayerOrigin.y;
|
||||
}
|
||||
|
||||
transform.tx -= _CGRectGetMinX(_backingStoreFrame);
|
||||
transform.ty -= _CGRectGetMinY(_backingStoreFrame);
|
||||
|
||||
|
||||
CGContextSaveGState(_context);
|
||||
CGContextConcatCTM(_context, transform);//_transformFromView);
|
||||
if (USE_BUFFER)
|
||||
@@ -485,18 +485,18 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
if (!_context)
|
||||
{
|
||||
_context = CGBitmapGraphicsContextCreate();
|
||||
|
||||
|
||||
_DOMContentsElement = _context.DOMElement;
|
||||
|
||||
|
||||
_DOMContentsElement.style.zIndex = -100;
|
||||
|
||||
_DOMContentsElement.style.overflow = "hidden";
|
||||
_DOMContentsElement.style.position = "absolute";
|
||||
_DOMContentsElement.style.visibility = "visible";
|
||||
|
||||
|
||||
_DOMContentsElement.width = ROUND(_CGRectGetWidth(_backingStoreFrame));
|
||||
_DOMContentsElement.height = ROUND(_CGRectGetHeight(_backingStoreFrame));
|
||||
|
||||
|
||||
_DOMContentsElement.style.top = "0px";
|
||||
_DOMContentsElement.style.left = "0px";
|
||||
_DOMContentsElement.style.width = ROUND(_CGRectGetWidth(_backingStoreFrame)) + "px";
|
||||
@@ -504,23 +504,23 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
|
||||
_DOMElement.appendChild(_DOMContentsElement);
|
||||
}
|
||||
|
||||
|
||||
if (USE_BUFFER)
|
||||
{
|
||||
if (_delegateRespondsToDisplayLayerSelector)
|
||||
return [_delegate displayInLayer:self];
|
||||
|
||||
|
||||
if (_CGRectGetWidth(_backingStoreFrame) == 0.0 || _CGRectGetHeight(_backingStoreFrame) == 0.0)
|
||||
return;
|
||||
|
||||
|
||||
if (!_contents)
|
||||
_contents = CABackingStoreCreate();
|
||||
|
||||
|
||||
CABackingStoreSetSize(_contents, _bounds.size);
|
||||
|
||||
|
||||
[self drawInContext:CABackingStoreGetContext(_contents)];
|
||||
}
|
||||
|
||||
|
||||
[self composite];
|
||||
}
|
||||
|
||||
@@ -535,7 +535,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
CGContextSetFillColor(aContext, _backgroundColor);
|
||||
CGContextFillRect(aContext, _bounds);
|
||||
}
|
||||
|
||||
|
||||
if (_delegateRespondsToDrawLayerInContextSelector)
|
||||
[_delegate drawLayer:self inContext:aContext];
|
||||
}
|
||||
@@ -559,9 +559,9 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
{
|
||||
if (_opacity == anOpacity)
|
||||
return;
|
||||
|
||||
|
||||
_opacity = anOpacity;
|
||||
|
||||
|
||||
_DOMElement.style.opacity = anOpacity;
|
||||
_DOMElement.style.filter = "alpha(opacity=" + anOpacity * 100 + ")";
|
||||
}
|
||||
@@ -600,7 +600,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
{
|
||||
if (_masksToBounds == masksToBounds)
|
||||
return;
|
||||
|
||||
|
||||
_masksToBounds = masksToBounds;
|
||||
_DOMElement.style.overflow = _masksToBounds ? "hidden" : "visible";
|
||||
}
|
||||
@@ -612,7 +612,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
- (void)setBackgroundColor:(CPColor)aColor
|
||||
{
|
||||
_backgroundColor = aColor;
|
||||
|
||||
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
@@ -665,10 +665,10 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
|
||||
{
|
||||
if (_owningView)
|
||||
[_owningView setLayer:nil];
|
||||
|
||||
|
||||
if (!_superlayer)
|
||||
return;
|
||||
|
||||
|
||||
_superlayer._DOMElement.removeChild(_DOMElement);
|
||||
[_superlayer._sublayers removeObject:self];
|
||||
|
||||
@@ -684,24 +684,24 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
|
||||
{
|
||||
if (!aLayer)
|
||||
return;
|
||||
|
||||
|
||||
var superlayer = [aLayer superlayer];
|
||||
|
||||
|
||||
if (superlayer == self)
|
||||
{
|
||||
var index = [_sublayers indexOfObjectIdenticalTo:aLayer];
|
||||
|
||||
if (index == anIndex)
|
||||
return;
|
||||
|
||||
|
||||
[_sublayers removeObjectAtIndex:index];
|
||||
|
||||
|
||||
if (index < anIndex)
|
||||
--anIndex;
|
||||
}
|
||||
else if (superlayer != nil)
|
||||
[aLayer removeFromSuperlayer];
|
||||
|
||||
|
||||
ADJUST_CONTENTS_ZINDEX(aLayer);
|
||||
|
||||
[_sublayers insertObject:aLayer atIndex:anIndex];
|
||||
@@ -710,9 +710,9 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
|
||||
_DOMElement.appendChild(DOM(aLayer));
|
||||
else
|
||||
_DOMElement.insertBefore(DOM(aLayer), _sublayers[anIndex + 1]._DOMElement);
|
||||
|
||||
|
||||
aLayer._superlayer = self;
|
||||
|
||||
|
||||
if (self != superlayer)
|
||||
_CALayerRecalculateGeometry(aLayer, 0xFFFFFFF);
|
||||
}
|
||||
@@ -726,7 +726,7 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
|
||||
- (void)insertSublayer:(CALayer)aLayer below:(CALayer)aSublayer
|
||||
{
|
||||
var index = aSublayer ? [_sublayers indexOfObjectIdenticalTo:aSublayer] : 0;
|
||||
|
||||
|
||||
[self insertSublayer:aLayer atIndex:index == CPNotFound ? _sublayers.length : index];
|
||||
}
|
||||
|
||||
@@ -754,16 +754,16 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
|
||||
{
|
||||
if (aSublayer == aLayer)
|
||||
return;
|
||||
|
||||
|
||||
// FIXME: EXCEPTION
|
||||
if (aSublayer._superlayer != self)
|
||||
{
|
||||
alert("EXCEPTION");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ADJUST_CONTENTS_ZINDEX(aLayer);
|
||||
|
||||
|
||||
[_sublayers replaceObjectAtIndex:[_sublayers indexOfObjectIdenticalTo:aSublayer] withObject:aLayer];
|
||||
_DOMElement.replaceChild(DOM(aSublayer), DOM(aLayer));
|
||||
}
|
||||
@@ -782,13 +782,13 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
|
||||
|
||||
if (mask & CALayerDOMUpdateMask)
|
||||
_CALayerUpdateDOM(layer, mask);
|
||||
|
||||
|
||||
if (mask & CALayerDisplayUpdateMask)
|
||||
[layer display];
|
||||
|
||||
|
||||
else if (mask & CALayerFrameSizeUpdateMask || mask & CALayerCompositeUpdateMask)
|
||||
[layer composite];
|
||||
|
||||
|
||||
layer._runLoopUpdateMask = 0;
|
||||
}
|
||||
window.loop= false;
|
||||
@@ -803,11 +803,11 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
|
||||
if (CALayerRegisteredRunLoopUpdates == nil)
|
||||
{
|
||||
CALayerRegisteredRunLoopUpdates = {};
|
||||
|
||||
|
||||
[[CPRunLoop currentRunLoop] performSelector:@selector(runLoopUpdateLayers)
|
||||
target:CALayer argument:nil order:0 modes:[CPDefaultRunLoopMode]];
|
||||
}
|
||||
|
||||
|
||||
_runLoopUpdateMask |= anUpdateMask;
|
||||
CALayerRegisteredRunLoopUpdates[[self UID]] = self;
|
||||
}
|
||||
@@ -846,7 +846,7 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
|
||||
}
|
||||
|
||||
/*!
|
||||
Marks the specified rectange as needing to be redrawn.
|
||||
Marks the specified rectangle as needing to be redrawn.
|
||||
@param aRect the area that needs to be redrawn.
|
||||
*/
|
||||
- (void)setNeedsDisplayInRect:(CGRect)aRect
|
||||
@@ -890,8 +890,8 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
|
||||
}
|
||||
|
||||
/*!
|
||||
Converts the rectangle from the receier's coordinate system to the specified layer's coordinate system.
|
||||
@param aRect the rectange to convert
|
||||
Converts the rectangle from the receiver's coordinate system to the specified layer's coordinate system.
|
||||
@param aRect the rectangle to convert
|
||||
@param aLayer the layer coordinate system to convert to
|
||||
@return the converted rectangle
|
||||
*/
|
||||
@@ -919,21 +919,21 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
|
||||
{
|
||||
if (_isHidden)
|
||||
return nil;
|
||||
|
||||
|
||||
var point = CGPointApplyAffineTransform(aPoint, _transformToLayer);
|
||||
//alert(point.x + " " + point.y);
|
||||
|
||||
|
||||
if (!_CGRectContainsPoint(_bounds, point))
|
||||
return nil;
|
||||
|
||||
|
||||
var layer = nil,
|
||||
index = _sublayers.length;
|
||||
|
||||
|
||||
// FIXME: this should take into account zPosition.
|
||||
while (index--)
|
||||
if (layer = [_sublayers[index] hitTest:point])
|
||||
return layer;
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -946,12 +946,12 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
|
||||
{
|
||||
if (_delegate == aDelegate)
|
||||
return;
|
||||
|
||||
|
||||
_delegate = aDelegate;
|
||||
|
||||
|
||||
_delegateRespondsToDisplayLayerSelector = [_delegate respondsToSelector:@selector(displayLayer:)];
|
||||
_delegateRespondsToDrawLayerInContextSelector = [_delegate respondsToSelector:@selector(drawLayer:inContext:)];
|
||||
|
||||
|
||||
if (_delegateRespondsToDisplayLayerSelector || _delegateRespondsToDrawLayerInContextSelector)
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
@@ -968,15 +968,15 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
|
||||
- (void)_setOwningView:(CPView)anOwningView
|
||||
{
|
||||
_owningView = anOwningView;
|
||||
|
||||
|
||||
if (_owningView)
|
||||
{
|
||||
_owningView = anOwningView;
|
||||
|
||||
|
||||
_bounds.size = CGSizeMakeCopy([_owningView bounds].size);
|
||||
_position = CGPointMake(_CGRectGetWidth(_bounds) * _anchorPoint.x, _CGRectGetHeight(_bounds) * _anchorPoint.y);
|
||||
}
|
||||
|
||||
|
||||
_CALayerRecalculateGeometry(self, CALayerGeometryPositionMask | CALayerGeometryBoundsMask);
|
||||
}
|
||||
|
||||
@@ -985,7 +985,7 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
|
||||
{
|
||||
_bounds.size = CGSizeMakeCopy([_owningView bounds].size);
|
||||
_position = CGPointMake(_CGRectGetWidth(_bounds) * _anchorPoint.x, _CGRectGetHeight(_bounds) * _anchorPoint.y);
|
||||
|
||||
|
||||
_CALayerRecalculateGeometry(self, CALayerGeometryPositionMask | CALayerGeometryBoundsMask);
|
||||
}
|
||||
|
||||
@@ -993,20 +993,20 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)
|
||||
- (void)_update
|
||||
{
|
||||
window.loop = true;
|
||||
|
||||
|
||||
var mask = _runLoopUpdateMask;
|
||||
|
||||
if (mask & CALayerDOMUpdateMask)
|
||||
_CALayerUpdateDOM(self, mask);
|
||||
|
||||
|
||||
if (mask & CALayerDisplayUpdateMask)
|
||||
[self display];
|
||||
|
||||
|
||||
else if (mask & CALayerFrameSizeUpdateMask || mask & CALayerCompositeUpdateMask)
|
||||
[self composite];
|
||||
|
||||
|
||||
_runLoopUpdateMask = 0;
|
||||
|
||||
|
||||
window.loop = false;
|
||||
}
|
||||
|
||||
@@ -1018,7 +1018,7 @@ function _CALayerUpdateSublayerTransformForSublayers(aLayer)
|
||||
anchorPoint = aLayer._anchorPoint,
|
||||
translateX = _CGRectGetWidth(bounds) * anchorPoint.x,
|
||||
translateY = _CGRectGetHeight(bounds) * anchorPoint.y;
|
||||
|
||||
|
||||
aLayer._sublayerTransformForSublayers = CGAffineTransformConcat(
|
||||
CGAffineTransformMakeTranslation(-translateX, -translateY),
|
||||
CGAffineTransformConcat(aLayer._sublayerTransform,
|
||||
@@ -1028,27 +1028,27 @@ function _CALayerUpdateSublayerTransformForSublayers(aLayer)
|
||||
function _CALayerUpdateDOM(aLayer, aMask)
|
||||
{
|
||||
var DOMElementStyle = aLayer._DOMElement.style;
|
||||
|
||||
|
||||
if (aMask & CALayerZPositionUpdateMask)
|
||||
DOMElementStyle.zIndex = aLayer._zPosition;
|
||||
|
||||
|
||||
var frame = aLayer._backingStoreFrame;
|
||||
|
||||
|
||||
if (aMask & CALayerFrameOriginUpdateMask)
|
||||
{
|
||||
DOMElementStyle.top = ROUND(_CGRectGetMinY(frame)) + "px";
|
||||
DOMElementStyle.left = ROUND(_CGRectGetMinX(frame)) + "px";
|
||||
}
|
||||
|
||||
|
||||
if (aMask & CALayerFrameSizeUpdateMask)
|
||||
{
|
||||
var width = MAX(0.0, ROUND(_CGRectGetWidth(frame))),
|
||||
height = MAX(0.0, ROUND(_CGRectGetHeight(frame))),
|
||||
DOMContentsElement = aLayer._DOMContentsElement;
|
||||
|
||||
|
||||
DOMElementStyle.width = width + "px";
|
||||
DOMElementStyle.height = height + "px";
|
||||
|
||||
|
||||
if (DOMContentsElement)
|
||||
{
|
||||
DOMContentsElement.width = width;
|
||||
@@ -1070,7 +1070,7 @@ function _CALayerRecalculateGeometry(aLayer, aGeometryChange)
|
||||
affineTransform = aLayer._affineTransform,
|
||||
backingStoreFrameSize = _CGSizeMakeCopy(aLayer._backingStoreFrame),
|
||||
hasCustomBackingStoreFrame = aLayer._hasCustomBackingStoreFrame;
|
||||
|
||||
|
||||
// Go to anchor, transform, go back to bounds.
|
||||
aLayer._transformFromLayer = CGAffineTransformConcat(
|
||||
CGAffineTransformMakeTranslation(-width * anchorPoint.x - _CGRectGetMinX(aLayer._bounds), -height * anchorPoint.y - _CGRectGetMinY(aLayer._bounds)),
|
||||
@@ -1082,68 +1082,68 @@ function _CALayerRecalculateGeometry(aLayer, aGeometryChange)
|
||||
// aLayer._transformFromLayer = CGAffineTransformConcat(aLayer._transformFromLayer, superlayer._sublayerTransformForSublayers);
|
||||
_CGAffineTransformConcatTo(aLayer._transformFromLayer, superlayer._sublayerTransformForSublayers, aLayer._transformFromLayer);
|
||||
}
|
||||
|
||||
|
||||
aLayer._transformToLayer = CGAffineTransformInvert(aLayer._transformFromLayer);
|
||||
|
||||
//aLayer._transformFromLayer.tx = ROUND(aLayer._transformFromLayer.tx);
|
||||
//aLayer._transformFromLayer.ty = ROUND(aLayer._transformFromLayer.ty);
|
||||
|
||||
|
||||
aLayer._frame = nil;
|
||||
aLayer._standardBackingStoreFrame = [aLayer convertRect:bounds toLayer:nil];
|
||||
|
||||
|
||||
if (superlayer)
|
||||
{
|
||||
var bounds = [superlayer bounds],
|
||||
frame = [superlayer convertRect:bounds toLayer:nil];
|
||||
|
||||
|
||||
aLayer._standardBackingStoreFrame.origin.x -= _CGRectGetMinX(frame);
|
||||
aLayer._standardBackingStoreFrame.origin.y -= _CGRectGetMinY(frame);
|
||||
}
|
||||
|
||||
// We used to use CGRectIntegral here, but what we actually want, is the largest integral
|
||||
// rect that would ever contain this box, since for any width/height, there are 2 (4)
|
||||
// rect that would ever contain this box, since for any width/height, there are 2 (4)
|
||||
// possible integral rects for it depending on it's position. It's OK that this is sometimes
|
||||
// bigger than the "optimal" bounding integral rect since that doesn't change drawing.
|
||||
|
||||
|
||||
var origin = aLayer._standardBackingStoreFrame.origin,
|
||||
size = aLayer._standardBackingStoreFrame.size;
|
||||
|
||||
|
||||
origin.x = FLOOR(origin.x);
|
||||
origin.y = FLOOR(origin.y);
|
||||
size.width = CEIL(size.width) + 1.0;
|
||||
size.height = CEIL(size.height) + 1.0;
|
||||
|
||||
|
||||
// FIXME: This avoids the central issue that a position change is sometimes a display and sometimes
|
||||
// a div move, and sometimes both.
|
||||
|
||||
|
||||
// Only use this frame if we don't currently have a custom backing store frame.
|
||||
if (!hasCustomBackingStoreFrame)
|
||||
{
|
||||
var backingStoreFrame = CGRectMakeCopy(aLayer._standardBackingStoreFrame);
|
||||
|
||||
// These values get rounded in the DOM, so don't both updating them if they're
|
||||
|
||||
// These values get rounded in the DOM, so don't both updating them if they're
|
||||
// not going to be different after rounding.
|
||||
if (ROUND(_CGRectGetMinX(backingStoreFrame)) != ROUND(_CGRectGetMinX(aLayer._backingStoreFrame)) ||
|
||||
ROUND(_CGRectGetMinY(backingStoreFrame)) != ROUND(_CGRectGetMinY(aLayer._backingStoreFrame)))
|
||||
[aLayer registerRunLoopUpdateWithMask:CALayerFrameOriginUpdateMask];
|
||||
|
||||
|
||||
// Any change in size due to a geometry change is purely due to rounding error.
|
||||
if ((_CGRectGetWidth(backingStoreFrame) != ROUND(_CGRectGetWidth(aLayer._backingStoreFrame)) ||
|
||||
_CGRectGetHeight(backingStoreFrame) != ROUND(_CGRectGetHeight(aLayer._backingStoreFrame))))
|
||||
[aLayer registerRunLoopUpdateWithMask:CALayerFrameSizeUpdateMask];
|
||||
|
||||
|
||||
aLayer._backingStoreFrame = backingStoreFrame;
|
||||
}
|
||||
|
||||
if (aGeometryChange & CALayerGeometryBoundsMask && aLayer._needsDisplayOnBoundsChange)
|
||||
[aLayer setNeedsDisplay];
|
||||
// We need to recomposite if we have a custom backing store frame, OR
|
||||
// We need to recompose if we have a custom backing store frame, OR
|
||||
// If the change is not solely composed of position and anchor points changes.
|
||||
// Anchor point and position changes simply move the object, requiring
|
||||
// Anchor point and position changes simply move the object, requiring
|
||||
// no re-rendering.
|
||||
else if (hasCustomBackingStoreFrame || (aGeometryChange & ~(CALayerGeometryPositionMask | CALayerGeometryAnchorPointMask)))
|
||||
[aLayer setNeedsComposite];
|
||||
|
||||
|
||||
var sublayers = aLayer._sublayers,
|
||||
index = 0,
|
||||
count = sublayers.length;
|
||||
@@ -1155,45 +1155,45 @@ function _CALayerRecalculateGeometry(aLayer, aGeometryChange)
|
||||
function _CALayerGetTransform(fromLayer, toLayer)
|
||||
{
|
||||
var transform = CGAffineTransformMakeIdentity();
|
||||
|
||||
|
||||
if (fromLayer)
|
||||
{
|
||||
var layer = fromLayer;
|
||||
|
||||
// If we have a fromLayer, "climb up" the layer tree until
|
||||
|
||||
// If we have a fromLayer, "climb up" the layer tree until
|
||||
// we hit the root node or we hit the toLayer.
|
||||
while (layer && layer != toLayer)
|
||||
{
|
||||
var transformFromLayer = layer._transformFromLayer;
|
||||
|
||||
|
||||
//transform = CGAffineTransformConcat(transform, layer._transformFromLayer);
|
||||
_CGAffineTransformConcatTo(transform, transformFromLayer, transform);
|
||||
|
||||
|
||||
layer = layer._superlayer;
|
||||
}
|
||||
|
||||
|
||||
// If we hit toLayer, then we're done.
|
||||
if (layer == toLayer)
|
||||
return transform;
|
||||
}
|
||||
|
||||
|
||||
var layers = [],
|
||||
layer = toLayer;
|
||||
|
||||
|
||||
while (layer)
|
||||
{
|
||||
layers.push(layer);
|
||||
layer = layer._superlayer;
|
||||
}
|
||||
|
||||
|
||||
var index = layers.length;
|
||||
|
||||
|
||||
while (index--)
|
||||
{
|
||||
var transformToLayer = layers[index]._transformToLayer;
|
||||
|
||||
|
||||
_CGAffineTransformConcatTo(transform, transformToLayer, transform);
|
||||
}
|
||||
|
||||
|
||||
return transform;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ function CGColorGetConstantColor(aColorName)
|
||||
}
|
||||
|
||||
/*!
|
||||
This function is for source compatability.
|
||||
This function is for source compatibility.
|
||||
*/
|
||||
function CGColorRetain(aColor)
|
||||
{
|
||||
@@ -55,7 +55,7 @@ function CGColorRetain(aColor)
|
||||
}
|
||||
|
||||
/*!
|
||||
This function is for source compatability.
|
||||
This function is for source compatibility.
|
||||
*/
|
||||
function CGColorRelease()
|
||||
{
|
||||
|
||||
@@ -79,7 +79,7 @@ kCGBlendModePlusLighter = 27;
|
||||
*/
|
||||
|
||||
/*!
|
||||
This function is just here for source compatability.
|
||||
This function is just here for source compatibility.
|
||||
It does nothing.
|
||||
@group CGContext
|
||||
*/
|
||||
@@ -88,7 +88,7 @@ function CGContextRelease()
|
||||
}
|
||||
|
||||
/*!
|
||||
This function is just here for source compatability.
|
||||
This function is just here for source compatibility.
|
||||
It does nothing.
|
||||
@param aContext a CGContext
|
||||
@return CGContext the context
|
||||
@@ -466,7 +466,7 @@ function CGContextTranslateCTM(aContext, tx, ty)
|
||||
/*!
|
||||
Sets the current offset, and blur for shadows in core graphics drawing operations
|
||||
@param aContext the CGContext of the shadow
|
||||
@param aSize a CGSize indicating the offset of the shaodw
|
||||
@param aSize a CGSize indicating the offset of the shadow
|
||||
@param aBlur a float indicating the blur radius
|
||||
@return void
|
||||
*/
|
||||
@@ -483,7 +483,7 @@ function CGContextSetShadow(aContext, aSize, aBlur)
|
||||
/*!
|
||||
Sets the current offset, blur, and color for shadows in core graphics drawing operations
|
||||
@param aContext the CGContext of the shadow
|
||||
@param aSize a CGSize indicating the offset of the shaodw
|
||||
@param aSize a CGSize indicating the offset of the shadow
|
||||
@param aBlur a float indicating the blur radius
|
||||
@param aColor a CPColor object indicating the color of the shadow
|
||||
@return void
|
||||
@@ -652,7 +652,7 @@ function CGContextSetStrokeColor(aContext, aColor)
|
||||
Fills a rounded rectangle.
|
||||
@param aContext the CGContext to draw into
|
||||
@param aRect the base rectangle
|
||||
@param aRadius the distance from the rectange corner to the rounded corner
|
||||
@param aRadius the distance from the rectangle corner to the rounded corner
|
||||
@param ne set it to \c YES for a rounded northeast corner
|
||||
@param se set it to \c YES for a rounded southeast corner
|
||||
@param sw set it to \c YES for a rounded southwest corner
|
||||
@@ -671,7 +671,7 @@ function CGContextFillRoundedRectangleInRect(aContext, aRect, aRadius, ne, se, s
|
||||
Strokes a rounded rectangle.
|
||||
@param aContext the CGContext to draw into
|
||||
@param aRect the base rectangle
|
||||
@param aRadius the distance from the rectange corner to the rounded corner
|
||||
@param aRadius the distance from the rectangle corner to the rounded corner
|
||||
@param ne set it to \c YES for a rounded northeast corner
|
||||
@param se set it to \c YES for a rounded southeast corner
|
||||
@param sw set it to \c YES for a rounded southwest corner
|
||||
|
||||
|
Before Width: | Height: | Size: 106 B |
|
Before Width: | Height: | Size: 106 B |
|
Before Width: | Height: | Size: 118 B |
|
Before Width: | Height: | Size: 121 B |
|
Before Width: | Height: | Size: 142 B |
|
Before Width: | Height: | Size: 245 B |
|
Before Width: | Height: | Size: 241 B |
|
Before Width: | Height: | Size: 126 B |
|
Before Width: | Height: | Size: 180 B |
|
Before Width: | Height: | Size: 181 B |
|
Before Width: | Height: | Size: 146 B |
|
Before Width: | Height: | Size: 322 B |
|
Before Width: | Height: | Size: 339 B |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 227 B |
|
Before Width: | Height: | Size: 307 B |
|
Before Width: | Height: | Size: 4.0 KiB |
@@ -804,6 +804,7 @@ var themedButtonValues = nil,
|
||||
// Global for reuse by CPTokenField.
|
||||
themedTextFieldValues =
|
||||
[
|
||||
[@"vertical-alignment", CPTopVerticalTextAlignment, CPThemeStateBezeled],
|
||||
[@"bezel-color", bezelColor, CPThemeStateBezeled],
|
||||
[@"bezel-color", bezelFocusedColor, CPThemeStateBezeled | CPThemeStateEditing],
|
||||
[@"bezel-color", bezelDisabledColor, CPThemeStateBezeled | CPThemeStateDisabled],
|
||||
@@ -821,8 +822,12 @@ var themedButtonValues = nil,
|
||||
[@"content-inset", CGInsetMake(0.0, 0.0, 0.0, 5.0), CPThemeStateTableDataView],
|
||||
|
||||
[@"text-color", [CPColor colorWithCalibratedWhite:51.0 / 255.0 alpha:1.0], CPThemeStateTableDataView],
|
||||
[@"text-color", [CPColor whiteColor], CPThemeStateTableDataView | CPThemeStateSelectedTableDataView],
|
||||
[@"font", [CPFont boldSystemFontOfSize:12.0], CPThemeStateTableDataView | CPThemeStateSelectedTableDataView],
|
||||
[@"text-color", [CPColor whiteColor], CPThemeStateTableDataView | CPThemeStateSelectedTableDataView],
|
||||
[@"font", [CPFont boldSystemFontOfSize:12.0], CPThemeStateTableDataView | CPThemeStateSelectedTableDataView],
|
||||
[@"text-color", [CPColor blackColor], CPThemeStateTableDataView | CPThemeStateEditing],
|
||||
[@"content-inset", CGInsetMake(7.0, 7.0, 5.0, 8.0), CPThemeStateTableDataView | CPThemeStateEditing],
|
||||
[@"font", [CPFont systemFontOfSize:12.0], CPThemeStateTableDataView | CPThemeStateEditing],
|
||||
[@"bezel-inset", CGInsetMake(-2.0, -2.0, -2.0, -2.0), CPThemeStateTableDataView | CPThemeStateEditing],
|
||||
|
||||
[@"text-color", [CPColor colorWithCalibratedWhite:125.0 / 255.0 alpha:1.0], CPThemeStateTableDataView | CPThemeStateGroupRow],
|
||||
[@"text-color", [CPColor colorWithCalibratedWhite:1.0 alpha:1.0], CPThemeStateTableDataView | CPThemeStateGroupRow | CPThemeStateSelectedTableDataView],
|
||||
@@ -1447,9 +1452,9 @@ var themedButtonValues = nil,
|
||||
alternatingRowColors = [[CPColor whiteColor], [CPColor colorWithRed:245.0 / 255.0 green:249.0 / 255.0 blue:252.0 / 255.0 alpha:1.0]],
|
||||
gridColor = [CPColor colorWithHexString:@"dce0e2"],
|
||||
selectionColor = [CPColor colorWithHexString:@"5f83b9"],
|
||||
sourceListSelectionColor = [CPDictionary dictionaryWithObjects: [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),
|
||||
[CPColor colorWithCalibratedRed:(61.0 / 255.0) green:(123.0 / 255.0) blue:(218.0 / 255.0) alpha:1.0],
|
||||
[CPColor colorWithCalibratedRed:(31.0 / 255.0) green:(92.0 / 255.0) blue:(207.0 / 255.0) alpha:1.0]
|
||||
sourceListSelectionColor = [CPDictionary dictionaryWithObjects: [CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceRGB(), [98.0 / 255.0, 143.0 / 210.0, 209.0 / 255.0, 1.0, 46.0 / 255.0, 88.0 / 176.0, 208.0 / 255.0,1.0], [0,1], 2),
|
||||
[CPColor colorWithCalibratedRed:81.0/255.0 green:127.0/255.0 blue:200.0/255.0 alpha:1.0],
|
||||
[CPColor colorWithCalibratedRed:34.0/255.0 green:63.0/255.0 blue:123.0/255.0 alpha:1.0]
|
||||
]
|
||||
forKeys: [CPSourceListGradient, CPSourceListTopLineColor, CPSourceListBottomLineColor]],
|
||||
|
||||
|
||||
@@ -175,6 +175,12 @@ var concat = Array.prototype.concat,
|
||||
FORWARD_TO_CONCRETE_CLASS();
|
||||
}
|
||||
|
||||
// FIXME: This should be defined in CPMutableArray, not here.
|
||||
- (id)initWithCapacity:(unsigned)aCapacity
|
||||
{
|
||||
FORWARD_TO_CONCRETE_CLASS();
|
||||
}
|
||||
|
||||
// Querying an array
|
||||
/*!
|
||||
Returns \c YES if the array contains \c anObject. Otherwise, it returns \c NO.
|
||||
@@ -517,6 +523,14 @@ var concat = Array.prototype.concat,
|
||||
objj_msgSend([self objectAtIndex:index], aSelector);
|
||||
}
|
||||
|
||||
- (void)enumerateObjectsUsingBlock:(Function)aFunction
|
||||
{
|
||||
var index = 0,
|
||||
count = [self count];
|
||||
|
||||
for (; index < count; ++index)
|
||||
aFunction([self objectAtIndex:index], index);
|
||||
}
|
||||
|
||||
// Comparing arrays
|
||||
/*!
|
||||
@@ -545,7 +559,7 @@ var concat = Array.prototype.concat,
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if anArray contains exactly the same objects as the reciever.
|
||||
Returns true if anArray contains exactly the same objects as the receiver.
|
||||
*/
|
||||
- (BOOL)isEqualToArray:(id)anArray
|
||||
{
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
Initializes an array able to store at least \c aCapacity items. Because CPArray
|
||||
is backed by JavaScript arrays, this method ends up simply returning a regular array.
|
||||
*/
|
||||
- (id)initWithCapacity:(unsigned)aCapacity
|
||||
/*- (id)initWithCapacity:(unsigned)aCapacity
|
||||
{
|
||||
return self;
|
||||
}
|
||||
}*/
|
||||
|
||||
// Adding and replacing objects
|
||||
/*!
|
||||
@@ -136,15 +136,15 @@
|
||||
@param anIndexSet the set of indices to array positions that will be replaced
|
||||
@param objects the array of objects to place in the specified indices
|
||||
*/
|
||||
- (void)replaceObjectsAtIndexes:(CPIndexSet)anIndexSet withObjects:(CPArray)objects
|
||||
- (void)replaceObjectsAtIndexes:(CPIndexSet)indexes withObjects:(CPArray)objects
|
||||
{
|
||||
var i = 0,
|
||||
index = [anIndexSet firstIndex];
|
||||
index = [indexes firstIndex];
|
||||
|
||||
while (index !== CPNotFound)
|
||||
{
|
||||
[self replaceObjectAtIndex:index withObject:objects[i++]];
|
||||
index = [anIndexSet indexGreaterThanIndex:index];
|
||||
[self replaceObjectAtIndex:index withObject:[objects objectAtIndex:i++]];
|
||||
index = [indexes indexGreaterThanIndex:index];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,14 +41,14 @@ var concat = Array.prototype.concat,
|
||||
|
||||
- (id)initWithArray:(CPArray)anArray copyItems:(BOOL)shouldCopyItems
|
||||
{
|
||||
if (!shouldCopyItems && anArray.isa === _CPJavaScriptArray)
|
||||
if (!shouldCopyItems && [anArray isKindOfClass:_CPJavaScriptArray])
|
||||
return slice.call(anArray, 0);
|
||||
|
||||
self = [super init];
|
||||
|
||||
var index = 0;
|
||||
|
||||
if (anArray.isa === _CPJavaScriptArray)
|
||||
if ([anArray isKindOfClass:_CPJavaScriptArray])
|
||||
{
|
||||
// If we're this far, shouldCopyItems must be YES.
|
||||
var count = anArray.length;
|
||||
@@ -90,7 +90,7 @@ var concat = Array.prototype.concat,
|
||||
|
||||
- (id)initWithObjects:(CPArray)objects count:(CPUInteger)aCount
|
||||
{
|
||||
if (objects.isa === _CPJavaScriptArray)
|
||||
if ([objects isKindOfClass:_CPJavaScriptArray])
|
||||
return slice.call(objects, 0);
|
||||
|
||||
var array = [],
|
||||
@@ -102,6 +102,11 @@ var concat = Array.prototype.concat,
|
||||
return array;
|
||||
}
|
||||
|
||||
- (id)initWithCapacity:(CPUInteger)aCapacity
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)count
|
||||
{
|
||||
return self.length;
|
||||
@@ -176,7 +181,7 @@ var concat = Array.prototype.concat,
|
||||
- (CPArray)arrayByAddingObject:(id)anObject
|
||||
{
|
||||
// concat flattens arrays, so wrap it in an *additional* array if anObject is an array itself.
|
||||
if ([anObject isKindOfClass:CPArray])
|
||||
if (anObject && anObject.isa && [anObject isKindOfClass:_CPJavaScriptArray])
|
||||
return concat.call(self, [anObject]);
|
||||
|
||||
return concat.call(self, anObject);
|
||||
@@ -187,7 +192,7 @@ var concat = Array.prototype.concat,
|
||||
if (!anArray)
|
||||
return [self copy];
|
||||
|
||||
return concat.call(self, anArray.isa === _CPJavaScriptArray ? anArray : [anArray _javaScriptArrayCopy]);
|
||||
return concat.call(self, [anArray isKindOfClass:_CPJavaScriptArray] ? anArray : [anArray _javaScriptArrayCopy]);
|
||||
}
|
||||
|
||||
- (CPArray)subarrayWithRange:(CPRange)aRange
|
||||
@@ -251,7 +256,7 @@ var concat = Array.prototype.concat,
|
||||
|
||||
- (void)setArray:(CPArray)anArray
|
||||
{
|
||||
if (anArray.isa === _CPJavaScriptArray)
|
||||
if ([anArray isKindOfClass:_CPJavaScriptArray])
|
||||
splice.apply(self, [0, self.length].concat(anArray));
|
||||
|
||||
else
|
||||
@@ -260,7 +265,7 @@ var concat = Array.prototype.concat,
|
||||
|
||||
- (void)addObjectsFromArray:(CPArray)anArray
|
||||
{
|
||||
if (anArray.isa === _CPJavaScriptArray)
|
||||
if ([anArray isKindOfClass:_CPJavaScriptArray])
|
||||
splice.apply(self, [self.length, 0].concat(anArray));
|
||||
|
||||
else
|
||||
|
||||
@@ -20,19 +20,20 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
@import "CPArray.j"
|
||||
@import "CPDictionary.j"
|
||||
@import "CPException.j"
|
||||
@import "CPObject.j"
|
||||
@import "CPRange.j"
|
||||
@import "CPString.j"
|
||||
|
||||
|
||||
/*!
|
||||
@class CPAttributedString
|
||||
@ingroup foundation
|
||||
@brief A mutable character string with attributes.
|
||||
|
||||
A character string with sets of attributes that apply to single or ranges of
|
||||
characters. The attributes are containted within a CPDictionary class.
|
||||
characters. The attributes are contained within a CPDictionary class.
|
||||
Attributes can be any name/value pair. The data type of the value is not
|
||||
restricted.
|
||||
This class is mutable.
|
||||
@@ -794,11 +795,11 @@
|
||||
|
||||
/*!
|
||||
@class CPMutableAttributedString
|
||||
@ingroup compatability
|
||||
@ingroup compatibility
|
||||
|
||||
This class is just an empty subclass of CPAttributedString.
|
||||
CPAttributedString already implements mutable methods and
|
||||
this class only exists for source compatability.
|
||||
this class only exists for source compatibility.
|
||||
*/
|
||||
@implementation CPMutableAttributedString : CPAttributedString
|
||||
|
||||
|
||||
@@ -21,12 +21,11 @@
|
||||
*/
|
||||
|
||||
@import "CPDictionary.j"
|
||||
@import "CPObject.j"
|
||||
@import "CPNotification.j"
|
||||
@import "CPNotificationCenter.j"
|
||||
@import "CPObject.j"
|
||||
|
||||
|
||||
CPBundleDidLoadNotification = "CPBundleDidLoadNotification";
|
||||
CPBundleDidLoadNotification = @"CPBundleDidLoadNotification";
|
||||
|
||||
/*!
|
||||
@class CPBundle
|
||||
|
||||
@@ -19,8 +19,11 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
@import <Foundation/CPObject.j>
|
||||
@import <Foundation/CPString.j>
|
||||
@import "CPArray.j"
|
||||
@import "CPException.j"
|
||||
@import "CPObject.j"
|
||||
@import "CPString.j"
|
||||
@import "CPURL.j"
|
||||
|
||||
// CPCharacterSet is a class cluster. Concrete implementations
|
||||
// follow after the main abstract class.
|
||||
@@ -48,7 +51,9 @@ var _builtInCharacterSets = {};
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
_inverted = NO;
|
||||
|
||||
if (self)
|
||||
_inverted = NO;
|
||||
|
||||
return self;
|
||||
}
|
||||
@@ -144,11 +149,11 @@ var _builtInCharacterSets = {};
|
||||
var cs = _builtInCharacterSets[csname];
|
||||
if (cs == nil)
|
||||
{
|
||||
var i,
|
||||
var i = 0,
|
||||
ranges = [CPArray array],
|
||||
rangeArray = eval(csname);
|
||||
|
||||
for (i = 0; i < rangeArray.length; i+= 2)
|
||||
for (; i < rangeArray.length; i+= 2)
|
||||
{
|
||||
var loc = rangeArray[i],
|
||||
length = rangeArray[i + 1],
|
||||
@@ -185,7 +190,9 @@ var _builtInCharacterSets = {};
|
||||
// Creates a range character set with multiple ranges.
|
||||
- (id)initWithRanges:(CPArray)ranges
|
||||
{
|
||||
if (self = [super init])
|
||||
self = [super init];
|
||||
|
||||
if (self)
|
||||
{
|
||||
_ranges = ranges;
|
||||
}
|
||||
@@ -224,9 +231,10 @@ var _builtInCharacterSets = {};
|
||||
|
||||
- (BOOL)hasMemberInPlane:(int)plane // TO DO : when inverted
|
||||
{
|
||||
// FIXME: range is undefined... don't know what's supposed to be going on here.
|
||||
// the highest Unicode plane we reach.
|
||||
// (There are 65536 code points in each plane.)
|
||||
var maxPlane = Math.floor((range.start + range.length - 1) / 65536); // should iterate _ranges
|
||||
var maxPlane = Math.floor((range.start + range.length - 1) / 65536); // FIXME: should iterate _ranges
|
||||
|
||||
return (plane <= maxPlane);
|
||||
}
|
||||
@@ -238,9 +246,9 @@ var _builtInCharacterSets = {};
|
||||
|
||||
- (void)addCharactersInString:(CPString)aString // Needs _inverted support
|
||||
{
|
||||
var i;
|
||||
var i = 0;
|
||||
|
||||
for (i = 0; i < aString.length; i++)
|
||||
for (; i < aString.length; i++)
|
||||
{
|
||||
var code = aString.charCodeAt(i),
|
||||
range = CPMakeRange(code,1);
|
||||
@@ -260,7 +268,9 @@ var _builtInCharacterSets = {};
|
||||
|
||||
- (id)initWithString:(CPString)s
|
||||
{
|
||||
if (self = [super init])
|
||||
self = [super init];
|
||||
|
||||
if (self)
|
||||
{
|
||||
_string = s;
|
||||
}
|
||||
@@ -307,8 +317,10 @@ var _builtInCharacterSets = {};
|
||||
|
||||
- (void)addCharactersInRange:(CPRange)aRange // Needs _inverted support
|
||||
{
|
||||
var i;
|
||||
for (i = aRange.location; i < aRange.location + aRange.length; i++)
|
||||
var i = aRange.location,
|
||||
count = aRange.location + aRange.length;
|
||||
|
||||
for (; i < count; i++)
|
||||
{
|
||||
var s = String.fromCharCode(i);
|
||||
|
||||
@@ -319,9 +331,9 @@ var _builtInCharacterSets = {};
|
||||
|
||||
- (void)addCharactersInString:(CPString)aString // Needs _inverted support
|
||||
{
|
||||
var i;
|
||||
var i = 0;
|
||||
|
||||
for (i = 0; i < aString.length; i++)
|
||||
for (; i < aString.length; i++)
|
||||
{
|
||||
var s = aString.charAt(i);
|
||||
|
||||
@@ -332,19 +344,19 @@ var _builtInCharacterSets = {};
|
||||
|
||||
@end
|
||||
|
||||
_CPCharacterSetTrimAtBeginning = 1 << 1;
|
||||
_CPCharacterSetTrimAtEnd = 1 << 2;
|
||||
_CPCharacterSetTrimAtBeginning = 1 << 1;
|
||||
_CPCharacterSetTrimAtEnd = 1 << 2;
|
||||
|
||||
@implementation CPString (CPCharacterSetAdditions)
|
||||
|
||||
/*!
|
||||
Tokenizes the receiver string using the charactes
|
||||
Tokenizes the receiver string using the characters
|
||||
in a given set. For example, if the receiver is:
|
||||
\c "Baku baku to jest skład."
|
||||
and the set is [CPCharacterSet whitespaceCharacterSet]
|
||||
the returned array would contain:
|
||||
<pre> ["Baku", "baku", "to", "jest", "", "skład."] </pre>
|
||||
Adjacent occurences of the separator characters produce empty strings in the result.
|
||||
Adjacent occurrences of the separator characters produce empty strings in the result.
|
||||
@author Arkadiusz Młynarczyk <arek@tupux.com>
|
||||
@param A character set containing the characters to use to split the receiver. Must not be nil.
|
||||
@return An CPArray object containing substrings from the receiver that have been divided by characters in separator.
|
||||
@@ -356,9 +368,10 @@ _CPCharacterSetTrimAtEnd = 1 << 2;
|
||||
reason:"componentsSeparatedByCharactersInSet: the separator can't be 'nil'"];
|
||||
|
||||
var components = [CPMutableArray array],
|
||||
componentRange = CPMakeRange(0, 0);
|
||||
componentRange = CPMakeRange(0, 0),
|
||||
i = 0;
|
||||
|
||||
for (var i = 0; i < self.length; i++)
|
||||
for (; i < self.length; i++)
|
||||
{
|
||||
if ([separator characterIsMember:self.charAt(i)])
|
||||
{
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
@import "CPException.j"
|
||||
@import "CPObject.j"
|
||||
|
||||
|
||||
/*!
|
||||
@class CPCoder
|
||||
@ingroup foundation
|
||||
@@ -147,7 +146,7 @@
|
||||
|
||||
/*!
|
||||
Called after an object is unarchived in case a different object should be used in place of it.
|
||||
The defaut method returns \c self. Interested subclasses should override this.
|
||||
The default method returns \c self. Interested subclasses should override this.
|
||||
@param aDecoder
|
||||
@return the original object or it's substitute.
|
||||
*/
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
@import "CPObject.j"
|
||||
@import "CPSet.j"
|
||||
|
||||
|
||||
/*!
|
||||
@class CPCountedSet
|
||||
@ingroup foundation
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
@import "CPObject.j"
|
||||
@import "CPString.j"
|
||||
|
||||
|
||||
/*!
|
||||
@class CPData
|
||||
@ingroup foundation
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
@import "CPObject.j"
|
||||
@import "CPString.j"
|
||||
|
||||
@import "CPException.j"
|
||||
|
||||
var CPDateReferenceDate = new Date(Date.UTC(2001, 1, 1, 0, 0, 0, 0));
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ CPDecimal format:
|
||||
function CPDecimalMakeWithString(string, locale)
|
||||
{
|
||||
if (!string)
|
||||
return CPDecimalMakeZero();
|
||||
return CPDecimalMakeNaN();
|
||||
|
||||
// Regexp solution as found in JSON spec, with working regexp (I added groupings)
|
||||
// Test here: http://www.regexplanet.com/simple/index.html
|
||||
@@ -112,11 +112,11 @@ function CPDecimalMakeWithString(string, locale)
|
||||
// (?:[eE]([+\-]?)(\d+))? - optional exponent part plus number in group
|
||||
// group 0: string, 1: sign, 2: integer, 3: decimal, 4: exponent sign, 5: exponent
|
||||
|
||||
// Note: this doesnt accept .01 for example, should it?
|
||||
// If yes simply add '?' after integer part group, ie ([+\-]?)((?:0|[1-9]\d*)?)
|
||||
// Note: this doesn't accept .01 for example, should it?
|
||||
// If yes simply add '?' after integer part group, i.e. ([+\-]?)((?:0|[1-9]\d*)?)
|
||||
var matches = string.match(/^([+\-]?)((?:0|[1-9]\d*))(?:\.(\d*))?(?:[eE]([+\-]?)(\d+))?$/);
|
||||
if (!matches)
|
||||
return nil;
|
||||
return CPDecimalMakeNaN();
|
||||
|
||||
var ds = matches[1],
|
||||
intpart = matches[2],
|
||||
@@ -143,23 +143,23 @@ function CPDecimalMakeWithString(string, locale)
|
||||
}
|
||||
|
||||
if (exponent > CPDecimalMaxExponent || exponent < CPDecimalMinExponent)
|
||||
return nil;
|
||||
return CPDecimalMakeNaN();
|
||||
|
||||
// Representation internally starts at most significant digit
|
||||
var m = [CPArray array],
|
||||
var m = [],
|
||||
i = 0;
|
||||
for (; i < (intpart?intpart.length:0); i++)
|
||||
{
|
||||
if (i >= CPDecimalMaxDigits)
|
||||
break; // truncate
|
||||
[m addObject:parseInt(intpart.charAt(i))];
|
||||
Array.prototype.push.call(m, parseInt(intpart.charAt(i)));
|
||||
}
|
||||
var j = 0;
|
||||
for (; j < (decpart?decpart.length:0); j++)
|
||||
{
|
||||
if ((i + j) >= CPDecimalMaxDigits)
|
||||
break; // truncate
|
||||
[m addObject:parseInt(decpart.charAt(j))];
|
||||
Array.prototype.push.call(m, parseInt(decpart.charAt(j)));
|
||||
}
|
||||
|
||||
var dcm = {_exponent:exponent, _isNegative:isNegative, _isCompact:NO, _isNaN:NO, _mantissa:m};
|
||||
@@ -170,14 +170,14 @@ function CPDecimalMakeWithString(string, locale)
|
||||
|
||||
/*!
|
||||
@ingroup foundation
|
||||
Creates a CPDecimal object from a given matissa and exponent. The sign is taken from the sign of the mantissa. This cant do a full 34 digit mantissa representation as JS's 32 bits or 64bit binary FP numbers cant represent that. So use the CPDecimalMakeWithString if you want longer mantissa.
|
||||
Creates a CPDecimal object from a given mantissa and exponent. The sign is taken from the sign of the mantissa. This cant do a full 34 digit mantissa representation as JS's 32 bits or 64bit binary FP numbers cant represent that. So use the CPDecimalMakeWithString if you want longer mantissa.
|
||||
@param mantissa the mantissa (though see above note)
|
||||
@param exponent the exponent
|
||||
@return A CPDecimal object, or nil on error.
|
||||
*/
|
||||
function CPDecimalMakeWithParts(mantissa, exponent)
|
||||
{
|
||||
var m = [CPArray array],
|
||||
var m = [],
|
||||
isNegative = NO;
|
||||
|
||||
if (mantissa < 0 )
|
||||
@@ -187,15 +187,15 @@ function CPDecimalMakeWithParts(mantissa, exponent)
|
||||
}
|
||||
|
||||
if (mantissa == 0)
|
||||
[m addObject: 0];
|
||||
Array.prototype.push.call(m, 0);
|
||||
|
||||
if (exponent > CPDecimalMaxExponent || exponent < CPDecimalMinExponent)
|
||||
return nil;
|
||||
return CPDecimalMakeNaN();
|
||||
|
||||
// remaining digits are disposed of via truncation
|
||||
while ((mantissa > 0) && ([m count] < CPDecimalMaxDigits)) // count selector here could be optimised away
|
||||
while ((mantissa > 0) && (m.length < CPDecimalMaxDigits)) // count selector here could be optimised away
|
||||
{
|
||||
[m insertObject:parseInt(mantissa % 10) atIndex:0];
|
||||
Array.prototype.unshift.call(m, parseInt(mantissa % 10));
|
||||
mantissa = FLOOR(mantissa / 10);
|
||||
}
|
||||
|
||||
@@ -239,6 +239,27 @@ function CPDecimalMakeNaN()
|
||||
return d;
|
||||
}
|
||||
|
||||
// private methods
|
||||
function _CPDecimalMakeMaximum()
|
||||
{
|
||||
var s = @"",
|
||||
i = 0;
|
||||
for (; i < CPDecimalMaxDigits; i++)
|
||||
s += "9";
|
||||
s += "e" + CPDecimalMaxExponent;
|
||||
return CPDecimalMakeWithString(s);
|
||||
}
|
||||
|
||||
function _CPDecimalMakeMinimum()
|
||||
{
|
||||
var s = @"-",
|
||||
i = 0;
|
||||
for (; i < CPDecimalMaxDigits; i++)
|
||||
s += "9";
|
||||
s += "e" + CPDecimalMaxExponent;
|
||||
return CPDecimalMakeWithString(s);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ingroup foundation
|
||||
Checks to see if a CPDecimal is zero. Can handle uncompacted strings.
|
||||
@@ -246,7 +267,7 @@ function CPDecimalMakeNaN()
|
||||
*/
|
||||
function CPDecimalIsZero(dcm)
|
||||
{
|
||||
// exponent doesnt matter as long as mantissa = 0
|
||||
// exponent doesn't matter as long as mantissa = 0
|
||||
if (!dcm._isNaN)
|
||||
{
|
||||
for (var i = 0; i < dcm._mantissa.length; i++)
|
||||
@@ -267,10 +288,10 @@ function CPDecimalIsZero(dcm)
|
||||
function CPDecimalIsOne(dcm)
|
||||
{
|
||||
CPDecimalCompact(dcm);
|
||||
// exponent doesnt matter as long as mantissa = 0
|
||||
// exponent doesn't matter as long as mantissa = 0
|
||||
if (!dcm._isNaN)
|
||||
{
|
||||
if (dcm._mantissa && ([dcm._mantissa count] == 1) && (dcm._mantissa[0] == 1))
|
||||
if (dcm._mantissa && (dcm._mantissa.length == 1) && (dcm._mantissa[0] == 1))
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
@@ -284,12 +305,12 @@ function _CPDecimalSet(t,s)
|
||||
t._isNegative = s._isNegative;
|
||||
t._isCompact = s._isCompact;
|
||||
t._isNaN = s._isNaN;
|
||||
t._mantissa = [s._mantissa copy];
|
||||
t._mantissa = Array.prototype.slice.call(s._mantissa, 0);
|
||||
}
|
||||
|
||||
function _CPDecimalSetZero(result)
|
||||
{
|
||||
result._mantissa = [CPArray arrayWithObject:0];
|
||||
result._mantissa = [0];
|
||||
result._exponent = 0;
|
||||
result._isNegative = NO;
|
||||
result._isCompact = YES;
|
||||
@@ -298,7 +319,7 @@ function _CPDecimalSetZero(result)
|
||||
|
||||
function _CPDecimalSetOne(result)
|
||||
{
|
||||
result._mantissa = [CPArray arrayWithObject:1];
|
||||
result._mantissa = [1];
|
||||
result._exponent = 0;
|
||||
result._isNegative = NO;
|
||||
result._isCompact = YES;
|
||||
@@ -327,13 +348,13 @@ function CPDecimalCopy(dcm)
|
||||
_isNegative:dcm._isNegative,
|
||||
_isCompact:dcm._isCompact,
|
||||
_isNaN:dcm._isNaN,
|
||||
_mantissa:[dcm._mantissa copy]
|
||||
_mantissa:Array.prototype.slice.call(dcm._mantissa, 0)
|
||||
};
|
||||
}
|
||||
|
||||
/*!
|
||||
@ingroup foundation
|
||||
Compare two CPDecimal objects. Order is left to right (ie Ascending would
|
||||
Compare two CPDecimal objects. Order is left to right (i.e. Ascending would
|
||||
mean left is smaller than right operand).
|
||||
@param leftOperand the left CPDecimal
|
||||
@param rightOperand the right CPDecimal
|
||||
@@ -341,6 +362,9 @@ function CPDecimalCopy(dcm)
|
||||
*/
|
||||
function CPDecimalCompare(leftOperand, rightOperand)
|
||||
{
|
||||
if (leftOperand._isNaN && rightOperand._isNaN)
|
||||
return CPOrderedSame;
|
||||
|
||||
if (leftOperand._isNegative != rightOperand._isNegative)
|
||||
{
|
||||
if (rightOperand._isNegative)
|
||||
@@ -349,8 +373,8 @@ function CPDecimalCompare(leftOperand, rightOperand)
|
||||
return CPOrderedAscending;
|
||||
}
|
||||
|
||||
var s1 = leftOperand._exponent + [leftOperand._mantissa count],
|
||||
s2 = rightOperand._exponent + [rightOperand._mantissa count];
|
||||
var s1 = leftOperand._exponent + leftOperand._mantissa.length,
|
||||
s2 = rightOperand._exponent + rightOperand._mantissa.length;
|
||||
|
||||
// Sign is the same, quick check size (length + exp)
|
||||
if (s1 < s2)
|
||||
@@ -369,7 +393,7 @@ function CPDecimalCompare(leftOperand, rightOperand)
|
||||
}
|
||||
|
||||
// Same size, so check mantissa
|
||||
var l = MIN([leftOperand._mantissa count], [rightOperand._mantissa count]),
|
||||
var l = MIN(leftOperand._mantissa.length, rightOperand._mantissa.length),
|
||||
i = 0;
|
||||
|
||||
for (; i < l; i++)
|
||||
@@ -393,14 +417,14 @@ function CPDecimalCompare(leftOperand, rightOperand)
|
||||
}
|
||||
|
||||
// Same digits, check length
|
||||
if ([leftOperand._mantissa count] > [rightOperand._mantissa count])
|
||||
if (leftOperand._mantissa.length > rightOperand._mantissa.length)
|
||||
{
|
||||
if (rightOperand._isNegative)
|
||||
return CPOrderedAscending;
|
||||
else
|
||||
return CPOrderedDescending;
|
||||
}
|
||||
if ([leftOperand._mantissa count] < [rightOperand._mantissa count])
|
||||
if (leftOperand._mantissa.length < rightOperand._mantissa.length)
|
||||
{
|
||||
if (rightOperand._isNegative)
|
||||
return CPOrderedDescending;
|
||||
@@ -420,8 +444,8 @@ function _SimpleAdd(result, leftOperand, rightOperand, roundingMode, longMode)
|
||||
|
||||
_CPDecimalSet(result, leftOperand);
|
||||
|
||||
var j = [leftOperand._mantissa count] - [rightOperand._mantissa count],
|
||||
l = [rightOperand._mantissa count],
|
||||
var j = leftOperand._mantissa.length - rightOperand._mantissa.length,
|
||||
l = rightOperand._mantissa.length,
|
||||
i = l - 1,
|
||||
carry = 0,
|
||||
error = CPCalculationNoError;
|
||||
@@ -443,7 +467,7 @@ function _SimpleAdd(result, leftOperand, rightOperand, roundingMode, longMode)
|
||||
|
||||
if (carry)
|
||||
{
|
||||
for (i = j-1; i >= 0; i--)
|
||||
for (i = j - 1; i >= 0; i--)
|
||||
{
|
||||
if (result._mantissa[i] != 9)
|
||||
{
|
||||
@@ -456,13 +480,13 @@ function _SimpleAdd(result, leftOperand, rightOperand, roundingMode, longMode)
|
||||
|
||||
if (carry)
|
||||
{
|
||||
[result._mantissa insertObject:1 atIndex:0];
|
||||
Array.prototype.splice.call(result._mantissa, 0, 0, 1);
|
||||
|
||||
// The number must be shifted to the right
|
||||
if ((CPDecimalMaxDigits * factor) == [leftOperand._mantissa count])
|
||||
if ((CPDecimalMaxDigits * factor) == leftOperand._mantissa.length)
|
||||
{
|
||||
var scale = - result._exponent - 1;
|
||||
CPDecimalRound(result, result,scale,roundingMode);
|
||||
CPDecimalRound(result, result, scale, roundingMode);
|
||||
}
|
||||
|
||||
if (CPDecimalMaxExponent < result._exponent)
|
||||
@@ -524,10 +548,10 @@ function CPDecimalAdd(result, leftOperand, rightOperand, roundingMode, longMode)
|
||||
|
||||
var normerror = CPDecimalNormalize(n1, n2, roundingMode, longMode);
|
||||
|
||||
// below is equiv of simple compare
|
||||
// below is equiv. of simple compare
|
||||
var comp = 0,
|
||||
ll = [n1._mantissa count],
|
||||
lr = [n2._mantissa count];
|
||||
ll = n1._mantissa.length,
|
||||
lr = n2._mantissa.length;
|
||||
if (ll == lr)
|
||||
comp = CPOrderedSame;
|
||||
else if (ll > lr)
|
||||
@@ -581,8 +605,8 @@ function _SimpleSubtract(result, leftOperand, rightOperand, roundingMode)
|
||||
{
|
||||
var error = CPCalculationNoError,
|
||||
borrow = 0,
|
||||
l = [rightOperand._mantissa count],
|
||||
j = [leftOperand._mantissa count] - l,
|
||||
l = rightOperand._mantissa.length,
|
||||
j = leftOperand._mantissa.length - l,
|
||||
i = l - 1;
|
||||
|
||||
_CPDecimalSet(result, leftOperand);
|
||||
@@ -604,7 +628,7 @@ function _SimpleSubtract(result, leftOperand, rightOperand, roundingMode)
|
||||
|
||||
if (borrow)
|
||||
{
|
||||
for (i = j-1; i >= 0; i--)
|
||||
for (i = j - 1; i >= 0; i--)
|
||||
{
|
||||
if (result._mantissa[i] != 0)
|
||||
{
|
||||
@@ -735,10 +759,10 @@ function _SimpleDivide(result, leftOperand, rightOperand, roundingMode)
|
||||
|
||||
_CPDecimalSetZero(result);
|
||||
|
||||
n1._mantissa = [CPArray array];
|
||||
n1._mantissa = [];
|
||||
|
||||
while ((k < [leftOperand._mantissa count]) || ([n1._mantissa count]
|
||||
&& !(([n1._mantissa count] == 1) && (n1._mantissa[0] == 0))))
|
||||
while ((k < leftOperand._mantissa.length) || (n1._mantissa.length
|
||||
&& !((n1._mantissa.length == 1) && (n1._mantissa[0] == 0))))
|
||||
{
|
||||
while (CPOrderedAscending == CPDecimalCompare(n1, rightOperand))
|
||||
{
|
||||
@@ -747,19 +771,19 @@ function _SimpleDivide(result, leftOperand, rightOperand, roundingMode)
|
||||
if (n1._exponent)
|
||||
{
|
||||
// Put back zeros removed by compacting
|
||||
[n1._mantissa addObject:0];
|
||||
Array.prototype.push.call(n1._mantissa, 0);
|
||||
n1._exponent--;
|
||||
n1._isCompact = NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (used < [leftOperand._mantissa count])
|
||||
if (used < leftOperand._mantissa.length)
|
||||
{
|
||||
// Fill up with own digits
|
||||
if ([n1._mantissa count] || leftOperand._mantissa[used])
|
||||
if (n1._mantissa.length || leftOperand._mantissa[used])
|
||||
{
|
||||
// only add 0 if there is already something
|
||||
[n1._mantissa addObject:(leftOperand._mantissa[used])];
|
||||
Array.prototype.push.call(n1._mantissa, (leftOperand._mantissa[used]));
|
||||
n1._isCompact = NO;
|
||||
}
|
||||
used++;
|
||||
@@ -773,15 +797,15 @@ function _SimpleDivide(result, leftOperand, rightOperand, roundingMode)
|
||||
break;
|
||||
}
|
||||
// Borrow one digit
|
||||
[n1._mantissa addObject:0];
|
||||
Array.prototype.push.call(n1._mantissa, 0);
|
||||
result._exponent--;
|
||||
}
|
||||
|
||||
// Zeros must be added while enough digits are fetched to do the
|
||||
// subtraction, but first time round this just add zeros at the
|
||||
// start of the number , increases k, and hence reduces
|
||||
// the avaialble precision. To solve this only inc k/add zeros if
|
||||
// this isnt first time round.
|
||||
// the available precision. To solve this only inc k/add zeros if
|
||||
// this isn't first time round.
|
||||
if (!firsttime)
|
||||
{
|
||||
k++;
|
||||
@@ -886,7 +910,7 @@ function CPDecimalDivide(result, leftOperand, rightOperand, roundingMode)
|
||||
return error;
|
||||
}
|
||||
|
||||
// Simple multiply O(n^2) , replace with something faster, likee divide-n-conquer algo?
|
||||
// Simple multiply O(n^2) , replace with something faster, like divide-n-conquer algo?
|
||||
function _SimpleMultiply(result, leftOperand, rightOperand, roundingMode, powerMode)
|
||||
{
|
||||
var error = CPCalculationNoError,
|
||||
@@ -898,11 +922,11 @@ function _SimpleMultiply(result, leftOperand, rightOperand, roundingMode, powerM
|
||||
|
||||
// Do every digit of the second number
|
||||
var i = 0;
|
||||
for (; i < [rightOperand._mantissa count]; i++)
|
||||
for (; i < rightOperand._mantissa.length; i++)
|
||||
{
|
||||
_CPDecimalSetZero(n);
|
||||
|
||||
n._exponent = [rightOperand._mantissa count] - i - 1;
|
||||
n._exponent = rightOperand._mantissa.length - i - 1;
|
||||
carry = 0;
|
||||
d = rightOperand._mantissa[i];
|
||||
|
||||
@@ -910,7 +934,7 @@ function _SimpleMultiply(result, leftOperand, rightOperand, roundingMode, powerM
|
||||
continue;
|
||||
|
||||
var j = 0;
|
||||
for (j = [leftOperand._mantissa count]-1; j >= 0; j--)
|
||||
for (j = leftOperand._mantissa.length - 1; j >= 0; j--)
|
||||
{
|
||||
e = leftOperand._mantissa[j] * d + carry;
|
||||
if (e >= 10)
|
||||
@@ -943,11 +967,11 @@ function _SimpleMultiply(result, leftOperand, rightOperand, roundingMode, powerM
|
||||
result._exponent += exp;
|
||||
|
||||
// perform round to CPDecimalMaxDigits
|
||||
if ([result._mantissa count] > CPDecimalMaxDigits && !powerMode)
|
||||
if (result._mantissa.length > CPDecimalMaxDigits && !powerMode)
|
||||
{
|
||||
result._isCompact = NO;
|
||||
var scale = CPDecimalMaxDigits - ([result._mantissa count] + result._exponent);
|
||||
CPDecimalRound(result, result, scale ,roundingMode); // calls compact
|
||||
var scale = CPDecimalMaxDigits - (result._mantissa.length + result._exponent);
|
||||
CPDecimalRound(result, result, scale, roundingMode); // calls compact
|
||||
|
||||
error = CPCalculationLossOfPrecision;
|
||||
}
|
||||
@@ -1001,10 +1025,10 @@ function CPDecimalMultiply(result, leftOperand, rightOperand, roundingMode, powe
|
||||
n1._isNegative = NO;
|
||||
n2._isNegative = NO;
|
||||
|
||||
// below is equiv of simple compare
|
||||
// below is equiv. of simple compare
|
||||
var comp = 0,
|
||||
ll = [n1._mantissa count],
|
||||
lr = [n2._mantissa count];
|
||||
ll = n1._mantissa.length,
|
||||
lr = n2._mantissa.length;
|
||||
if (ll == lr)
|
||||
comp = CPOrderedSame;
|
||||
else if (ll > lr)
|
||||
@@ -1133,7 +1157,7 @@ function CPDecimalPower(result, dcm, power, roundingMode)
|
||||
/*!
|
||||
@ingroup foundation
|
||||
Normalises 2 CPDecimals. Normalisation is the process of modifying a
|
||||
numbers manitssa to ensure that both CPDecimals have the same exponent.
|
||||
numbers mantissa to ensure that both CPDecimals have the same exponent.
|
||||
@param dcm1 the first CPDecimal
|
||||
@param dcm2 the second CPDecimal
|
||||
@param roundingMode the rounding mode for the operation
|
||||
@@ -1159,8 +1183,8 @@ function CPDecimalNormalize(dcm1, dcm2, roundingMode, longMode)
|
||||
e2 = dcm2._exponent;
|
||||
|
||||
// Add zeros
|
||||
var l2 = [dcm2._mantissa count],
|
||||
l1 = [dcm1._mantissa count],
|
||||
var l2 = dcm2._mantissa.length,
|
||||
l1 = dcm1._mantissa.length,
|
||||
l = 0;
|
||||
|
||||
var e = 0;
|
||||
@@ -1178,16 +1202,16 @@ function CPDecimalNormalize(dcm1, dcm2, roundingMode, longMode)
|
||||
e = e1 - e2;
|
||||
|
||||
if (e2 > e1)
|
||||
l = MIN((CPDecimalMaxDigits*factor) - l2, e); //(e2 - e1));
|
||||
l = MIN((CPDecimalMaxDigits * factor) - l2, e); //(e2 - e1));
|
||||
else
|
||||
l = MIN((CPDecimalMaxDigits*factor) - l1, e); //(e1 - e2));
|
||||
l = MIN((CPDecimalMaxDigits * factor) - l1, e); //(e1 - e2));
|
||||
|
||||
for (var i = 0; i < l; i++)
|
||||
{
|
||||
if (e2 > e1)
|
||||
[dcm2._mantissa addObject:0]; //dcm2._mantissa[i + l2] = 0;
|
||||
Array.prototype.push.call(dcm2._mantissa, 0); //dcm2._mantissa[i + l2] = 0;
|
||||
else
|
||||
[dcm1._mantissa addObject:0];
|
||||
Array.prototype.push.call(dcm1._mantissa, 0);
|
||||
}
|
||||
if (e2 > e1)
|
||||
{
|
||||
@@ -1222,7 +1246,7 @@ function CPDecimalNormalize(dcm1, dcm2, roundingMode, longMode)
|
||||
// Some zeros where cut of again by compacting
|
||||
if (e2 > e1)
|
||||
{
|
||||
l1 = [dcm1._mantissa count];
|
||||
l1 = dcm1._mantissa.length;
|
||||
l = MIN((CPDecimalMaxDigits * factor) - l1, ABS(dcm1._exponent - dcm2._exponent));
|
||||
for (var i = 0; i < l; i++)
|
||||
{
|
||||
@@ -1233,7 +1257,7 @@ function CPDecimalNormalize(dcm1, dcm2, roundingMode, longMode)
|
||||
}
|
||||
else
|
||||
{
|
||||
l2 = [dcm2._mantissa count];
|
||||
l2 = dcm2._mantissa.length;
|
||||
l = MIN((CPDecimalMaxDigits * factor) - l2, ABS(dcm2._exponent - dcm1._exponent));
|
||||
for (var i = 0; i < l; i++)
|
||||
{
|
||||
@@ -1277,7 +1301,7 @@ function CPDecimalRound(result, dcm, scale ,roundingMode)
|
||||
|
||||
_CPDecimalSet(result,dcm);
|
||||
|
||||
var mc = [result._mantissa count],
|
||||
var mc = result._mantissa.length,
|
||||
l = mc + scale + result._exponent;
|
||||
|
||||
if (mc <= l)
|
||||
@@ -1326,7 +1350,7 @@ function CPDecimalRound(result, dcm, scale ,roundingMode)
|
||||
break;
|
||||
}
|
||||
// cut mantissa
|
||||
result._mantissa = [result._mantissa subarrayWithRange:CPMakeRange(0, l)];
|
||||
result._mantissa = Array.prototype.slice.call(result._mantissa, 0, l);
|
||||
|
||||
if (up)
|
||||
{
|
||||
@@ -1349,7 +1373,7 @@ function CPDecimalRound(result, dcm, scale ,roundingMode)
|
||||
// Overflow in rounding.
|
||||
// Add one zero add the end. There must be space as
|
||||
// we just cut off some digits.
|
||||
[result._mantissa addObject:0];
|
||||
Array.prototype.push.call(result._mantissa, 0);
|
||||
}
|
||||
else
|
||||
result._exponent++;
|
||||
@@ -1368,7 +1392,7 @@ function CPDecimalRound(result, dcm, scale ,roundingMode)
|
||||
function CPDecimalCompact(dcm)
|
||||
{
|
||||
// if positive or zero exp leading zeros simply delete, trailing ones u need to increment exponent
|
||||
if (!dcm || [dcm._mantissa count] == 0 || CPDecimalIsNotANumber(dcm) )
|
||||
if (!dcm || dcm._mantissa.length == 0 || CPDecimalIsNotANumber(dcm) )
|
||||
return;
|
||||
|
||||
|
||||
@@ -1379,20 +1403,20 @@ function CPDecimalCompact(dcm)
|
||||
return;
|
||||
}
|
||||
// leading zeros, when exponent is zero these mean we need to move our decimal point to compact
|
||||
// if exp is zero does it make sense to have them? dont think so so delete them
|
||||
// if exp is zero does it make sense to have them? don't think so so delete them
|
||||
while (dcm._mantissa[0] === 0)
|
||||
{
|
||||
[dcm._mantissa removeObjectAtIndex:0];
|
||||
Array.prototype.shift.call(dcm._mantissa);
|
||||
}
|
||||
// trailing zeros, strip them
|
||||
while ([dcm._mantissa lastObject] === 0)
|
||||
while (dcm._mantissa[dcm._mantissa.length - 1] === 0)
|
||||
{
|
||||
[dcm._mantissa removeLastObject];
|
||||
Array.prototype.pop.call(dcm._mantissa);
|
||||
dcm._exponent++;
|
||||
if (dcm._exponent + 1 > CPDecimalMaxExponent)
|
||||
{
|
||||
// TODO: test case for this
|
||||
// overflow if we compact anymore, so dont
|
||||
// overflow if we compact anymore, so don't
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1411,13 +1435,18 @@ function CPDecimalString(dcm, locale)
|
||||
{
|
||||
// Cocoa seems to just add all the zeros... this maybe controlled by locale,
|
||||
// will check.
|
||||
if (dcm._isNaN)
|
||||
return @"NaN";
|
||||
|
||||
var string = @"",
|
||||
i = 0;
|
||||
|
||||
if (dcm._isNegative)
|
||||
string += "-";
|
||||
var k = [dcm._mantissa count],
|
||||
|
||||
var k = dcm._mantissa.length,
|
||||
l = ((dcm._exponent < 0) ? dcm._exponent : 0) + k;
|
||||
|
||||
if (l < 0)
|
||||
{
|
||||
// add leading zeros
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
@import "CPArray.j"
|
||||
@import "CPEnumerator.j"
|
||||
@import "CPException.j"
|
||||
@import "CPNull.j"
|
||||
@import "CPObject.j"
|
||||
|
||||
|
||||
/* @ignore */
|
||||
@implementation _CPDictionaryValueEnumerator : CPEnumerator
|
||||
{
|
||||
@@ -345,7 +345,7 @@
|
||||
@return A new array containing the keys corresponding to all occurrences of anObject in the receiver. If no object matching anObject is found, returns an empty array.
|
||||
|
||||
Each object in the receiver is sent an isEqual: message to determine if it's equal to anObject.
|
||||
If the check for isEqual fails a check is made to see if the two objects are the same object. This provides compatability for JSObjects.
|
||||
If the check for isEqual fails a check is made to see if the two objects are the same object. This provides compatibility for JSObjects.
|
||||
*/
|
||||
- (CPArray)allKeysForObject:(id)anObject
|
||||
{
|
||||
@@ -594,11 +594,11 @@
|
||||
|
||||
/*!
|
||||
@class CPMutableDictionary
|
||||
@ingroup compatability
|
||||
@ingroup compatibility
|
||||
|
||||
This class is just an empty subclass of CPDictionary.
|
||||
CPDictionary already implements mutable methods and
|
||||
this class only exists for source compatability.
|
||||
this class only exists for source compatibility.
|
||||
*/
|
||||
@implementation CPMutableDictionary : CPDictionary
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
@import "CPObject.j"
|
||||
|
||||
|
||||
/*!
|
||||
@class CPEnumerator
|
||||
@ingroup foundation
|
||||
|
||||
@@ -24,11 +24,10 @@
|
||||
@import "CPObject.j"
|
||||
@import "CPString.j"
|
||||
|
||||
|
||||
CPInvalidArgumentException = "CPInvalidArgumentException";
|
||||
CPUnsupportedMethodException = "CPUnsupportedMethodException";
|
||||
CPRangeException = "CPRangeException";
|
||||
CPInternalInconsistencyException = "CPInternalInconsistencyException";
|
||||
CPInvalidArgumentException = @"CPInvalidArgumentException";
|
||||
CPUnsupportedMethodException = @"CPUnsupportedMethodException";
|
||||
CPRangeException = @"CPRangeException";
|
||||
CPInternalInconsistencyException = @"CPInternalInconsistencyException";
|
||||
|
||||
/*!
|
||||
@class CPException
|
||||
@@ -90,7 +89,9 @@ if (input == nil)
|
||||
*/
|
||||
- (id)initWithName:(CPString)aName reason:(CPString)aReason userInfo:(CPDictionary)aUserInfo
|
||||
{
|
||||
if (self = [super init])
|
||||
self = [super init];
|
||||
|
||||
if (self)
|
||||
{
|
||||
name = aName;
|
||||
message = aReason;
|
||||
@@ -162,9 +163,9 @@ if (input == nil)
|
||||
|
||||
@end
|
||||
|
||||
var CPExceptionNameKey = "CPExceptionNameKey",
|
||||
CPExceptionReasonKey = "CPExceptionReasonKey",
|
||||
CPExceptionUserInfoKey = "CPExceptionUserInfoKey";
|
||||
var CPExceptionNameKey = @"CPExceptionNameKey",
|
||||
CPExceptionReasonKey = @"CPExceptionReasonKey",
|
||||
CPExceptionUserInfoKey = @"CPExceptionUserInfoKey";
|
||||
|
||||
@implementation CPException (CPCoding)
|
||||
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
@import "CPException.j"
|
||||
@import "CPObject.j"
|
||||
|
||||
|
||||
@implementation CPFormatter : CPObject
|
||||
|
||||
/*!
|
||||
@@ -57,13 +56,11 @@
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
/*- (CPAttributedString)attributedStringForObjectValue:(id)anObject withDefaultAttributes:(CPDictionary)attributes
|
||||
{
|
||||
|
||||
}*/
|
||||
|
||||
|
||||
/*!
|
||||
The default implementation of this method invokes stringForObjectValue:.
|
||||
|
||||
@@ -73,14 +70,13 @@
|
||||
this method if you want the dollar signs in displayed strings removed for editing.
|
||||
|
||||
@param anObject the object for which to return an editing string
|
||||
@return CPString object that is used for editing the textual represntation of an object
|
||||
@return CPString object that is used for editing the textual representation of an object
|
||||
*/
|
||||
- (CPString)editingStringForObjectValue:(id)anObject
|
||||
{
|
||||
return [self stringForObjectValue:anObject];
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
The default implementation of this method raises an exception.
|
||||
|
||||
@@ -93,7 +89,7 @@
|
||||
|
||||
@param anObject if conversion is successful, upon return contains the object created from the string
|
||||
@param aString the string to parse.
|
||||
@param anError if non-nil, if there is an error durring the conversion, upon return contains an CPString object that describes the problem.
|
||||
@param anError if non-nil, if there is an error during the conversion, upon return contains an CPString object that describes the problem.
|
||||
@return BOOL YES if the conversion from the string to a view content object was successful, otherwise NO.
|
||||
*/
|
||||
- (BOOL)getObjectValue:(id)anObject forString:(CPString)aString errorDescription:(CPString)anError
|
||||
@@ -102,7 +98,6 @@
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Returns a Boolean value that indicates whether a partial string is valid.
|
||||
|
||||
@@ -122,7 +117,7 @@
|
||||
|
||||
@param aPartialString the text currently in the view.
|
||||
@param aNewString if aPartialString needs to be modified, upon return contains the replacement string.
|
||||
@param anError if non-nil, if validation fails contains a CPString object that desibes the problem.
|
||||
@param anError if non-nil, if validation fails contains a CPString object that describes the problem.
|
||||
@return YES if aPartialString is an acceptable value, otherwise NO.
|
||||
*/
|
||||
- (BOOL)isPartialStringValid:(CPString)aPartialString newEditingString:(CPString)aNewString errorDescription:(CPString)anError
|
||||
@@ -146,7 +141,7 @@
|
||||
@param aProposedSelectedRange The selection range that will be used if the string is accepted or replaced.
|
||||
@param originalString The original string, before the proposed change.
|
||||
@param originalSelectedRange The selection range over which the change is to take place.
|
||||
@param error If non-nil, if validation fails contains an CPString object that descibes the problem.
|
||||
@param error If non-nil, if validation fails contains an CPString object that describes the problem.
|
||||
@return YES if aPartialString is acceptable, otherwise NO.
|
||||
|
||||
*/
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
@import <Foundation/CPObject.j>
|
||||
@import "CPArray.j"
|
||||
@import "CPObject.j"
|
||||
@import "CPOperation.j"
|
||||
|
||||
|
||||
/*!
|
||||
@class CPFunctionOperation
|
||||
@brief Represents an operation using a JavaScript function that can be run in an CPOperationQueue
|
||||
@@ -32,7 +32,6 @@
|
||||
CPArray _functions;
|
||||
}
|
||||
|
||||
|
||||
- (void)main
|
||||
{
|
||||
if (_functions && [_functions count] > 0)
|
||||
@@ -50,7 +49,9 @@
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if (self = [super init])
|
||||
self = [super init];
|
||||
|
||||
if (self)
|
||||
{
|
||||
_functions = [];
|
||||
}
|
||||
|
||||
@@ -1,10 +1,29 @@
|
||||
/*
|
||||
* CPIndexPath.j
|
||||
* Foundation
|
||||
*
|
||||
* Copyright 2008, 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 "CPObject.j"
|
||||
@import "CPArray.j"
|
||||
@import "CPException.j"
|
||||
@import "CPObject.j"
|
||||
@import "CPRange.j"
|
||||
@import "CPSortDescriptor.j"
|
||||
@import "CPException.j"
|
||||
|
||||
|
||||
@implementation CPIndexPath : CPObject
|
||||
{
|
||||
|
||||
@@ -20,10 +20,10 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
@import "CPArray.j"
|
||||
@import "CPObject.j"
|
||||
@import "CPRange.j"
|
||||
|
||||
|
||||
#define _CPMaxRange(aRange) ((aRange).location + (aRange).length)
|
||||
#define _CPMakeRange(aLocation, aLength) { location:(aLocation), length:aLength }
|
||||
#define _CPMakeRangeCopy(aRange) { location:(aRange).location, length:(aRange).length }
|
||||
@@ -159,7 +159,7 @@
|
||||
var rangesCount = _ranges.length,
|
||||
otherRanges = anIndexSet._ranges;
|
||||
|
||||
// If we have a discrepency in the number of ranges or the number of indexes,
|
||||
// If we have a discrepancy in the number of ranges or the number of indexes,
|
||||
// simply return NO.
|
||||
if (rangesCount !== otherRanges.length || _count !== anIndexSet._count)
|
||||
return NO;
|
||||
@@ -215,7 +215,7 @@
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c YES if the receving index set contains all the indices in the argument.
|
||||
Returns \c YES if the receiving index set contains all the indices in the argument.
|
||||
@param anIndexSet the set of indices to check for in the receiving index set
|
||||
*/
|
||||
- (BOOL)containsIndexes:(CPIndexSet)anIndexSet
|
||||
@@ -836,7 +836,7 @@ var CPIndexSetCountKey = @"CPIndexSetCountKey",
|
||||
/*!
|
||||
Creates a deep copy of the index set. The returned copy
|
||||
is mutable. The reason for the two copy methods is for
|
||||
source compatability with GNUStep code.
|
||||
source compatibility with GNUStep code.
|
||||
@return the index set copy
|
||||
*/
|
||||
- (id)copy
|
||||
@@ -847,7 +847,7 @@ var CPIndexSetCountKey = @"CPIndexSetCountKey",
|
||||
/*!
|
||||
Creates a deep copy of the index set. The returned copy
|
||||
is mutable. The reason for the two copy methods is for
|
||||
source compatability with GNUStep code.
|
||||
source compatibility with GNUStep code.
|
||||
@return the index set copy
|
||||
*/
|
||||
- (id)mutableCopy
|
||||
@@ -859,11 +859,11 @@ var CPIndexSetCountKey = @"CPIndexSetCountKey",
|
||||
|
||||
/*!
|
||||
@class CPMutableIndexSet
|
||||
@ingroup compatability
|
||||
@ingroup compatibility
|
||||
|
||||
This class is an empty of subclass of CPIndexSet.
|
||||
CPIndexSet already implements mutable methods, and
|
||||
this class only exists for source compatability.
|
||||
this class only exists for source compatibility.
|
||||
*/
|
||||
@implementation CPMutableIndexSet : CPIndexSet
|
||||
|
||||
|
||||
@@ -20,10 +20,8 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
@import "CPException.j"
|
||||
@import "CPObject.j"
|
||||
|
||||
|
||||
/*!
|
||||
@class CPInvocation
|
||||
@ingroup foundation
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
@import "CPObject.j"
|
||||
@import "CPOperation.j"
|
||||
|
||||
|
||||
/*!
|
||||
@class CPInvocationOperation
|
||||
@brief Represents an operation using an invocation that can be run in an CPOperationQueue
|
||||
|
||||
@@ -20,8 +20,9 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
@import "CPException.j"
|
||||
@import "CPObject.j"
|
||||
|
||||
@import "CPRunLoop.j"
|
||||
|
||||
CPJSONPConnectionCallbacks = {};
|
||||
|
||||
@@ -68,16 +69,19 @@ CPJSONPCallbackReplacementString = @"${JSONP_CALLBACK}";
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
_request = aRequest;
|
||||
_delegate = aDelegate;
|
||||
if (self)
|
||||
{
|
||||
_request = aRequest;
|
||||
_delegate = aDelegate;
|
||||
|
||||
_callbackParameter = aString;
|
||||
_callbackParameter = aString;
|
||||
|
||||
if (!_callbackParameter && [[_request URL] absoluteString].indexOf(CPJSONPCallbackReplacementString) < 0)
|
||||
[CPException raise:CPInvalidArgumentException reason:@"JSONP source specified without callback parameter or CPJSONPCallbackReplacementString in URL."];
|
||||
if (!_callbackParameter && [[_request URL] absoluteString].indexOf(CPJSONPCallbackReplacementString) < 0)
|
||||
[CPException raise:CPInvalidArgumentException reason:@"JSONP source specified without callback parameter or CPJSONPCallbackReplacementString in URL."];
|
||||
|
||||
if (shouldStartImmediately)
|
||||
[self start];
|
||||
if (shouldStartImmediately)
|
||||
[self start];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
@import "CPArray.j"
|
||||
@import "CPDictionary.j"
|
||||
@import "CPException.j"
|
||||
@import "CPIndexSet.j"
|
||||
@import "CPNull.j"
|
||||
@import "CPObject.j"
|
||||
@import "CPSet.j"
|
||||
|
||||
@@ -209,20 +209,16 @@ var _changeKindForSetMutationKind = function(mutationKind)
|
||||
{
|
||||
switch (mutationKind)
|
||||
{
|
||||
case CPKeyValueUnionSetMutation:
|
||||
return CPKeyValueChangeInsertion;
|
||||
case CPKeyValueMinusSetMutation:
|
||||
return CPKeyValueChangeRemoval;
|
||||
case CPKeyValueIntersectSetMutation:
|
||||
return CPKeyValueChangeRemoval;
|
||||
case CPKeyValueSetSetMutation:
|
||||
return CPKeyValueChangeReplacement;
|
||||
case CPKeyValueUnionSetMutation: return CPKeyValueChangeInsertion;
|
||||
case CPKeyValueMinusSetMutation: return CPKeyValueChangeRemoval;
|
||||
case CPKeyValueIntersectSetMutation: return CPKeyValueChangeRemoval;
|
||||
case CPKeyValueSetSetMutation: return CPKeyValueChangeReplacement;
|
||||
}
|
||||
}
|
||||
|
||||
var kvoNewAndOld = CPKeyValueObservingOptionNew | CPKeyValueObservingOptionOld,
|
||||
DependentKeysKey = "$KVODEPENDENT",
|
||||
KVOProxyKey = "$KVOPROXY";
|
||||
var kvoNewAndOld = CPKeyValueObservingOptionNew | CPKeyValueObservingOptionOld,
|
||||
DependentKeysKey = "$KVODEPENDENT",
|
||||
KVOProxyKey = "$KVOPROXY";
|
||||
|
||||
//rule of thumb: _ methods are called on the real proxy object, others are called on the "fake" proxy object (aka the real object)
|
||||
|
||||
@@ -777,7 +773,7 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew | CPKeyValueObservingOptionOld,
|
||||
if (setMutationKind)
|
||||
{
|
||||
//old and new values for unordered to-many relationships can only be calculated before
|
||||
//set precalculated hidden new value as soon as "didChangeValue..." is called!
|
||||
//set recalculated hidden new value as soon as "didChangeValue..." is called!
|
||||
var newValue = changes[_CPKeyValueChangeSetMutationNewValueKey];
|
||||
[changes setValue:newValue forKey:CPKeyValueChangeNewKey];
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
@import "CPString.j"
|
||||
@import "CPValue.j"
|
||||
|
||||
|
||||
var CPArchiverReplacementClassNames = nil;
|
||||
|
||||
var _CPKeyedArchiverDidEncodeObjectSelector = 1,
|
||||
@@ -84,7 +83,7 @@ var _CPKeyedArchiverStringClass = Nil,
|
||||
|
||||
@delegate -(void)archiverDidFinish:(CPKeyedArchiver)archiver;
|
||||
Called when the archiver finishes encoding.
|
||||
@param archiver the arhiver that finished encoding
|
||||
@param archiver the archiver that finished encoding
|
||||
|
||||
@delegate -(id)archiver:(CPKeyedArchiver)archiver willEncodeObject:(id)object;
|
||||
Called when an object is about to be encoded. Allows the delegate to replace
|
||||
@@ -371,7 +370,7 @@ var _CPKeyedArchiverStringClass = Nil,
|
||||
}
|
||||
|
||||
/*!
|
||||
Encdoes an object
|
||||
Encodes an object
|
||||
@param anObject the object to encode
|
||||
@param aKey the key to associate with the object
|
||||
*/
|
||||
@@ -476,7 +475,7 @@ var _CPKeyedArchiverEncodeObject = function(self, anObject, isConditional)
|
||||
// We wrap primitive JavaScript objects in a unique subclass of CPValue.
|
||||
// This way, when we unarchive, we know to unwrap it, since
|
||||
// _CPKeyedArchiverValue should not be used anywhere else.
|
||||
if (anObject !== nil && !anObject.isa)
|
||||
if (anObject !== nil && anObject !== undefined && !anObject.isa)
|
||||
anObject = [_CPKeyedArchiverValue valueWithJSObject:anObject];
|
||||
|
||||
// Get the proper replacement object
|
||||
|
||||
@@ -21,15 +21,15 @@
|
||||
*/
|
||||
|
||||
@import "CPArray.j"
|
||||
@import "CPCoder.j"
|
||||
@import "CPData.j"
|
||||
@import "CPDictionary.j"
|
||||
@import "CPCoder.j"
|
||||
@import "CPException.j"
|
||||
@import "CPKeyedArchiver.j"
|
||||
@import "CPNull.j"
|
||||
@import "CPNumber.j"
|
||||
@import "CPString.j"
|
||||
|
||||
|
||||
CPInvalidUnarchiveOperationException = @"CPInvalidUnarchiveOperationException";
|
||||
|
||||
var _CPKeyedUnarchiverCannotDecodeObjectOfClassNameOriginalClassesSelector = 1 << 0,
|
||||
@@ -89,7 +89,7 @@ var CPArrayClass = Ni
|
||||
@delegate -(id)unarchiver:(CPKeyedUnarchiver)unarchiver didDecodeObject:(id)object;
|
||||
Called when the unarchiver decodes an object.
|
||||
@param unarchiver the unarchiver doing the decoding
|
||||
@param object the decoded objec
|
||||
@param object the decoded object
|
||||
@return a substitute to use for the decoded object. This can be the same object argument provide,
|
||||
another object or \c nil.
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
@import "CPException.j"
|
||||
@import "CPObject.j"
|
||||
|
||||
|
||||
/*!
|
||||
@class CPNotification
|
||||
@ingroup foundation
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
@import "CPNotification.j"
|
||||
@import "CPNull.j"
|
||||
|
||||
|
||||
var CPNotificationDefaultCenter = nil;
|
||||
|
||||
/*!
|
||||
@@ -75,7 +74,7 @@ var CPNotificationDefaultCenter = nil;
|
||||
Adds an object as an observer. The observer will receive notifications with the specified name
|
||||
and/or containing the specified object (depending on if they are \c nil.
|
||||
@param anObserver the observing object
|
||||
@param aSelector the message sent to the observer when a notification occurrs
|
||||
@param aSelector the message sent to the observer when a notification occurs
|
||||
@param aNotificationName the name of the notification the observer wants to watch
|
||||
@param anObject the object in the notification the observer wants to watch
|
||||
*/
|
||||
|
||||