Compare commits

..
Author SHA1 Message Date
Alexander LjungbergandStefan Eilers b6e77f4be3 Fixed: menus not closing on left click.
Previously, clicking outside a menu on a control would not close the menu. Also clicking on the menu header again would open a second menu.

This error was caused by the control receiving the click and starting its own tracking, depriving the menu of the mouse up event it was awaiting.

The behaviour to wait for the mouse up was wrong to begin with. Menus should close on mouse down.

This fix closes the menu on left mouse down anywhere but the menu, while still allowing the click to pass through to any control underneath the cursor.

Fixes #1833.
2013-03-14 13:23:22 +01:00
Alexander Ljungberg 81d0812172 Merge branch 'refs/heads/slevenbits-platform-resize-fix' into slevenbits 2013-03-11 17:49:38 +00:00
Alexander Ljungberg a426802b1a Merge branch 'master' into slevenbits 2013-02-24 17:54:41 +00:00
Alexander Ljungberg 64f85002b1 Merge branch 'master' of github.com:slevenbits/cappuccino into slevenbits 2013-02-19 23:18:01 +00:00
Alexander Ljungberg d4b7fd635d Merge branch 'refs/heads/master' into slevenbits 2013-02-19 23:16:56 +00:00
Ilya Kulakov cca8dd0056 Fix comment to -[CPCollectionView setItemPrototype:].
Item prototype is a subclass of CPViewController, not CPView.
2013-02-20 04:44:46 +07:00
Alexander Ljungberg d03ae79092 Merge branch 'refs/heads/master' into slevenbits 2013-02-19 10:49:39 +00:00
Alexander Ljungberg cd2b2a4d61 Merge branch 'refs/heads/master' into slevenbits 2013-02-06 16:37:49 +00:00
Alexander Ljungberg 0a8214b4cb Merge branch 'refs/heads/master' into slevenbits 2013-02-04 16:51:29 +00:00
Alexander Ljungberg 2be644d4b1 Merge branch 'refs/heads/master' into slevenbits 2013-02-02 11:15:29 +00:00
Alexander Ljungberg ce9531c80c Merge tag 'v0.9.6' into slevenbits 2013-01-21 12:43:45 +00:00
Alexander Ljungberg 6aa62762d6 Merge branch 'master' of github.com:slevenbits/cappuccino into slevenbits 2013-01-15 16:09:35 +00:00
Alexander Ljungberg 18bf69d2f3 Merge branch 'refs/heads/0.9.6' into slevenbits 2013-01-15 16:09:24 +00:00
Aparajita Fishman 541c351757 Merge branch 'refs/heads/upstream' 2013-01-12 14:46:34 +07:00
Aparajita Fishman 94ee1af33b Merge branch 'refs/heads/upstream' 2013-01-12 09:11:48 +07:00
Aparajita Fishman 7f8d58d457 Merge branch 'refs/heads/new-window-resize' 2013-01-05 11:17:02 +08:00
Alexander Ljungberg a391e2787b Merge branch 'new-window-resize' into slevenbits 2013-01-04 12:07:03 +00:00
Aparajita Fishman d9d9ea9804 Merge branch 'new-window-resize' 2013-01-04 15:22:01 +08:00
Alexander Ljungberg 261c0df2e7 Merge branch 'refs/heads/master' into slevenbits 2012-12-31 17:39:14 +00:00
Alexander Ljungberg 2fd6e7432a Merge branch 'refs/heads/window-resize' into slevenbits 2012-12-31 17:39:07 +00:00
Aparajita Fishman 0d674c3496 Finished full window resize support
- The main run loop resets the cursor if it falls outside of all windows during a mouse move.
- Added cursors supported by CSS that are not in NSCursor.
- Code cleanup in CPCursor.
- Cursors now indicate available resize directions if there is a window min/max size.
- Reduced slop to 3, what it is in Cocoa.
- Added a second non-min/max window to the demo.
2012-12-26 14:54:27 -08:00
Aparajita Fishman a15b24b9be Support for resizing windows on all sides 2012-12-24 08:53:18 -08:00
Alexander Ljungberg d0988fa5b0 Merge branch 'refs/heads/slevenbits-tokenfield-close-fix' into slevenbits 2012-12-21 17:07:39 +00:00
Alexander Ljungberg b7031f2f77 Unit test token field autocomplete window close. 2012-12-21 16:53:21 +00:00
Alexander Ljungberg 588da9addb Fixed: token field access of DOM in non-DOM apps.
Without this fix, the internal [tokenField _editorValue] would check the DOM input element even if !PLATFORM(DOM), which could potentially crash unit tests and future non DOM implementations.

The fix returns an empty string for non-DOM platforms.
2012-12-21 16:44:35 +00:00
Alexander Ljungberg 8f8f1a0224 Fixed: token field autocomplete menu remaining after window closed.
Without this change, closing the window containing a token field showing an autocomplete menu would result in a detached autocomplete menu hanging around.

This fix checks for window close notifications and makes sure to dismiss the menu if the window closes.
2012-12-21 15:00:20 +00:00
Alexander Ljungberg 90640b824c Merge branch 'refs/heads/slevenbits-tokenfield-value-fix' into slevenbits 2012-12-14 15:14:15 +00:00
Alexander Ljungberg 252144950a Merge branch 'refs/heads/slevenbits-popover-firefox-fix' into slevenbits 2012-12-13 14:09:18 +00:00
Alexander Ljungberg 17e49c458e Merge branch 'refs/heads/slevenbits-key-popover-fix' into slevenbits 2012-12-12 18:17:34 +00:00
Alexander Ljungberg 7fbe571e04 Merge remote-tracking branch 'slevenbits/slevenbits-tokenfield-scroll-fix' into slevenbits 2012-12-12 17:50:41 +00:00
Alexander Ljungberg b0051603da Merge remote-tracking branch 'slevenbits/slevenbits-editable-tokenfield-fix' into slevenbits 2012-12-12 17:50:33 +00:00
Alexander Ljungberg 1bed7e7108 Merge remote-tracking branch 'slevenbits/slevenbits-editable-tokenfield-fix' into slevenbits 2012-12-11 17:28:17 +00:00
Alexander Ljungberg 60fd129bd9 Merge remote-tracking branch 'slevenbits/slevenbits-settimeout-fix' into slevenbits 2012-12-11 13:05:43 +00:00
Alexander Ljungberg d4f9e7cba4 Merge branch 'master' into slevenbits 2012-11-30 00:07:07 +00:00
Alexander Ljungberg db1bf80cd4 Merge branch 'refs/heads/slevenbits-tabbing-fix' into slevenbits 2012-11-26 23:33:30 +00:00
Alexander Ljungberg 2ea24ed2dc Merge branch 'slevenbits-tokenfield-autocomplete-position' into slevenbits 2012-11-26 13:41:39 +00:00
Alexander Ljungberg abfb23d931 Merge branch 'refs/heads/slevenbits-tab-view-resize-fix' into slevenbits 2012-11-25 18:00:20 +00:00
Alexander Ljungberg 868480ada5 Merge branch 'refs/heads/master' into slevenbits 2012-11-25 17:59:48 +00:00
Alexander Ljungberg 8902acba04 Merge branch 'master' into slevenbits 2012-11-17 11:58:46 +00:00
Alexander Ljungberg 9b9380c18e Merge branch 'refs/heads/master' into slevenbits 2012-11-15 17:15:18 +00:00
Aparajita Fishman 3992ca71c6 Merge branch 'clickedColumn' 2012-10-02 17:20:53 -04:00
Aparajita Fishman 3a04bb2957 Merge branch 'refs/heads/upstream' 2012-09-29 05:28:41 -04:00
Aparajita Fishman 1c3300b066 Merge branch 'tag-fix' 2012-09-28 16:21:27 -04:00
Aparajita Fishman b443cb806a Both cells and controls can have tags in IB, control tag should take precedence 2012-09-28 16:13:24 -04:00
Alexander Ljungberg adbc420e0f Merge branch 'master' into slevenbits 2012-09-04 16:39:20 +01:00
Alexander Ljungberg e95648ca16 Merge branch 'master' into slevenbits 2012-09-03 20:20:52 +01:00
Alexander Ljungberg d0d66227cb Merge branch 'master' into slevenbits 2012-09-03 11:36:33 +01:00
Alexander Ljungberg 9d57d02eb5 Merge branch 'master' into slevenbits 2012-09-02 23:12:16 +01:00
Alexander Ljungberg bc93b3f6c7 Merge branch 'master' into slevenbits 2012-08-31 22:31:58 +01:00
Alexander Ljungberg 63b57b886e Merge branch 'master' into slevenbits 2012-08-31 22:12:16 +01:00
Alexander Ljungberg 10f6c8e8f6 Merge branch 'master' into slevenbits 2012-08-16 19:14:36 +01:00
Alexander Ljungberg 7b3136dae3 Merge branch 'master' into slevenbits 2012-08-15 18:32:36 +01:00
Alexander Ljungberg b7ee0fe44d Merge branch 'master' into slevenbits 2012-08-15 13:39:09 +01:00
Alexander Ljungberg 0150271e67 Merge branch 'master' into slevenbits 2012-08-15 02:09:40 +01:00
Alexander Ljungberg e23ba0852b Merge branch 'master' of github.com:slevenbits/cappuccino into slevenbits 2012-08-11 19:36:01 +01:00
Alexander Ljungberg 7cae90f8f9 Merge branch 'master' into slevenbits 2012-08-11 19:35:39 +01:00
Aparajita Fishman 9e1d09909e Merge branch 'stringValue-fix' 2012-08-09 20:31:37 -07:00
Alexander Ljungberg 306f2c987c Merge branch 'master' of github.com:slevenbits/cappuccino into slevenbits 2012-08-10 03:55:23 +01:00
Alexander Ljungberg 42200ce567 Merge branch 'master' into slevenbits 2012-08-10 03:55:03 +01:00
Aparajita Fishman 79cd71d2ab Merge branch 'fix-xcc-warnings' 2012-08-09 12:17:52 -07:00
Aparajita Fishman 081cf61e68 Merge branch 'refs/heads/upstream' 2012-08-09 11:27:32 -07:00
Alexander Ljungberg ed0fd87646 Merge branch 'master' into slevenbits 2012-08-07 12:32:47 +01:00
Alexander Ljungberg 4136953752 Merge branch 'refs/heads/master' into slevenbits 2012-08-06 14:03:37 +01:00
Alexander Ljungberg e70430057e Merge branch 'master' of github.com:slevenbits/cappuccino into slevenbits 2012-08-05 12:39:19 +01:00
Alexander Ljungberg 8498e28b70 Merge branch 'master' into slevenbits 2012-08-05 12:37:55 +01:00
Eric Wong 7ad24efe4f Merge branch 'cpdecimalnumber-fix' 2012-08-05 10:10:40 +08:00
Alexander Ljungberg a055d6d97e Merge branch 'refs/heads/master' into slevenbits 2012-08-04 14:11:25 +01:00
Alexander Ljungberg 23ed09a84e Merge branch 'refs/heads/master' into slevenbits 2012-08-02 15:54:36 +01:00
Aparajita Fishman 8e6119000d Added CPViewController -isViewLoaded, fixed CPWindowController -setViewController to use that
Before this fix, CPWindowController -setViewController was unconditionally loading the view, which should not happen.
2012-07-26 06:39:31 -07:00
Alexander Ljungberg 1db154ac5b Merge branch 'refs/heads/master' into slevenbits 2012-07-26 13:34:45 +01:00
Alexander Ljungberg 7ab833495f Merge branch 'refs/heads/master' into slevenbits 2012-07-23 15:39:03 +02:00
Alexander Ljungberg 60a33b9592 Merge branch 'master' of github.com:slevenbits/cappuccino into slevenbits 2012-07-19 01:07:29 +01:00
Alexander Ljungberg 7429687932 Merge branch 'master' into slevenbits 2012-07-19 01:06:41 +01:00
Aparajita Fishman fe04cfbe1f Merge branch 'refs/heads/upstream' 2012-07-18 14:48:56 -07:00
Alexander Ljungberg d57f5427fb Merge branch 'master' into slevenbits 2012-07-18 19:23:05 +01:00
Aparajita Fishman 6537a44c02 Merge branch 'refs/heads/upstream' 2012-07-18 09:53:32 -07:00
Aparajita Fishman f8cc2eb670 Merge branch 'refs/heads/upstream' 2012-07-17 15:12:50 -07:00
Alexander Ljungberg c83b4bf3af Merge branch 'master' into slevenbits 2012-07-17 23:02:17 +01:00
Alexander Ljungberg 5c5d2e47a9 Merge branch 'master' into slevenbits 2012-07-17 21:11:45 +01:00
Alexander Ljungberg 9e20f209bf Merge branch 'master' of github.com:slevenbits/cappuccino into slevenbits 2012-07-16 03:17:39 +01:00
Alexander Ljungberg ce5c6d9b96 Merge branch 'master' into slevenbits 2012-07-16 03:17:12 +01:00
Aparajita Fishman c166a20b89 Merge branch 'dictionary-key-methods' 2012-07-15 09:28:15 -07:00
Alexander Ljungberg 1cbf927684 Merge branch 'master' of github.com:slevenbits/cappuccino into slevenbits 2012-07-14 14:13:05 +01:00
Alexander Ljungberg 9fdfc4025a Merge branch 'refs/heads/master' into slevenbits 2012-07-14 14:12:53 +01:00
Aparajita Fishman 4958b4c47b Merge branch 'master' of github.com:slevenbits/cappuccino 2012-07-13 21:05:36 -07:00
Aparajita Fishman fedb24c2f3 Merge branch 'text-size-theming' 2012-07-13 21:02:46 -07:00
Aparajita Fishman e61a2a296e Merge branch 'master' of github.com:cappuccino/cappuccino 2012-07-13 21:00:35 -07:00
Alexander Ljungberg 0e87659093 Merge branch 'refs/heads/master' into slevenbits 2012-07-13 15:35:29 +01:00
Alexander Ljungberg eb990b6d4f Merge branch 'refs/heads/master' into slevenbits 2012-07-13 11:38:49 +01:00
Aparajita Fishman 12ea224f21 Merge branch 'master' of github.com:cappuccino/cappuccino 2012-07-12 17:21:40 -07:00
Aparajita Fishman 98260630ac Merge branch 'master' of github.com:cappuccino/cappuccino 2012-07-12 15:17:06 -07:00
Aparajita Fishman ba7fa38924 Merge branch 'master' of github.com:cappuccino/cappuccino 2012-07-12 07:15:19 -07:00
Aparajita Fishman 744bbd15d7 Merge branch 'master' of github.com:cappuccino/cappuccino 2012-07-11 09:24:35 -07:00
Aparajita Fishman 61f683b2e3 Merge branch 'text-clip-fix' 2012-07-11 09:11:04 -07:00
Aparajita Fishman 49521b44fb Merge branch 'system-font' 2012-07-10 18:54:42 -07:00
Aparajita Fishman f76404ef5e Merge branch 'refs/heads/system-font' 2012-07-10 16:41:06 -07:00
Aparajita Fishman 4df0b7c940 Merge branch 'archive-formatter' 2012-07-09 21:31:09 -07:00
Aparajita Fishman 6cd2c96152 Merge branch 'system-font' 2012-07-09 16:50:55 -07:00
Aparajita Fishman 106e21b79c Merge branch 'system-font' 2012-07-09 15:33:34 -07:00
Alexander Ljungberg 970dc912cb Merge branch 'master' into slevenbits 2012-07-09 20:32:07 +01:00
Alexander Ljungberg 6f84440bcd Merge branch 'master' into slevenbits 2012-07-08 21:29:08 +01:00
Alexander Ljungberg 4f69d82a4e Merge branch 'master' into slevenbits 2012-07-08 14:13:37 +01:00
Aparajita Fishman b85e44098b Merge branch 'CPComboBox' 2012-07-06 08:51:19 -07:00
1111 changed files with 41381 additions and 105029 deletions
-4
View File
@@ -5,15 +5,11 @@ Demos
./Aristo
WebSite
.push-package
*.xcodeproj*
*.xcodeproj/*.pbxuser
*.xcodeproj/*.perspectivev3
xcuserdata/
!*.xcodeproj/project.pbxproj
*.xCodeSupport/
*.XcodeSupport/
*XcodeSupport/
Tests/Manual/**/*.xcodeproj
*.sublime-project
*.sublime-workspace
*.tm_properties
+1 -1
View File
@@ -1,6 +1,6 @@
language: node_js
node_js:
- 0.8
install: ./bootstrap.sh --noprompt --directory ./narwhal
install: ./bootstrap.sh --quiet --noprompt --directory ./narwhal
script: jake test
env: PATH="$TRAVIS_BUILD_DIR/narwhal/bin:$PATH" CAPP_BUILD="$TRAVIS_BUILD_DIR/Build" NARWHAL_ENGINE=rhino
+1 -6
View File
@@ -20,14 +20,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "_CPObject+Theme.j"
@import "_CPToolTip.j"
@import "CALayer.j"
@import "CGGeometry.j"
@import "CPAccordionView.j"
@import "CPAlert.j"
@import "CPAnimation.j"
@import "CPAppearance.j"
@import "CPApplication.j"
@import "CPArrayController.j"
@import "CPBezierPath.j"
@@ -57,7 +55,6 @@
@import "CPController.j"
@import "CPCookie.j"
@import "CPCursor.j"
@import "CPDatePicker.j"
@import "CPDocument.j"
@import "CPDocumentController.j"
@import "CPEvent.j"
@@ -103,14 +100,12 @@
@import "CPTokenField.j"
@import "CPToolbar.j"
@import "CPToolbarItem.j"
@import "CPTrackingArea.j"
@import "CPTreeNode.j"
@import "CPUserDefaultsController.j"
@import "CPView.j"
@import "CPViewAnimation.j"
@import "CPViewController.j"
@import "CPVisualEffectView.j"
@import "CPWebView.j"
@import "CPWindow.j"
@import "CPWindowController.j"
@import "CPWorkspace.j"
@import "CPWorkspace.j"
+14 -14
View File
@@ -106,7 +106,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
_itemViews = [];
_expandedItemIndexes = [CPIndexSet indexSet];
[self setItemHeaderPrototype:[[CPButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 24.0)]];
[self setItemHeaderPrototype:[[CPButton alloc] initWithFrame:_CGRectMake(0.0, 0.0, 100.0, 24.0)]];
}
return self;
@@ -258,18 +258,18 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
- (void)setFrameSize:(CGSize)aSize
{
var width = CGRectGetWidth([self frame]);
var width = _CGRectGetWidth([self frame]);
[super setFrameSize:aSize];
if (width !== CGRectGetWidth([self frame]))
if (width !== _CGRectGetWidth([self frame]))
[self _invalidateItemsStartingAtIndex:0];
}
- (void)layoutSubviews
{
if (_items.length <= 0)
return [self setFrameSize:CGSizeMake(CGRectGetWidth([self frame]), 0.0)];
return [self setFrameSize:_CGSizeMake(_CGRectGetWidth([self frame]), 0.0)];
if (_dirtyItemIndex === CPNotFound)
return;
@@ -278,7 +278,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
var index = _dirtyItemIndex,
count = _itemViews.length,
width = CGRectGetWidth([self bounds]),
width = _CGRectGetWidth([self bounds]),
y = index > 0 ? CGRectGetMaxY([_itemViews[index - 1] frame]) : 0.0;
// Do this now (instead of after looping), so that if we are made dirty again in the middle we don't blow this value away.
@@ -293,7 +293,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
y = CGRectGetMaxY([itemView frame]);
}
[self setFrameSize:CGSizeMake(CGRectGetWidth([self frame]), y)];
[self setFrameSize:_CGSizeMake(_CGRectGetWidth([self frame]), y)];
}
@end
@@ -310,7 +310,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
- (id)initWithAccordionView:(CPAccordionView)anAccordionView
{
self = [super initWithFrame:CGRectMakeZero()];
self = [super initWithFrame:_CGRectMakeZero()];
if (self)
{
@@ -376,21 +376,21 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection
- (void)setFrameY:(float)aY width:(float)aWidth
{
var headerHeight = CGRectGetHeight([_headerView frame]);
var headerHeight = _CGRectGetHeight([_headerView frame]);
// Size to fit or something?
[_headerView setFrameSize:CGSizeMake(aWidth, headerHeight)];
[_contentView setFrameOrigin:CGPointMake(0.0, headerHeight)];
[_headerView setFrameSize:_CGSizeMake(aWidth, headerHeight)];
[_contentView setFrameOrigin:_CGPointMake(0.0, headerHeight)];
if ([self isCollapsed])
[self setFrame:CGRectMake(0.0, aY, aWidth, headerHeight)];
[self setFrame:_CGRectMake(0.0, aY, aWidth, headerHeight)];
else
{
var contentHeight = CGRectGetHeight([_contentView frame]);
var contentHeight = _CGRectGetHeight([_contentView frame]);
[_contentView setFrameSize:CGSizeMake(aWidth, contentHeight)];
[self setFrame:CGRectMake(0.0, aY, aWidth, contentHeight + headerHeight)];
[_contentView setFrameSize:_CGSizeMake(aWidth, contentHeight)];
[self setFrame:_CGRectMake(0.0, aY, aWidth, contentHeight + headerHeight)];
}
}
+82 -190
View File
@@ -41,10 +41,6 @@
@global CPApp
var CPAlertDelegate_alertShowHelp_ = 1 << 0,
CPAlertDelegate_alertDidEnd_returnCode_ = 1 << 1;
@typedef CPAlertStyle
/*
@global
@group CPAlertStyle
@@ -63,62 +59,6 @@ CPCriticalAlertStyle = 2;
var bottomHeight = 71;
@protocol CPAlertDelegate <CPObject>
@optional
- (BOOL)alertShowHelp:(CPAlert)alert;
- (void)alertDidEnd:(CPAlert)theAlert returnCode:(int)returnCode;
@end
@implementation _CPAlertThemeView : CPView
+ (CPString)defaultThemeClass
{
return @"alert";
}
+ (CPDictionary)themeAttributes
{
return @{
@"size": CGSizeMake(400.0, 110.0),
@"content-inset": CGInsetMake(15, 15, 15, 50),
@"informative-offset": 6,
@"button-offset": 10,
@"message-text-alignment": CPJustifiedTextAlignment,
@"message-text-color": [CPColor blackColor],
@"message-text-font": [CPFont boldSystemFontOfSize:13.0],
@"message-text-shadow-color": [CPNull null],
@"message-text-shadow-offset": CGSizeMakeZero(),
@"informative-text-alignment": CPJustifiedTextAlignment,
@"informative-text-color": [CPColor blackColor],
@"informative-text-font": [CPFont systemFontOfSize:12.0],
@"informative-text-shadow-color": [CPNull null],
@"informative-text-shadow-offset": CGSizeMakeZero(),
@"image-offset": CGPointMake(15, 12),
@"information-image": [CPNull null],
@"warning-image": [CPNull null],
@"error-image": [CPNull null],
@"help-image": [CPNull null],
@"help-image-left-offset": 15,
@"help-image-pressed": [CPNull null],
@"suppression-button-y-offset": 0.0,
@"suppression-button-x-offset": 0.0,
@"default-elements-margin": 3.0,
@"suppression-button-text-color": [CPColor blackColor],
@"suppression-button-text-font": [CPFont systemFontOfSize:12.0],
@"suppression-button-text-shadow-color": [CPNull null],
@"suppression-button-text-shadow-offset": 0.0,
@"modal-window-button-margin-y": 0.0,
@"modal-window-button-margin-x": 0.0,
@"standard-window-button-margin-y": 0.0,
@"standard-window-button-margin-x": 0.0,
};
}
@end
/*!
@ingroup appkit
@@ -143,33 +83,31 @@ var bottomHeight = 71;
*/
@implementation CPAlert : CPObject
{
BOOL _showHelp @accessors(property=showsHelp);
BOOL _showSuppressionButton @accessors(property=showsSuppressionButton);
BOOL _showHelp @accessors(property=showsHelp);
BOOL _showSuppressionButton @accessors(property=showsSuppressionButton);
CPAlertStyle _alertStyle @accessors(property=alertStyle);
CPString _title @accessors(property=title);
CPView _accessoryView @accessors(property=accessoryView);
CPImage _icon @accessors(property=icon);
CPAlertStyle _alertStyle @accessors(property=alertStyle);
CPString _title @accessors(property=title);
CPView _accessoryView @accessors(property=accessoryView);
CPImage _icon @accessors(property=icon);
CPArray _buttons @accessors(property=buttons, readonly);
CPCheckBox _suppressionButton @accessors(property=suppressionButton, readonly);
CPArray _buttons @accessors(property=buttons, readonly);
CPCheckBox _suppressionButton @accessors(property=suppressionButton, readonly);
id <CPAlertDelegate> _delegate @accessors(property=delegate);
id _modalDelegate;
SEL _didEndSelector @accessors(property=didEndSelector);
Function _didEndBlock;
unsigned _implementedDelegateMethods;
id _delegate @accessors(property=delegate);
id _modalDelegate;
SEL _didEndSelector;
_CPAlertThemeView _themeView @accessors(property=themeView, readonly);
CPWindow _window @accessors(property=window, readonly);
int _defaultWindowStyle;
_CPAlertThemeView _themeView @accessors(property=themeView, readonly);
CPWindow _window @accessors(property=window, readonly);
int _defaultWindowStyle;
CPImageView _alertImageView;
CPTextField _informativeLabel;
CPTextField _messageLabel;
CPButton _alertHelpButton;
CPImageView _alertImageView;
CPTextField _informativeLabel;
CPTextField _messageLabel;
CPButton _alertHelpButton;
BOOL _needsLayout;
BOOL _needsLayout;
}
#pragma mark Creating Alerts
@@ -248,30 +186,6 @@ var bottomHeight = 71;
return self;
}
#pragma mark -
#pragma mark Delegate
/*!
Set the delegate of the receiver
@param aDelegate the delegate object for the alert.
*/
- (void)setDelegate:(id <CPAlertDelegate>)aDelegate
{
if (_delegate === aDelegate)
return;
_delegate = aDelegate;
_implementedDelegateMethods = 0;
if ([_delegate respondsToSelector:@selector(alertShowHelp:)])
_implementedDelegateMethods |= CPAlertDelegate_alertShowHelp_;
if ([_delegate respondsToSelector:@selector(alertDidEnd:returnCode:)])
_implementedDelegateMethods |= CPAlertDelegate_alertDidEnd_returnCode_;
}
#pragma mark Accessors
- (CPTheme)theme
@@ -304,21 +218,22 @@ var bottomHeight = 71;
[_themeView setValue:aValue forThemeAttribute:aName];
}
- (void)setValue:(id)aValue forThemeAttribute:(CPString)aName inState:(ThemeState)aState
- (void)setValue:(id)aValue forThemeAttribute:(CPString)aName inState:(CPThemeState)aState
{
[_themeView setValue:aValue forThemeAttribute:aName inState:aState];
}
/*! @deprecated */
- (void)setWindowStyle:(int)style
/*! @deprecated
*/
- (void)setWindowStyle:(int)aStyle
{
CPLog.warn("DEPRECATED: setWindowStyle: is deprecated. use setTheme: instead");
[self setTheme:(style === CPHUDBackgroundWindowMask) ? [CPTheme defaultHudTheme] : [CPTheme defaultTheme]];
[self setTheme:(aStyle === CPHUDBackgroundWindowMask) ? [CPTheme defaultHudTheme] : [CPTheme defaultTheme]];
}
/*! @deprecated */
/*! @deprecated
*/
- (int)windowStyle
{
CPLog.warn("DEPRECATED: windowStyle: is deprecated. use theme instead");
@@ -327,19 +242,18 @@ var bottomHeight = 71;
/*!
Set the text of the alert's message.
set the text of the alert's message
@param aText CPString containing the text
*/
- (void)setMessageText:(CPString)text
- (void)setMessageText:(CPString)aText
{
[_messageLabel setStringValue:text];
[_messageLabel setStringValue:aText];
_needsLayout = YES;
}
/*!
Return the content of the message text.
return the content of the message text
@return CPString containing the message text
*/
- (CPString)messageText
@@ -348,13 +262,13 @@ var bottomHeight = 71;
}
/*!
Set the text of the alert's informative text.
set the text of the alert's informative text
@param aText CPString containing the informative text
*/
- (void)setInformativeText:(CPString)text
- (void)setInformativeText:(CPString)aText
{
[_informativeLabel setStringValue:text];
[_informativeLabel setStringValue:aText];
_needsLayout = YES;
}
@@ -371,7 +285,6 @@ var bottomHeight = 71;
/*!
Sets the title of the alert window.
This API is not present in Cocoa.
@param aTitle CPString containing the window title
*/
- (void)setTitle:(CPString)aTitle
@@ -381,7 +294,7 @@ var bottomHeight = 71;
}
/*!
Set the accessory view.
set the accessory view
@param aView the accessory view
*/
@@ -392,7 +305,7 @@ var bottomHeight = 71;
}
/*!
Set if the alert shows the suppression button.
set if alert shows the suppression button
@param shouldShowSuppressionButton YES or NO
*/
@@ -683,17 +596,6 @@ var bottomHeight = 71;
[CPApp runModalForWindow:_window];
}
/*!
The same as \c runModal, but executes the code in \c block when the
alert is dismissed.
*/
- (void)runModalWithDidEndBlock:(Function /*(CPAlert alert, int returnCode)*/)block
{
_didEndBlock = block;
[self runModal];
}
/*!
Runs the receiver modally as an alert sheet attached to a specified window.
@@ -728,20 +630,6 @@ var bottomHeight = 71;
[self beginSheetModalForWindow:aWindow modalDelegate:nil didEndSelector:nil contextInfo:nil];
}
/*!
Runs the receiver modally as an alert sheet attached to a specified window.
Executes the code in \c block when the alert is dismissed.
@param window The parent window for the sheet.
@param block Code block to execute on dismissal
*/
- (void)beginSheetModalForWindow:(CPWindow)aWindow didEndBlock:(Function /*(CPAlert alert, int returnCode)*/)block
{
_didEndBlock = block;
[self beginSheetModalForWindow:aWindow modalDelegate:nil didEndSelector:nil contextInfo:nil];
}
#pragma mark Private
/*!
@@ -754,7 +642,6 @@ var bottomHeight = 71;
_window = [[CPPanel alloc] initWithContentRect:frame styleMask:forceStyle || _defaultWindowStyle];
[_window setLevel:CPStatusWindowLevel];
[_window setPlatformWindow:[[CPApp keyWindow] platformWindow]];
if (_title)
[_window setTitle:_title];
@@ -781,7 +668,8 @@ var bottomHeight = 71;
*/
- (@action)_showHelp:(id)aSender
{
[self _sendDelegateAlertShowHelp];
if ([_delegate respondsToSelector:@selector(alertShowHelp:)])
[_delegate alertShowHelp:self];
}
/*
@@ -808,57 +696,61 @@ var bottomHeight = 71;
*/
- (void)_alertDidEnd:(CPWindow)aWindow returnCode:(int)returnCode contextInfo:(id)contextInfo
{
if (_didEndBlock)
{
if (typeof(_didEndBlock) === "function")
_didEndBlock(self, returnCode);
else
CPLog.warn("%s: didEnd block is not a function", [self description]);
if (_didEndSelector)
objj_msgSend(_modalDelegate, _didEndSelector, self, returnCode, contextInfo);
// didEnd blocks are transient
_didEndBlock = nil;
}
else if (_modalDelegate)
{
if (_didEndSelector)
_modalDelegate.isa.objj_msgSend3(_modalDelegate, _didEndSelector, self, returnCode, contextInfo);
}
else if (_delegate)
{
if (_didEndSelector)
_delegate.isa.objj_msgSend2(_delegate, _didEndSelector, self, returnCode);
else
[self _sendDelegateAlertDidEndReturnCode:returnCode];
}
_modalDelegate = nil;
_didEndSelector = nil;
if ([_delegate respondsToSelector:@selector(alertDidEnd:returnCode:)])
[_delegate alertDidEnd:self returnCode:returnCode];
}
@end
@implementation _CPAlertThemeView : CPView
@implementation CPAlert (CPAlertDelegate)
/*!
@ignore
Call the delegate alertDidEnd:returnCode
*/
- (void)_sendDelegateAlertDidEndReturnCode:(int)returnCode
+ (CPString)defaultThemeClass
{
if (!(_implementedDelegateMethods & CPAlertDelegate_alertDidEnd_returnCode_))
return;
[_delegate alertDidEnd:self returnCode:returnCode];
return @"alert";
}
/*!
@ignore
Call the delegate alertShowHelp:
*/
- (BOOL)_sendDelegateAlertShowHelp
+ (id)themeAttributes
{
if (!(_implementedDelegateMethods & CPAlertDelegate_alertShowHelp_))
return YES;
return [_delegate alertShowHelp:self];
return @{
@"size": CGSizeMake(400.0, 110.0),
@"content-inset": CGInsetMake(15, 15, 15, 50),
@"informative-offset": 6,
@"button-offset": 10,
@"message-text-alignment": CPJustifiedTextAlignment,
@"message-text-color": [CPColor blackColor],
@"message-text-font": [CPFont boldSystemFontOfSize:13.0],
@"message-text-shadow-color": [CPNull null],
@"message-text-shadow-offset": CGSizeMakeZero(),
@"informative-text-alignment": CPJustifiedTextAlignment,
@"informative-text-color": [CPColor blackColor],
@"informative-text-font": [CPFont systemFontOfSize:12.0],
@"informative-text-shadow-color": [CPNull null],
@"informative-text-shadow-offset": CGSizeMakeZero(),
@"image-offset": CGPointMake(15, 12),
@"information-image": [CPNull null],
@"warning-image": [CPNull null],
@"error-image": [CPNull null],
@"help-image": [CPNull null],
@"help-image-left-offset": 15,
@"help-image-pressed": [CPNull null],
@"suppression-button-y-offset": 0.0,
@"suppression-button-x-offset": 0.0,
@"default-elements-margin": 3.0,
@"suppression-button-text-color": [CPColor blackColor],
@"suppression-button-text-font": [CPFont systemFontOfSize:12.0],
@"suppression-button-text-shadow-color": [CPNull null],
@"suppression-button-text-shadow-offset": 0.0,
@"modal-window-button-margin-y": 0.0,
@"modal-window-button-margin-x": 0.0,
@"standard-window-button-margin-y": 0.0,
@"standard-window-button-margin-x": 0.0,
};
}
@end
+33 -113
View File
@@ -26,26 +26,25 @@
@import "CAMediaTimingFunction.j"
@protocol CPAnimationDelegate <CPObject>
@optional
- (BOOL)animationShouldStart:(CPAnimation)animation;
- (float)animation:(CPAnimation)animation valueForProgress:(float)progress;
- (void)animationDidEnd:(CPAnimation)animation;
- (void)animationDidStop:(CPAnimation)animation;
@end
var CPAnimationDelegate_animationShouldStart_ = 1 << 1,
CPAnimationDelegate_animation_valueForProgress_ = 1 << 2,
CPAnimationDelegate_animationDidEnd_ = 1 << 3,
CPAnimationDelegate_animationDidStop_ = 1 << 4;
@typedef CPAnimationCurve
/*
@global
@group CPAnimationCurve
*/
CPAnimationEaseInOut = 0;
/*
@global
@group CPAnimationCurve
*/
CPAnimationEaseIn = 1;
/*
@global
@group CPAnimationCurve
*/
CPAnimationEaseOut = 2;
/*
@global
@group CPAnimationCurve
*/
CPAnimationLinear = 3;
ACTUAL_FRAME_RATE = 0;
@@ -81,18 +80,17 @@ ACTUAL_FRAME_RATE = 0;
*/
@implementation CPAnimation : CPObject
{
CPTimeInterval _lastTime;
CPTimeInterval _duration;
CPTimeInterval _lastTime;
CPTimeInterval _duration;
CPAnimationCurve _animationCurve;
CAMediaTimingFunction _timingFunction;
CPAnimationCurve _animationCurve;
CAMediaTimingFunction _timingFunction;
float _frameRate;
float _progress;
float _frameRate;
float _progress;
id <CPAnimationDelegate> _delegate;
CPTimer _timer;
unsigned _implementedDelegateMethods;
id _delegate;
CPTimer _timer;
}
/*!
@@ -216,25 +214,9 @@ ACTUAL_FRAME_RATE = 0;
Sets the animation's delegate.
@param aDelegate the new delegate
*/
- (void)setDelegate:(id <CPAnimationDelegate>)aDelegate
- (void)setDelegate:(id)aDelegate
{
if (_delegate === aDelegate)
return;
_delegate = aDelegate;
_implementedDelegateMethods = 0;
if ([_delegate respondsToSelector:@selector(animationShouldStart:)])
_implementedDelegateMethods |= CPAnimationDelegate_animationShouldStart_;
if ([_delegate respondsToSelector:@selector(animationDidEnd:)])
_implementedDelegateMethods |= CPAnimationDelegate_animationDidEnd_;
if ([_delegate respondsToSelector:@selector(animationDidStop:)])
_implementedDelegateMethods |= CPAnimationDelegate_animationDidStop_;
if ([_delegate respondsToSelector:@selector(animation:valueForProgress:)])
_implementedDelegateMethods |= CPAnimationDelegate_animation_valueForProgress_;
}
/*!
@@ -245,7 +227,7 @@ ACTUAL_FRAME_RATE = 0;
- (void)startAnimation
{
// If we're already animating, or our delegate stops us, animate.
if (_timer || ![self _sendDelegateAnimationShouldStart])
if (_timer || _delegate && [_delegate respondsToSelector:@selector(animationShouldStart:)] && ![_delegate animationShouldStart:self])
return;
if (_progress === 1.0)
@@ -254,9 +236,7 @@ ACTUAL_FRAME_RATE = 0;
ACTUAL_FRAME_RATE = 0;
_lastTime = new Date();
var timerInterval = _frameRate <= 0.0 ? 0.0001 : 1.0 / _frameRate;
_timer = [CPTimer scheduledTimerWithTimeInterval:timerInterval target:self selector:@selector(animationTimerDidFire:) userInfo:nil repeats:YES];
_timer = [CPTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(animationTimerDidFire:) userInfo:nil repeats:YES];
}
/*
@@ -278,7 +258,8 @@ ACTUAL_FRAME_RATE = 0;
[_timer invalidate];
_timer = nil;
[self _sendDelegateAnimationDidEnd];
if ([_delegate respondsToSelector:@selector(animationDidEnd:)])
[_delegate animationDidEnd:self];
}
}
@@ -293,7 +274,8 @@ ACTUAL_FRAME_RATE = 0;
[_timer invalidate];
_timer = nil;
[self _sendDelegateAnimationDidStop];
if ([_delegate respondsToSelector:@selector(animationDidStop:)])
[_delegate animationDidStop:self];
}
/*!
@@ -329,8 +311,8 @@ ACTUAL_FRAME_RATE = 0;
{
var t = [self currentProgress];
if ([self _delegateRespondsToAnimationValueForProgress])
return [self _sendDelegateAnimationValueForProgress:t];
if ([_delegate respondsToSelector:@selector(animation:valueForProgress:)])
return [_delegate animation:self valueForProgress:t];
if (_animationCurve == CPAnimationLinear)
return t;
@@ -346,68 +328,6 @@ ACTUAL_FRAME_RATE = 0;
@end
@implementation CPAnimation (CPAnimationDelegate)
/*!
@ignore
Check if the delegate responds to animation:valueForProgress:
*/
- (BOOL)_delegateRespondsToAnimationValueForProgress
{
return _implementedDelegateMethods & CPAnimationDelegate_animation_valueForProgress_;
}
/*!
@ignore
Call delegate animationShouldStart:
*/
- (BOOL)_sendDelegateAnimationShouldStart
{
if (!(_implementedDelegateMethods & CPAnimationDelegate_animationShouldStart_))
return YES;
return [_delegate animationShouldStart:self];
}
/*!
@ignore
Call delegate animation:valueForProgress:
*/
- (float)_sendDelegateAnimationValueForProgress:(float)aProgress
{
if (!(_implementedDelegateMethods & CPAnimationDelegate_animation_valueForProgress_))
return aProgress;
return [_delegate animation:self valueForProgress:aProgress];
}
/*!
@ignore
Call delegate animationDidEnd:
*/
- (void)_sendDelegateAnimationDidEnd
{
if (!(_implementedDelegateMethods & CPAnimationDelegate_animationDidEnd_))
return;
[_delegate animationDidEnd:self];
}
/*!
@ignore
Call delegate animationDidStop:
*/
- (void)_sendDelegateAnimationDidStop
{
if (!(_implementedDelegateMethods & CPAnimationDelegate_animationDidStop_))
return;
[_delegate animationDidStop:self];
}
@end
// currently used function to determine time
// 1:1 conversion to js from webkit source files
// UnitBezier.h, WebCore_animation_AnimationBase.cpp
-162
View File
@@ -1,162 +0,0 @@
/*
* CPAppearance.j
* AppKit
*
* Created by Antoine Mercadal.
* Copyright 2015, Cappuccino Project.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/Foundation.j>
@import "CPTheme.j"
CPAppearanceNameAqua = @"CPAppearanceNameAqua";
CPAppearanceNameLightContent = @"CPAppearanceNameLightContent";
CPAppearanceNameVibrantDark = @"CPAppearanceNameVibrantDark";
CPAppearanceNameVibrantLight = @"CPAppearanceNameVibrantLight";
var _CPAppearanceCurrent = nil,
_CPAppearancesRegistry = @{};
@protocol CPAppearanceCustomization <CPObject>
@required
- (CPAppearance)appearance;
- (void)setAppearance:(CPAppearance)appearance;
- (CPAppearance)effectiveAppearance;
- (void)setEffectiveAppearance:(CPAppearance)appearance;
@end
CPThemeStateAppearanceAqua = CPThemeState("appearance-aqua");
CPThemeStateAppearanceLightContent = CPThemeState("appearance-light-content");
CPThemeStateAppearanceVibrantLight = CPThemeState("appearance-vibrant-light");
CPThemeStateAppearanceVibrantDark = CPThemeState("appearance-vibrant-dark");
/*!
@ingroup appkit
A CPAppareance represents the appearance of an to a subset of UI elements.
This is a very lightweight implementation of the NSAppearance system, but
We are using it for compliance, and especially for the CPVisualEffectView
*/
@implementation CPAppearance : CPObject
{
BOOL _allowsVibrancy @accessors(property=allowsVibrancy);
CPString _name;
}
#pragma mark -
#pragma mark Class Methods
/*! Returns the current default CPAppearance
*/
+ (CPAppearance)currentAppearance
{
if (!_CPAppearanceCurrent)
_CPAppearanceCurrent = [CPAppearance appearanceNamed:CPAppearanceNameAqua];
return _CPAppearanceCurrent;
}
/*! Sets the current default CPAppearance
@param appearance the new current appearance
*/
+ (void)setCurrentAppearance:(CPAppearance)anAppearance
{
_CPAppearanceCurrent = anAppearance;
}
/*! Returns the CPAppearance object with the given name
@param name the name of the appearance
*/
+ (CPAppearance)appearanceNamed:(CPString)aName
{
if (![_CPAppearancesRegistry containsKey:aName])
{
[_CPAppearancesRegistry setObject:[[CPAppearance alloc] initWithAppearanceNamed:aName bundle:nil]
forKey:aName];
}
return [_CPAppearancesRegistry objectForKey:aName];
}
#pragma mark -
#pragma mark Initialization
/*! Creates a CPAppearance object initialized to the specified appearance file in the specified bundle
This method does actually nothing special. It just creates a default appearance object
*/
- (id)initWithAppearanceNamed:(CPString)aName bundle:(CPBundle)bundle
{
if (self = [super init])
{
_name = aName;
_allowsVibrancy = YES;
if ([_CPAppearancesRegistry containsKey:aName])
[CPException raise:CPInternalInconsistencyException reason:"Appearance with name '" + aName + "' is already declared."];
[_CPAppearancesRegistry setObject:self forKey:aName];
}
return self;
}
#pragma mark -
#pragma mark Implementation
- (BOOL)isEqual:(id)anObject
{
if (![anObject isKindOfClass:CPAppearance])
return NO;
return self._name == anObject._name;
}
- (CPString)description
{
return @"<CPAppearance @" + [self UID] + @" name: " + _name + ">";
}
#pragma mark -
#pragma mark CPCoding
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super init])
{
_name = [aCoder decodeObjectForKey:@"_name"];
_allowsVibrancy = [aCoder decodeBoolForKey:@"_allowsVibrancy"];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:_name forKey:@"_name"];
[aCoder encodeBool:_allowsVibrancy forKey:@"_allowsVibrancy"];
}
@end
+108 -130
View File
@@ -20,9 +20,10 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#import "../Foundation/CPRange.h"
@import <Foundation/CPBundle.j>
@import "CPApplication_Constants.j"
@import "CPCompatibility.j"
@import "CPColorPanel.j"
@import "CPCursor.j"
@@ -35,33 +36,28 @@
@import "CPPanel.j"
@import "CPPlatform.j"
@import "CPWindowController.j"
@import "_CPPopoverWindow.j"
@typedef CPModalSession
var CPMainCibFile = @"CPMainCibFile",
CPMainCibFileHumanFriendly = @"Main cib file base name",
CPEventModifierFlags = 0;
CPApp = nil;
@protocol CPApplicationDelegate <CPObject>
CPApplicationWillFinishLaunchingNotification = @"CPApplicationWillFinishLaunchingNotification";
CPApplicationDidFinishLaunchingNotification = @"CPApplicationDidFinishLaunchingNotification";
CPApplicationWillTerminateNotification = @"CPApplicationWillTerminateNotification";
CPApplicationWillBecomeActiveNotification = @"CPApplicationWillBecomeActiveNotification";
CPApplicationDidBecomeActiveNotification = @"CPApplicationDidBecomeActiveNotification";
CPApplicationWillResignActiveNotification = @"CPApplicationWillResignActiveNotification";
CPApplicationDidResignActiveNotification = @"CPApplicationDidResignActiveNotification";
@optional
- (CPApplicationTerminateReply)applicationShouldTerminate:(CPApplication)sender;
- (CPString)applicationShouldTerminateMessage:(CPApplication)sender;
- (void)applicationDidBecomeActive:(CPNotification)aNotification;
- (void)applicationDidChangeScreenParameters:(CPNotification)aNotification;
- (void)applicationDidFinishLaunching:(CPNotification)aNotification;
- (void)applicationDidResignActive:(CPNotification)aNotification;
- (void)applicationWillBecomeActive:(CPNotification)aNotification;
- (void)applicationWillFinishLaunching:(CPNotification)aNotification;
- (void)applicationWillResignActive:(CPNotification)aNotification;
- (void)applicationWillTerminate:(CPNotification)aNotification;
CPTerminateNow = YES;
CPTerminateCancel = NO;
CPTerminateLater = -1; // not currently supported
@end
var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
CPApplicationDelegate_applicationShouldTerminateMessage_ = 1 << 1;
CPRunStoppedResponse = -1000;
CPRunAbortedResponse = -1001;
CPRunContinuesResponse = -1002;
/*!
@ingroup appkit
@@ -90,38 +86,36 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
*/
@implementation CPApplication : CPResponder
{
CPArray _eventListeners;
int _eventListenerInsertionIndex;
CPArray _eventListeners;
int _eventListenerInsertionIndex;
CPEvent _currentEvent;
CPWindow _lastMouseMoveWindow;
CPEvent _currentEvent;
CPWindow _lastMouseMoveWindow;
CPArray _windows;
CPWindow _keyWindow;
CPWindow _mainWindow;
CPWindow _previousKeyWindow;
CPWindow _previousMainWindow;
CPArray _windows;
CPWindow _keyWindow;
CPWindow _mainWindow;
CPWindow _previousKeyWindow;
CPWindow _previousMainWindow;
CPDocumentController _documentController;
CPDocumentController _documentController;
CPModalSession _currentSession;
CPModalSession _currentSession;
//
id <CPApplicationDelegate> _delegate;
CPInteger _implementedDelegateMethods;
id _delegate;
BOOL _finishedLaunching;
BOOL _isActive;
BOOL _finishedLaunching;
BOOL _isActive;
CPDictionary _namedArgs;
CPArray _args;
CPString _fullArgsString;
CPDictionary _namedArgs;
CPArray _args;
CPString _fullArgsString;
CPImage _applicationIconImage;
CPImage _applicationIconImage;
CPPanel _aboutPanel;
CPPanel _aboutPanel;
CPThemeBlend _themeBlend @accessors(property=themeBlend);
CPThemeBlend _themeBlend @accessors(property=themeBlend);
}
/*!
@@ -167,13 +161,11 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
react to these events.
@param aDelegate the delegate object
*/
- (void)setDelegate:(id <CPApplicationDelegate>)aDelegate
- (void)setDelegate:(id)aDelegate
{
if (_delegate == aDelegate)
return;
_implementedDelegateMethods = 0;
var defaultCenter = [CPNotificationCenter defaultCenter],
delegateNotifications =
[
@@ -183,8 +175,7 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
CPApplicationDidBecomeActiveNotification, @selector(applicationDidBecomeActive:),
CPApplicationWillResignActiveNotification, @selector(applicationWillResignActive:),
CPApplicationDidResignActiveNotification, @selector(applicationDidResignActive:),
CPApplicationWillTerminateNotification, @selector(applicationWillTerminate:),
CPApplicationDidChangeScreenParametersNotification, @selector(applicationDidChangeScreenParameters:)
CPApplicationWillTerminateNotification, @selector(applicationWillTerminate:)
],
count = [delegateNotifications count];
@@ -214,12 +205,6 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
if ([_delegate respondsToSelector:selector])
[defaultCenter addObserver:_delegate selector:selector name:notificationName object:self];
}
if ([_delegate respondsToSelector:@selector(applicationShouldTerminate:)])
_implementedDelegateMethods |= CPApplicationDelegate_applicationShouldTerminate_
if ([_delegate respondsToSelector:@selector(applicationShouldTerminateMessage:)])
_implementedDelegateMethods |= CPApplicationDelegate_applicationShouldTerminateMessage_
}
/*!
@@ -388,32 +373,22 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
applicationVersion = [options objectForKey:@"ApplicationVersion"] || [mainInfo objectForKey:@"CPBundleShortVersionString"],
copyright = [options objectForKey:@"Copyright"] || [mainInfo objectForKey:@"CPHumanReadableCopyright"];
var windowWidth = 275,
windowHeight = 223,
imgWidth = 100,
imgHeight = 100,
interField = 8,
aboutPanel = [[CPWindow alloc] initWithContentRect:CGRectMake(0, 0, windowWidth, windowHeight) styleMask:CPClosableWindowMask],
imageView = [[CPImageView alloc] initWithFrame:CGRectMake((windowWidth / 2) - (imgWidth / 2), interField, imgWidth, imgHeight)],
applicationLabel = [[CPTextField alloc] initWithFrame:CGRectMake(17, imgHeight + 16, windowWidth - 34, 24)],
versionLabel = [[CPTextField alloc] initWithFrame:CGRectMake(17, imgHeight + 48, windowWidth - 34, 16)],
copyrightLabel = [[CPTextField alloc] initWithFrame:CGRectMake(17, imgHeight + 72, windowWidth - 34, 32)],
contentView = [aboutPanel contentView];
var aboutPanelPath = [[CPBundle bundleForClass:[CPWindowController class]] pathForResource:@"AboutPanel.cib"],
aboutPanelController = [CPWindowController alloc],
aboutPanelController = [aboutPanelController initWithWindowCibPath:aboutPanelPath owner:aboutPanelController],
aboutPanel = [aboutPanelController window],
contentView = [aboutPanel contentView],
imageView = [contentView viewWithTag:1],
applicationLabel = [contentView viewWithTag:2],
versionLabel = [contentView viewWithTag:3],
copyrightLabel = [contentView viewWithTag:4],
standardPath = [[CPBundle bundleForClass:[self class]] pathForResource:@"standardApplicationIcon.png"];
// FIXME move this into the CIB eventually
[applicationLabel setFont:[CPFont boldSystemFontOfSize:[CPFont systemFontSize] + 2]];
[applicationLabel setAlignment:CPCenterTextAlignment];
[versionLabel setFont:[CPFont systemFontOfSize:[CPFont systemFontSize] - 1]];
[versionLabel setAlignment:CPCenterTextAlignment];
[copyrightLabel setFont:[CPFont systemFontOfSize:[CPFont systemFontSize] - 1]];
[copyrightLabel setAlignment:CPCenterTextAlignment];
[copyrightLabel setLineBreakMode:CPLineBreakByWordWrapping];
[contentView addSubview:imageView];
[contentView addSubview:applicationLabel];
[contentView addSubview:versionLabel];
[contentView addSubview:copyrightLabel];
var standardPath = [[CPBundle bundleForClass:[self class]] pathForResource:@"standardApplicationIcon.png"];
[imageView setImage:applicationIcon || [[CPImage alloc] initWithContentsOfFile:standardPath
size:CGSizeMake(256, 256)]];
@@ -427,7 +402,7 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
else
[versionLabel setStringValue:@""];
[copyrightLabel setStringValue:copyright || @""];
[copyrightLabel setStringValue:copyright || ""];
[aboutPanel center];
_aboutPanel = aboutPanel;
@@ -441,7 +416,12 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
{
// callback method for terminate:
if (didCloseAll)
[self replyToApplicationShouldTerminate:[self _sendDelegateApplicationShouldTerminate]];
{
if ([_delegate respondsToSelector:@selector(applicationShouldTerminate:)])
[self replyToApplicationShouldTerminate:[_delegate applicationShouldTerminate:self]];
else
[self replyToApplicationShouldTerminate:YES];
}
}
- (void)replyToApplicationShouldTerminate:(BOOL)terminate
@@ -455,22 +435,16 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
- (void)activateIgnoringOtherApps:(BOOL)shouldIgnoreOtherApps
{
if (_isActive)
return;
[self _willBecomeActive];
[CPPlatform activateIgnoringOtherApps:shouldIgnoreOtherApps];
_isActive = YES;
[self _didBecomeActive];
[self _willResignActive];
}
- (void)deactivate
{
if (!_isActive)
return;
[self _willResignActive];
[CPPlatform deactivate];
@@ -496,15 +470,6 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
- (void)run
{
[self finishLaunching];
[self sendEvent:[CPEvent otherEventWithType:CPAppKitDefined
location:CGPointMakeZero()
modifierFlags:0
timestamp:[CPEvent currentTimestamp]
windowNumber:[_keyWindow windowNumber]
context:nil
subtype:nil
data1:nil
data2:nil]];
}
// Managing the Event Loop
@@ -613,8 +578,8 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
/* @ignore */
- (BOOL)_handleKeyEquivalent:(CPEvent)anEvent
{
return [[self keyWindow] performKeyEquivalent:anEvent] ||
[[self mainMenu] performKeyEquivalent:anEvent];
return [[self keyWindow] performKeyEquivalent:anEvent] ||
[[self mainMenu] performKeyEquivalent:anEvent];
}
/*!
@@ -628,10 +593,33 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
var theWindow = [anEvent window];
#if PLATFORM(DOM)
var willPropagate = [[theWindow platformWindow] _willPropagateCurrentDOMEvent];
// temporarily pretend we won't propagate the event. we'll restore the saved value later
// we do this outside the if so that changes user code might make in _handleKeyEquiv. are preserved
[[theWindow platformWindow] _propagateCurrentDOMEvent:NO];
#endif
// Check if this is a candidate for key equivalent...
if ([anEvent _couldBeKeyEquivalent] && [self _handleKeyEquivalent:anEvent])
// The key equivalent was handled.
{
#if PLATFORM(DOM)
var characters = [anEvent characters],
modifierFlags = [anEvent modifierFlags];
// Unconditionally propagate on these keys to solve browser copy paste bugs
if ((characters == "c" || characters == "x" || characters == "v") && (modifierFlags & CPPlatformActionKeyMask))
[[theWindow platformWindow] _propagateCurrentDOMEvent:YES];
#endif
return;
}
#if PLATFORM(DOM)
// if we make it this far, then restore the original willPropagate value
[[theWindow platformWindow] _propagateCurrentDOMEvent:willPropagate];
#endif
if ([anEvent type] == CPMouseMoved)
{
@@ -642,10 +630,10 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
}
/*
Event listeners are processed from back to front so that newer event listeners normally take
precedence. If during the execution of a callback a new event listener is added, it should
be inserted after the current callback but before any higher priority callbacks. This makes
repeating event listeners (those that reinsert themselves) stable relative to each other.
Event listeners are processed from back to front so that newer event listeners normally take
precedence. If during the execution of a callback a new event listener is added, it should
be inserted after the current callback but before any higher priority callbacks. This makes
repeating event listeners (those that reinsert themselves) stable relative to each other.
*/
for (var i = _eventListeners.length - 1; i >= 0; i--)
{
@@ -666,7 +654,6 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
}
}
}
_eventListenerInsertionIndex = _eventListeners.length;
if (theWindow)
@@ -719,7 +706,7 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
- (CPArray)windows
{
// Return all windows, but not the CPNull placeholder in _windows[0].
return [_windows subarrayWithRange:CPMakeRange(1, [_windows count] - 1)];
return [_windows subarrayWithRange:_CPMakeRange(1, [_windows count] - 1)];
}
/*!
@@ -984,7 +971,7 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
*/
- (void)setTarget:(id)aTarget selector:(SEL)aSelector forNextEventMatchingMask:(unsigned int)aMask untilDate:(CPDate)anExpiration inMode:(CPString)aMode dequeue:(BOOL)shouldDequeue
{
_eventListeners.splice(_eventListenerInsertionIndex++, 0, _CPEventListenerMake(aMask, function (anEvent) { if (aTarget != null) aTarget.isa.objj_msgSend1(aTarget, aSelector, anEvent); }, shouldDequeue));
_eventListeners.splice(_eventListenerInsertionIndex++, 0, _CPEventListenerMake(aMask, function (anEvent) { objj_msgSend(aTarget, aSelector, anEvent); }, shouldDequeue));
}
/*!
@@ -1002,10 +989,10 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
@param aSheet the window to display as a sheet
@param aWindow the window that will hold the sheet as a child
@param aModalDelegate
@param didEndSelector
@param contextInfo
@param aDidEndSelector
@param aContextInfo
*/
- (void)beginSheet:(CPWindow)aSheet modalForWindow:(CPWindow)aWindow modalDelegate:(id)aModalDelegate didEndSelector:(SEL)didEndSelector contextInfo:(id)contextInfo
- (void)beginSheet:(CPWindow)aSheet modalForWindow:(CPWindow)aWindow modalDelegate:(id)aModalDelegate didEndSelector:(SEL)aDidEndSelector contextInfo:(id)aContextInfo
{
if ([aWindow isSheet])
{
@@ -1013,10 +1000,17 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
return;
}
if (![aWindow attachedSheet])
[aSheet._windowView _enableSheet:YES inWindow:aWindow];
[aSheet._windowView _enableSheet:YES];
[aWindow _attachSheet:aSheet modalDelegate:aModalDelegate didEndSelector:didEndSelector contextInfo:contextInfo];
// -dw- if a sheet is already visible, we skip this since it serves no purpose and causes
// orderOut: to be called on the sheet, which is not what we want.
if (![aWindow isVisible])
{
[aWindow orderFront:self];
[aSheet setPlatformWindow:[aWindow platformWindow]];
}
[aWindow _attachSheet:aSheet modalDelegate:aModalDelegate didEndSelector:aDidEndSelector contextInfo:aContextInfo];
}
/*!
@@ -1041,7 +1035,7 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
var aWindow = [_windows objectAtIndex:count],
context = aWindow._sheetContext;
if (context && context["sheet"] === sheet)
if (context != nil && context["sheet"] === sheet)
{
context["returnCode"] = returnCode;
[aWindow _endSheet];
@@ -1202,7 +1196,7 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
[[self keyWindow] orderFront:self];
else if ([self mainWindow])
[[self mainWindow] makeKeyAndOrderFront:self];
else if ([self mainMenu])
else
[[self mainMenu]._menuWindow makeKeyWindow]; //FIXME this may not actually work
_previousKeyWindow = nil;
@@ -1220,22 +1214,6 @@ var CPApplicationDelegate_applicationShouldTerminate_ = 1 << 0,
userInfo:nil];
}
- (BOOL)_sendDelegateApplicationShouldTerminate
{
if (!(_implementedDelegateMethods & CPApplicationDelegate_applicationShouldTerminate_))
return YES;
return [_delegate applicationShouldTerminate:self];
}
- (CPString)_sendDelegateApplicationShouldTerminateMessage
{
if (!(_implementedDelegateMethods & CPApplicationDelegate_applicationShouldTerminateMessage_))
return @"You have attempted to leave this page. Are you sure you want to exit this page?";
return [_delegate applicationShouldTerminateMessage:self];
}
- (void)_didResignActive
{
if (self._activeMenu)
@@ -1358,7 +1336,7 @@ var _CPAppBootstrapperActions = nil;
{
var action = _CPAppBootstrapperActions.shift();
if (self.isa.objj_msgSend0(self, action))
if (objj_msgSend(self, action))
return;
}
@@ -1402,8 +1380,8 @@ var _CPAppBootstrapperActions = nil;
if (mainCibFile)
{
[mainBundle loadCibFile:mainCibFile
externalNameTable:@{ CPCibOwner: CPApp }
loadDelegate:self];
externalNameTable:@{ CPCibOwner: CPApp }
loadDelegate:self];
return YES;
}
@@ -1480,7 +1458,7 @@ var _CPAppBootstrapperActions = nil;
+ (void)cibDidFailToLoad:(CPCib)aCib
{
throw new Error("Could not load main cib file. Did you forget to nib2cib it?");
throw new Error("Could not load main cib file (Did you forget to nib2cib it?).");
}
+ (void)reset
-41
View File
@@ -1,41 +0,0 @@
/*
* CPApplication_Constants.j
* AppKit
*
* Created by Aparajita Fishman.
* Copyright 2013 The Cappuccino Project
*
* 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
*/
CPApp = nil;
CPApplicationWillFinishLaunchingNotification = @"CPApplicationWillFinishLaunchingNotification";
CPApplicationDidFinishLaunchingNotification = @"CPApplicationDidFinishLaunchingNotification";
CPApplicationWillTerminateNotification = @"CPApplicationWillTerminateNotification";
CPApplicationWillBecomeActiveNotification = @"CPApplicationWillBecomeActiveNotification";
CPApplicationDidBecomeActiveNotification = @"CPApplicationDidBecomeActiveNotification";
CPApplicationWillResignActiveNotification = @"CPApplicationWillResignActiveNotification";
CPApplicationDidResignActiveNotification = @"CPApplicationDidResignActiveNotification";
CPApplicationDidChangeScreenParametersNotification = @"CPApplicationDidChangeScreenParametersNotification";
@typedef CPApplicationTerminateReply
CPTerminateNow = YES;
CPTerminateCancel = NO;
CPTerminateLater = -1; // not currently supported
CPRunStoppedResponse = -1000;
CPRunAbortedResponse = -1001;
CPRunContinuesResponse = -1002;
+13 -28
View File
@@ -23,7 +23,7 @@
*/
@import <Foundation/CPIndexSet.j>
@import <Foundation/CPPredicate.j>
@import "CPObjectController.j"
@import "CPKeyValueBinding.j"
@@ -65,51 +65,51 @@
+ (CPSet)keyPathsForValuesAffectingContentArray
{
return [CPSet setWithObjects:@"content"];
return [CPSet setWithObjects:"content"];
}
+ (CPSet)keyPathsForValuesAffectingArrangedObjects
{
// Also depends on "filterPredicate" but we'll handle that manually.
return [CPSet setWithObjects:@"content", @"sortDescriptors"];
return [CPSet setWithObjects:"content", "sortDescriptors"];
}
+ (CPSet)keyPathsForValuesAffectingSelection
{
return [CPSet setWithObjects:@"selectionIndexes"];
return [CPSet setWithObjects:"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingSelectionIndex
{
return [CPSet setWithObjects:@"selectionIndexes"];
return [CPSet setWithObjects:"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingSelectionIndexes
{
// When the arranged objects change, selection preservation may cause the indexes
// to change.
return [CPSet setWithObjects:@"arrangedObjects"];
return [CPSet setWithObjects:"arrangedObjects"];
}
+ (CPSet)keyPathsForValuesAffectingSelectedObjects
{
// Don't need to depend on arrangedObjects here because selectionIndexes already does.
return [CPSet setWithObjects:@"selectionIndexes"];
return [CPSet setWithObjects:"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingCanRemove
{
return [CPSet setWithObjects:@"selectionIndexes"];
return [CPSet setWithObjects:"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingCanSelectNext
{
return [CPSet setWithObjects:@"selectionIndexes"];
return [CPSet setWithObjects:"selectionIndexes"];
}
+ (CPSet)keyPathsForValuesAffectingCanSelectPrevious
{
return [CPSet setWithObjects:@"selectionIndexes"];
return [CPSet setWithObjects:"selectionIndexes"];
}
@@ -744,7 +744,6 @@
return;
var willClearPredicate = NO;
if (_clearsFilterPredicateOnInsertion && _filterPredicate)
{
[self willChangeValueForKey:@"filterPredicate"];
@@ -793,18 +792,10 @@
// not appear in arrangedObjects and we do not have to update at all.
*/
// TODO: Remove these lines when granular notifications are implemented
var proxy = [_CPKVOProxy proxyForObject:self];
[proxy setAdding:YES];
// This will also send notifications for arrangedObjects.
// This will also send notificaitons for arrangedObjects.
[self didChangeValueForKey:@"content"];
if (willClearPredicate)
[self didChangeValueForKey:@"filterPredicate"];
// TODO: Remove this line when granular notifications are implemented
[proxy setAdding:NO];
}
/*!
@@ -820,7 +811,6 @@
return;
var willClearPredicate = NO;
if (_clearsFilterPredicateOnInsertion && _filterPredicate)
{
[self willChangeValueForKey:@"filterPredicate"];
@@ -858,15 +848,9 @@
if ([self avoidsEmptySelection] && [[self selectionIndexes] count] <= 0 && [_contentObject count] > 0)
[self __setSelectionIndexes:[CPIndexSet indexSetWithIndex:0]];
var proxy = [_CPKVOProxy proxyForObject:self];
[proxy setAdding:YES];
[self didChangeValueForKey:@"content"];
if (willClearPredicate)
[self didChangeValueForKey:@"filterPredicate"];
[proxy setAdding:NO];
}
/*!
@@ -930,10 +914,11 @@
var newObject = [self automaticallyPreparesContent] ? [self newObject] : [self _defaultNewObject],
lastSelectedIndex = [_selectionIndexes lastIndex];
if (lastSelectedIndex !== CPNotFound)
if (lastSelectedIndex)
[self insertObject:newObject atArrangedObjectIndex:lastSelectedIndex];
else
[self addObject:newObject];
}
/*!
-45
View File
@@ -48,8 +48,6 @@ var DefaultLineWidth = 1.0;
{
CGPath _path;
float _lineWidth;
CPArray _lineDashes;
float _lineDashesPhase;
}
/*!
@@ -147,8 +145,6 @@ var DefaultLineWidth = 1.0;
{
_path = CGPathCreateMutable();
_lineWidth = [[self class] defaultLineWidth];
_lineDashesPhase = 0;
_lineDashes = [];
}
return self;
@@ -209,7 +205,6 @@ var DefaultLineWidth = 1.0;
CGContextBeginPath(ctx);
CGContextAddPath(ctx, _path);
CGContextSetLineWidth(ctx, [self lineWidth]);
CGContextSetLineDash(ctx, _lineDashesPhase, _lineDashes);
CGContextStrokePath(ctx);
}
@@ -223,50 +218,10 @@ var DefaultLineWidth = 1.0;
CGContextBeginPath(ctx);
CGContextAddPath(ctx, _path);
CGContextSetLineWidth(ctx, [self lineWidth]);
CGContextSetLineDash(ctx, _lineDashesPhase, _lineDashes);
CGContextClosePath(ctx);
CGContextFillPath(ctx);
}
/*!
Cocoa compatibility.
*/
- (void)getLineDash:(CPArrayRef)patternRef count:(NSInteger)count phase:(CGFloatRef)phaseRef
{
return [self getLineDash:patternRef phase:phaseRef];
}
/*!
Retrieve the line dash pattern and phase and write them into the provided references.
*/
- (void)getLineDash:(CPArrayRef)patternRef phase:(CGFloatRef)phaseRef
{
if (patternRef)
@deref(patternRef) = [_lineDashes copy];
if (phaseRef)
@deref(phaseRef) = _lineDashesPhase;
}
/*!
Cocoa compatibility.
*/
- (void)setLineDash:(CPArray)aPattern count:(NSInteger)count phase:(CGFloat)aPhase
{
[self setLineDash:aPattern phase:aPhase];
}
/*!
Set stroke line dash pattern.
@param aPattern an array of stroke-skip lengths such as [2, 2, 4, 4]
@param aPhase amount of shift for the starting position of the first stroke
*/
- (void)setLineDash:(CPArray)aPattern phase:(CGFloat)aPhase
{
_lineDashes = aPattern;
_lineDashesPhase = aPhase;
}
/*!
Get the line width.
*/
+7 -10
View File
@@ -24,7 +24,6 @@
@import "CPView.j"
// CPBoxType
@typedef CPBoxType
CPBoxPrimary = 0;
CPBoxSecondary = 1;
CPBoxSeparator = 2;
@@ -32,14 +31,12 @@ CPBoxOldStyle = 3;
CPBoxCustom = 4;
// CPBorderType
@typedef CPBorderType
CPNoBorder = 0;
CPLineBorder = 1;
CPBezelBorder = 2;
CPGrooveBorder = 3;
// CPTitlePosition
@typedef CPTitlePosition
CPNoTitle = 0;
CPAboveTop = 1;
CPAtTop = 2;
@@ -79,7 +76,7 @@ CPBelowBottom = 6;
return @"box";
}
+ (CPDictionary)themeAttributes
+ (id)themeAttributes
{
return @{
@"background-color": [CPNull null],
@@ -447,9 +444,9 @@ CPBelowBottom = 6;
case CPBoxSeparator:
// 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)
if (_CGRectGetWidth(bounds) === 5.0)
return [self _drawVerticalSeparatorInRect:bounds];
else if (CGRectGetHeight(bounds) === 5.0)
else if (_CGRectGetHeight(bounds) === 5.0)
return [self _drawHorizontalSeparatorInRect:bounds];
break;
@@ -496,8 +493,8 @@ CPBelowBottom = 6;
CGContextSetStrokeColor(context, [self borderColor]);
CGContextSetLineWidth(context, 1.0);
CGContextMoveToPoint(context, CGRectGetMinX(aRect), CGRectGetMidY(aRect));
CGContextAddLineToPoint(context, CGRectGetWidth(aRect), CGRectGetMidY(aRect));
CGContextMoveToPoint(context, _CGRectGetMinX(aRect), _CGRectGetMidY(aRect));
CGContextAddLineToPoint(context, _CGRectGetWidth(aRect), _CGRectGetMidY(aRect));
CGContextStrokePath(context);
}
@@ -508,8 +505,8 @@ CPBelowBottom = 6;
CGContextSetStrokeColor(context, [self borderColor]);
CGContextSetLineWidth(context, 1.0);
CGContextMoveToPoint(context, CGRectGetMidX(aRect), CGRectGetMinY(aRect));
CGContextAddLineToPoint(context, CGRectGetMidX(aRect), CGRectGetHeight(aRect));
CGContextMoveToPoint(context, _CGRectGetMidX(aRect), _CGRectGetMinY(aRect));
CGContextAddLineToPoint(context, _CGRectGetMidX(aRect), _CGRectGetHeight(aRect));
CGContextStrokePath(context);
}
+79 -279
View File
@@ -20,7 +20,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/CPObject.j>
@import <Foundation/CPIndexSet.j>
@import "CPControl.j"
@@ -31,86 +30,40 @@
@global CPApp
@protocol CPBrowserDelegate <CPObject>
@optional
- (BOOL)browser:(CPBrowser)browser acceptDrop:(id)info atRow:(CPInteger)row column:(CPInteger)column dropOperation:(CPTableViewDropOperation)dropOperation;
- (BOOL)browser:(CPBrowser)browser canDragRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(CPInteger)column withEvent:(CPEvent )event;
- (BOOL)browser:(CPBrowser)browser isLeafItem:(id)item;
- (BOOL)browser:(CPBrowser)browser shouldSelectRowIndexes:(CPIndexSet)anIndexSet inColumn:(CPInteger)column;
- (BOOL)browser:(CPBrowser)browser writeRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(CPInteger)column toPasteboard:(CPPasteboard)pasteboard;
- (CPDragOperation)browser:(CPBrowser)browser validateDrop:(id)info proposedRow:(CPInteger)row column:(CPInteger)column dropOperation:(CPTableViewDropOperation)dropOperation;
- (CPImage)browser:(CPBrowser)browser imageValueForItem:(id)anItem;
- (CPImage)browser:(CPBrowser)browser draggingImageForRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(CPInteger)column withEvent:(CPEvent)event offset:(CGPoint)dragImageOffset;
- (CPImage)browser:(CPBrowser)browser imageValueForItem:(id)item;
- (CPIndexSet)browser:(CPBrowser)browser selectionIndexesForProposedSelection:(CPIndexSet)proposedSelectionIndexes inColumn:(CPInteger)column;
- (CPInteger)browser:(CPBrowser)browser numberOfChildrenOfItem:(id)item;
- (CPView)browser:(CPBrowser)browser draggingViewForRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(CPInteger)column withEvent:(CPEvent)event offset:(CGPoint)dragImageOffset;
- (id)browser:(CPBrowser)browser child:(CPInteger)index ofItem:(id)item;
- (id)browser:(CPBrowser)browser objectValueForItem:(id)item;
- (id)rootItemForBrowser:(CPBrowser)browser;
- (void)browser:(CPBrowser)browser didChangeLastColumn:(CPInteger)oldLastColumn toColumn:(CPInteger)column;
- (void)browser:(CPBrowser)browser didResizeColumn:(CPInteger)column;
- (void)browserSelectionIsChanging:(CPBrowser)browser;
- (void)browserSelectionDidChange:(CPBrowser)browser;
@end
var CPBrowserDelegate_browser_acceptDrop_atRow_column_dropOperation_ = 1 << 1,
CPBrowserDelegate_browser_canDragRowsWithIndexes_inColumn_withEvent_ = 1 << 2,
CPBrowserDelegate_browser_isLeafItem_ = 1 << 3,
CPBrowserDelegate_browser_shouldSelectRowIndexes_inColumn_ = 1 << 4,
CPBrowserDelegate_browser_writeRowsWithIndexes_inColumn_toPasteboard_ = 1 << 5,
CPBrowserDelegate_browser_validateDrop_proposedRow_column_dropOperation_ = 1 << 6,
CPBrowserDelegate_browser_imageValueForItem_ = 1 << 7,
CPBrowserDelegate_browser_draggingImageForRowsWithIndexes_inColumn_withEvent_offset_ = 1 << 8,
CPBrowserDelegate_browser_imageValueForItem_ = 1 << 9,
CPBrowserDelegate_browser_selectionIndexesForProposedSelection_inColumn_ = 1 << 10,
CPBrowserDelegate_browser_numberOfChildrenOfItem_ = 1 << 11,
CPBrowserDelegate_browser_draggingViewForRowsWithIndexes_inColumn_withEvent_offset_ = 1 << 12,
CPBrowserDelegate_browser_child_ofItem_ = 1 << 13,
CPBrowserDelegate_browser_objectValueForItem_ = 1 << 14,
CPBrowserDelegate_rootItemForBrowser_ = 1 << 15,
CPBrowserDelegate_browser_didChangeLastColumn_toColumn_ = 1 << 16,
CPBrowserDelegate_browser_didResizeColumn_ = 1 << 17,
CPBrowserDelegate_browserSelectionIsChanging_ = 1 << 18,
CPBrowserDelegate_browserSelectionDidChange_ = 1 << 19;
/*!
@ingroup appkit
@class CPBrowser
*/
@implementation CPBrowser : CPControl
{
id <CPBrowserDelegate> _delegate;
CPString _pathSeparator;
unsigned _implementedDelegateMethods;
id _delegate;
CPString _pathSeparator;
CPView _contentView;
CPScrollView _horizontalScrollView;
CPView _prototypeView;
CPView _contentView;
CPScrollView _horizontalScrollView;
CPView _prototypeView;
CPArray _tableViews;
CPArray _tableDelegates;
CPArray _tableViews;
CPArray _tableDelegates;
id _rootItem;
id _rootItem;
BOOL _delegateSupportsImages;
BOOL _delegateSupportsImages;
SEL _doubleAction @accessors(property=doubleAction);
SEL _doubleAction @accessors(property=doubleAction);
BOOL _allowsMultipleSelection;
BOOL _allowsEmptySelection;
BOOL _allowsMultipleSelection;
BOOL _allowsEmptySelection;
Class _tableViewClass @accessors(property=tableViewClass);
Class _tableViewClass @accessors(property=tableViewClass);
float _rowHeight;
float _imageWidth;
float _leafWidth;
float _minColumnWidth;
float _defaultColumnWidth @accessors(property=defaultColumnWidth);
float _rowHeight;
float _imageWidth;
float _leafWidth;
float _minColumnWidth;
float _defaultColumnWidth @accessors(property=defaultColumnWidth);
CPArray _columnWidths;
CPArray _columnWidths;
}
+ (CPString)defaultThemeClass
@@ -118,7 +71,7 @@ var CPBrowserDelegate_browser_acceptDrop_atRow_column_dropOperation_
return "browser";
}
+ (CPDictionary)themeAttributes
+ (id)themeAttributes
{
return @{
@"image-control-resize": [CPNull null],
@@ -184,74 +137,10 @@ var CPBrowserDelegate_browser_acceptDrop_atRow_column_dropOperation_
[CPKeyedArchiver archivedDataWithRootObject:_prototypeView]];
}
- (void)setDelegate:(id <CPBrowserDelegate>)anObject
- (void)setDelegate:(id)anObject
{
if (_delegate === anObject)
return;
_delegate = anObject;
_implementedDelegateMethods = 0;
_delegateSupportsImages = NO;
if ([_delegate respondsToSelector:@selector(browser:acceptDrop:atRow:column:dropOperation:)])
_implementedDelegateMethods |= CPBrowserDelegate_browser_acceptDrop_atRow_column_dropOperation_;
if ([_delegate respondsToSelector:@selector(browser:canDragRowsWithIndexes:inColumn:withEvent:)])
_implementedDelegateMethods |= CPBrowserDelegate_browser_canDragRowsWithIndexes_inColumn_withEvent_;
if ([_delegate respondsToSelector:@selector(browser:isLeafItem:)])
_implementedDelegateMethods |= CPBrowserDelegate_browser_isLeafItem_;
if ([_delegate respondsToSelector:@selector(browser:shouldSelectRowIndexes:inColumn:)])
_implementedDelegateMethods |= CPBrowserDelegate_browser_shouldSelectRowIndexes_inColumn_;
if ([_delegate respondsToSelector:@selector(browser:writeRowsWithIndexes:inColumn:toPasteboard:)])
_implementedDelegateMethods |= CPBrowserDelegate_browser_writeRowsWithIndexes_inColumn_toPasteboard_;
if ([_delegate respondsToSelector:@selector(browser:validateDrop:proposedRow:column:dropOperation:)])
_implementedDelegateMethods |= CPBrowserDelegate_browser_validateDrop_proposedRow_column_dropOperation_;
if ([_delegate respondsToSelector:@selector(browser:imageValueForItem:)])
_implementedDelegateMethods |= CPBrowserDelegate_browser_imageValueForItem_;
if ([_delegate respondsToSelector:@selector(browser:draggingImageForRowsWithIndexes:inColumn:withEvent:offset:)])
_implementedDelegateMethods |= CPBrowserDelegate_browser_draggingImageForRowsWithIndexes_inColumn_withEvent_offset_;
if ([_delegate respondsToSelector:@selector(browser:imageValueForItem:)])
{
_delegateSupportsImages = YES;
_implementedDelegateMethods |= CPBrowserDelegate_browser_imageValueForItem_;
}
if ([_delegate respondsToSelector:@selector(browser:selectionIndexesForProposedSelection:inColumn:)])
_implementedDelegateMethods |= CPBrowserDelegate_browser_selectionIndexesForProposedSelection_inColumn_;
if ([_delegate respondsToSelector:@selector(browser:numberOfChildrenOfItem:)])
_implementedDelegateMethods |= CPBrowserDelegate_browser_numberOfChildrenOfItem_;
if ([_delegate respondsToSelector:@selector(browser:draggingViewForRowsWithIndexes:inColumn:withEvent:offset:)])
_implementedDelegateMethods |= CPBrowserDelegate_browser_draggingViewForRowsWithIndexes_inColumn_withEvent_offset_;
if ([_delegate respondsToSelector:@selector(browser:child:ofItem:)])
_implementedDelegateMethods |= CPBrowserDelegate_browser_child_ofItem_;
if ([_delegate respondsToSelector:@selector(browser:objectValueForItem:)])
_implementedDelegateMethods |= CPBrowserDelegate_browser_objectValueForItem_;
if ([_delegate respondsToSelector:@selector(rootItemForBrowser:)])
_implementedDelegateMethods |= CPBrowserDelegate_rootItemForBrowser_;
if ([_delegate respondsToSelector:@selector(browser:didChangeLastColumn:toColumn:)])
_implementedDelegateMethods |= CPBrowserDelegate_browser_didChangeLastColumn_toColumn_;
if ([_delegate respondsToSelector:@selector(browser:didChangeLastColumn:)])
_implementedDelegateMethods |= CPBrowserDelegate_browser_didResizeColumn_;
if ([_delegate respondsToSelector:@selector(browserSelectionIsChanging:)])
_implementedDelegateMethods |= CPBrowserDelegate_browserSelectionIsChanging_;
if ([_delegate respondsToSelector:@selector(browserSelectionDidChange:)])
_implementedDelegateMethods |= CPBrowserDelegate_browserSelectionDidChange_;
_delegateSupportsImages = [_delegate respondsToSelector:@selector(browser:imageValueForItem:)];
[self loadColumnZero];
}
@@ -273,13 +162,16 @@ var CPBrowserDelegate_browser_acceptDrop_atRow_column_dropOperation_
- (void)loadColumnZero
{
_rootItem = [self _sendDelegateRootItemForBrowser];
if ([_delegate respondsToSelector:@selector(rootItemForBrowser:)])
_rootItem = [_delegate rootItemForBrowser:self];
else
_rootItem = nil;
[self setLastColumn:-1];
[self addColumn];
}
- (void)setLastColumn:(CPInteger)columnIndex
- (void)setLastColumn:(int)columnIndex
{
if (columnIndex >= _tableViews.length)
return;
@@ -287,18 +179,14 @@ var CPBrowserDelegate_browser_acceptDrop_atRow_column_dropOperation_
var oldValue = _tableViews.length - 1,
indexPlusOne = columnIndex + 1; // unloads all later columns.
if (columnIndex > 0)
[_tableViews[columnIndex - 1] setNeedsDisplay:YES];
[_tableViews[columnIndex] setNeedsDisplay:YES];
[[_tableViews.slice(indexPlusOne) valueForKey:"enclosingScrollView"]
makeObjectsPerformSelector:@selector(removeFromSuperview)];
_tableViews = _tableViews.slice(0, indexPlusOne);
_tableDelegates = _tableDelegates.slice(0, indexPlusOne);
[self _sendDelegateBrowserDidChangeLastColumn:oldValue toColumn:columnIndex];
if ([_delegate respondsToSelector:@selector(browser:didChangeLastColumn:toColumn:)])
[_delegate browser:self didChangeLastColumn:oldValue toColumn:columnIndex];
[self tile];
}
@@ -398,7 +286,7 @@ var CPBrowserDelegate_browser_acceptDrop_atRow_column_dropOperation_
[aTableView addTableColumn:column];
}
- (void)reloadColumn:(CPInteger)column
- (void)reloadColumn:(int)column
{
[[self tableViewInColumn:column] reloadData];
}
@@ -466,17 +354,17 @@ var CPBrowserDelegate_browser_acceptDrop_atRow_column_dropOperation_
// ITEMS
- (id)itemAtRow:(CPInteger)row inColumn:(CPInteger)column
- (id)itemAtRow:(int)row inColumn:(int)column
{
return [_tableDelegates[column] childAtIndex:row];
}
- (BOOL)isLeafItem:(id)item
{
return (_implementedDelegateMethods & CPBrowserDelegate_browser_isLeafItem_) && [_delegate browser:self isLeafItem:item];
return [_delegate respondsToSelector:@selector(browser:isLeafItem:)] && [_delegate browser:self isLeafItem:item];
}
- (id)parentForItemsInColumn:(CPInteger)column
- (id)parentForItemsInColumn:(int)column
{
return [_tableDelegates[column] _item];
}
@@ -600,7 +488,9 @@ var CPBrowserDelegate_browser_acceptDrop_atRow_column_dropOperation_
{
_columnWidths[column] = aWidth;
[self _sendDelegateBrowserDidResizeColumn:column];
if ([_delegate respondsToSelector:@selector(browser:didResizeColumn:)])
[_delegate browser:self didResizeColumn:column];
[self tile];
}
@@ -715,12 +605,15 @@ var CPBrowserDelegate_browser_acceptDrop_atRow_column_dropOperation_
if (column < 0 || column > [self lastColumn] + 1)
return;
indexSet = [self _sendDelegateBrowserSelectionIndexesForProposedSelection:indexSet inColumn:column];
if ([_delegate respondsToSelector:@selector(browser:selectionIndexesForProposedSelection:inColumn:)])
indexSet = [_delegate browser:self selectionIndexesForProposedSelection:indexSet inColumn:column];
if (![self _sendDelegateBrowserShouldSelectRowIndexes:indexSet inColumn:column])
if ([_delegate respondsToSelector:@selector(browser:shouldSelectRowIndexes:inColumn:)] &&
![_delegate browser:self shouldSelectRowIndexes:indexSet inColumn:column])
return;
[self _sendDelegateBrowserSelectionIsChanging];
if ([_delegate respondsToSelector:@selector(browserSelectionIsChanging:)])
[_delegate browserSelectionIsChanging:self];
if (column > [self lastColumn])
[self addColumn];
@@ -731,7 +624,8 @@ var CPBrowserDelegate_browser_acceptDrop_atRow_column_dropOperation_
[self scrollColumnToVisible:column];
[self _sendDelegateBrowserSelectionDidChange];
if ([_delegate respondsToSelector:@selector(browserSelectionDidChange:)])
[_delegate browserSelectionDidChange:self];
}
- (void)setBackgroundColor:(CPColor)aColor
@@ -753,6 +647,30 @@ var CPBrowserDelegate_browser_acceptDrop_atRow_column_dropOperation_
[_tableViews makeObjectsPerformSelector:@selector(registerForDraggedTypes:) withObject:types];
}
- (BOOL)canDragRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(int)columnIndex withEvent:(CPEvent)dragEvent
{
if ([_delegate respondsToSelector:@selector(browser:canDragRowsWithIndexes:inColumn:withEvent:)])
return [_delegate browser:self canDragRowsWithIndexes:rowIndexes inColumn:columnIndex withEvent:dragEvent];
return YES;
}
- (CPImage)draggingImageForRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(int)columnIndex withEvent:(CPEvent)dragEvent offset:(CGPoint)dragImageOffset
{
if ([_delegate respondsToSelector:@selector(browser:draggingImageForRowsWithIndexes:inColumn:withEvent:offset:)])
return [_delegate browser:self draggingImageForRowsWithIndexes:rowIndexes inColumn:columnIndex withEvent:dragEvent offset:dragImageOffset];
return nil;
}
- (CPView)draggingViewForRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(int)columnIndex withEvent:(CPEvent)dragEvent offset:(CGPoint)dragImageOffset
{
if ([_delegate respondsToSelector:@selector(browser:draggingViewForRowsWithIndexes:inColumn:withEvent:offset:)])
return [_delegate browser:self draggingViewForRowsWithIndexes:rowIndexes inColumn:columnIndex withEvent:dragEvent offset:dragImageOffset];
return nil;
}
@end
@implementation CPBrowser (CPCoding)
@@ -848,7 +766,7 @@ var CPBrowserDelegate_browser_acceptDrop_atRow_column_dropOperation_
CPBrowser _browser @accessors;
}
- (id)initWithFrame:(CGRect)aFrame
- (void)initWithFrame:(CGRect)aFrame
{
if (self = [super initWithFrame:aFrame])
{
@@ -902,14 +820,6 @@ var CPBrowserDelegate_browser_acceptDrop_atRow_column_dropOperation_
return _browser;
}
/*!
@ignore
*/
- (BOOL)_isFocused
{
return ([super _isFocused] || [_browser tableViewInColumn:[_browser selectedColumn]] === self);
}
- (BOOL)canDragRowsWithIndexes:(CPIndexSet)rowIndexes atPoint:(CGPoint)mouseDownPoint
{
return [_browser canDragRowsWithIndexes:rowIndexes inColumn:[_browser columnOfTableView:self] withEvent:[CPApp currentEvent]];
@@ -937,6 +847,8 @@ var CPBrowserDelegate_browser_acceptDrop_atRow_column_dropOperation_
@end
@import <Foundation/CPObject.j>
@implementation _CPBrowserTableDelegate : CPObject
{
CPBrowser _browser @accessors;
@@ -977,22 +889,22 @@ var CPBrowserDelegate_browser_acceptDrop_atRow_column_dropOperation_
[_browser selectRowIndexes:selectedIndexes inColumn:_index];
}
- (id)childAtIndex:(CPUInteger)index
- (id)childAtIndex:(unsigned)index
{
return [_delegate browser:_browser child:index ofItem:_item];
}
- (BOOL)tableView:(CPTableView)aTableView acceptDrop:(id)info row:(CPInteger)row dropOperation:(CPTableViewDropOperation)operation
- (BOOL)tableView:(CPTableView)aTableView acceptDrop:(id)info row:(int)row dropOperation:(CPTableViewDropOperation)operation
{
if (_browser._implementedDelegateMethods & CPBrowserDelegate_browser_acceptDrop_atRow_column_dropOperation_)
if ([_delegate respondsToSelector:@selector(browser:acceptDrop:atRow:column:dropOperation:)])
return [_delegate browser:_browser acceptDrop:info atRow:row column:_index dropOperation:operation];
else
return NO;
}
- (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(id)info proposedRow:(CPInteger)row proposedDropOperation:(CPTableViewDropOperation)operation
- (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(id)info proposedRow:(int)row proposedDropOperation:(CPTableViewDropOperation)operation
{
if (_browser._implementedDelegateMethods & CPBrowserDelegate_browser_validateDrop_proposedRow_column_dropOperation_)
if ([_delegate respondsToSelector:@selector(browser:validateDrop:proposedRow:column:dropOperation:)])
return [_delegate browser:_browser validateDrop:info proposedRow:row column:_index dropOperation:operation];
else
return CPDragOperationNone;
@@ -1000,7 +912,7 @@ var CPBrowserDelegate_browser_acceptDrop_atRow_column_dropOperation_
- (BOOL)tableView:(CPTableView)aTableView writeRowsWithIndexes:(CPIndexSet)rowIndexes toPasteboard:(CPPasteboard)pboard
{
if (_browser._implementedDelegateMethods & CPBrowserDelegate_browser_writeRowsWithIndexes_inColumn_toPasteboard_)
if ([_delegate respondsToSelector:@selector(browser:writeRowsWithIndexes:inColumn:toPasteboard:)])
return [_delegate browser:_browser writeRowsWithIndexes:rowIndexes inColumn:_index toPasteboard:pboard];
else
return NO;
@@ -1055,7 +967,7 @@ var CPBrowserDelegate_browser_acceptDrop_atRow_column_dropOperation_
var imageView = [self layoutEphemeralSubviewNamed:@"image-view"
positioned:CPWindowAbove
relativeToEphemeralSubviewNamed:nil],
isHighlighted = [self hasThemeState:CPThemeStateSelectedDataView];
isHighlighted = [self themeState] & CPThemeStateSelectedDataView;
[imageView setImage: _isLeaf ? (isHighlighted ? _highlightedBranchImage : _branchImage) : nil];
[imageView setImageScaling:CPImageScaleNone];
@@ -1070,7 +982,7 @@ var CPBrowserDelegate_browser_acceptDrop_atRow_column_dropOperation_
[aCoder encodeObject:_highlightedBranchImage forKey:"_CPBrowserLeafViewHighlightedBranchImageKey"];
}
- (id)initWithCoder:(CPCoder)aCoder
- (void)initWithCoder:(CPCoder)aCoder
{
if (self = [super initWithCoder:aCoder])
{
@@ -1083,115 +995,3 @@ var CPBrowserDelegate_browser_acceptDrop_atRow_column_dropOperation_
}
@end
@implementation CPBrowser (CPBrowserDelegate)
/*!
@ignore
Call delegate rootItemForBrowser:
*/
- (id)_sendDelegateRootItemForBrowser
{
if (!(_implementedDelegateMethods & CPBrowserDelegate_rootItemForBrowser_))
return nil;
return [_delegate rootItemForBrowser:self];
}
/*!
@ignore
Call delegate browser:didChangeLastColumn:toColumn:
*/
- (void)_sendDelegateBrowserDidChangeLastColumn:(CPInteger)lastColumn toColumn:(CPInteger)newColumn
{
if (!(_implementedDelegateMethods & CPBrowserDelegate_browser_didChangeLastColumn_toColumn_))
return;
[_delegate browser:self didChangeLastColumn:lastColumn toColumn:newColumn];
}
/*!
@ignore
Call delegate browser:didResizeColumn:
*/
- (void)_sendDelegateBrowserDidResizeColumn:(CPInteger)column
{
if (!(_implementedDelegateMethods & CPBrowserDelegate_browser_didResizeColumn_))
return;
[_delegate browser:self didResizeColumn:column];
}
/*!
@ignore
Call delegate browserSelectionIsChanging:
*/
- (void)_sendDelegateBrowserSelectionIsChanging
{
if (!(_implementedDelegateMethods & CPBrowserDelegate_browserSelectionIsChanging_))
return;
[_delegate browserSelectionIsChanging:self];
}
/*!
@ignore
Call delegate browser:shouldSelectRowIndexes:inColumn:
*/
- (BOOL)_sendDelegateBrowserShouldSelectRowIndexes:(CPIndexSet)anIndexSet inColumn:(CPInteger)aColumn
{
if (!(_implementedDelegateMethods & CPBrowserDelegate_browser_shouldSelectRowIndexes_inColumn_))
return YES;
return [_delegate browser:self shouldSelectRowIndexes:anIndexSet inColumn:aColumn];
}
/*!
@ignore
Call delegate browser:selectionIndexesForProposedSelection:inColumn:
*/
- (CPIndexSet)_sendDelegateBrowserSelectionIndexesForProposedSelection:(CPIndexSet)anIndexSet inColumn:(CPInteger)aColumn
{
if (!(_implementedDelegateMethods & CPBrowserDelegate_browser_selectionIndexesForProposedSelection_inColumn_))
return anIndexSet;
return [_delegate browser:self selectionIndexesForProposedSelection:anIndexSet inColumn:aColumn];
}
/*!
@ignore
Call delegate browserSelectionDidChange
*/
- (void)_sendDelegateBrowserSelectionDidChange
{
if (!(_implementedDelegateMethods & CPBrowserDelegate_browserSelectionDidChange_))
return;
[_delegate browserSelectionDidChange:self];
}
- (BOOL)canDragRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(CPInteger)columnIndex withEvent:(CPEvent)dragEvent
{
if (_implementedDelegateMethods & CPBrowserDelegate_browser_canDragRowsWithIndexes_inColumn_withEvent_)
return [_delegate browser:self canDragRowsWithIndexes:rowIndexes inColumn:columnIndex withEvent:dragEvent];
return YES;
}
- (CPImage)draggingImageForRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(CPInteger)columnIndex withEvent:(CPEvent)dragEvent offset:(CGPoint)dragImageOffset
{
if (_implementedDelegateMethods & CPBrowserDelegate_browser_draggingImageForRowsWithIndexes_inColumn_withEvent_offset_)
return [_delegate browser:self draggingImageForRowsWithIndexes:rowIndexes inColumn:columnIndex withEvent:dragEvent offset:dragImageOffset];
return nil;
}
- (CPView)draggingViewForRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(CPInteger)columnIndex withEvent:(CPEvent)dragEvent offset:(CGPoint)dragImageOffset
{
if (_implementedDelegateMethods & CPBrowserDelegate_browser_draggingViewForRowsWithIndexes_inColumn_withEvent_offset_)
return [_delegate browser:self draggingViewForRowsWithIndexes:rowIndexes inColumn:columnIndex withEvent:dragEvent offset:dragImageOffset];
return nil;
}
@end
+41 -62
View File
@@ -29,7 +29,8 @@
@import "CPWindow_Constants.j"
/* @group CPBezelStyle */
@typedef CPBezelStyle
// IB style
CPRoundedBezelStyle = 1; // Push
CPRegularSquareBezelStyle = 2; // Bevel
CPThickSquareBezelStyle = 3;
@@ -48,7 +49,6 @@ CPHUDBezelStyle = -1;
/* @group CPButtonType */
@typedef CPButtonType
CPMomentaryLightButton = 0;
CPPushOnPushOffButton = 1;
CPToggleButton = 2;
@@ -72,14 +72,13 @@ CPPushInCellMask = CPPushInButtonMask;
CPChangeGrayCellMask = CPGrayButtonMask;
CPChangeBackgroundCellMask = CPBackgroundButtonMask;
CPButtonStateMixed = CPThemeState("mixed");
CPButtonStateBezelStyleRounded = CPThemeState("rounded");
CPButtonStateBezelStyleRoundRect = CPThemeState("roundRect");
CPButtonStateMixed = CPThemeState("mixed");
CPButtonStateBezelStyleRounded = CPThemeState("rounded");
// add all future correspondance between bezel styles and theme state here.
var CPButtonBezelStyleStateMap = @{
CPRoundedBezelStyle: CPButtonStateBezelStyleRounded,
CPRoundRectBezelStyle: CPButtonStateBezelStyleRoundRect,
CPRoundRectBezelStyle: [CPNull null],
};
/// @cond IGNORE
@@ -108,6 +107,7 @@ CPButtonImageOffset = 3.0;
// NS-style Display Properties
CPBezelStyle _bezelStyle;
CPControlSize _controlSize;
CPString _keyEquivalent;
unsigned _keyEquivalentModifierMask;
@@ -149,13 +149,13 @@ CPButtonImageOffset = 3.0;
return @"button";
}
+ (CPDictionary)themeAttributes
+ (id)themeAttributes
{
return @{
@"image": [CPNull null],
@"image-offset": 0.0,
@"bezel-inset": CGInsetMakeZero(),
@"content-inset": CGInsetMakeZero(),
@"bezel-inset": _CGInsetMakeZero(),
@"content-inset": _CGInsetMakeZero(),
@"bezel-color": [CPNull null],
};
}
@@ -188,6 +188,8 @@ CPButtonImageOffset = 3.0;
- (void)_init
{
_controlSize = CPRegularControlSize;
_keyEquivalent = @"";
_keyEquivalentModifierMask = 0;
@@ -198,20 +200,6 @@ CPButtonImageOffset = 3.0;
[self setButtonType:CPMomentaryPushInButton];
}
#pragma mark -
#pragma mark Control Size
- (void)setControlSize:(CPControlSize)aControlSize
{
[super setControlSize:aControlSize];
if ([self isBordered])
[self _sizeToControlSize];
}
#pragma mark -
// Setting the state
/*!
Returns a Boolean value indicating whether the button allows a mixed state.
@@ -280,7 +268,7 @@ CPButtonImageOffset = 3.0;
break;
case CPOffState:
[self unsetThemeStates:[CPThemeStateSelected, CPButtonStateMixed, CPThemeStateHighlighted]];
[self unsetThemeState:CPThemeStateSelected | CPButtonStateMixed | CPThemeStateHighlighted];
}
}
@@ -304,7 +292,7 @@ CPButtonImageOffset = 3.0;
}
/*!
Sets the button's state to the next available state.
Sets the button's next state to \c aState.
@param aState Possible states are any of the CPButton globals:
\c CPOffState, \c CPOnState, \c CPMixedState
*/
@@ -460,47 +448,38 @@ CPButtonImageOffset = 3.0;
{
switch (aButtonType)
{
case CPMomentaryLightButton:
[self setHighlightsBy:CPChangeGrayCellMask | CPChangeBackgroundCellMask];
[self setShowsStateBy:CPNoCellMask];
break;
case CPMomentaryLightButton: [self setHighlightsBy:CPChangeGrayCellMask | CPChangeBackgroundCellMask];
[self setShowsStateBy:CPNoCellMask];
break;
case CPMomentaryPushInButton:
[self setHighlightsBy:CPPushInCellMask | CPChangeGrayCellMask | CPChangeBackgroundCellMask];
[self setShowsStateBy:CPNoCellMask];
break;
case CPMomentaryPushInButton: [self setHighlightsBy:CPPushInCellMask | CPChangeGrayCellMask | CPChangeBackgroundCellMask];
[self setShowsStateBy:CPNoCellMask];
break;
case CPMomentaryChangeButton:
[self setHighlightsBy:CPContentsCellMask];
[self setShowsStateBy:CPNoCellMask];
break;
case CPMomentaryChangeButton: [self setHighlightsBy:CPContentsCellMask];
[self setShowsStateBy:CPNoCellMask];
break;
case CPPushOnPushOffButton:
[self setHighlightsBy:CPPushInCellMask | CPChangeGrayCellMask | CPChangeBackgroundCellMask];
[self setShowsStateBy:CPChangeBackgroundCellMask | CPChangeGrayCellMask];
break;
case CPPushOnPushOffButton: [self setHighlightsBy:CPPushInCellMask | CPChangeGrayCellMask | CPChangeBackgroundCellMask];
[self setShowsStateBy:CPChangeBackgroundCellMask | CPChangeGrayCellMask];
break;
case CPOnOffButton:
[self setHighlightsBy:CPChangeGrayCellMask | CPChangeBackgroundCellMask];
[self setShowsStateBy:CPChangeGrayCellMask | CPChangeBackgroundCellMask];
break;
case CPOnOffButton: [self setHighlightsBy:CPChangeGrayCellMask | CPChangeBackgroundCellMask];
[self setShowsStateBy:CPChangeGrayCellMask | CPChangeBackgroundCellMask];
break;
case CPToggleButton:
[self setHighlightsBy:CPPushInCellMask | CPContentsCellMask];
[self setShowsStateBy:CPContentsCellMask];
break;
case CPToggleButton: [self setHighlightsBy:CPPushInCellMask | CPContentsCellMask];
[self setShowsStateBy:CPContentsCellMask];
break;
case CPSwitchButton:
[CPException raise:CPInvalidArgumentException
reason:"The CPSwitchButton type is not supported in Cappuccino, use the CPCheckBox class instead."];
case CPSwitchButton: [CPException raise:CPInvalidArgumentException
reason:"The CPSwitchButton type is not supported in Cappuccino, use the CPCheckBox class instead."];
case CPRadioButton:
[CPException raise:CPInvalidArgumentException
reason:"The CPRadioButton type is not supported in Cappuccino, use the CPRadio class instead."];
case CPRadioButton: [CPException raise:CPInvalidArgumentException
reason:"The CPRadioButton type is not supported in Cappuccino, use the CPRadio class instead."];
default:
[CPException raise:CPInvalidArgumentException
reason:"Unknown button type."];
default: [CPException raise:CPInvalidArgumentException
reason:"Unknown button type."];
}
[self setImageDimsWhenDisabled:YES];
@@ -617,7 +596,7 @@ CPButtonImageOffset = 3.0;
{
var contentInset = [self currentValueForThemeAttribute:@"content-inset"];
return CGRectInsetByInset(bounds, contentInset);
return _CGRectInsetByInset(bounds, contentInset);
}
- (CGRect)bezelRectForBounds:(CGRect)bounds
@@ -628,7 +607,7 @@ CPButtonImageOffset = 3.0;
var bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"];
return CGRectInsetByInset(bounds, bezelInset);
return _CGRectInsetByInset(bounds, bezelInset);
}
- (CGSize)_minimumFrameSize
@@ -688,14 +667,14 @@ CPButtonImageOffset = 3.0;
{
if (aName === "bezel-view")
{
var view = [[CPView alloc] initWithFrame:CGRectMakeZero()];
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
[view setHitTests:NO];
return view;
}
else
return [[_CPImageAndTextView alloc] initWithFrame:CGRectMakeZero()];
return [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()];
}
- (void)layoutSubviews
+11 -41
View File
@@ -26,10 +26,7 @@
@class CPSplitView
@global CPPopUpButtonStatePullsDown
@global CPKeyValueChangeOldKey
@global CPKeyValueChangeNewKey
@global CPKeyValueObservingOptionNew
@global CPKeyValueObservingOptionOld
@implementation CPButtonBar : CPView
{
@@ -82,7 +79,7 @@
return @"button-bar";
}
+ (CPDictionary)themeAttributes
+ (id)themeAttributes
{
return @{
@"resize-control-inset": CGInsetMake(0.0, 0.0, 0.0, 0.0),
@@ -112,8 +109,6 @@
- (void)awakeFromCib
{
[super awakeFromCib];
var view = [self superview],
subview = self;
@@ -134,20 +129,10 @@
- (void)setButtons:(CPArray)buttons
{
for (var i = [_buttons count] - 1; i >= 0; i--)
{
[_buttons[i] removeFromSuperview];
[_buttons[i] removeObserver:self forKeyPath:@"hidden"];
}
_buttons = [CPArray arrayWithArray:buttons];
for (var i = [_buttons count] - 1; i >= 0; i--)
{
[_buttons[i] addObserver:self forKeyPath:@"hidden" options:CPKeyValueObservingOptionNew | CPKeyValueObservingOptionOld context:nil];
for (var i = 0, count = [_buttons count]; i < count; i++)
[_buttons[i] setBordered:YES];
}
[self setNeedsLayout];
}
@@ -233,15 +218,8 @@
count = [buttonsNotHidden count];
while (count--)
{
var button = buttonsNotHidden[count];
if ([button isHidden])
{
[button removeFromSuperview];
[buttonsNotHidden removeObject:button];
}
}
if ([buttonsNotHidden[count] isHidden])
[buttonsNotHidden removeObject:buttonsNotHidden[count]];
var currentButtonOffset = _resizeControlIsLeftAligned ? CGRectGetMaxX([self bounds]) + 1 : -1,
bounds = [self bounds],
@@ -272,15 +250,15 @@
currentButtonOffset += width - 1;
}
[button setValue:normalColor forThemeAttribute:@"bezel-color" inStates:[CPThemeStateNormal, CPThemeStateBordered]];
[button setValue:highlightedColor forThemeAttribute:@"bezel-color" inStates:[CPThemeStateHighlighted, CPThemeStateBordered, ]];
[button setValue:disabledColor forThemeAttribute:@"bezel-color" inStates:[CPThemeStateDisabled, CPThemeStateBordered]];
[button setValue:normalColor forThemeAttribute:@"bezel-color" inState:CPThemeStateNormal | CPThemeStateBordered];
[button setValue:highlightedColor forThemeAttribute:@"bezel-color" inState:CPThemeStateHighlighted | CPThemeStateBordered];
[button setValue:disabledColor forThemeAttribute:@"bezel-color" inState:CPThemeStateDisabled | CPThemeStateBordered];
[button setValue:textColor forThemeAttribute:@"text-color" inState:CPThemeStateBordered];
// FIXME shouldn't need this
[button setValue:normalColor forThemeAttribute:@"bezel-color" inStates:[CPThemeStateNormal, CPThemeStateBordered, CPPopUpButtonStatePullsDown]];
[button setValue:highlightedColor forThemeAttribute:@"bezel-color" inStates:[CPThemeStateHighlighted, CPThemeStateBordered, CPPopUpButtonStatePullsDown]];
[button setValue:disabledColor forThemeAttribute:@"bezel-color" inStates:[CPThemeStateDisabled, CPThemeStateBordered, CPPopUpButtonStatePullsDown]];
[button setValue:normalColor forThemeAttribute:@"bezel-color" inState:CPThemeStateNormal | CPThemeStateBordered | CPPopUpButtonStatePullsDown];
[button setValue:highlightedColor forThemeAttribute:@"bezel-color" inState:CPThemeStateHighlighted | CPThemeStateBordered | CPPopUpButtonStatePullsDown];
[button setValue:disabledColor forThemeAttribute:@"bezel-color" inState:CPThemeStateDisabled | CPThemeStateBordered | CPPopUpButtonStatePullsDown];
[self addSubview:button];
}
@@ -296,14 +274,6 @@
}
}
- (void)observeValueForKeyPath:(CPString)keyPath ofObject:(id)object change:(CPDictionary)change context:(id)context
{
if ([change objectForKey:CPKeyValueChangeOldKey] == [change objectForKey:CPKeyValueChangeNewKey])
return;
[self setNeedsLayout];
}
- (void)setFrameSize:(CGSize)aSize
{
[super setFrameSize:aSize];
-24
View File
@@ -111,30 +111,6 @@ CPCheckBoxImageOffset = 4.0;
return startedTracking;
}
#pragma mark -
#pragma mark Override methods from CPButton
- (CGSize)_minimumFrameSize
{
var size = [super _minimumFrameSize],
contentView = [self ephemeralSubviewNamed:@"content-view"];
if (!contentView && [[self title] length])
{
var minSize = [self currentValueForThemeAttribute:@"min-size"],
maxSize = [self currentValueForThemeAttribute:@"max-size"];
// Here we always add the min size to the control which is the size of the view of the checkBox
size.width += minSize.width + CPCheckBoxImageOffset;
if (maxSize.width >= 0.0)
size.width = MIN(size.width, maxSize.width);
}
return size;
}
@end
@implementation _CPCheckBoxValueBinder : CPBinder
+42 -9
View File
@@ -46,12 +46,49 @@
return;
if (_documentView)
{
var defaultCenter = [CPNotificationCenter defaultCenter];
[defaultCenter
removeObserver:self
name:CPViewFrameDidChangeNotification
object:_documentView];
[defaultCenter
removeObserver:self
name:CPViewBoundsDidChangeNotification
object:_documentView];
[_documentView removeFromSuperview];
}
_documentView = aView;
if (_documentView)
{
[self addSubview:_documentView];
[self _observeDocumentView];
}
}
- (void)_observeDocumentView
{
var defaultCenter = [CPNotificationCenter defaultCenter];
[_documentView setPostsFrameChangedNotifications:YES];
[_documentView setPostsBoundsChangedNotifications:YES];
[defaultCenter
addObserver:self
selector:@selector(viewFrameChanged:)
name:CPViewFrameDidChangeNotification
object:_documentView];
[defaultCenter
addObserver:self
selector:@selector(viewBoundsChanged:)
name:CPViewBoundsDidChangeNotification
object:_documentView];
}
/*!
@@ -71,19 +108,19 @@
- (CGPoint)constrainScrollPoint:(CGPoint)aPoint
{
if (!_documentView)
return CGPointMakeZero();
return _CGPointMakeZero();
var documentFrame = [_documentView frame];
aPoint.x = MAX(0.0, MIN(aPoint.x, MAX(CGRectGetWidth(documentFrame) - CGRectGetWidth(_bounds), 0.0)));
aPoint.y = MAX(0.0, MIN(aPoint.y, MAX(CGRectGetHeight(documentFrame) - CGRectGetHeight(_bounds), 0.0)));
aPoint.x = MAX(0.0, MIN(aPoint.x, MAX(_CGRectGetWidth(documentFrame) - _CGRectGetWidth(_bounds), 0.0)));
aPoint.y = MAX(0.0, MIN(aPoint.y, MAX(_CGRectGetHeight(documentFrame) - _CGRectGetHeight(_bounds), 0.0)));
return aPoint;
}
- (void)setBoundsOrigin:(CGPoint)aPoint
{
if (CGPointEqualToPoint(_bounds.origin, aPoint))
if (_CGPointEqualToPoint(_bounds.origin, aPoint))
return;
[super setBoundsOrigin:aPoint];
@@ -193,11 +230,6 @@
return [self scrollToPoint:CGPointMake(bounds.origin.x - deltaX, bounds.origin.y - deltaY)];
}
- (CGRect)documentVisibleRect
{
return [_documentView visibleRect];
}
@end
@@ -212,6 +244,7 @@ var CPClipViewDocumentViewKey = @"CPScrollViewDocumentView";
// Don't call setDocumentView: here. It calls addSubview:, but it's A) not necessary since the
// view hierarchy is fully encoded and B) dangerous if the subview is not fully decoded.
_documentView = [aCoder decodeObjectForKey:CPClipViewDocumentViewKey];
[self _observeDocumentView];
}
return self;
+162 -342
View File
@@ -20,6 +20,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#import "../Foundation/CPRange.h"
@import <Foundation/CPArray.j>
@import <Foundation/CPData.j>
@import <Foundation/CPIndexSet.j>
@@ -32,35 +34,8 @@
@import "CPPasteboard.j"
@import "CPView.j"
@class _CPCollectionViewDropIndicator
@class CPClipView
var CPCollectionViewDelegate_collectionView_acceptDrop_index_dropOperation_ = 1 << 0,
CPCollectionViewDelegate_collectionView_canDragItemsAtIndexes_withEvent_ = 1 << 1,
CPCollectionViewDelegate_collectionView_writeItemsAtIndexes_toPasteboard_ = 1 << 2,
CPCollectionViewDelegate_collectionView_dragTypesForItemsAtIndexes_ = 1 << 3,
CPCollectionViewDelegate_collectionView_dataForItemsAtIndexes_forType_ = 1 << 4,
CPCollectionViewDelegate_collectionView_validateDrop_proposedIndex_dropOperation_ = 1 << 5,
CPCollectionViewDelegate_collectionView_didDoubleClickOnItemAtIndex_ = 1 << 6,
CPCollectionViewDelegate_collectionView_menuForItemAtIndex_ = 1 << 7,
CPCollectionViewDelegate_collectionView_draggingViewForItemsAtIndexes_withEvent_offset = 1 << 8;
@protocol CPCollectionViewDelegate <CPObject>
@optional
- (BOOL)collectionView:(CPCollectionView)collectionView acceptDrop:(id)draggingInfo index:(CPInteger)index dropOperation:(CPCollectionViewDropOperation)dropOperation;
- (BOOL)collectionView:(CPCollectionView)collectionView canDragItemsAtIndexes:(CPIndexSet)indexes withEvent:(CPEvent)event;
- (BOOL)collectionView:(CPCollectionView)collectionView writeItemsAtIndexes:(CPIndexSet)indexes toPasteboard:(CPPasteboard)pasteboard;
- (CPArray)collectionView:(CPCollectionView)collectionView dragTypesForItemsAtIndexes:(CPIndexSet)indexes;
- (CPData)collectionView:(CPCollectionView)collectionView dataForItemsAtIndexes:(CPIndexSet)indices forType:(CPString)aType;
- (CPDragOperation)collectionView:(CPCollectionView)collectionView validateDrop:(id)draggingInfo proposedIndex:(CPInteger)proposedDropIndex dropOperation:(CPCollectionViewDropOperation)proposedDropOperation;
- (CPMenu)collectionView:(CPCollectionView)collectionView menuForItemAtIndex:(CPInteger)anIndex;
- (CPView)collectionView:(CPCollectionView)collectionView dragginViewForItemsAtIndexes:(CPIndexSet)indexes withEvent:(CPEvent)event offset:(CGPoint)dragImageOffset;
- (void)collectionView:(CPCollectionView)collectionView didDoubleClickOnItemAtIndex:(int)index;
@end
var HORIZONTAL_MARGIN = 2;
/*!
@ingroup appkit
@@ -72,6 +47,10 @@ var HORIZONTAL_MARGIN = 2;
@par Delegate Methods
@delegate - (void)collectionViewDidChangeSelection:(CPCollectionView)collectionView;
DEPRECATED: Please do not use.
@param collectionView the collection view who's selection changed
@delegate - (void)collectionView:(CPCollectionView)collectionView didDoubleClickOnItemAtIndex:(int)index;
Called when the user double-clicks on an item in the collection view.
@param collectionView the collection view that received the double-click
@@ -90,54 +69,56 @@ var HORIZONTAL_MARGIN = 2;
@param indices the indices to obtain drag types
@return an array of drag types (CPString)
*/
var HORIZONTAL_MARGIN = 2;
@implementation CPCollectionView : CPView
{
CPArray _content;
CPArray _items;
CPArray _content;
CPArray _items;
CPData _itemData;
CPCollectionViewItem _itemPrototype;
CPCollectionViewItem _itemForDragging;
CPMutableArray _cachedItems;
CPData _itemData;
CPCollectionViewItem _itemPrototype;
CPCollectionViewItem _itemForDragging;
CPMutableArray _cachedItems;
unsigned _maxNumberOfRows;
unsigned _maxNumberOfColumns;
unsigned _maxNumberOfRows;
unsigned _maxNumberOfColumns;
CGSize _minItemSize;
CGSize _maxItemSize;
CGSize _minItemSize;
CGSize _maxItemSize;
CPArray _backgroundColors;
CPArray _backgroundColors;
float _tileWidth;
float _tileWidth;
BOOL _isSelectable;
BOOL _allowsMultipleSelection;
BOOL _allowsEmptySelection;
CPIndexSet _selectionIndexes;
BOOL _isSelectable;
BOOL _allowsMultipleSelection;
BOOL _allowsEmptySelection;
CPIndexSet _selectionIndexes;
CGSize _itemSize;
CGSize _itemSize;
float _horizontalMargin;
float _verticalMargin;
float _horizontalMargin;
float _verticalMargin;
unsigned _numberOfRows;
unsigned _numberOfColumns;
unsigned _numberOfRows;
unsigned _numberOfColumns;
id <CPCollectionViewDelegate> _delegate;
unsigned _implementedDelegateMethods;
id _delegate;
CPEvent _mouseDownEvent;
CPEvent _mouseDownEvent;
BOOL _needsMinMaxItemSizeUpdate;
CGSize _storedFrameSize;
BOOL _needsMinMaxItemSizeUpdate;
CGSize _storedFrameSize;
BOOL _uniformSubviewsResizing @accessors(property=uniformSubviewsResizing);
BOOL _lockResizing;
BOOL _uniformSubviewsResizing @accessors(property=uniformSubviewsResizing);
BOOL _lockResizing;
CPInteger _currentDropIndex;
CPDragOperation _currentDragOperation;
CPInteger _currentDropIndex;
CPDragOperation _currentDragOperation;
_CPCollectionViewDropIndicator _dropView;
_CPCollectionViewDropIndicator _dropView;
}
- (id)initWithFrame:(CGRect)aFrame
@@ -149,8 +130,8 @@ var HORIZONTAL_MARGIN = 2;
_maxNumberOfRows = 0;
_maxNumberOfColumns = 0;
_minItemSize = CGSizeMakeZero();
_maxItemSize = CGSizeMakeZero();
_minItemSize = _CGSizeMakeZero();
_maxItemSize = _CGSizeMakeZero();
[self setBackgroundColors:nil];
@@ -174,11 +155,11 @@ var HORIZONTAL_MARGIN = 2;
_numberOfColumns = CPNotFound;
_numberOfRows = CPNotFound;
_itemSize = CGSizeMakeZero();
_itemSize = _CGSizeMakeZero();
_selectionIndexes = [CPIndexSet indexSet];
_storedFrameSize = CGSizeMakeZero();
_storedFrameSize = _CGSizeMakeZero();
_needsMinMaxItemSizeUpdate = YES;
_uniformSubviewsResizing = NO;
@@ -192,94 +173,51 @@ var HORIZONTAL_MARGIN = 2;
[self setAutoresizingMask:0];
}
#pragma mark -
#pragma mark Delegate
/*!
Set the delegate of the receiver
@param aDelegate the delegate object for the collectionView.
*/
- (void)setDelegate:(id <CPCollectionViewDelegate>)aDelegate
{
if (_delegate === aDelegate)
return;
_delegate = aDelegate;
_implementedDelegateMethods = 0;
if ([_delegate respondsToSelector:@selector(collectionView:acceptDrop:index:dropOperation:)])
_implementedDelegateMethods |= CPCollectionViewDelegate_collectionView_acceptDrop_index_dropOperation_;
if ([_delegate respondsToSelector:@selector(collectionView:canDragItemsAtIndexes:withEvent:)])
_implementedDelegateMethods |= CPCollectionViewDelegate_collectionView_canDragItemsAtIndexes_withEvent_;
if ([_delegate respondsToSelector:@selector(collectionView:writeItemsAtIndexes:toPasteboard:)])
_implementedDelegateMethods |= CPCollectionViewDelegate_collectionView_writeItemsAtIndexes_toPasteboard_;
if ([_delegate respondsToSelector:@selector(collectionView:dragTypesForItemsAtIndexes:)])
_implementedDelegateMethods |= CPCollectionViewDelegate_collectionView_dragTypesForItemsAtIndexes_;
if ([_delegate respondsToSelector:@selector(collectionView:dataForItemsAtIndexes:forType:)])
_implementedDelegateMethods |= CPCollectionViewDelegate_collectionView_dataForItemsAtIndexes_forType_;
if ([_delegate respondsToSelector:@selector(collectionView:validateDrop:proposedIndex:dropOperation:)])
_implementedDelegateMethods |= CPCollectionViewDelegate_collectionView_validateDrop_proposedIndex_dropOperation_;
if ([_delegate respondsToSelector:@selector(collectionView:didDoubleClickOnItemAtIndex:)])
_implementedDelegateMethods |= CPCollectionViewDelegate_collectionView_didDoubleClickOnItemAtIndex_;
if ([_delegate respondsToSelector:@selector(collectionView:menuForItemAtIndex:)])
_implementedDelegateMethods |= CPCollectionViewDelegate_collectionView_menuForItemAtIndex_;
if ([_delegate respondsToSelector:@selector(collectionView:draggingViewForItemsAtIndexes:withEvent:offset:)])
_implementedDelegateMethods |= CPCollectionViewDelegate_collectionView_draggingViewForItemsAtIndexes_withEvent_offset;
}
/*!
Sets the item prototype to \c anItem
@param anItem the new item prototype.
@note
- If anItem is located in an external cib file, representedObject, outlets, and bindings will be automatically restored when an item is created.
- If anItem and its view belong to the same cib as the collection view, the item prototype should implement the CPCoding protocol because the item is copied by archiving and unarchiving the prototypal view.
@note
Bindings won't be restored through archiving, instead you need to subclass the -representedObject: method and update the view there.
The item prototype should implement the CPCoding protocol
because the item is copied by archiving and unarchiving.
@par Example:
Example:
@code
@implementation MyCustomPrototypeItem: CPCollectionViewItem
{
@outlet CPTextField textField;
}
<pre>
@implement MyCustomViewItem : CPCollectionViewItem
{
CPArray items @accessors;
}
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
- (id)initWithCibName:(CPString)aCibNameOrNil bundle:(CPBundle)aCibBundleOrNil
{
self = [super initWithCibName:aCibNameOrNil bundle:aCibBundleOrNil];
if (self)
{
items = [];
}
return self;
}
textField = [aCoder decodeObjectForKey:@"TextField"];
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
items = [aCoder decodeObjectForKey:@"KEY"];
return self;
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:items forKey:@"KEY"];
[super encodeWithCoder:aCoder];
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeConditionalObject:textField forKey:@"TextField"];
}
@end
</pre>
- (void)setRepresentedObject:(id)anObject
{
[super setRepresentedObject:anObject];
[textField setStringValue:[anObject objectForKey:@"value"]];
[[self view] setColor:[anObject objectForKey:@"color"]];
}
@end
@endcode
This will allow the collection view to create multiple 'clean' copies
of the item prototype which will maintain the original values for item
and all of the properties archived by the super class.
@param anItem the new item prototype
*/
- (void)setItemPrototype:(CPCollectionViewItem)anItem
{
@@ -464,6 +402,12 @@ var HORIZONTAL_MARGIN = 2;
var binderClass = [[self class] _binderClassForBinding:@"selectionIndexes"];
[[binderClass getBinding:@"selectionIndexes" forObject:self] reverseSetValueFor:@"selectionIndexes"];
if ([_delegate respondsToSelector:@selector(collectionViewDidChangeSelection:)])
{
CPLog.warn("The delegate method collectionViewDidChangeSelection: is deprecated and will be removed in a future version, please bind to selectionIndexes instead.");
[_delegate collectionViewDidChangeSelection:self];
}
}
/*!
@@ -518,12 +462,12 @@ var HORIZONTAL_MARGIN = 2;
[self tileIfNeeded:NO];
}
- (void)resizeSubviewsWithOldSize:(CGSize)oldBoundsSize
- (void)resizeSubviewsWithOldSize:(CPSize)oldBoundsSize
{
// Desactivate subviews autoresizing
}
- (void)resizeWithOldSuperviewSize:(CGSize)oldBoundsSize
- (void)resizeWithOldSuperviewSize:(CPSize)oldBoundsSize
{
if (_lockResizing)
return;
@@ -565,7 +509,7 @@ var HORIZONTAL_MARGIN = 2;
if (!lazyFlag ||
_numberOfColumns !== oldNumberOfColumns ||
_numberOfRows !== oldNumberOfRows ||
!CGSizeEqualToSize(_itemSize, oldItemSize))
!_CGSizeEqualToSize(_itemSize, oldItemSize))
[self displayItems:_items frameSize:_storedFrameSize itemSize:_itemSize columns:_numberOfColumns rows:_numberOfRows count:count];
}
@@ -574,7 +518,7 @@ var HORIZONTAL_MARGIN = 2;
{
var width = aSuperviewSize.width,
height = aSuperviewSize.height,
itemSize = CGSizeMakeCopy(_minItemSize),
itemSize = _CGSizeMakeCopy(_minItemSize),
maxItemSizeWidth = _maxItemSize.width,
maxItemSizeHeight = _maxItemSize.height,
itemsCount = [_items count],
@@ -608,13 +552,13 @@ var HORIZONTAL_MARGIN = 2;
height = MAX(height, numberOfRows * (_minItemSize.height + _verticalMargin));
var itemSizeHeight = FLOOR(height / numberOfRows) - _verticalMargin;
var itemSizeHeight = FLOOR(height / numberOfRows);
if (maxItemSizeHeight > 0)
itemSizeHeight = MIN(itemSizeHeight, maxItemSizeHeight);
_itemSize = CGSizeMake(MAX(_minItemSize.width, itemSize.width), MAX(_minItemSize.height, itemSizeHeight));
_storedFrameSize = CGSizeMake(MAX(width, _minItemSize.width), height);
_itemSize = _CGSizeMake(MAX(_minItemSize.width, itemSize.width), MAX(_minItemSize.height, itemSizeHeight));
_storedFrameSize = _CGSizeMake(MAX(width, _minItemSize.width), height);
_numberOfColumns = numberOfColumns;
_numberOfRows = numberOfRows;
countRef(MIN(itemsCount, numberOfColumns * numberOfRows));
@@ -635,7 +579,7 @@ var HORIZONTAL_MARGIN = 2;
if (idx >= displayCount)
{
[view setFrameOrigin:CGPointMake(-anItemSize.width, -anItemSize.height)];
[view setFrameOrigin:_CGPointMake(-anItemSize.width, -anItemSize.height)];
return;
}
@@ -645,7 +589,7 @@ var HORIZONTAL_MARGIN = 2;
y += _verticalMargin + anItemSize.height;
}
[view setFrameOrigin:CGPointMake(x, y)];
[view setFrameOrigin:_CGPointMake(x, y)];
[view setFrameSize:anItemSize];
x += anItemSize.width + _horizontalMargin;
@@ -748,12 +692,12 @@ var HORIZONTAL_MARGIN = 2;
if (aSize === nil || aSize === undefined)
[CPException raise:CPInvalidArgumentException reason:"Invalid value provided for minimum size"];
if (CGSizeEqualToSize(_minItemSize, aSize))
if (_CGSizeEqualToSize(_minItemSize, aSize))
return;
_minItemSize = CGSizeMakeCopy(aSize);
_minItemSize = _CGSizeMakeCopy(aSize);
if (CGSizeEqualToSize(_minItemSize, CGSizeMakeZero()))
if (_CGSizeEqualToSize(_minItemSize, _CGSizeMakeZero()))
_needsMinMaxItemSizeUpdate = YES;
[self tile];
@@ -773,10 +717,10 @@ var HORIZONTAL_MARGIN = 2;
*/
- (void)setMaxItemSize:(CGSize)aSize
{
if (CGSizeEqualToSize(_maxItemSize, aSize))
if (_CGSizeEqualToSize(_maxItemSize, aSize))
return;
_maxItemSize = CGSizeMakeCopy(aSize);
_maxItemSize = _CGSizeMakeCopy(aSize);
// if (_maxItemSize.width == 0 || _maxItemSize.height == 0)
// _needsMinMaxItemSizeUpdate = YES;
@@ -818,8 +762,8 @@ var HORIZONTAL_MARGIN = 2;
- (void)mouseUp:(CPEvent)anEvent
{
if ([_selectionIndexes count] && [anEvent clickCount] == 2)
[self _sendDelegateDidDoubleClickOnItemAtIndex:[_selectionIndexes firstIndex]];
if ([_selectionIndexes count] && [anEvent clickCount] == 2 && [_delegate respondsToSelector:@selector(collectionView:didDoubleClickOnItemAtIndex:)])
[_delegate collectionView:self didDoubleClickOnItemAtIndex:[_selectionIndexes firstIndex]];
}
- (void)mouseDown:(CPEvent)anEvent
@@ -847,14 +791,10 @@ var HORIZONTAL_MARGIN = 2;
var firstSelectedIndex = [[self selectionIndexes] firstIndex],
newSelectedRange = nil;
// This catches the case where the shift key is held down for the first selection.
if (firstSelectedIndex === CPNotFound)
firstSelectedIndex = index;
if (index < firstSelectedIndex)
newSelectedRange = CPMakeRange(index, (firstSelectedIndex - index) + 1);
newSelectedRange = _CPMakeRange(index, (firstSelectedIndex - index) + 1);
else
newSelectedRange = CPMakeRange(firstSelectedIndex, (index - firstSelectedIndex) + 1);
newSelectedRange = _CPMakeRange(firstSelectedIndex, (index - firstSelectedIndex) + 1);
indexes = [[self selectionIndexes] copy];
[indexes addIndexesInRange:newSelectedRange];
@@ -893,7 +833,7 @@ var HORIZONTAL_MARGIN = 2;
[self tile];
}
- (void)setUniformSubviewsResizing:(BOOL)flag
- (void)setUniformSubviewsResizing:(float)flag
{
_uniformSubviewsResizing = flag;
[self tileIfNeeded:NO];
@@ -909,6 +849,15 @@ var HORIZONTAL_MARGIN = 2;
return _verticalMargin;
}
/*!
Sets the collection view's delegate
@param aDelegate the new delegate
*/
- (void)setDelegate:(id)aDelegate
{
_delegate = aDelegate;
}
/*!
Returns the collection view's delegate
*/
@@ -922,13 +871,13 @@ var HORIZONTAL_MARGIN = 2;
*/
- (CPMenu)menuForEvent:(CPEvent)theEvent
{
if (![self _delegateRespondsToCollectionViewMenuForItemAtIndex])
if (![[self delegate] respondsToSelector:@selector(collectionView:menuForItemAtIndex:)])
return [super menuForEvent:theEvent];
var location = [self convertPoint:[theEvent locationInWindow] fromView:nil],
index = [self _indexAtPoint:location];
return [self _sendDelegateMenuForItemAtIndex:index];
return [_delegate collectionView:self menuForItemAtIndex:index];
}
- (int)_indexAtPoint:(CGPoint)thePoint
@@ -946,12 +895,12 @@ var HORIZONTAL_MARGIN = 2;
return CPNotFound;
}
- (CPCollectionViewItem)itemAtIndex:(CPUInteger)anIndex
- (CPCollectionViewItem)itemAtIndex:(unsigned)anIndex
{
return [_items objectAtIndex:anIndex];
}
- (CGRect)frameForItemAtIndex:(CPUInteger)anIndex
- (CGRect)frameForItemAtIndex:(unsigned)anIndex
{
return [[[self itemAtIndex:anIndex] view] frame];
}
@@ -986,7 +935,7 @@ var HORIZONTAL_MARGIN = 2;
*/
- (void)pasteboard:(CPPasteboard)aPasteboard provideDataForType:(CPString)aType
{
[aPasteboard setData:[self _sendDelegateDataForItemsAtIndexes:_selectionIndexes forType:aType] forType:aType];
[aPasteboard setData:[_delegate collectionView:self dataForItemsAtIndexes:_selectionIndexes forType:aType] forType:aType];
}
- (void)_createDropIndicatorIfNeeded
@@ -994,9 +943,9 @@ var HORIZONTAL_MARGIN = 2;
// Create and position the drop indicator view.
if (!_dropView)
_dropView = [[_CPCollectionViewDropIndicator alloc] initWithFrame:CGRectMake(-8, -8, 0, 0)];
_dropView = [[_CPCollectionViewDropIndicator alloc] initWithFrame:_CGRectMake(-8, -8, 0, 0)];
[_dropView setFrameSize:CGSizeMake(10, _itemSize.height + _verticalMargin)];
[_dropView setFrameSize:_CGSizeMake(10, _itemSize.height + _verticalMargin)];
[self addSubview:_dropView];
}
@@ -1016,29 +965,30 @@ var HORIZONTAL_MARGIN = 2;
(ABS(locationInWindow.y - mouseDownLocationInWindow.y) < 3))
return;
if (![self _delegateRespondsToCollectionViewDragTypesForItemsAtIndexes])
if (![_delegate respondsToSelector:@selector(collectionView:dragTypesForItemsAtIndexes:)])
return;
// If we don't have any selected items, we've clicked away, and thus the drag is meaningless.
if (![_selectionIndexes count])
return;
if (![self _sendDelegateCanDragItemsAtIndexes:_selectionIndexes withEvent:_mouseDownEvent])
if ([_delegate respondsToSelector:@selector(collectionView:canDragItemsAtIndexes:withEvent:)] &&
![_delegate collectionView:self canDragItemsAtIndexes:_selectionIndexes withEvent:_mouseDownEvent])
return;
// Set up the pasteboard
var dragTypes = [self _sendDelegateDragTypesForItemsAtIndexes:_selectionIndexes];
var dragTypes = [_delegate collectionView:self dragTypesForItemsAtIndexes:_selectionIndexes];
[[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:dragTypes owner:self];
var dragImageOffset = CGSizeMakeZero(),
view = [self _sendDelegateDraggingViewForItemsAtIndexes:_selectionIndexes withEvent:_mouseDownEvent offset:dragImageOffset];
var dragImageOffset = _CGSizeMakeZero(),
view = [self _draggingViewForItemsAtIndexes:_selectionIndexes withEvent:_mouseDownEvent offset:dragImageOffset];
[view setFrameSize:_itemSize];
[view setAlphaValue:0.7];
var dragLocation = [self convertPoint:locationInWindow fromView:nil],
dragPoint = CGPointMake(dragLocation.x - _itemSize.width / 2 , dragLocation.y - _itemSize.height / 2);
dragPoint = _CGPointMake(dragLocation.x - _itemSize.width / 2 , dragLocation.y - _itemSize.height / 2);
[self dragView:view
at:dragPoint
@@ -1049,6 +999,14 @@ var HORIZONTAL_MARGIN = 2;
slideBack:YES];
}
- (CPView)_draggingViewForItemsAtIndexes:(CPIndexSet)indexes withEvent:(CPEvent)anEvent offset:(CGPoint)offset
{
if ([_delegate respondsToSelector:@selector(collectionView:draggingViewForItemsAtIndexes:withEvent:offset:)])
return [_delegate collectionView:self draggingViewForItemsAtIndexes:indexes withEvent:anEvent offset:offset];
return [self draggingViewForItemsAtIndexes:indexes withEvent:anEvent offset:offset];
}
- (CPView)draggingViewForItemsAtIndexes:(CPIndexSet)indexes withEvent:(CPEvent)event offset:(CGPoint)dragImageOffset
{
var idx = _content[[indexes firstIndex]];
@@ -1061,6 +1019,14 @@ var HORIZONTAL_MARGIN = 2;
return [_itemForDragging view];
}
- (BOOL)_canDragItemsAtIndexes:(CPIndexSet)indexes withEvent:(CPEvent)anEvent
{
if ([self respondsToSelector:@selector(collectionView:canDragItemsAtIndexes:withEvent:)])
return [_delegate collectionView:self canDragItemsAtIndexes:indexes withEvent:anEvent];
return YES;
}
- (CPDragOperation)draggingEntered:(id)draggingInfo
{
var dropIndex = -1,
@@ -1098,14 +1064,16 @@ var HORIZONTAL_MARGIN = 2;
var result = CPDragOperationMove,
dropIndex = [self _dropIndexForDraggingInfo:draggingInfo proposedDropOperation:dropOperation];
if ([self _delegateRespondsToCollectionViewValidateDropProposedIndexDropOperation])
if ([_delegate respondsToSelector:@selector(collectionView:validateDrop:proposedIndex:dropOperation:)])
{
var dropIndexRef2 = @ref(dropIndex);
result = [self _sendDelegateValidateDrop:draggingInfo proposedIndex:dropIndexRef2 dropOperation:dropOperation];
result = [_delegate collectionView:self validateDrop:draggingInfo proposedIndex:dropIndexRef2 dropOperation:dropOperation];
if (result !== CPDragOperationNone)
{
dropIndex = dropIndexRef2();
}
}
dropIndexRef(dropIndex);
@@ -1139,7 +1107,7 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype:
var result = NO;
if (_currentDragOperation && _currentDropIndex !== -1)
result = [self _sendDelegateAcceptDrop:draggingInfo index:_currentDropIndex dropOperation:1];
result = [_delegate collectionView:self acceptDrop:draggingInfo index:_currentDropIndex dropOperation:1];
[self draggingEnded:draggingInfo]; // Is this correct ?
@@ -1152,12 +1120,12 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype:
_currentDragOperation = dragOperation;
var frameOrigin,
dropviewFrameWidth = CGRectGetWidth([_dropView frame]);
dropviewFrameWidth = _CGRectGetWidth([_dropView frame]);
if (_currentDropIndex == -1 || _currentDragOperation == CPDragOperationNone)
frameOrigin = CGPointMake(-dropviewFrameWidth, 0);
frameOrigin = _CGPointMake(-dropviewFrameWidth, 0);
else if (_currentDropIndex == 0)
frameOrigin = CGPointMake(0, 0);
frameOrigin = _CGPointMake(0, 0);
else
{
var offset;
@@ -1174,7 +1142,7 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype:
var rect = [self frameForItemAtIndex:dropIndex];
frameOrigin = CGPointMake(CGRectGetMaxX(rect) + offset, rect.origin.y - _verticalMargin);
frameOrigin = _CGPointMake(_CGRectGetMaxX(rect) + offset, rect.origin.y - _verticalMargin);
}
[_dropView setFrameOrigin:frameOrigin];
@@ -1221,8 +1189,8 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype:
- (void)drawRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort],
width = CGRectGetWidth(aRect),
circleRect = CGRectMake(1, 1, width - 2, width - 2);
width = _CGRectGetWidth(aRect),
circleRect = _CGRectMake(1, 1, width - 2, width - 2);
CGContextSetStrokeColor(context, [CPColor colorWithHexString:@"4886ca"]);
CGContextSetFillColor(context, [CPColor whiteColor]);
@@ -1236,8 +1204,8 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype:
//then draw the line
CGContextBeginPath(context);
CGContextMoveToPoint(context, FLOOR(width / 2), CGRectGetMinY(aRect) + width);
CGContextAddLineToPoint(context, FLOOR(width / 2), CGRectGetHeight(aRect));
CGContextMoveToPoint(context, FLOOR(width / 2), _CGRectGetMinY(aRect) + width);
CGContextAddLineToPoint(context, FLOOR(width / 2), _CGRectGetHeight(aRect));
CGContextStrokePath(context);
}
@@ -1247,12 +1215,7 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype:
- (void)_modifySelectionWithNewIndex:(int)anIndex direction:(int)aDirection expand:(BOOL)shouldExpand
{
var count = [[self items] count];
if (count === 0)
return;
anIndex = MIN(MAX(anIndex, 0), count - 1);
anIndex = MIN(MAX(anIndex, 0), [[self items] count] - 1);
if (_allowsMultipleSelection && shouldExpand)
{
@@ -1262,9 +1225,9 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype:
// if the direction is backward (-1) check with the bottom anchor
if (aDirection === -1)
[indexes addIndexesInRange:CPMakeRange(anIndex, bottomAnchor - anIndex + 1)];
[indexes addIndexesInRange:_CPMakeRange(anIndex, bottomAnchor - anIndex + 1)];
else
[indexes addIndexesInRange:CPMakeRange(topAnchor, anIndex - topAnchor + 1)];
[indexes addIndexesInRange:_CPMakeRange(topAnchor, anIndex - topAnchor + 1)];
}
else
indexes = [CPIndexSet indexSetWithIndex:anIndex];
@@ -1277,7 +1240,7 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype:
{
var frame = [self frameForItemsAtIndexes:[self selectionIndexes]];
if (!CGRectIsEmpty(frame))
if (!_CGRectIsNull(frame))
[self scrollRectToVisible:frame];
}
@@ -1357,14 +1320,13 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype:
[self interpretKeyEvents:[anEvent]];
}
- (void)setAutoresizingMask:(unsigned)aMask
- (void)setAutoresizingMask:(int)aMask
{
[super setAutoresizingMask:0];
}
@end
@implementation CPCollectionView (Deprecated)
- (CGRect)rectForItemAtIndex:(int)anIndex
@@ -1385,148 +1347,6 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype:
@end
@implementation CPCollectionView (CPCollectionViewDelegate)
/*
@ignore
Return YES if the delegate implements collectionView:validateDrop:proposedIndex:dropOperation:
*/
- (BOOL)_delegateRespondsToCollectionViewValidateDropProposedIndexDropOperation
{
return _implementedDelegateMethods & CPCollectionViewDelegate_collectionView_validateDrop_proposedIndex_dropOperation_;
}
/*
@ignore
Return YES if the delegate implements collectionView:menuForItemAtIndex:
*/
- (BOOL)_delegateRespondsToCollectionViewMenuForItemAtIndex
{
return _implementedDelegateMethods & CPCollectionViewDelegate_collectionView_menuForItemAtIndex_;
}
/*
@ignore
Return YES if the delegate implements collectionView:dragTypesForItemsAtIndexes:
*/
- (BOOL)_delegateRespondsToCollectionViewDragTypesForItemsAtIndexes
{
return _implementedDelegateMethods & CPCollectionViewDelegate_collectionView_dragTypesForItemsAtIndexes_;
}
/*!
@ignore
Call delegate collectionView:acceptDrop:index:dropOperation:
*/
- (BOOL)_sendDelegateAcceptDrop:(id)draggingInfo index:(CPInteger)index dropOperation:(CPCollectionViewDropOperation)dropOperation
{
if (!(_implementedDelegateMethods & CPCollectionViewDelegate_collectionView_acceptDrop_index_dropOperation_))
return NO;
return [_delegate collectionView:self acceptDrop:draggingInfo index:index dropOperation:dropOperation];
}
/*!
@ignore
Call delegate collectionView:canDragItemsAtIndexes:withEvent:
*/
- (BOOL)_sendDelegateCanDragItemsAtIndexes:(CPIndexSet)indexes withEvent:(CPEvent)anEvent
{
if (!(_implementedDelegateMethods & CPCollectionViewDelegate_collectionView_canDragItemsAtIndexes_withEvent_))
return YES;
return [_delegate collectionView:self canDragItemsAtIndexes:indexes withEvent:anEvent];
}
/*!
@ignore
Call delegate collectionView:writeItemsAtIndexes:toPasteboard:
*/
- (BOOL)_sendDelegateWriteItemsAtIndexes:(CPIndexSet)indexes toPasteboard:(CPPasteboard)pasteboard
{
if (!(_implementedDelegateMethods & CPCollectionViewDelegate_collectionView_writeItemsAtIndexes_toPasteboard_))
return NO;
return [_delegate collectionView:self writeItemsAtIndexes:indexes toPasteboard:pasteboard];
}
/*!
@ignore
Call delegate collectionView:dragTypesForItemsAtIndexes:
*/
- (CPArray)_sendDelegateDragTypesForItemsAtIndexes:(CPIndexSet)indexes
{
if (!(_implementedDelegateMethods & CPCollectionViewDelegate_collectionView_dragTypesForItemsAtIndexes_))
return [];
return [_delegate collectionView:self dragTypesForItemsAtIndexes:indexes];
}
/*!
@ignore
Call delegate collectionView:dataForItemsAtIndexes:forType:
*/
- (CPData)_sendDelegateDataForItemsAtIndexes:(CPIndexSet)indexes forType:(CPString)aType
{
if (!(_implementedDelegateMethods & CPCollectionViewDelegate_collectionView_dataForItemsAtIndexes_forType_))
return nil;
return [_delegate collectionView:self dataForItemsAtIndexes:indexes forType:aType];
}
/*!
@ignore
Call delegate collectionView:validateDrop:proposedIndex:dropOperation:
*/
- (CPDragOperation)_sendDelegateValidateDrop:(id)draggingInfo proposedIndex:(CPInteger)proposedDropIndex dropOperation:(CPCollectionViewDropOperation)proposedDropOperation
{
if (!(_implementedDelegateMethods & CPCollectionViewDelegate_collectionView_validateDrop_proposedIndex_dropOperation_))
return CPDragOperationNone;
return [_delegate collectionView:self validateDrop:draggingInfo proposedIndex:proposedDropIndex dropOperation:proposedDropOperation];
}
/*!
@ignore
Call delegate collectionView:didDoubleClickOnItemAtIndex:
*/
- (void)_sendDelegateDidDoubleClickOnItemAtIndex:(int)index
{
if (!(_implementedDelegateMethods & CPCollectionViewDelegate_collectionView_didDoubleClickOnItemAtIndex_))
return;
return [_delegate collectionView:self didDoubleClickOnItemAtIndex:index];
}
/*!
@ignore
Call delegate collectionView:menuForItemAtIndex:
*/
- (void)_sendDelegateMenuForItemAtIndex:(CPInteger)anIndex
{
if (!(_implementedDelegateMethods & CPCollectionViewDelegate_collectionView_menuForItemAtIndex_))
return nil;
return [_delegate collectionView:self menuForItemAtIndex:anIndex];
}
/*!
@ignore
Call delegate draggingViewForItemsAtIndexes:withEvent:offset:
*/
- (CPView)_sendDelegateDraggingViewForItemsAtIndexes:(CPIndexSet)indexes withEvent:(CPEvent)anEvent offset:(CGPoint)dragImageOffset
{
if (!(_implementedDelegateMethods & CPCollectionViewDelegate_collectionView_draggingViewForItemsAtIndexes_withEvent_offset))
return [self draggingViewForItemsAtIndexes:indexes withEvent:anEvent offset:dragImageOffset];
return [_delegate collectionView:self draggingViewForItemsAtIndexes:indexes withEvent:anEvent offset:dragImageOffset];
}
@end
var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeKey",
CPCollectionViewMaxItemSizeKey = @"CPCollectionViewMaxItemSizeKey",
CPCollectionViewVerticalMarginKey = @"CPCollectionViewVerticalMarginKey",
@@ -1568,10 +1388,10 @@ var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeK
{
[super encodeWithCoder:aCoder];
if (!CGSizeEqualToSize(_minItemSize, CGSizeMakeZero()))
if (!_CGSizeEqualToSize(_minItemSize, _CGSizeMakeZero()))
[aCoder encodeSize:_minItemSize forKey:CPCollectionViewMinItemSizeKey];
if (!CGSizeEqualToSize(_maxItemSize, CGSizeMakeZero()))
if (!_CGSizeEqualToSize(_maxItemSize, _CGSizeMakeZero()))
[aCoder encodeSize:_maxItemSize forKey:CPCollectionViewMaxItemSizeKey];
[aCoder encodeInt:_maxNumberOfRows forKey:CPCollectionViewMaxNumberOfRowsKey];
+26 -148
View File
@@ -25,7 +25,6 @@
@import "CGColor.j"
@import "_CPObject+Theme.j"
@import "CPCompatibility.j"
@import "CPImage.j"
@@ -66,8 +65,7 @@ var cachedBlackColor,
cachedOrangeColor,
cachedPurpleColor,
cachedShadowColor,
cachedClearColor,
cachedThemeColor;
cachedClearColor;
/// @endcond
@@ -80,7 +78,7 @@ var cachedBlackColor,
<p>It also provides some class helper methods that
returns instances of commonly used colors.</p>
*/
@implementation CPColor : CPObject <CPTheme>
@implementation CPColor : CPObject
{
CPArray _components;
@@ -88,27 +86,6 @@ var cachedBlackColor,
CPString _cssString;
}
#pragma mark -
#pragma mark Theming
+ (CPString)defaultThemeClass
{
return "color";
}
+ (CPDictionary)themeAttributes
{
return @{
@"alternate-selected-control-color": [CPNull null],
@"secondary-selected-control-color" : [CPNull null]
};
}
#pragma mark -
#pragma mark Static methods
/*!
Creates a color in the RGB colorspace, with an alpha value.
Each component should be between the range of 0.0 to 1.0. For
@@ -179,15 +156,11 @@ var cachedBlackColor,
}
/*!
Creates a new color based on the given HSB components.
Creates a new color in HSB space.
Note: earlier versions of this method took a hue component as degrees between 0-360,
and saturation and brightness components as percent between 0-100. This method has
now been corrected to take all components in the 0-1 range as in Cocoa.
@param hue the hue component (0.0-1.0)
@param saturation the saturation component (0.0-1.0)
@param brightness the brightness component (0.0-1.0)
@param hue the hue value
@param saturation the saturation value
@param brightness the brightness value
@return the initialized color
*/
@@ -196,61 +169,25 @@ var cachedBlackColor,
return [self colorWithHue:hue saturation:saturation brightness:brightness alpha:1.0];
}
/*!
Calibrated colors are not supported in Cappuccino.
This method has the same result as [CPColor colorWithHue:saturation:brightness:alpha:].
*/
+ (CPColor)colorWithCalibratedHue:(float)hue saturation:(float)saturation brightness:(float)brightness alpha:(float)alpha
{
return [self colorWithHue:hue saturation:saturation brightness:brightness alpha:alpha];
}
/*!
Creates a new color based on the given HSB components.
Note: earlier versions of this method took a hue component as degrees between 0-360,
and saturation and brightness components as percent between 0-100. This method has
now been corrected to take all components in the 0-1 range as in Cocoa.
@param hue the hue component (0.0-1.0)
@param saturation the saturation component (0.0-1.0)
@param brightness the brightness component (0.0-1.0)
@param alpha the opacity component (0.0-1.0)
@return the initialized color
*/
+ (CPColor)colorWithHue:(float)hue saturation:(float)saturation brightness:(float)brightness alpha:(float)alpha
{
// Clamp values.
hue = MAX(MIN(hue, 1.0), 0.0);
saturation = MAX(MIN(saturation, 1.0), 0.0);
brightness = MAX(MIN(brightness, 1.0), 0.0);
if (saturation === 0.0)
return [CPColor colorWithCalibratedWhite:brightness alpha:alpha];
return [CPColor colorWithCalibratedWhite:brightness / 100.0 alpha:alpha];
var f = (hue * 360) % 60,
p = (brightness * (1 - saturation)),
q = (brightness * (60 - saturation * f)) / 60,
t = (brightness * (60 - saturation * (60 - f))) / 60,
b = brightness;
var f = hue % 60,
p = (brightness * (100 - saturation)) / 10000,
q = (brightness * (6000 - saturation * f)) / 600000,
t = (brightness * (6000 - saturation * (60 -f))) / 600000,
b = brightness / 100.0;
switch (FLOOR(hue * 6))
switch (FLOOR(hue / 60))
{
case 0:
case 6:
return [CPColor colorWithCalibratedRed:b green:t blue:p alpha:alpha];
case 1:
return [CPColor colorWithCalibratedRed:q green:b blue:p alpha:alpha];
case 2:
return [CPColor colorWithCalibratedRed:p green:b blue:t alpha:alpha];
case 3:
return [CPColor colorWithCalibratedRed:p green:q blue:b alpha:alpha];
case 4:
return [CPColor colorWithCalibratedRed:t green:p blue:b alpha:alpha];
case 5:
return [CPColor colorWithCalibratedRed:b green:p blue:q alpha:alpha];
case 0: return [CPColor colorWithCalibratedRed:b green:t blue:p alpha:alpha];
case 1: return [CPColor colorWithCalibratedRed:q green:b blue:p alpha:alpha];
case 2: return [CPColor colorWithCalibratedRed:p green:b blue:t alpha:alpha];
case 3: return [CPColor colorWithCalibratedRed:p green:q blue:b alpha:alpha];
case 4: return [CPColor colorWithCalibratedRed:t green:p blue:b alpha:alpha];
case 5: return [CPColor colorWithCalibratedRed:b green:p blue:q alpha:alpha];
}
}
@@ -459,22 +396,14 @@ var cachedBlackColor,
return cachedClearColor;
}
+ (CPColor)_cachedThemeColor
{
if (!cachedThemeColor)
cachedThemeColor = [self colorWithCalibratedWhite:0.0 alpha:0.0];
return cachedThemeColor;
}
+ (CPColor)alternateSelectedControlColor
{
return [[self _cachedThemeColor] valueForThemeAttribute:@"alternate-selected-control-color"];
return [[CPColor alloc] _initWithRGBA:[0.22, 0.46, 0.84, 1.0]];
}
+ (CPColor)secondarySelectedControlColor
{
return [[self _cachedThemeColor] valueForThemeAttribute:@"secondary-selected-control-color"];
return [[CPColor alloc] _initWithRGBA:[0.83, 0.83, 0.83, 1.0]];
}
/*!
@@ -520,10 +449,6 @@ var cachedBlackColor,
// use it (issue #1413.)
[self _initCSSStringFromComponents];
_theme = [CPTheme defaultTheme];
_themeState = CPThemeStateNormal;
[self _loadThemeAttributes];
return self;
}
@@ -537,10 +462,6 @@ var cachedBlackColor,
_components = components;
[self _initCSSStringFromComponents];
_theme = [CPTheme defaultTheme];
_themeState = CPThemeStateNormal;
[self _loadThemeAttributes];
}
return self;
@@ -567,10 +488,6 @@ var cachedBlackColor,
_patternImage = anImage;
_cssString = "url(\"" + [_patternImage filename] + "\")";
_components = [0.0, 0.0, 0.0, 1.0];
_theme = [CPTheme defaultTheme];
_themeState = CPThemeStateNormal;
[self _loadThemeAttributes];
}
return self;
@@ -658,9 +575,6 @@ var cachedBlackColor,
/*!
Returns an array with the HSB values for this color.
The values are expressed as fractions between 0.0-1.0.
The index values are ordered as:
<pre>
<b>Index</b> <b>Component</b>
@@ -707,36 +621,12 @@ var cachedBlackColor,
}
return [
hue,
saturation,
brightness
ROUND(hue * 360.0),
ROUND(saturation * 100.0),
ROUND(brightness * 100.0)
];
}
/*!
Returns the hue component, the H in HSB, of the receiver.
*/
- (float)hueComponent
{
return [self hsbComponents][0];
}
/*!
Returns the saturation component, the S in HSB, of the receiver.
*/
- (float)saturationComponent
{
return [self hsbComponents][1];
}
/*!
Returns the brightness component, the B in HSB, of the receiver.
*/
- (float)brightnessComponent
{
return [self hsbComponents][2];
}
/*!
Returns the CSS representation of this color. The color will
be in one of the following forms:
@@ -856,12 +746,6 @@ url("data:image/png;base64,BASE64ENCODEDDATA") // if there is a pattern image
return [CPColor colorWithRed:RAND() green:RAND() blue:RAND() alpha:1.0];
}
+ (CPColor)checkerBoardColor
{
// Thanks to cocco http://stackoverflow.com/a/18368212/76900.
return [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEX////MzMw46qqDAAAAEElEQVQImWNg+M+AFeEQBgB+vw/xfUUZkgAAAABJRU5ErkJggg=="]];
}
@end
/// @cond IGNORE
@@ -878,13 +762,9 @@ var CPColorComponentsKey = @"CPColorComponentsKey",
- (id)initWithCoder:(CPCoder)aCoder
{
if ([aCoder containsValueForKey:CPColorPatternImageKey])
self = [self _initWithPatternImage:[aCoder decodeObjectForKey:CPColorPatternImageKey]];
else
self = [self _initWithRGBA:[aCoder decodeObjectForKey:CPColorComponentsKey]];
return [self _initWithPatternImage:[aCoder decodeObjectForKey:CPColorPatternImageKey]];
[self _decodeThemeObjectsWithCoder:aCoder];
return self;
return [self _initWithRGBA:[aCoder decodeObjectForKey:CPColorComponentsKey]];
}
/*!
@@ -897,8 +777,6 @@ var CPColorComponentsKey = @"CPColorComponentsKey",
[aCoder encodeObject:_patternImage forKey:CPColorPatternImageKey];
else
[aCoder encodeObject:_components forKey:CPColorComponentsKey];
[self _encodeThemeObjectsWithCoder:aCoder];
}
@end
+3 -5
View File
@@ -27,9 +27,6 @@
@import "CPView.j"
@class CPSlider
@class _CPColorPanelToolbar
@class _CPColorPanelSwatches
@class _CPColorPanelPreview
@global CPApp
@@ -71,6 +68,7 @@ var SharedColorPanel = nil,
*/
@implementation CPColorPanel : CPPanel
{
_CPColorPanelToolbar _toolbar;
_CPColorPanelSwatches _swatchView;
_CPColorPanelPreview _previewView;
@@ -578,7 +576,7 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
[aPasteboard setData:[CPKeyedArchiver archivedDataWithRootObject:_dragColor] forType:aType];
}
- (void)performDragOperation:(id /*<CPDraggingInfo>*/)aSender
- (void)performDragOperation:(id <CPDraggingInfo>)aSender
{
var location = [self convertPoint:[aSender draggingLocation] fromView:nil],
pasteboard = [aSender draggingPasteboard],
@@ -617,7 +615,7 @@ var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie";
return _colorPanel;
}
- (void)performDragOperation:(id /*<CPDraggingInfo>*/)aSender
- (void)performDragOperation:(id <CPDraggingInfo>)aSender
{
var pasteboard = [aSender draggingPasteboard];
+10 -12
View File
@@ -25,8 +25,6 @@
@import "CPView.j"
@class CPSlider
@class CPColorPanel
@class __CPColorWheel
@global CPColorPickerViewWidth
@global CPColorPickerViewHeight
@@ -117,12 +115,12 @@
- (id)initView
{
var aFrame = CGRectMake(0, 0, CPColorPickerViewWidth, CPColorPickerViewHeight);
var aFrame = _CGRectMake(0, 0, CPColorPickerViewWidth, CPColorPickerViewHeight);
_pickerView = [[CPView alloc] initWithFrame:aFrame];
[_pickerView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
_brightnessSlider = [[CPSlider alloc] initWithFrame:CGRectMake(0, (aFrame.size.height - 34), aFrame.size.width, 15)];
_brightnessSlider = [[CPSlider alloc] initWithFrame:_CGRectMake(0, (aFrame.size.height - 34), aFrame.size.width, 15)];
[_brightnessSlider setValue:15.0 forThemeAttribute:@"track-width"];
[_brightnessSlider setValue:[CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPColorPicker class]] pathForResource:@"brightness_bar.png"]]] forThemeAttribute:@"track-color"];
@@ -135,7 +133,7 @@
[_brightnessSlider setAction:@selector(brightnessSliderDidChange:)];
[_brightnessSlider setAutoresizingMask:CPViewWidthSizable | CPViewMinYMargin];
_hueSaturationView = [[__CPColorWheel alloc] initWithFrame:CGRectMake(0, 0, aFrame.size.width, aFrame.size.height - 38)];
_hueSaturationView = [[__CPColorWheel alloc] initWithFrame:_CGRectMake(0, 0, aFrame.size.width, aFrame.size.height - 38)];
[_hueSaturationView setDelegate:self];
[_hueSaturationView setAutoresizingMask:(CPViewWidthSizable | CPViewHeightSizable)];
@@ -160,12 +158,12 @@
brightness = [_brightnessSlider floatValue];
[_hueSaturationView setWheelBrightness:brightness / 100.0];
[_brightnessSlider setBackgroundColor:[CPColor colorWithHue:hue / 360.0 saturation:saturation / 100.0 brightness:1]];
[_brightnessSlider setBackgroundColor:[CPColor colorWithHue:hue saturation:saturation brightness:100]];
var colorPanel = [self colorPanel],
opacity = [colorPanel opacity];
_cachedColor = [CPColor colorWithHue:hue / 360.0 saturation:saturation / 100.0 brightness:brightness / 100.0 alpha:opacity];
_cachedColor = [CPColor colorWithHue:hue saturation:saturation brightness:brightness alpha:opacity];
[[self colorPanel] setColor:_cachedColor];
}
@@ -196,10 +194,10 @@
var hsb = [newColor hsbComponents];
[_hueSaturationView setPositionToColor:newColor];
[_brightnessSlider setFloatValue:hsb[2] * 100.0];
[_hueSaturationView setWheelBrightness:hsb[2]];
[_brightnessSlider setFloatValue:hsb[2]];
[_hueSaturationView setWheelBrightness:hsb[2] / 100.0];
[_brightnessSlider setBackgroundColor:[CPColor colorWithHue:hsb[0] saturation:hsb[1] brightness:1]];
[_brightnessSlider setBackgroundColor:[CPColor colorWithHue:hsb[0] saturation:hsb[1] brightness:100]];
}
- (CPImage)provideNewButtonImage
@@ -368,8 +366,8 @@
{
var hsb = [aColor hsbComponents],
bounds = [self bounds],
angle = [self degreesToRadians:hsb[0] * 360.0],
distance = hsb[1] * _radius;
angle = [self degreesToRadians:hsb[0]],
distance = (hsb[1] / 100.0) * _radius;
[self setAngle:angle distance:distance];
}
+13 -47
View File
@@ -58,13 +58,13 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
return @"colorwell";
}
+ (CPDictionary)themeAttributes
+ (id)themeAttributes
{
return @{
@"bezel-inset": CGInsetMakeZero(),
@"bezel-inset": _CGInsetMakeZero(),
@"bezel-color": [CPNull null],
@"content-inset": CGInsetMake(3.0, 3.0, 3.0, 3.0),
@"content-border-inset": CGInsetMakeZero(),
@"content-inset": _CGInsetMake(3.0, 3.0, 3.0, 3.0),
@"content-border-inset": _CGInsetMakeZero(),
@"content-border-color": [CPNull null],
};
}
@@ -86,12 +86,14 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
_active = NO;
_color = [CPColor whiteColor];
[self setBordered:YES];
[self _registerForNotifications];
}
return self;
}
- (void)_registerNotifications
- (void)_registerForNotifications
{
var defaultCenter = [CPNotificationCenter defaultCenter];
@@ -108,22 +110,6 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
object:[CPColorPanel sharedColorPanel]];
}
- (void)_removeNotifications
{
var defaultCenter = [CPNotificationCenter defaultCenter];
[defaultCenter
removeObserver:self
name:_CPColorWellDidBecomeExclusiveNotification
object:nil];
[defaultCenter
removeObserver:self
name:CPWindowWillCloseNotification
object:[CPColorPanel sharedColorPanel]];
}
/*!
Sets whether the color well is bordered.
*/
@@ -263,21 +249,21 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
{
var contentInset = [self currentValueForThemeAttribute:@"content-inset"];
return CGRectInsetByInset(bounds, contentInset);
return _CGRectInsetByInset(bounds, contentInset);
}
- (CGRect)bezelRectForBounds:(CGRect)bounds
{
var bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"];
return CGRectInsetByInset(bounds, bezelInset);
return _CGRectInsetByInset(bounds, bezelInset);
}
- (CGRect)contentBorderRectForBounds:(CGRect)bounds
{
var contentBorderInset = [self currentValueForThemeAttribute:@"content-border-inset"];
return CGRectInsetByInset(bounds, contentBorderInset);
return _CGRectInsetByInset(bounds, contentBorderInset);
}
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aName
@@ -297,7 +283,7 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
- (CPView)createEphemeralSubviewNamed:(CPString)aName
{
var view = [[CPView alloc] initWithFrame:CGRectMakeZero()];
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
[view setHitTests:NO];
@@ -326,28 +312,6 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
[contentBorderView setBackgroundColor:[self currentValueForThemeAttribute:@"content-border-color"]];
}
#pragma mark -
#pragma mark Observers method
- (void)_addObservers
{
if (_isObserving)
return;
[super _addObservers];
[self _registerNotifications];
}
- (void)_removeObservers
{
if (!_isObserving)
return;
[super _removeObservers];
[self _removeNotifications];
}
@end
@implementation CPColorWellValueBinder : CPBinder
@@ -399,6 +363,8 @@ var CPColorWellColorKey = "CPColorWellColorKey",
_active = NO;
_color = [aCoder decodeObjectForKey:CPColorWellColorKey];
[self setBordered:[aCoder decodeBoolForKey:CPColorWellBorderedKey]];
[self _registerForNotifications];
}
return self;
+80 -183
View File
@@ -25,27 +25,6 @@
@import "_CPPopUpList.j"
// TODO : should conform to protocol CPTextFieldDelegate
@protocol CPComboBoxDelegate <CPObject>
@optional
- (void)comboBoxSelectionIsChanging:(CPNotification)aNotification;
- (void)comboBoxSelectionDidChange:(CPNotification)aNotification;
- (void)comboBoxWillPopUp:(CPNotification)aNotification;
- (void)comboBoxWillDismiss:(CPNotification)aNotification;
@end
@protocol CPComboBoxDataSource <CPObject>
@optional
- (CPString)comboBox:(CPComboBox)aComboBox completedString:(CPString)uncompletedString;
- (id)comboBox:(CPComboBox)aComboBox objectValueForItemAtIndex:(int)index;
- (int)comboBox:(CPComboBox)aComboBox indexOfItemWithStringValue:(CPString)stringValue;
- (int)numberOfItemsInComboBox:(CPComboBox)aComboBox;
@end
CPComboBoxSelectionDidChangeNotification = @"CPComboBoxSelectionDidChangeNotification";
CPComboBoxSelectionIsChangingNotification = @"CPComboBoxSelectionIsChangingNotification";
CPComboBoxWillDismissNotification = @"CPComboBoxWillDismissNotification";
@@ -53,11 +32,6 @@ CPComboBoxWillPopUpNotification = @"CPComboBoxWillPopUpNotification";
CPComboBoxStateButtonBordered = CPThemeState("button-bordered");
var CPComboBoxDelegate_comboBoxSelectionIsChanging_ = 1 << 0,
CPComboBoxDelegate_comboBoxSelectionDidChange_ = 1 << 1,
CPComboBoxDelegate_comboBoxWillPopUp_ = 1 << 2,
CPComboBoxDelegate_comboBoxWillDismiss_ = 1 << 3;
var CPComboBoxTextSubview = @"text",
CPComboBoxButtonSubview = @"button",
CPComboBoxDefaultNumberOfVisibleItems = 5,
@@ -66,20 +40,17 @@ var CPComboBoxTextSubview = @"text",
@implementation CPComboBox : CPTextField
{
BOOL _canComplete;
BOOL _completes;
BOOL _forceSelection;
BOOL _hasVerticalScroller;
BOOL _popUpButtonCausedResign;
BOOL _usesDataSource;
CGSize _intercellSpacing;
CPArray _items;
id <CPComboBoxDataSource> _dataSource;
CPInteger _implementedDelegateComboBoxMethods;
CPString _selectedStringValue;
float _itemHeight;
int _numberOfVisibleItems;
_CPPopUpList _listDelegate;
CPArray _items;
_CPPopUpList _listDelegate;
CPComboBoxDataSource _dataSource;
BOOL _usesDataSource;
BOOL _completes;
BOOL _canComplete;
int _numberOfVisibleItems;
BOOL _forceSelection;
BOOL _hasVerticalScroller;
CPString _selectedStringValue;
BOOL _popUpButtonCausedResign;
}
+ (CPString)defaultThemeClass
@@ -87,11 +58,11 @@ var CPComboBoxTextSubview = @"text",
return "combobox";
}
+ (CPDictionary)themeAttributes
+ (id)themeAttributes
{
return @{
@"popup-button-size": CGSizeMake(21.0, 29.0),
@"border-inset": CGInsetMake(3.0, 3.0, 3.0, 3.0),
@"popup-button-size": _CGSizeMake(21.0, 29.0),
@"border-inset": _CGInsetMake(3.0, 3.0, 3.0, 3.0),
};
}
@@ -148,9 +119,7 @@ var CPComboBoxTextSubview = @"text",
return;
_hasVerticalScroller = flag;
if (_listDelegate)
[[_listDelegate scrollView] setHasVerticalScroller:_hasVerticalScroller];
[[_listDelegate scrollView] setHasVerticalScroller:flag];
}
- (CGSize)intercellSpacing
@@ -160,13 +129,7 @@ var CPComboBoxTextSubview = @"text",
- (void)setIntercellSpacing:(CGSize)aSize
{
if (_intercellSpacing && CGSizeEqualToSize(aSize, _intercellSpacing))
return;
_intercellSpacing = aSize;
if (_listDelegate)
[[_listDelegate tableView] setIntercellSpacing:_intercellSpacing];
[[_listDelegate tableView] setIntercellSpacing:aSize];
}
- (BOOL)isButtonBordered
@@ -189,18 +152,10 @@ var CPComboBoxTextSubview = @"text",
- (void)setItemHeight:(float)itemHeight
{
if (itemHeight === _itemHeight)
return;
[[_listDelegate tableView] setRowHeight:itemHeight];
_itemHeight = itemHeight;
if (_listDelegate)
{
[[_listDelegate tableView] setRowHeight:_itemHeight];
// FIXME: This shouldn't be necessary, but CPTableView does not tile after setRowHeight
[[_listDelegate tableView] reloadData];
}
// FIXME: This shouldn't be necessary, but CPTableView does not tile after setRowHeight
[[_listDelegate tableView] reloadData];
}
- (int)numberOfVisibleItems
@@ -216,7 +171,7 @@ var CPComboBoxTextSubview = @"text",
#pragma mark Setting a Delegate
- (id <CPComboBoxDelegate>)delegate
- (id < CPComboBoxDelegate >)delegate
{
return [super delegate];
}
@@ -227,28 +182,48 @@ var CPComboBoxTextSubview = @"text",
protocol, in actual fact it doesn't. Also note that the same
delegate may conform to the NSTextFieldDelegate protocol.
*/
- (void)setDelegate:(id <CPComboBoxDelegate>)aDelegate
- (void)setDelegate:(id < CPComboBoxDelegate >)aDelegate
{
var delegate = [self delegate];
if (aDelegate === delegate)
return;
_implementedDelegateComboBoxMethods = 0;
var defaultCenter = [CPNotificationCenter defaultCenter];
if (delegate)
{
[defaultCenter removeObserver:delegate name:CPComboBoxSelectionIsChangingNotification object:self];
[defaultCenter removeObserver:delegate name:CPComboBoxSelectionDidChangeNotification object:self];
[defaultCenter removeObserver:delegate name:CPComboBoxWillDismissNotification object:self];
[defaultCenter removeObserver:delegate name:CPComboBoxWillPopUpNotification object:self];
}
if (aDelegate)
{
if ([aDelegate respondsToSelector:@selector(comboBoxSelectionIsChanging:)])
_implementedDelegateComboBoxMethods |= CPComboBoxDelegate_comboBoxSelectionIsChanging_;
[defaultCenter addObserver:delegate
selector:@selector(comboBoxSelectionIsChanging:)
name:CPComboBoxSelectionIsChangingNotification
object:self];
if ([aDelegate respondsToSelector:@selector(comboBoxSelectionDidChange:)])
_implementedDelegateComboBoxMethods |= CPComboBoxDelegate_comboBoxSelectionDidChange_;
[defaultCenter addObserver:delegate
selector:@selector(comboBoxSelectionDidChange:)
name:CPComboBoxSelectionDidChangeNotification
object:self];
if ([aDelegate respondsToSelector:@selector(comboBoxWillPopUp:)])
_implementedDelegateComboBoxMethods |= CPComboBoxDelegate_comboBoxWillPopUp_;
[defaultCenter addObserver:delegate
selector:@selector(comboBoxWillPopUp:)
name:CPComboBoxWillPopUpNotification
object:self];
if ([aDelegate respondsToSelector:@selector(comboBoxWillDismiss:)])
_implementedDelegateComboBoxMethods |= CPComboBoxDelegate_comboBoxWillDismiss_;
[defaultCenter addObserver:delegate
selector:@selector(comboBoxWillDissmis:)
name:CPComboBoxWillDismissNotification
object:self];
}
[super setDelegate:aDelegate];
@@ -256,7 +231,7 @@ var CPComboBoxTextSubview = @"text",
#pragma mark Setting a Data Source
- (id <CPComboBoxDataSource>)dataSource
- (id < CPComboBoxDataSource >)dataSource
{
if (!_usesDataSource)
[self _dataSourceWarningForMethod:_cmd condition:NO];
@@ -264,12 +239,10 @@ var CPComboBoxTextSubview = @"text",
return _dataSource;
}
- (void)setDataSource:(id <CPComboBoxDataSource>)aSource
- (void)setDataSource:(id < CPComboBoxDataSource >)aSource
{
if (!_usesDataSource)
{
[self _dataSourceWarningForMethod:_cmd condition:NO];
}
else if (_dataSource !== aSource)
{
if (![aSource respondsToSelector:@selector(numberOfItemsInComboBox:)] ||
@@ -278,9 +251,7 @@ var CPComboBoxTextSubview = @"text",
CPLog.warn("Illegal %s data source (%s). Must implement numberOfItemsInComboBox: and comboBox:objectValueForItemAtIndex:", [self className], [aSource description]);
}
else
{
_dataSource = aSource;
}
}
}
@@ -398,57 +369,49 @@ var CPComboBoxTextSubview = @"text",
if (_listDelegate === aDelegate)
return;
[self _removeObserversForListDelegate:_listDelegate];
var defaultCenter = [CPNotificationCenter defaultCenter];
if (_listDelegate)
{
[defaultCenter removeObserver:self name:_CPPopUpListWillPopUpNotification object:_listDelegate];
[defaultCenter removeObserver:self name:_CPPopUpListWillDismissNotification object:_listDelegate];
[defaultCenter removeObserver:self name:_CPPopUpListDidDismissNotification object:_listDelegate];
[defaultCenter removeObserver:self name:_CPPopUpListItemWasClickedNotification object:_listDelegate];
var oldTableView = [_listDelegate tableView];
if (oldTableView)
{
[defaultCenter removeObserver:self name:CPTableViewSelectionIsChangingNotification object:oldTableView];
[defaultCenter removeObserver:self name:CPTableViewSelectionDidChangeNotification object:oldTableView];
}
}
_listDelegate = aDelegate;
// We only add the observers if the CPComboBox is displayed
if ([self window])
[self _addObserversForListDelegate:_listDelegate]
// Apply our text style to the list
[_listDelegate setFont:[self font]];
[_listDelegate setAlignment:[self alignment]];
[[_listDelegate scrollView] setHasVerticalScroller:_hasVerticalScroller];
if (_intercellSpacing)
[[_listDelegate tableView] setIntercellSpacing:_intercellSpacing];
if (_itemHeight)
[[_listDelegate tableView] setRowHeight:_itemHeight];
}
- (void)_addObserversForListDelegate:(_CPPopUpList)aDelegate
{
if (!aDelegate)
return;
var defaultCenter = [CPNotificationCenter defaultCenter];
[defaultCenter addObserver:self
selector:@selector(comboBoxWillPopUp:)
name:_CPPopUpListWillPopUpNotification
object:aDelegate];
object:_listDelegate];
[defaultCenter addObserver:self
selector:@selector(comboBoxWillDismiss:)
name:_CPPopUpListWillDismissNotification
object:aDelegate];
object:_listDelegate];
[defaultCenter addObserver:self
selector:@selector(listDidDismiss:)
name:_CPPopUpListDidDismissNotification
object:aDelegate];
object:_listDelegate];
[defaultCenter addObserver:self
selector:@selector(itemWasClicked:)
name:_CPPopUpListItemWasClickedNotification
object:aDelegate];
object:_listDelegate];
[[aDelegate scrollView] setHasVerticalScroller:_hasVerticalScroller];
[[_listDelegate scrollView] setHasVerticalScroller:_hasVerticalScroller];
var tableView = [aDelegate tableView];
var tableView = [_listDelegate tableView];
[defaultCenter addObserver:self
selector:@selector(comboBoxSelectionIsChanging:)
@@ -459,27 +422,10 @@ var CPComboBoxTextSubview = @"text",
selector:@selector(comboBoxSelectionDidChange:)
name:CPTableViewSelectionDidChangeNotification
object:tableView];
}
- (void)_removeObserversForListDelegate:(_CPPopUpList)aDelegate
{
if (!aDelegate)
return;
var defaultCenter = [CPNotificationCenter defaultCenter];
[defaultCenter removeObserver:self name:_CPPopUpListWillPopUpNotification object:aDelegate];
[defaultCenter removeObserver:self name:_CPPopUpListWillDismissNotification object:aDelegate];
[defaultCenter removeObserver:self name:_CPPopUpListDidDismissNotification object:aDelegate];
[defaultCenter removeObserver:self name:_CPPopUpListItemWasClickedNotification object:aDelegate];
var oldTableView = [aDelegate tableView];
if (oldTableView)
{
[defaultCenter removeObserver:self name:CPTableViewSelectionIsChangingNotification object:oldTableView];
[defaultCenter removeObserver:self name:CPTableViewSelectionDidChangeNotification object:oldTableView];
}
// Apply our text style to the list
[_listDelegate setFont:[self font]];
[_listDelegate setAlignment:[self alignment]];
}
- (int)indexOfItemWithObjectValue:(id)anObject
@@ -524,6 +470,8 @@ var CPComboBoxTextSubview = @"text",
if (!_listDelegate)
[self setListDelegate:[[_CPPopUpList alloc] initWithDataSource:self]];
[self _selectMatchingItem];
// Note the offset here is 1 less than the focus ring width because the outer edge
// of the focus ring is very transparent and it looks better if the list is closer.
if (CPComboBoxFocusRingWidth < 0)
@@ -534,7 +482,6 @@ var CPComboBoxTextSubview = @"text",
}
[_listDelegate popUpRelativeToRect:[self _borderFrame] view:self offset:CPComboBoxFocusRingWidth - 1];
[self _selectMatchingItem];
}
/*! @ignore */
@@ -843,17 +790,7 @@ var CPComboBoxTextSubview = @"text",
// In FireFox this needs to be done in setTimeout, otherwise there is no caret
// We have to save the input element now, when we lose focus it will change.
var element = [self _inputElement];
[[CPRunLoop mainRunLoop] performBlock:function()
{
// This will prevent to jump to the focused element
var previousScrollingOrigin = [self _scrollToVisibleRectAndReturnPreviousOrigin];
element.focus();
[self _restorePreviousScrollingOrigin:previousScrollingOrigin];
} argument:nil order:0 modes:[CPDefaultRunLoopMode]];
window.setTimeout(function() { element.focus(); }, 0);
#endif
return NO;
@@ -880,17 +817,13 @@ var CPComboBoxTextSubview = @"text",
- (void)setFont:(CPFont)aFont
{
[super setFont:aFont];
if (_listDelegate)
[_listDelegate setFont:aFont];
[_listDelegate setFont:aFont];
}
- (void)setAlignment:(CPTextAlignment)alignment
{
[super setAlignment:alignment];
if (_listDelegate)
[_listDelegate setAlignment:alignment];
[_listDelegate setAlignment:alignment];
}
#pragma mark Pop Up Button Layout
@@ -921,7 +854,7 @@ var CPComboBoxTextSubview = @"text",
{
if (aName === "popup-button-view")
{
var view = [[_CPComboBoxPopUpButton alloc] initWithFrame:CGRectMakeZero() comboBox:self];
var view = [[_CPComboBoxPopUpButton alloc] initWithFrame:_CGRectMakeZero() comboBox:self];
return view;
}
@@ -961,9 +894,7 @@ var CPComboBoxTextSubview = @"text",
index = [_dataSource comboBox:self indexOfItemWithStringValue:stringValue]
}
else
{
index = [self indexOfItemWithObjectValue:stringValue];
}
[_listDelegate selectRow:index];
@@ -1015,28 +946,6 @@ var CPComboBoxTextSubview = @"text",
}
}
#pragma mark -
#pragma mark Observers method
- (void)_addObservers
{
if (_isObserving)
return;
[super _addObservers];
[self _addObserversForListDelegate:_listDelegate];
}
- (void)_removeObservers
{
if (!_isObserving)
return;
[super _removeObservers];
[self _removeObserversForListDelegate:_listDelegate];
}
@end
@implementation CPComboBox (CPComboBoxDelegate)
@@ -1044,36 +953,24 @@ var CPComboBoxTextSubview = @"text",
/*! @ignore */
- (void)comboBoxSelectionIsChanging:(CPNotification)aNotification
{
if (_implementedDelegateComboBoxMethods & CPComboBoxDelegate_comboBoxSelectionIsChanging_)
[_delegate comboBoxSelectionIsChanging:[[CPNotification alloc] initWithName:CPComboBoxSelectionIsChangingNotification object:self userInfo:nil]];
[[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxSelectionIsChangingNotification object:self];
}
/*! @ignore */
- (void)comboBoxSelectionDidChange:(CPNotification)aNotification
{
if (_implementedDelegateComboBoxMethods & CPComboBoxDelegate_comboBoxSelectionDidChange_)
[_delegate comboBoxSelectionDidChange:[[CPNotification alloc] initWithName:CPComboBoxSelectionDidChangeNotification object:self userInfo:nil]];
[[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxSelectionDidChangeNotification object:self];
}
/*! @ignore */
- (void)comboBoxWillPopUp:(CPNotification)aNotification
{
if (_implementedDelegateComboBoxMethods & CPComboBoxDelegate_comboBoxWillPopUp_)
[_delegate comboBoxWillPopUp:[[CPNotification alloc] initWithName:CPComboBoxWillPopUpNotification object:self userInfo:nil]];
[[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxWillPopUpNotification object:self];
}
/*! @ignore */
- (void)comboBoxWillDismiss:(CPNotification)aNotification
{
if (_implementedDelegateComboBoxMethods & CPComboBoxDelegate_comboBoxWillDismiss_)
[_delegate comboBoxWillDismiss:[[CPNotification alloc] initWithName:CPComboBoxWillDismissNotification object:self userInfo:nil]];
[[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxWillDismissNotification object:self];
}
+4 -59
View File
@@ -46,9 +46,7 @@ CPHTMLDragAndDropFeature = 8;
CPJavaScriptInnerTextFeature = 9;
CPJavaScriptTextContentFeature = 10;
// In onpaste, oncopy and oncut events, the event has an event.clipboardData from which the current pasteboard contents can be read with event.clipboardData.getData.
CPJavaScriptClipboardEventsFeature = 11;
// window.clipboardData exists and can be read and written to at any time using window.clipboardData.getData/setData.
CPJavaScriptClipboardAccessFeature = 12;
CPJavaScriptCanvasDrawFeature = 13;
CPJavaScriptCanvasTransformFeature = 14;
@@ -78,21 +76,11 @@ CPInputOnInputEventFeature = 30;
CPFileAPIFeature = 31;
CPAltEnterTextAreaFeature = 32;
/*
When an absolutely positioned div (CPView) with an absolutely positioned canvas in it (CPView with drawRect:) moves things on top of the canvas (subviews) don't redraw correctly. E.g. if you have a bunch of text fields in a CPBox in a sheet which animates in, some of the text fields might not be visible because the CPBox has a canvas at the bottom and the box moved form offscreen to onscreen. This bug is probably very related: https://bugs.webkit.org/show_bug.cgi?id=67203
*/
CPCanvasParentDrawErrorsOnMovementBug = 1 << 0;
// The paste event is only sent if an input or textarea has focus.
CPJavaScriptPasteRequiresEditableTarget = 1 << 1;
// Redirecting the focus of the browser on keydown to an input for Cmd-V or Ctrl-V makes the paste fail.
CPJavaScriptPasteCantRefocus = 1 << 2;
var USER_AGENT = "",
PLATFORM_ENGINE = CPUnknownBrowserEngine,
PLATFORM_FEATURES = [],
@@ -102,7 +90,6 @@ var USER_AGENT = "",
// default these features to true
PLATFORM_FEATURES[CPInputTypeCanBeChangedFeature] = YES;
PLATFORM_FEATURES[CPInputSetFontOutsideOfDOM] = YES;
PLATFORM_FEATURES[CPAltEnterTextAreaFeature] = YES;
if (typeof window !== "undefined" && typeof window.navigator !== "undefined")
USER_AGENT = window.navigator.userAgent;
@@ -131,9 +118,6 @@ else if (typeof window !== "undefined" && window.attachEvent) // Must follow Ope
// Tested in Internet Explore 8 and 9.
PLATFORM_FEATURES[CPInputSetFontOutsideOfDOM] = NO;
// IE allows free clipboard access.
PLATFORM_FEATURES[CPJavaScriptClipboardAccessFeature] = YES;
}
// WebKit
@@ -145,8 +129,11 @@ else if (USER_AGENT.indexOf("AppleWebKit/") != -1)
PLATFORM_FEATURES[CPCSSRGBAFeature] = YES;
PLATFORM_FEATURES[CPHTMLContentEditableFeature] = YES;
if (USER_AGENT.indexOf("Chrome") === -1)
PLATFORM_FEATURES[CPHTMLDragAndDropFeature] = YES;
PLATFORM_FEATURES[CPJavaScriptClipboardEventsFeature] = YES;
PLATFORM_FEATURES[CPJavaScriptClipboardAccessFeature] = NO;
PLATFORM_FEATURES[CPJavaScriptClipboardAccessFeature] = YES;
PLATFORM_FEATURES[CPJavaScriptShadowFeature] = YES;
var versionStart = USER_AGENT.indexOf("AppleWebKit/") + "AppleWebKit/".length,
@@ -172,14 +159,7 @@ else if (USER_AGENT.indexOf("AppleWebKit/") != -1)
PLATFORM_FEATURES[CPInput1PxLeftPadding] = YES;
if (USER_AGENT.indexOf("Chrome") === CPNotFound)
{
PLATFORM_FEATURES[CPSOPDisabledFromFileURLs] = YES;
PLATFORM_FEATURES[CPHTMLDragAndDropFeature] = YES;
// https://bugs.webkit.org/show_bug.cgi?id=75891
PLATFORM_BUGS |= CPJavaScriptPasteRequiresEditableTarget;
// https://bugs.webkit.org/show_bug.cgi?id=39689
PLATFORM_BUGS |= CPJavaScriptPasteCantRefocus;
}
// Assume this bug was introduced around Safari 5.1/Chrome 16. This could probably be tighter.
if (majorVersion > 533)
@@ -210,18 +190,6 @@ else if (USER_AGENT.indexOf("Gecko") !== -1) // Must follow KHTML check.
// Some day this might be fixed and should be version prefixed. No known fixed version yet.
PLATFORM_FEATURES[CPInput1PxLeftPadding] = YES;
PLATFORM_FEATURES[CPAltEnterTextAreaFeature] = NO;
// This was supposed to be added in Firefox 22, but when testing with the latest beta as of 2013-06-14
// it does not seem to work. It seems to exhibit the CPJavaScriptPasteRequiresEditableTarget problem,
// and in addition doesn't seem to work with our native copy code either.
/*if (version >= 22.0)
{
PLATFORM_FEATURES[CPJavaScriptClipboardEventsFeature] = YES;
// TODO File a bug at https://bugzilla.mozilla.org/. In other browsers, one can return "false" from the
// beforepaste event to indicate a paste should be enabled even that the DOMEvent.target is not editable.
PLATFORM_BUGS |= CPJavaScriptPasteRequiresEditableTarget;
}*/
}
// Feature-specific checks
@@ -355,20 +323,6 @@ function CPBrowserStyleProperty(aProperty)
r = candidates[PLATFORM_STYLE_JS_PROPERTIES['transition']] || nil;
break;
case 'transformorigin':
var candidates = {
'WebkitTransform' : 'WebkitTransformOrigin',
'MozTransform' : 'MozTransformOrigin',
'OTransform' : 'OTransformOrigin',
'msTransform' : 'MSTransformOrigin',
'transform' : 'transformOrigin'
};
r = candidates[PLATFORM_STYLE_JS_PROPERTIES['transform']] || nil;
break;
default:
var prefixes = ["Webkit", "Moz", "O", "ms"],
strippedProperty = aProperty.split('-').join(' '),
@@ -438,12 +392,3 @@ function CPBrowserCSSProperty(aProperty)
return browserProperty.toLowerCase();
}
function CPBrowserBackingStorePixelRatio(context)
{
return context.webkitBackingStorePixelRatio ||
context.mozBackingStorePixelRatio ||
context.msBackingStorePixelRatio ||
context.oBackingStorePixelRatio ||
context.backingStorePixelRatio || 1;
}
+21 -228
View File
@@ -27,28 +27,19 @@
@import "CPShadow.j"
@import "CPView.j"
@import "CPKeyValueBinding.j"
@import "CPTrackingArea.j"
@global CPApp
@protocol CPControlTextEditingDelegate <CPObject>
CPLeftTextAlignment = 0;
CPRightTextAlignment = 1;
CPCenterTextAlignment = 2;
CPJustifiedTextAlignment = 3;
CPNaturalTextAlignment = 4;
@optional
- (void)controlTextDidBeginEditing:(CPNotification)aNotification;
- (void)controlTextDidChange:(CPNotification)aNotification;
- (void)controlTextDidEndEditing:(CPNotification)aNotification;
- (void)controlTextDidFocus:(CPNotification)aNotification;
- (void)controlTextDidBlur:(CPNotification)aNotification;
- (BOOL)control:(CPControl)control didFailToFormatString:(CPString)string errorDescription:(CPString)error;
@end
@typedef CPControlSize
CPRegularControlSize = 0;
CPSmallControlSize = 1;
CPMiniControlSize = 2;
@typedef CPLineBreakMode
CPLineBreakByWordWrapping = 0;
CPLineBreakByCharWrapping = 1;
CPLineBreakByClipping = 2;
@@ -56,13 +47,11 @@ CPLineBreakByTruncatingHead = 3;
CPLineBreakByTruncatingTail = 4;
CPLineBreakByTruncatingMiddle = 5;
@typedef CPVerticalTextAlignment
CPTopVerticalTextAlignment = 1;
CPCenterVerticalTextAlignment = 2;
CPBottomVerticalTextAlignment = 3;
// Deprecated for use with images, use the CPImageScale constants
@typedef CPImageScaling
CPScaleProportionally = 0;
CPScaleToFit = 1;
CPScaleNone = 2;
@@ -72,7 +61,6 @@ CPImageScaleAxesIndependently = 1;
CPImageScaleNone = 2;
CPImageScaleProportionallyUpOrDown = 3;
@typedef CPCellImagePosition
CPNoImage = 0;
CPImageOnly = 1;
CPImageLeft = 2;
@@ -118,10 +106,6 @@ var CPControlBlackColor = [CPColor blackColor];
BOOL _trackingWasWithinFrame;
unsigned _trackingMouseDownFlags;
CGPoint _previousTrackingLocation;
CPControlSize _controlSize;
CPWritingDirection _baseWritingDirection @accessors(property=baseWritingDirection);
}
+ (CPDictionary)themeAttributes
@@ -133,12 +117,11 @@ var CPControlBlackColor = [CPColor blackColor];
@"text-color": [CPColor blackColor],
@"font": [CPFont systemFontOfSize:CPFontCurrentSystemSize],
@"text-shadow-color": [CPNull null],
@"text-shadow-offset": CGSizeMakeZero(),
@"text-shadow-offset": _CGSizeMakeZero(),
@"image-position": CPImageLeft,
@"image-scaling": CPScaleToFit,
@"min-size": CGSizeMakeZero(),
@"max-size": CGSizeMake(-1.0, -1.0),
@"nib2cib-adjustment-frame": CGRectMakeZero()
@"min-size": _CGSizeMakeZero(),
@"max-size": _CGSizeMake(-1.0, -1.0),
};
}
@@ -194,94 +177,13 @@ var CPControlBlackColor = [CPColor blackColor];
if (self)
{
_sendActionOn = CPLeftMouseUpMask;
_sendActionOn = CPLeftMouseUpMask;
_trackingMouseDownFlags = 0;
}
return self;
}
#pragma mark -
#pragma mark Control Size
/*!
Returns the control's control size
*/
- (CPControlSize)controlSize
{
return _controlSize;
}
/*!
Sets the control's size.
@param aControlSize the control's size
*/
- (void)setControlSize:(CPControlSize)aControlSize
{
if (_controlSize === aControlSize)
return;
[self unsetThemeState:[self _controlSizeThemeState]];
_controlSize = aControlSize;
[self setThemeState:[self _controlSizeThemeState]];
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
/*!
Gets the current theme state according to the current controlSize.
@return a CPThemeState
*/
- (ThemeState)_controlSizeThemeState
{
switch (_controlSize)
{
case CPSmallControlSize:
return CPThemeStateControlSizeSmall;
case CPMiniControlSize:
return CPThemeStateControlSizeMini;
case CPRegularControlSize:
default:
return CPThemeStateControlSizeRegular;
}
}
/*!
@ignore
Change frame size according to the theme control size theme constraints
Basically for height to min-size.
*/
- (void)_sizeToControlSize
{
var frameSize = [self frameSize],
minSize = [self currentValueForThemeAttribute:@"min-size"],
maxSize = [self currentValueForThemeAttribute:@"max-size"];
if (minSize.width > 0)
{
frameSize.width = MAX(minSize.width, frameSize.width);
if (maxSize.width > 0)
frameSize.width = MIN(maxSize.width, frameSize.width);
}
if (minSize.height > 0)
{
frameSize.height = MAX(minSize.height, frameSize.height);
if (maxSize.height > 0)
frameSize.height = MIN(maxSize.height, frameSize.height);
}
[self setFrameSize:frameSize];
}
#pragma mark -
/*!
Sets the receiver's target action.
@@ -420,11 +322,11 @@ var CPControlBlackColor = [CPColor blackColor];
_previousTrackingLocation = currentLocation;
}
- (void)setState:(CPInteger)state
- (void)setState:(int)state
{
}
- (CPInteger)nextState
- (int)nextState
{
return 0;
}
@@ -628,7 +530,7 @@ var CPControlBlackColor = [CPColor blackColor];
return formattedValue;
}
return (_value === undefined || _value === nil) ? @"" : String(_value);
return (_value === undefined || _value === nil) ? "" : String(_value);
}
/*!
@@ -705,7 +607,7 @@ var CPControlBlackColor = [CPColor blackColor];
if ([note object] != self)
return;
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidBeginEditingNotification object:self userInfo:@{"CPFieldEditor": [note object]}];
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidBeginEditingNotification object:self userInfo:@{ "CPFieldEditor": [note object] }];
}
- (void)textDidChange:(CPNotification)note
@@ -714,7 +616,7 @@ var CPControlBlackColor = [CPColor blackColor];
if ([note object] != self)
return;
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidChangeNotification object:self userInfo:@{"CPFieldEditor": [note object]}];
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidChangeNotification object:self userInfo:@{ "CPFieldEditor": [note object] }];
}
- (void)textDidEndEditing:(CPNotification)note
@@ -725,49 +627,7 @@ var CPControlBlackColor = [CPColor blackColor];
[self _reverseSetBinding];
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidEndEditingNotification object:self userInfo:[note userInfo]];
}
/*!
@ignore
Return the currentTextMovement needed by the delegate textDidEndEditing
This is going to check the currentEvent of the CPApp
*/
- (unsigned)_currentTextMovement
{
var currentEvent = [CPApp currentEvent],
keyCode = [currentEvent keyCode],
modifierFlags = [currentEvent modifierFlags];
switch (keyCode)
{
case CPEscapeKeyCode:
return CPCancelTextMovement;
case CPLeftArrowKeyCode:
return CPLeftTextMovement;
case CPRightArrowKeyCode:
return CPRightTextMovement;
case CPUpArrowKeyCode:
return CPUpTextMovement;
case CPDownArrowKeyCode:
return CPDownTextMovement;
case CPReturnKeyCode:
return CPReturnTextMovement;
case CPTabKeyCode:
if (modifierFlags & CPShiftKeyMask)
return CPBacktabTextMovement;
return CPTabTextMovement;
default:
return CPOtherTextMovement;
}
[[CPNotificationCenter defaultCenter] postNotificationName:CPControlTextDidEndEditingNotification object:self userInfo:@{ "CPFieldEditor": [note object] }];
}
/*!
@@ -953,7 +813,7 @@ var CPControlBlackColor = [CPColor blackColor];
/*!
Returns the image scaling of the control.
*/
- (CPUInteger)imageScaling
- (CPImageScaling)imageScaling
{
return [self valueForThemeAttribute:@"image-scaling"];
}
@@ -1011,74 +871,16 @@ var CPControlBlackColor = [CPColor blackColor];
return [self hasThemeState:CPThemeStateHighlighted];
}
#pragma mark -
#pragma mark Base writing direction
/*!
Sets the initial writing direction of the receiver
@param writingDirection - It could be CPWritingDirectionNatural, CPWritingDirectionLeftToRight, CPWritingDirectionRightToLeft
*/
- (void)setBaseWritingDirection:(CPWritingDirection)writingDirection
{
if (writingDirection == _baseWritingDirection)
return;
[self willChangeValueForKey:@"baseWritingDirection"];
_baseWritingDirection = writingDirection;
[self didChangeValueForKey:@"baseWritingDirection"];
#if PLATFORM(DOM)
var style;
switch (_baseWritingDirection)
{
case CPWritingDirectionNatural:
style = "initial";
break;
case CPWritingDirectionLeftToRight:
style = "ltr";
break;
case CPWritingDirectionRightToLeft:
style = "rtl";
break;
default:
style = "initial";
}
_DOMElement.style.direction = style;
#endif
}
@end
@implementation CPControl (CPTrackingArea)
- (void)updateTrackingAreas
{
[self removeAllTrackingAreas];
[self addTrackingArea:[[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
options:CPTrackingMouseEnteredAndExited | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
owner:self
userInfo:nil]];
}
@end
var CPControlActionKey = @"CPControlActionKey",
CPControlControlSizeKey = @"CPControlControlSizeKey",
var CPControlValueKey = @"CPControlValueKey",
CPControlControlStateKey = @"CPControlControlStateKey",
CPControlFormatterKey = @"CPControlFormatterKey",
CPControlIsEnabledKey = @"CPControlIsEnabledKey",
CPControlSendActionOnKey = @"CPControlSendActionOnKey",
CPControlSendsActionOnEndEditingKey = @"CPControlSendsActionOnEndEditingKey",
CPControlTargetKey = @"CPControlTargetKey",
CPControlValueKey = @"CPControlValueKey",
CPControlBaseWrittingDirectionKey = @"CPControlBaseWrittingDirectionKey";
CPControlActionKey = @"CPControlActionKey",
CPControlSendActionOnKey = @"CPControlSendActionOnKey",
CPControlFormatterKey = @"CPControlFormatterKey",
CPControlSendsActionOnEndEditingKey = @"CPControlSendsActionOnEndEditingKey",
__Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
@@ -1105,10 +907,6 @@ var CPControlActionKey = @"CPControlActionKey",
[self setSendsActionOnEndEditing:[aCoder decodeBoolForKey:CPControlSendsActionOnEndEditingKey]];
[self setFormatter:[aCoder decodeObjectForKey:CPControlFormatterKey]];
[self setControlSize:[aCoder decodeIntForKey:CPControlControlSizeKey]];
[self setBaseWritingDirection:[aCoder decodeIntForKey:CPControlBaseWrittingDirectionKey]];
}
return self;
@@ -1141,11 +939,6 @@ var CPControlActionKey = @"CPControlActionKey",
if (_formatter !== nil)
[aCoder encodeObject:_formatter forKey:CPControlFormatterKey];
[aCoder encodeInt:_controlSize forKey:CPControlControlSizeKey];
[aCoder encodeInt:_baseWritingDirection forKey:CPControlBaseWrittingDirectionKey];
}
@end
+1 -6
View File
@@ -22,7 +22,6 @@ Cursor support by browser:
*/
@import <Foundation/CPObject.j>
@import "CPImage.j"
@global CPApp
@@ -117,15 +116,11 @@ var currentCursor = nil,
- (void)push
{
cursorStack.push(self);
currentCursor = self;
currentCursor = cursorStack.push(self);
}
- (void)set
{
if (currentCursor === self)
return;
currentCursor = self;
#if PLATFORM(DOM)
-738
View File
@@ -1,738 +0,0 @@
/* CPDatePicker.j
* AppKit
*
* Created by Alexandre Wilhelm
* Copyright 2012 <alexandre.wilhelmfr@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import "CPControl.j"
@import "CPFont.j"
@import "CPTextField.j"
@import "_CPDatePickerTextField.j"
@import "_CPDatePickerCalendar.j"
@import <Foundation/CPArray.j>
@import <Foundation/CPObject.j>
@import <Foundation/CPDate.j>
@import <Foundation/CPLocale.j>
@import <Foundation/CPTimeZone.j>
@class CPStepper
@class CPApp
@global CPLocaleLanguageCode
@global CPDateFormatterShortStyle
var CPDatePicker_validateProposedDateValue_timeInterval = 1 << 1;
CPSingleDateMode = 0;
CPRangeDateMode = 1;
CPTextFieldAndStepperDatePickerStyle = 0;
CPClockAndCalendarDatePickerStyle = 1;
CPTextFieldDatePickerStyle = 2;
CPHourMinuteDatePickerElementFlag = 0x000c;
CPHourMinuteSecondDatePickerElementFlag = 0x000e;
CPTimeZoneDatePickerElementFlag = 0x0010;
CPYearMonthDatePickerElementFlag = 0x00c0;
CPYearMonthDayDatePickerElementFlag = 0x00e0;
CPEraDatePickerElementFlag = 0x0100;
/*!
@ingroup appkit
This control displays a datepicker in a Cappuccino application
*/
@implementation CPDatePicker : CPControl
{
BOOL _isBordered @accessors(getter=isBordered, setter=setBordered:);
BOOL _isBezeled @accessors(getter=isBezeled, setter=setBezeled:);
BOOL _drawsBackground @accessors(property=drawsBackground);
CPDate _dateValue @accessors(property=dateValue);
CPDate _minDate @accessors(property=minDate);
CPDate _maxDate @accessors(property=maxDate);
CPFont _textFont @accessors(property=textFont);
CPLocale _locale @accessors(property=locale);
//CPCalendar _calendar @accessors(property=calendar);
CPTimeZone _timeZone @accessors(property=timeZone);
id _delegate @accessors(property=delegate);
CPInteger _datePickerElements @accessors(property=datePickerElements);
CPInteger _datePickerMode @accessors(property=datePickerMode);
CPInteger _datePickerStyle @accessors(property=datePickerStyle);
CPInteger _timeInterval @accessors(property=timeInterval);
BOOL _invokedByUserEvent;
_CPDatePickerTextField _datePickerTextfield;
_CPDatePickerCalendar _datePickerCalendar;
unsigned _implementedCDatePickerDelegateMethods;
}
#pragma mark -
#pragma mark Theme methods
+ (CPString)defaultThemeClass
{
return @"datePicker";
}
+ (CPDictionary)themeAttributes
{
return @{
@"bezel-color": [CPColor clearColor],
@"border-width" : 1.0,
@"border-color": [CPColor clearColor],
@"content-inset": CGInsetMakeZero(),
@"bezel-inset": CGInsetMakeZero(),
@"datepicker-textfield-bezel-color": [CPColor clearColor],
@"min-size-datepicker-textfield": CGSizeMakeZero(),
@"content-inset-datepicker-textfield": CGInsetMakeZero(),
@"content-inset-datepicker-textfield-separator": CGInsetMakeZero(),
@"separator-content-inset": CGInsetMakeZero(),
@"date-hour-margin": 5.0,
@"stepper-margin": 5.0,
@"bezel-color-calendar": [CPColor clearColor],
@"title-text-color": [CPColor blackColor],
@"title-text-shadow-color": [CPColor clearColor],
@"title-text-shadow-offset": CGSizeMakeZero(),
@"title-font": [CPNull null],
@"weekday-text-color": [CPColor blackColor],
@"weekday-text-shadow-color": [CPColor clearColor],
@"weekday-text-shadow-offset": CGSizeMakeZero(),
@"weekday-font": [CPNull null],
@"arrow-image-left": [CPNull null],
@"arrow-image-right": [CPNull null],
@"arrow-image-left-highlighted": [CPNull null],
@"arrow-image-right-highlighted": [CPNull null],
@"arrow-inset": CGInsetMakeZero(),
@"circle-image": [CPNull null],
@"circle-image-highlighted": [CPNull null],
@"tile-text-color": [CPColor blackColor],
@"tile-text-shadow-color": [CPColor clearColor],
@"tile-text-shadow-offset": CGSizeMakeZero(),
@"tile-font": [CPNull null],
@"size-tile": CGSizeMakeZero(),
@"size-calendar": CGSizeMakeZero(),
@"size-header": CGSizeMakeZero(),
@"min-size-calendar": CGSizeMakeZero(),
@"max-size-calendar": CGSizeMakeZero(),
@"bezel-color-clock": [CPColor clearColor],
@"clock-text-color": [CPColor blackColor],
@"clock-text-shadow-color": [CPColor clearColor],
@"clock-text-shadow-offset": CGSizeMakeZero(),
@"clock-font": [CPNull null],
@"second-hand-image": [CPNull null],
@"hour-hand-image": [CPNull null],
@"middle-hand-image": [CPNull null],
@"minute-hand-image": [CPNull null],
@"size-clock": CGSizeMakeZero(),
@"second-hand-size": CGSizeMakeZero(),
@"hour-hand-size": CGSizeMakeZero(),
@"middle-hand-size": CGSizeMakeZero(),
@"minute-hand-size": CGSizeMakeZero(),
};
}
#pragma mark -
#pragma mark Binding methods
+ (Class)_binderClassForBinding:(CPString)theBinding
{
if (theBinding == CPValueBinding || theBinding == CPMinValueBinding || theBinding == CPMaxValueBinding)
return [_CPDatePickerValueBinder class];
return [super _binderClassForBinding:theBinding];
}
- (CPString)_replacementKeyPathForBinding:(CPString)aBinding
{
if (aBinding == CPValueBinding)
return @"dateValue";
if (aBinding == CPMinValueBinding)
return @"minDate";
if (aBinding == CPMaxValueBinding)
return @"maxDate";
return [super _replacementKeyPathForBinding:aBinding];
}
#pragma mark -
#pragma mark Init methods
- (id)initWithFrame:(CGRect)aFrame
{
if (self = [super initWithFrame:aFrame])
{
_drawsBackground = YES;
_datePickerStyle = CPTextFieldAndStepperDatePickerStyle;
_datePickerMode = CPSingleDateMode;
_datePickerElements = CPYearMonthDayDatePickerElementFlag | CPHourMinuteSecondDatePickerElementFlag;
_timeInterval = 0;
_implementedCDatePickerDelegateMethods = 0;
[self setObjectValue:[CPDate date]];
_minDate = [CPDate distantPast];
_maxDate = [CPDate distantFuture];
[self setBezeled:YES];
[self setBordered:YES];
[self _init];
}
return self
}
- (void)_init
{
if (!_locale)
_locale = [CPLocale currentLocale];
_datePickerTextfield = [[_CPDatePickerTextField alloc] initWithFrame:[self bounds] withDatePicker:self];
[_datePickerTextfield setDateValue:_dateValue];
_datePickerCalendar = [[_CPDatePickerCalendar alloc] initWithFrame:[self bounds] withDatePicker:self];
[_datePickerCalendar setDateValue:_dateValue];
// We might have been unarchived in a disabled state.
[_datePickerTextfield setEnabled:[self isEnabled]];
[self setNeedsDisplay:YES];
[self setNeedsLayout];
}
#pragma mark -
#pragma mark Control Size
- (void)setControlSize:(CPControlSize)aControlSize
{
[super setControlSize:aControlSize];
if ([self datePickerStyle] == CPTextFieldAndStepperDatePickerStyle || [self datePickerStyle] == CPTextFieldDatePickerStyle)
[self _sizeToControlSize];
}
#pragma mark -
#pragma mark Delegate methods
/*! Set the delegate of the datePicker
@param aDelegate delegate of the datePicker
*/
- (void)setDelegate:(id)aDelegate
{
_delegate = aDelegate;
_implementedCDatePickerDelegateMethods = 0;
// Look if the delegate implements or not the delegate methods
if ([_delegate respondsToSelector:@selector(datePicker:validateProposedDateValue:timeInterval:)])
_implementedCDatePickerDelegateMethods |= CPDatePicker_validateProposedDateValue_timeInterval;
}
#pragma mark -
#pragma mark Layout method
/*! Layout the subviews
*/
- (void)layoutSubviews
{
[super layoutSubviews];
if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
{
if (![_datePickerTextfield superview])
[self addSubview:_datePickerTextfield];
if ([_datePickerCalendar superview])
[_datePickerCalendar removeFromSuperview];
[_datePickerTextfield setControlSize:[self controlSize]];
[_datePickerTextfield setNeedsLayout];
[_datePickerTextfield setNeedsDisplay:YES];
}
else
{
if (![_datePickerCalendar superview])
[self addSubview:_datePickerCalendar];
if ([_datePickerTextfield superview])
[_datePickerTextfield removeFromSuperview];
[_datePickerCalendar setNeedsLayout];
[_datePickerCalendar setNeedsDisplay:YES];
}
}
#pragma mark -
#pragma mark Setter
/*! Return the objectValue of the datePicker. The objectValue should take the timeZoneEffect
*/
- (id)objectValue
{
// TODO : add timeZone effect. How to do it because js ???
return _dateValue
}
/*! Set the objectValue of the datePicker. It has to be a CPDate
@param aDateValue the dateValue
*/
- (void)setObjectValue:(CPDate)aValue
{
if (![aValue isKindOfClass:[CPDate class]])
return;
[self setDateValue:aValue];
}
/* Set the dateValue of the datePicker
@param aDateValue the dateValue
*/
- (void)setDateValue:(CPDate)aDateValue
{
if (aDateValue == nil)
return;
_invokedByUserEvent = NO;
[self _setDateValue:aDateValue timeInterval:_timeInterval];
}
/*! Set the dateValue and the timeInterval. This method checks the min and max date of the datePicker also. It will call the delegate if possible.
@param aDateValue the dateValue
@param aTimeInterval the timeInterval
*/
- (void)_setDateValue:(CPDate)aDateValue timeInterval:(CPTimeInterval)aTimeInterval
{
// Make sure to have a valid date and avoid NaN values
if (!isFinite(aDateValue))
{
[CPException raise:CPInvalidArgumentException
reason:@"aDateValue is not valid"];
return;
}
if (_minDate)
aDateValue = new Date (MAX(aDateValue, _minDate));
if (_maxDate)
aDateValue = new Date (MIN(aDateValue, _maxDate));
aTimeInterval = MAX(MIN(aTimeInterval, [_maxDate timeIntervalSinceDate:aDateValue]), [_minDate timeIntervalSinceDate:aDateValue]);
if ([aDateValue isEqualToDate:_dateValue] && aTimeInterval == _timeInterval)
{
if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
[_datePickerTextfield setDateValue:_dateValue];
else
[_datePickerCalendar setDateValue:_dateValue];
return;
}
if (_implementedCDatePickerDelegateMethods & CPDatePicker_validateProposedDateValue_timeInterval)
{
// constrain timeInterval also
var aStartDateRef = function(x){if (typeof x == 'undefined') return aDateValue; aDateValue = x;}
var aTimeIntervalRef = function(x){if (typeof x == 'undefined') return aTimeInterval; aTimeInterval = x;}
[_delegate datePicker:self validateProposedDateValue:aStartDateRef timeInterval:aTimeIntervalRef];
}
[self willChangeValueForKey:@"objectValue"];
[self willChangeValueForKey:@"dateValue"];
_dateValue = aDateValue;
[super setObjectValue:_dateValue];
[self didChangeValueForKey:@"objectValue"];
[self didChangeValueForKey:@"dateValue"];
[self willChangeValueForKey:@"timeInterval"];
_timeInterval = (_datePickerMode == CPSingleDateMode)? 0 : aTimeInterval;
[self didChangeValueForKey:@"timeInterval"];
if (_invokedByUserEvent)
[self sendAction:[self action] to:[self target]];
if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
[_datePickerTextfield setDateValue:_dateValue];
else
[_datePickerCalendar setDateValue:_dateValue];
}
/*! Set the minDate of the datePicker
@param aMinDate the minDate
*/
- (void)setMinDate:(CPDate)aMinDate
{
[self willChangeValueForKey:@"minDate"];
_minDate = aMinDate;
[self didChangeValueForKey:@"minDate"];
[self _setDateValue:_dateValue timeInterval:_timeInterval];
}
/*! Set the maxDate of the datePicker
@param aMaxDate the maxDate
*/
- (void)setMaxDate:(CPDate)aMaxDate
{
[self willChangeValueForKey:@"maxDate"];
_maxDate = aMaxDate;
[self didChangeValueForKey:@"maxDate"];
[self _setDateValue:_dateValue timeInterval:_timeInterval];
}
/*! Set the syle of the datePicker
@param aDatePickerStyle the datePicker style
*/
- (void)setDatePickerStyle:(CPInteger)aDatePickerStyle
{
_datePickerStyle = aDatePickerStyle;
[self setControlSize:[self controlSize]];
[self setNeedsDisplay:YES];
[self setNeedsLayout];
}
/*! Set the elements of the datePicker
@param aDatePickerElements the datePicker elements
*/
- (void)setDatePickerElements:(CPInteger)aDatePickerElements
{
_datePickerElements = aDatePickerElements;
[self setNeedsDisplay:YES];
[self setNeedsLayout];
}
/*! Set the mode of the datePicker
@param aDatePickerMode the datePicker mode
*/
- (void)setDatePickerMode:(CPInteger)aDatePickerMode
{
_datePickerMode = aDatePickerMode;
if (_datePickerMode == CPSingleDateMode)
[self _setDateValue:[self dateValue] timeInterval:0];
[self setNeedsDisplay:YES];
[self setNeedsLayout];
}
/*! Set the timeInterval of the datePicker
@param aTimeInterval the timeInterval of the datePicker
*/
- (void)setTimeInterval:(CPInteger)aTimeInterval
{
if (_datePickerMode == CPSingleDateMode)
return;
[self _setDateValue:[self dateValue] timeInterval:aTimeInterval];
}
/*! Set the locale of the datePicker. This update laso the locale of the formatter.
@param aLocale the locale
*/
- (void)setLocale:(CPLocale)aLocale
{
_locale = aLocale;
if (_formatter)
{
[self willChangeValueForKey:@"locale"];
[_formatter setLocale:_locale];
[self didChangeValueForKey:@"locale"];
}
// This will update the textFields (usefull when changing with a date with pm and am)
[_datePickerTextfield setDateValue:_dateValue];
[self setNeedsDisplay:YES];
[self setNeedsLayout];
}
/*!
Sets whether the datepicker will have a bezeled border.
@param shouldBeBezeled \c YES means the datepicker will draw a bezeled border
*/
- (void)setBezeled:(BOOL)shouldBeBezeled
{
_isBezeled = shouldBeBezeled;
if (shouldBeBezeled)
[self setThemeState:CPThemeStateBezeled];
else
[self unsetThemeState:CPThemeStateBezeled];
}
/*!
Sets whether the datepicker will have a border drawn. (actually it does nothing)
@param shouldBeBordered \c YES makes the datepicker draw a border
*/
- (void)setBordered:(BOOL)shouldBeBordered
{
_isBordered = shouldBeBordered;
if (shouldBeBordered)
[self setThemeState:CPThemeStateBordered];
else
[self unsetThemeState:CPThemeStateBordered];
}
/*!
Sets the font of the control.
@param aFont
*/
- (void)setTextFont:(CPFont)aFont
{
[self setFont:aFont];
}
/*! 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 a boolean. YES if the control should be enabled, otherwise NO.
*/
- (void)setEnabled:(BOOL)aBoolean
{
[super setEnabled:aBoolean];
[_datePickerTextfield setEnabled:aBoolean];
[_datePickerCalendar setEnabled:aBoolean];
}
/*! Set the background color of the datePicker
@param aColor
*/
- (void)setBackgroundColor:(CPColor)aColor
{
_backgroundColor = aColor;
[self setNeedsLayout];
}
/*! Set the boolean drawsBackgroundColor
@param aBoolean
*/
- (void)setDrawsBackground:(BOOL)aBoolean
{
[self willChangeValueForKey:@"drawsBackground"];
_drawsBackground = aBoolean;
[self didChangeValueForKey:@"drawsBackground"];
[self setNeedsLayout];
}
/*! Set the timeZone
@param aTimeZone
*/
- (void)setTimeZone:(CPTimeZone)aTimeZone
{
[self willChangeValueForKey:@"timeZone"];
_timeZone = aTimeZone;
[self didChangeValueForKey:@"timeZone"];
[self setNeedsLayout];
if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
[_datePickerTextfield setDateValue:_dateValue];
else
[_datePickerCalendar setDateValue:_dateValue];
}
#pragma mark -
#pragma mark First responder methods
/*! Return YES if style is set to CPTextFieldAndStepperDatePickerStyle or CPTextFieldDatePickerStyle
*/
- (BOOL)becomeFirstResponder
{
if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
{
if (![super becomeFirstResponder])
return NO;
[_datePickerTextfield _selectTextFieldWithFlags:[[CPApp currentEvent] modifierFlags]];
return YES;
}
return NO;
}
/*! Return YES
*/
- (BOOL)acceptsFirstResponder
{
return YES;
}
/*! Return YES
*/
- (BOOL)resignFirstResponder
{
if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
[_datePickerTextfield resignFirstResponder];
return YES;
}
#pragma mark -
#pragma mark getter
/*!
Returns \c YES if the textfield is bezeled.
*/
- (BOOL)isBezeled
{
return [self hasThemeState:CPThemeStateBezeled];
}
/*!
Returns \c YES if the textfield has a border.
*/
- (BOOL)isBordered
{
return [self hasThemeState:CPThemeStateBordered];
}
/*!
Returns the font of the control.
*/
- (CPFont)textFont
{
return [self font];
}
/*! Check if we are in the american format or not. Depending on the locale
*/
- (BOOL)_isAmericanFormat
{
return [[_locale objectForKey:CPLocaleCountryCode] isEqualToString:@"US"];
}
#pragma mark -
#pragma mark Key event
/*! Key down event
@param anEvent
*/
- (void)keyDown:(CPEvent)anEvent
{
if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
[_datePickerTextfield keyDown:anEvent];
}
@end
var CPDatePickerModeKey = @"CPDatePickerModeKey",
CPIntervalKey = @"CPIntervalKey",
CPMinDateKey = @"CPMinDateKey",
CPMaxDateKey = @"CPMaxDateKey",
CPBackgroundColorKey = @"CPBackgroundColorKey",
CPDrawsBackgroundKey = @"CPDrawsBackgroundKey",
CPTextFontKey = @"CPTextFontKey",
CPDatePickerElementsKey = @"CPDatePickerElementsKey",
CPDatePickerStyleKey = @"CPDatePickerStyleKey",
CPLocaleKey = @"CPLocaleKey",
CPBorderedKey = @"CPBorderedKey",
CPDateValueKey = @"CPDateValueKey";
@implementation CPDatePicker (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
if (self)
{
_textFont = [aCoder decodeObjectForKey:CPTextFontKey];
_minDate = [aCoder decodeObjectForKey:CPMinDateKey] || [CPDate distantPast];
_maxDate = [aCoder decodeObjectForKey:CPMaxDateKey] || [CPDate distantFuture];
_timeInterval = [aCoder decodeDoubleForKey:CPIntervalKey];
_datePickerMode = [aCoder decodeIntForKey:CPDatePickerModeKey];
_datePickerElements = [aCoder decodeIntForKey:CPDatePickerElementsKey];
[self setDatePickerStyle:[aCoder decodeIntForKey:CPDatePickerStyleKey]];
_locale = [aCoder decodeObjectForKey:CPLocaleKey];
_dateValue = [aCoder decodeObjectForKey:CPDateValueKey];
_backgroundColor = [aCoder decodeObjectForKey:CPBackgroundColorKey];
_drawsBackground = [aCoder decodeBoolForKey:CPDrawsBackgroundKey];
_isBordered = [aCoder decodeBoolForKey:CPBorderedKey];
[self _init];
}
return self
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
// FIXME Do we need to encode _datePickerTextfield and _datePickerCalendar? As subviews they'll be encoded, but when we decode we recreate them anyhow.
[super encodeWithCoder:aCoder];
[aCoder encodeDouble:_timeInterval forKey:CPIntervalKey];
[aCoder encodeInt:_datePickerMode forKey:CPDatePickerModeKey];
[aCoder encodeInt:_datePickerStyle forKey:CPDatePickerStyleKey];
[aCoder encodeInt:_datePickerElements forKey:CPDatePickerElementsKey];
[aCoder encodeObject:_minDate forKey:CPMinDateKey];
[aCoder encodeObject:_maxDate forKey:CPMaxDateKey]
[aCoder encodeObject:_dateValue forKey:CPDateValueKey];;
[aCoder encodeObject:_textFont forKey:CPTextFontKey];
[aCoder encodeObject:_locale forKey:CPLocaleKey];
[aCoder encodeObject:_backgroundColor forKey:CPBackgroundColorKey];
[aCoder encodeObject:_drawsBackground forKey:CPDrawsBackgroundKey];
[aCoder encodeObject:_isBordered forKey:CPBorderedKey];
}
@end
@implementation _CPDatePickerValueBinder : CPBinder
{
}
@end
@implementation CPDate (CPDatePickerAdditions)
- (int)_daysInMonth
{
return 32 - new Date(self.getFullYear(), self.getMonth(), 32).getDate();
}
- (void)_resetToMidnight
{
self.setHours(0);
self.setMinutes(0);
self.setSeconds(0);
self.setMilliseconds(0);
}
- (void)_resetToLastSeconds
{
self.setHours(23);
self.setMinutes(59);
self.setSeconds(59);
self.setMilliseconds(99);
}
@end
File diff suppressed because it is too large Load Diff
-313
View File
@@ -1,313 +0,0 @@
/*
* _CPDatePickerClock.j
* AppKit
*
* Created by Alexandre Wilhelm
* Copyright 2012 <alexandre.wilhelmfr@gmail.com>
*
* 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 "CPView.j"
@import "CPTextField.j"
@import "CPImageView.j"
@import "CALayer.j"
@class _CPCibCustomResource
@class CPDatePicker
@global CPHourMinuteSecondDatePickerElementFlag
@global CPTextFieldAndStepperDatePickerStyle
@global CPTextFieldDatePickerStyle
var RADIANS = Math.PI / 180;
@implementation _CPDatePickerClock : CPView
{
BOOL _isEnabled;
CALayer _rootLayer;
CALayer _hourHandLayer;
CALayer _minuteHandLayer;
CALayer _secondHandLayer;
CALayer _middleHandLayer;
CPDatePicker _datePicker;
CPTextField _PMAMTextField;
}
#pragma mark -
#pragma mark Init methods
- (id)initWithFrame:(CGRect)aFrame datePicker:(CPDatePicker)aDatePicker
{
if (self = [super initWithFrame:aFrame])
{
_datePicker = aDatePicker;
_PMAMTextField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
[_PMAMTextField setValue:[_datePicker valueForThemeAttribute:@"clock-font" inState:CPThemeStateNormal] forThemeAttribute:@"font" inState:CPThemeStateNormal];
[_PMAMTextField setValue:[_datePicker valueForThemeAttribute:@"clock-text-color" inState:CPThemeStateNormal] forThemeAttribute:@"text-color" inState:CPThemeStateNormal];
[_PMAMTextField setValue:[_datePicker valueForThemeAttribute:@"clock-text-shadow-color" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateNormal];
[_PMAMTextField setValue:[_datePicker valueForThemeAttribute:@"clock-text-shadow-offset" inState:CPThemeStateNormal] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateNormal];
[_PMAMTextField setValue:[_datePicker valueForThemeAttribute:@"clock-font" inState:CPThemeStateDisabled] forThemeAttribute:@"font" inState:CPThemeStateDisabled];
[_PMAMTextField setValue:[_datePicker valueForThemeAttribute:@"clock-text-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-color" inState:CPThemeStateDisabled];
[_PMAMTextField setValue:[_datePicker valueForThemeAttribute:@"clock-text-shadow-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled];
[_PMAMTextField setValue:[_datePicker valueForThemeAttribute:@"clock-text-shadow-offset" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled];
[self addSubview:_PMAMTextField];
var middleHandSize = [_datePicker valueForThemeAttribute:@"middle-hand-size"],
minuteHandSize = [_datePicker valueForThemeAttribute:@"minute-hand-size"],
hourHandSize = [_datePicker valueForThemeAttribute:@"hour-hand-size"],
secondHandSize = [_datePicker valueForThemeAttribute:@"second-hand-size"];
// We use layer to make the rotation possible
_hourHandLayer = [[HandLayer alloc] initWithSize:hourHandSize];
[_hourHandLayer setBounds:CGRectMake(0, 0, aFrame.size.width, aFrame.size.height)];
[_hourHandLayer setAnchorPoint:CGPointMakeZero()];
[_hourHandLayer setPosition:CGPointMake(0.0, 0.0)];
_minuteHandLayer = [[HandLayer alloc] initWithSize:minuteHandSize];
[_minuteHandLayer setBounds:CGRectMake(0, 0, aFrame.size.width, aFrame.size.height)];
[_minuteHandLayer setAnchorPoint:CGPointMakeZero()];
[_minuteHandLayer setPosition:CGPointMake(0.0, 0.0)];
_secondHandLayer = [[HandLayer alloc] initWithSize:secondHandSize];
[_secondHandLayer setBounds:CGRectMake(0, 0, aFrame.size.width, aFrame.size.height)];
[_secondHandLayer setAnchorPoint:CGPointMakeZero()];
[_secondHandLayer setPosition:CGPointMake(0.0, 0.0)];
_middleHandLayer = [[HandLayer alloc] initWithSize:middleHandSize];
[_middleHandLayer setBounds:CGRectMake(0, 0, aFrame.size.width, aFrame.size.height)];
[_middleHandLayer setAnchorPoint:CGPointMakeZero()];
[_middleHandLayer setPosition:CGPointMake(0.0, 0.0)];
_rootLayer = [CALayer layer];
[self setWantsLayer:YES];
[self setLayer:_rootLayer];
[_hourHandLayer setNeedsDisplay];
[_middleHandLayer setNeedsDisplay];
[_secondHandLayer setNeedsDisplay];
[_minuteHandLayer setNeedsDisplay];
[_rootLayer addSublayer:_hourHandLayer];
[_rootLayer addSublayer:_minuteHandLayer];
[_rootLayer addSublayer:_secondHandLayer];
[_rootLayer addSublayer:_middleHandLayer];
[_rootLayer setNeedsDisplay];
}
return self;
}
#pragma mark -
#pragma mark Layout methods
- (void)layoutSubviews
{
if ([_datePicker datePickerStyle] == CPTextFieldAndStepperDatePickerStyle || [_datePicker datePickerStyle] == CPTextFieldDatePickerStyle)
return;
[super layoutSubviews];
var bounds = [self bounds],
dateValue = [[_datePicker dateValue] copy];
[dateValue _dateWithTimeZone:[_datePicker timeZone]];
[self setBackgroundColor:[_datePicker currentValueForThemeAttribute:@"bezel-color-clock"]];
[_middleHandLayer setImage:[_datePicker currentValueForThemeAttribute:@"middle-hand-image"]];
[_hourHandLayer setImage:[_datePicker currentValueForThemeAttribute:@"hour-hand-image"]];
[_minuteHandLayer setImage:[_datePicker currentValueForThemeAttribute:@"minute-hand-image"]];
[_secondHandLayer setImage:[_datePicker currentValueForThemeAttribute:@"second-hand-image"]];
if ([_datePicker _isAmericanFormat])
{
if (dateValue.getHours() > 11)
[_PMAMTextField setStringValue:@"PM"]
else
[_PMAMTextField setStringValue:@"AM"];
[_PMAMTextField sizeToFit];
[_PMAMTextField setFrameOrigin:CGPointMake(bounds.size.width / 2 - [_PMAMTextField frameSize].width / 2, bounds.size.height / 2 + 15)];
[_PMAMTextField setHidden:NO];
}
else
{
[_PMAMTextField setHidden:YES];
}
[_hourHandLayer setRotationRadians:[self _hourPositionRadianForDate:dateValue]];
[_minuteHandLayer setRotationRadians:[self _minutePositionRadianForDate:dateValue]];
[_secondHandLayer setRotationRadians:[self _secondPositionRadianForDate:dateValue]];
[_PMAMTextField setEnabled:_isEnabled];
[_hourHandLayer setEnabled:_isEnabled];
[_middleHandLayer setEnabled:_isEnabled];
[_secondHandLayer setEnabled:_isEnabled];
[_minuteHandLayer setEnabled:_isEnabled];
// Check if we have to display the hand second
if (([_datePicker datePickerElements] & CPHourMinuteSecondDatePickerElementFlag) == CPHourMinuteSecondDatePickerElementFlag)
[_secondHandLayer setHidden:NO];
else
[_secondHandLayer setHidden:YES];
[_rootLayer setNeedsDisplay];
}
#pragma mark -
#pragma mark Accessors
- (float)_hourPositionRadianForDate:(CPDate)aDate
{
var hours = aDate.getHours() + aDate.getMinutes() / 60;
return (360 * hours / 12) * RADIANS;
}
- (float)_secondPositionRadianForDate:(CPDate)aDate
{
return (360 * aDate.getSeconds() / 60) * RADIANS;
}
- (float)_minutePositionRadianForDate:(CPDate)aDate
{
var minutes = aDate.getMinutes() + aDate.getSeconds() / 60;
return (360 * minutes / 60) * RADIANS;
}
- (void)setEnabled:(BOOL)shouldEnable
{
shouldEnable = !!shouldEnable;
if (shouldEnable === _isEnabled)
return;
_isEnabled = shouldEnable;
[self setNeedsLayout];
// FIXME: This is a workaround for an apparent bug in CALayer.
// Without pumping the event loop, the sublayers of _rootLayer
// (the hands) are not redrawn until an event occurs.
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
}
@end
@implementation HandLayer : CALayer
{
BOOL _isEnabled @accessors(setter=setEnabled:, getter=isEnabled);
CPImage _image;
CALayer _imageLayer;
float _rotationRadians;
}
#pragma mark -
#pragma mark Init methods
- (id)initWithSize:(CGSize)aSize
{
if (self = [super init])
{
_isEnabled = YES;
_imageLayer = [CALayer layer];
_rotationRadians = 0;
[_imageLayer setDelegate:self];
[_imageLayer setBounds:CGRectMake(0.0, 0.0, aSize.width, aSize.height)];
[self addSublayer:_imageLayer];
}
return self;
}
#pragma mark -
#pragma mark Setter Getter methods
/*!
Set the bounds of the layer. The imageLayer will be at the center of this bounds.
*/
- (void)setBounds:(CGRect)aRect
{
[super setBounds:aRect];
[_imageLayer setPosition:CGPointMake(CGRectGetMidX(aRect), CGRectGetMidY(aRect))];
}
- (void)setImage:(CPImage)anImage
{
if (_image === anImage)
return;
if ([anImage isKindOfClass:[_CPCibCustomResource class]])
_image = [anImage imageFromCoder:nil];
else
_image = anImage;
[_imageLayer setNeedsDisplay];
}
- (void)setRotationRadians:(float)radians
{
if (_rotationRadians === radians)
return;
_rotationRadians = radians;
[_imageLayer setAffineTransform:CGAffineTransformScale(
CGAffineTransformMakeRotation(_rotationRadians),
1.0, 1.0)];
}
- (void)setEnabled:(BOOL)shouldEnable
{
shouldEnable = !!shouldEnable;
if (_isEnabled === shouldEnable)
return;
_isEnabled = shouldEnable;
[self setNeedsDisplay];
[_imageLayer setNeedsDisplay];
}
- (void)imageDidLoad:(CPImage)anImage
{
[_imageLayer setNeedsDisplay];
}
- (void)drawLayer:(CALayer)aLayer inContext:(CGContext)aContext
{
if ([_image loadStatus] != CPImageLoadStatusCompleted)
[_image setDelegate:self];
else
CGContextDrawImage(aContext, [aLayer bounds], _image);
}
@end
File diff suppressed because it is too large Load Diff
+38 -33
View File
@@ -244,6 +244,11 @@ var CPDocumentUntitledCount = 0;
{
}
- (CPWindowController)firstEligibleExistingWindowController
{
return nil;
}
// Creating and managing window controllers
/*!
Creates the window controller for this document.
@@ -256,7 +261,6 @@ var CPDocumentUntitledCount = 0;
- (void)makeViewAndWindowControllers
{
var viewCibName = [self viewCibName],
windowCibName = [self windowCibName],
viewController = nil,
windowController = nil;
@@ -264,21 +268,31 @@ var CPDocumentUntitledCount = 0;
if ([viewCibName length])
viewController = [[CPViewController alloc] initWithCibName:viewCibName bundle:nil owner:self];
// From a cib if we have one.
if ([windowCibName length])
windowController = [[CPWindowController alloc] initWithWindowCibName:windowCibName owner:self];
// If we have a view controller, check if we have a free window for it.
if (viewController)
windowController = [self firstEligibleExistingWindowController];
// If not you get a standard window capable of displaying multiple documents and view
else if (viewController)
// If not, create one.
if (!windowController)
{
var view = [viewController view],
viewFrame = [view frame];
var windowCibName = [self windowCibName];
viewFrame.origin = CGPointMake(50, 50);
// From a cib if we have one.
if ([windowCibName length])
windowController = [[CPWindowController alloc] initWithWindowCibName:windowCibName owner:self];
var theWindow = [[CPWindow alloc] initWithContentRect:viewFrame styleMask:CPTitledWindowMask | CPClosableWindowMask | CPMiniaturizableWindowMask | CPResizableWindowMask];
// If not you get a standard window capable of displaying multiple documents and view
else if (viewController)
{
var view = [viewController view],
viewFrame = [view frame];
windowController = [[CPWindowController alloc] initWithWindow:theWindow];
viewFrame.origin = CGPointMake(50, 50);
var theWindow = [[CPWindow alloc] initWithContentRect:viewFrame styleMask:CPTitledWindowMask | CPClosableWindowMask | CPMiniaturizableWindowMask | CPResizableWindowMask];
windowController = [[CPWindowController alloc] initWithWindow:theWindow];
}
}
if (windowController && viewController)
@@ -515,9 +529,7 @@ var CPDocumentUntitledCount = 0;
alert("There was an error retrieving the document.");
var theDelegate = session.delegate;
theDelegate.isa.objj_msgSend3(theDelegate, session.didReadSelector, self, NO, session.contextInfo);
objj_msgSend(session.delegate, session.didReadSelector, self, NO, session.contextInfo);
}
else
{
@@ -542,9 +554,7 @@ var CPDocumentUntitledCount = 0;
_writeRequest = nil;
var theDelegate = session.delegate;
theDelegate.isa.objj_msgSend3(theDelegate, session.didSaveSelector, self, NO, session.contextInfo);
objj_msgSend(session.delegate, session.didSaveSelector, self, NO, session.contextInfo);
[self _sendDocumentSavedNotification:NO];
}
}
@@ -557,15 +567,14 @@ var CPDocumentUntitledCount = 0;
*/
- (void)connection:(CPURLConnection)aConnection didReceiveData:(CPString)aData
{
var session = aConnection.session,
theDelegate = session.delegate;
var session = aConnection.session;
// READ
if (aConnection == _readConnection)
{
[self readFromData:[CPData dataWithRawString:aData] ofType:session.fileType error:nil];
theDelegate.isa.objj_msgSend3(theDelegate, session.didReadSelector, self, YES, session.contextInfo);
objj_msgSend(session.delegate, session.didReadSelector, self, YES, session.contextInfo);
}
else
{
@@ -574,7 +583,7 @@ var CPDocumentUntitledCount = 0;
_writeRequest = nil;
theDelegate.isa.objj_msgSend3(theDelegate, session.didSaveSelector, self, YES, session.contextInfo);
objj_msgSend(session.delegate, session.didSaveSelector, self, YES, session.contextInfo);
[self _sendDocumentSavedNotification:YES];
}
}
@@ -585,11 +594,10 @@ var CPDocumentUntitledCount = 0;
*/
- (void)connection:(CPURLConnection)aConnection didFailWithError:(CPError)anError
{
var session = aConnection.session,
theDelegate = session.delegate;
var session = aConnection.session;
if (_readConnection == aConnection)
theDelegate.isa.objj_msgSend3(theDelegate, session.didReadSelector, self, NO, session.contextInfo);
objj_msgSend(session.delegate, session.didReadSelector, self, NO, session.contextInfo);
else
{
@@ -603,7 +611,7 @@ var CPDocumentUntitledCount = 0;
alert("There was an error saving the document.");
theDelegate.isa.objj_msgSend3(theDelegate, session.didSaveSelector, self, NO, session.contextInfo);
objj_msgSend(session.delegate, session.didSaveSelector, self, NO, session.contextInfo);
[self _sendDocumentSavedNotification:NO];
}
}
@@ -864,24 +872,21 @@ var CPDocumentUntitledCount = 0;
[self canCloseDocumentWithDelegate:self shouldCloseSelector:@selector(_document:shouldClose:context:) contextInfo:{delegate:delegate, selector:selector, context:info}];
else if ([delegate respondsToSelector:selector])
delegate.isa.objj_msgSend3(delegate, selector, self, YES, info);
objj_msgSend(delegate, selector, self, YES, info);
}
- (void)_document:(CPDocument)aDocument shouldClose:(BOOL)shouldClose context:(Object)context
{
var theDelegate = context.delegate;
if (aDocument === self && shouldClose)
[self close];
if (theDelegate != null)
theDelegate.isa.objj_msgSend3(theDelegate, context.selector, aDocument, shouldClose, context.context);
objj_msgSend(context.delegate, context.selector, aDocument, shouldClose, context.context);
}
- (void)canCloseDocumentWithDelegate:(id)aDelegate shouldCloseSelector:(SEL)aSelector contextInfo:(Object)context
{
if (![self isDocumentEdited])
return [aDelegate respondsToSelector:aSelector] && aDelegate.isa.objj_msgSend3(aDelegate, aSelector, self, YES, context);
return [aDelegate respondsToSelector:aSelector] && objj_msgSend(aDelegate, aSelector, self, YES, context);
_canCloseAlert = [[CPAlert alloc] init];
@@ -910,8 +915,8 @@ var CPDocumentUntitledCount = 0;
if (returnCode === 0)
[self saveDocumentWithDelegate:delegate didSaveSelector:selector contextInfo:context];
else if (delegate != null)
delegate.isa.objj_msgSend3(delegate, selector, self, returnCode === 2, context);
else
objj_msgSend(delegate, selector, self, returnCode === 2, context);
_canCloseAlert = nil;
}
+2 -39
View File
@@ -253,14 +253,6 @@ var CPSharedDocumentController = nil;
return _documents;
}
/*!
Returns the CPDocument object associated with the main window.
*/
- (CPDocument)currentDocument
{
return [[[CPApp mainWindow] windowController] document];
}
/*!
Adds \c aDocument under the control of the receiver.
@param aDocument the document to add
@@ -279,33 +271,6 @@ var CPSharedDocumentController = nil;
[_documents removeObjectIdenticalTo:aDocument];
}
/*!
Returns the document object whose window controller
owns a specified window.
*/
- (CPDocument)documentForWindow:(CPWindow)aWindow
{
return [[aWindow windowController] document];
}
/*!
Returns a Boolean value that indicates whether the receiver
has any documents with unsaved changes.
*/
- (BOOL)hasEditedDocuments
{
var iter = [_documents objectEnumerator],
obj;
while ((obj = [iter nextObject]) !== nil)
{
if ([obj isDocumentEdited])
return YES;
}
return NO;
}
- (CPString)defaultType
{
return [_documentTypes[0] objectForKey:@"CPBundleTypeName"];
@@ -402,10 +367,8 @@ var CPSharedDocumentController = nil;
}
}
var theDelegate = context.delegate;
if ([theDelegate respondsToSelector:context.selector])
theDelegate.isa.objj_msgSend3(theDelegate, context.selector, self, [[self documents] count] === 0, context.context);
if ([context.delegate respondsToSelector:context.selector])
objj_msgSend(context.delegate, context.selector, self, [[self documents] count] === 0, context.context);
}
@end
+19 -28
View File
@@ -163,7 +163,7 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
if (self)
{
_draggedWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessWindowMask];
_draggedWindow = [[CPWindow alloc] initWithContentRect:_CGRectMakeZero() styleMask:CPBorderlessWindowMask];
[_draggedWindow setLevel:CPDraggingWindowLevel];
}
@@ -201,12 +201,7 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
- (void)draggingSourceUpdatedWithGlobalLocation:(CGPoint)aGlobalLocation
{
if (![CPPlatform supportsDragAndDrop])
{
var frame = [_draggedWindow frame];
frame.origin.x = aGlobalLocation.x - _draggingOffset.width;
frame.origin.y = aGlobalLocation.y - _draggingOffset.height;
[_draggedWindow _setFrame:frame display:YES animate:NO constrainWidth:NO constrainHeight:NO];
}
[_draggedWindow setFrameOrigin:_CGPointMake(aGlobalLocation.x - _draggingOffset.width, aGlobalLocation.y - _draggingOffset.height)];
if (_implementedDraggingSourceMethods & CPDraggingSource_draggedImage_movedTo_)
[_draggingSource draggedImage:[_draggedView image] movedTo:aGlobalLocation];
@@ -270,10 +265,10 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
{
if ([scrollView hasVerticalScroller])
{
if (eventLocation.y < CGRectGetMinY(insetBounds))
deltaY = CGRectGetMinY(insetBounds) - eventLocation.y;
else if (eventLocation.y > CGRectGetMaxY(insetBounds))
deltaY = CGRectGetMaxY(insetBounds) - eventLocation.y;
if (eventLocation.y < _CGRectGetMinY(insetBounds))
deltaY = _CGRectGetMinY(insetBounds) - eventLocation.y;
else if (eventLocation.y > _CGRectGetMaxY(insetBounds))
deltaY = _CGRectGetMaxY(insetBounds) - eventLocation.y;
if (deltaY < -insetBounds.size.height)
deltaY = -insetBounds.size.height;
if (deltaY > insetBounds.size.height)
@@ -282,17 +277,17 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
if ([scrollView hasHorizontalScroller])
{
if (eventLocation.x < CGRectGetMinX(insetBounds))
deltaX = CGRectGetMinX(insetBounds) - eventLocation.x;
else if (eventLocation.x > CGRectGetMaxX(insetBounds))
deltaX = CGRectGetMaxX(insetBounds) - eventLocation.x;
if (eventLocation.x < _CGRectGetMinX(insetBounds))
deltaX = _CGRectGetMinX(insetBounds) - eventLocation.x;
else if (eventLocation.x > _CGRectGetMaxX(insetBounds))
deltaX = _CGRectGetMaxX(insetBounds) - eventLocation.x;
if (deltaX < -insetBounds.size.width)
deltaX = -insetBounds.size.width;
if (deltaX > insetBounds.size.width)
deltaX = insetBounds.size.width;
}
var scrollPoint = CGPointMake(bounds.origin.x - deltaX, bounds.origin.y - deltaY);
var scrollPoint = _CGPointMake(bounds.origin.x - deltaX, bounds.origin.y - deltaY);
[contentView scrollToPoint:scrollPoint];
[[scrollView _headerView] scrollPoint:scrollPoint];
@@ -370,26 +365,22 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
if (mouseDownWindow)
mouseDownEventLocation = [mouseDownWindow convertBaseToGlobal:mouseDownEventLocation];
_draggingOffset = CGSizeMake(mouseDownEventLocation.x - viewLocation.x, mouseDownEventLocation.y - viewLocation.y);
_draggingOffset = _CGSizeMake(mouseDownEventLocation.x - viewLocation.x, mouseDownEventLocation.y - viewLocation.y);
}
else
_draggingOffset = CGSizeMakeZero();
_draggingOffset = _CGSizeMakeZero();
if ([CPPlatform isBrowser])
[_draggedWindow setPlatformWindow:[aWindow platformWindow]];
[aView setFrameOrigin:CGPointMakeZero()];
[aView setFrameOrigin:_CGPointMakeZero()];
var mouseLocation = [CPEvent mouseLocation],
viewSize = [aView frameSize],
startDragLocationX = mouseLocation.x - _draggingOffset.width,
startDragLocationY = mouseLocation.y - _draggingOffset.height,
draggedWindowFrame = CGRectMake(startDragLocationX, startDragLocationY, viewSize.width, viewSize.height);
var mouseLocation = [CPEvent mouseLocation];
// Place it where the mouse pointer is.
_startDragLocation = CGPointMake(startDragLocationX, startDragLocationY);
[_draggedWindow _setFrame:draggedWindowFrame display:YES animate:NO constrainWidth:NO constrainHeight:NO];
_startDragLocation = _CGPointMake(mouseLocation.x - _draggingOffset.width, mouseLocation.y - _draggingOffset.height);
[_draggedWindow setFrameOrigin:_startDragLocation];
[_draggedWindow setFrameSize:[aView frame].size];
[[_draggedWindow contentView] addSubview:aView];
@@ -438,7 +429,7 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
var imageSize = [anImage size];
if (!_imageView)
_imageView = [[CPImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, imageSize.width, imageSize.height)];
_imageView = [[CPImageView alloc] initWithFrame:_CGRectMake(0.0, 0.0, imageSize.width, imageSize.height)];
[_imageView setImage:anImage];
-1
View File
@@ -20,7 +20,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@typedef CPDragOperation
CPDragOperationNone = 0;
CPDragOperationCopy = 1 << 1;
CPDragOperationLink = 1 << 1;
+2 -116
View File
@@ -29,18 +29,11 @@
@import "CPCompatibility.j"
@import "CGGeometry.j"
@import "CPText.j"
@import "CPTrackingArea.j"
@class CPTextField
@class CPWindow
@class CPGraphicsContext
@global CPApp
@typedef DOMEvent
@typedef CPEventType
var _CPEventPeriodicEventPeriod = 0,
_CPEventPeriodicEventTimer = nil,
_CPEventUpperCaseRegex = new RegExp("[A-Z]"),
@@ -75,16 +68,6 @@ var _CPEventPeriodicEventPeriod = 0,
float _deltaX;
float _deltaY;
float _deltaZ;
float _scrollingDeltaX;
float _scrollingDeltaY;
BOOL _hasPreciseScrollingDeltas;
#if PLATFORM(DOM)
BOOL _suppressCappuccinoCut;
BOOL _suppressCappuccinoPaste;
#endif
CPTrackingArea _trackingArea;
}
/*!
@@ -144,27 +127,6 @@ var _CPEventPeriodicEventPeriod = 0,
timestamp:aTimestamp windowNumber:aWindowNumber context:aGraphicsContext eventNumber:anEventNumber clickCount:aClickCount pressure:aPressure];
}
/*!
Creates a new mouse tracking 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
@param aTimestamp the time the event occurred
@param aWindowNumber the number of the CPWindow where the event occurred
@param aGraphicsContext the graphics context where the event occurred
@param anEventNumber a number for this event
@param aTrackingArea the tracking area that triggered the event
@throws CPInternalInconsistencyException if an invalid event type is provided
@return the new mouse event
*/
+ (id)enterExitEventWithType:(CPEventType)anEventType location:(CGPoint)aPoint modifierFlags:(unsigned)modifierFlags
timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext
eventNumber:(int)anEventNumber trackingArea:(CPTrackingArea)aTrackingArea
{
return [[self alloc] _initEnterExitEventWithType:anEventType location:aPoint modifierFlags:modifierFlags timestamp:aTimestamp windowNumber:aWindowNumber context:aGraphicsContext eventNumber:anEventNumber trackingArea:aTrackingArea];
}
/*!
Creates a new custom event.
@@ -196,9 +158,7 @@ var _CPEventPeriodicEventPeriod = 0,
// Make sure these are 0 rather than nil.
_deltaX = 0;
_scrollingDeltaX = 0;
_deltaY = 0;
_scrollingDeltaY = 0;
_deltaZ = 0;
}
@@ -225,28 +185,6 @@ var _CPEventPeriodicEventPeriod = 0,
return self;
}
/* @ignore */
- (id)_initEnterExitEventWithType:(CPEventType)anEventType location:(CGPoint)aPoint modifierFlags:(unsigned)modifierFlags
timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext
eventNumber:(int)anEventNumber trackingArea:(CPTrackingArea)aTrackingArea
{
if ((anEventType != CPMouseEntered) && (anEventType != CPMouseExited) && (anEventType != CPCursorUpdate))
[CPException raise:CPInternalInconsistencyException reason:"Invalid event type"];
if (self = [self _initWithType:anEventType])
{
_location = CGPointCreateCopy(aPoint);
_modifierFlags = modifierFlags;
_timestamp = aTimestamp;
_context = aGraphicsContext;
_eventNumber = anEventNumber;
_trackingArea = aTrackingArea;
_window = [CPApp windowWithWindowNumber:aWindowNumber];
}
return self;
}
/* @ignore */
- (id)_initKeyEventWithType:(CPEventType)anEventType location:(CGPoint)aPoint modifierFlags:(unsigned int)modifierFlags
timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext
@@ -282,7 +220,6 @@ var _CPEventPeriodicEventPeriod = 0,
_subtype = aSubtype;
_data1 = aData1;
_data2 = aData2;
_windowNumber = aWindowNumber;
}
return self;
@@ -298,7 +235,7 @@ var _CPEventPeriodicEventPeriod = 0,
*/
- (CGPoint)locationInWindow
{
return CGPointMakeCopy(_location);
return _CGPointMakeCopy(_location);
}
- (CGPoint)globalLocation
@@ -475,31 +412,6 @@ var _CPEventPeriodicEventPeriod = 0,
return _deltaZ;
}
- (BOOL)hasPreciseScrollingDeltas
{
return !!_hasPreciseScrollingDeltas;
}
/*!
Returns the change in points on the x-axis for a mouse movement, unless hasPreciseScrollingDeltas is NO,
in which case the change is measured in number of "lines" or "rows" and needs to be multiplied as appropriate
to get change in pixels.
*/
- (float)scrollingDeltaX
{
return _scrollingDeltaX;
}
/*!
Returns the change in points on the y-axis for a mouse movement, unless hasPreciseScrollingDeltas is NO,
in which case the change is measured in number of "lines" or "columns" and needs to be multiplied as appropriate
to get change in pixels.
*/
- (float)scrollingDeltaY
{
return _scrollingDeltaY;
}
- (BOOL)_triggersKeyEquivalent:(CPString)aKeyEquivalent withModifierMask:aKeyEquivalentModifierMask
{
if (!aKeyEquivalent)
@@ -561,24 +473,6 @@ var _CPEventPeriodicEventPeriod = 0,
return !firstResponderIsText;
}
/*!
Return YES if this event is a part of processing a browser controlled cut or paste event
where the browser will go ahead and do the work of cutting or pasting within the input
element after processing of this event. The implication is that it should not be done by
the CPTextField (or whatever else is controlling the input) since this would result in
nothing being cut (because the field already cut the text out), or a double paste
(because the field pasted as well as the browser).
*/
- (BOOL)_platformIsEffectingCutOrPaste
{
#if PLATFORM(DOM)
return _suppressCappuccinoCut || _suppressCappuccinoPaste;
#else
return NO;
#endif
}
/*!
Generates periodic events every \c aPeriod seconds.
@@ -629,19 +523,11 @@ var _CPEventPeriodicEventPeriod = 0,
}
}
- (CPTrackingArea)trackingArea
{
if ((_type !== CPMouseEntered) && (_type !== CPMouseExited) && (_type !== CPCursorUpdate))
[CPException raise:CPInternalInconsistencyException format:@"You can't call trackingArea for events of type %#x", _type]
return _trackingArea;
}
@end
function _CPEventFirePeriodEvent()
{
[CPApp sendEvent:[CPEvent otherEventWithType:CPPeriodic location:CGPointMakeZero() modifierFlags:0 timestamp:[CPEvent currentTimestamp] windowNumber:0 context:nil subtype:0 data1:0 data2:0]];
[CPApp sendEvent:[CPEvent otherEventWithType:CPPeriodic location:_CGPointMakeZero() modifierFlags:0 timestamp:[CPEvent currentTimestamp] windowNumber:0 context:nil subtype:0 data1:0 data2:0]];
}
var CPEventClass = [CPEvent class];
+1 -1
View File
@@ -189,7 +189,7 @@ var IEFlashCLSID = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
return @"CPFV_" + [self UID];
}
- (void)mouseMoved:(CPEvent)sommit
- (void)mouseMoved:(id)sommit
{
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
}
+11 -13
View File
@@ -37,12 +37,12 @@ CPFontCurrentSystemSize = -1;
// For internal use only by this class and subclasses
_CPFontSystemFacePlaceholder = "_CPFontSystemFacePlaceholder";
var _CPFontCache = {},
_CPSystemFontCache = {},
_CPFontSystemFontFace = CPFontDefaultSystemFontFace,
_CPFontSystemFontSize = 12,
_CPFontFallbackFaces = CPFontDefaultSystemFontFace.split(", "),
_CPFontStripRegExp = new RegExp("(^\\s*[\"']?|[\"']?\\s*$)", "g");
var _CPFontCache = {},
_CPSystemFontCache = {},
_CPFontSystemFontFace = CPFontDefaultSystemFontFace,
_CPFontSystemFontSize = 12,
_CPFontFallbackFaces = CPFontDefaultSystemFontFace.split(", "),
_CPFontStripRegExp = new RegExp("(^\\s*[\"']?|[\"']?\\s*$)", "g");
#define _CPRealFontSize(aSize) (aSize <= 0 ? _CPFontSystemFontSize : aSize)
@@ -174,20 +174,18 @@ following:
return _CPFontSystemFontSize;
}
+ (CPFont)systemFontForControlSize:(CPControlSize)aSize
+ (float)systemFontSizeForControlSize:(CPControlSize)aSize
{
// TODO These sizes should be themable or made less arbitrary in some other way.
switch (aSize)
{
case CPSmallControlSize:
return [self systemFontOfSize:_CPFontSystemFontSize - 1];
return _CPFontSystemFontSize - 1;
case CPMiniControlSize:
return [self systemFontOfSize:_CPFontSystemFontSize - 2];
return _CPFontSystemFontSize - 2;
case CPRegularControlSize:
default:
return [self systemFontOfSize:_CPFontSystemFontSize];
return _CPFontSystemFontSize;
}
}
@@ -208,7 +206,7 @@ following:
var systemSize = String(_CPFontSystemFontSize),
currentSize = String(CPFontCurrentSystemSize);
for (var key in _CPSystemFontCache)
for (key in _CPSystemFontCache)
{
if (_CPSystemFontCache.hasOwnProperty(key) &&
(key.indexOf(systemSize) === 0 || key.indexOf(currentSize) === 0))
+6 -6
View File
@@ -108,13 +108,13 @@ CPGradientDrawsAfterEndingLocation = kCGGradientDrawsAfterEndLocation;
angle = ((angle % 360.0) + 360.0) % 360.0;
if (angle < 90.0)
startPoint = CGPointMake(CGRectGetMinX(rect), CGRectGetMinY(rect));
startPoint = _CGPointMake(_CGRectGetMinX(rect), _CGRectGetMinY(rect));
else if (angle < 180.0)
startPoint = CGPointMake(CGRectGetMaxX(rect), CGRectGetMinY(rect));
startPoint = _CGPointMake(_CGRectGetMaxX(rect), _CGRectGetMinY(rect));
else if (angle < 270.0)
startPoint = CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(rect));
startPoint = _CGPointMake(_CGRectGetMaxX(rect), _CGRectGetMaxY(rect));
else
startPoint = CGPointMake(CGRectGetMinX(rect), CGRectGetMaxY(rect));
startPoint = _CGPointMake(_CGRectGetMinX(rect), _CGRectGetMaxY(rect));
// A line segment comes out of the starting point at the given angle, with the first colour
// at the starting point and the last at the end. To do what drawInRect: is supposed to do
@@ -129,9 +129,9 @@ CPGradientDrawsAfterEndingLocation = kCGGradientDrawsAfterEndLocation;
// This simplifies down to (in the first quadrant) rectWidth * cos(a) + rectHeight * sin(a).
var radians = PI * angle / 180.0,
length = ABS(CGRectGetWidth(rect) * COS(radians)) + ABS(CGRectGetHeight(rect) * SIN(radians));
length = ABS(_CGRectGetWidth(rect) * COS(radians)) + ABS(_CGRectGetHeight(rect) * SIN(radians));
endPoint = CGPointMake(startPoint.x + length * COS(radians),
endPoint = _CGPointMake(startPoint.x + length * COS(radians),
startPoint.y + length * SIN(radians));
[self drawFromPoint:startPoint toPoint:endPoint options:CPGradientDrawsBeforeStartingLocation | CPGradientDrawsAfterEndingLocation];
+12 -12
View File
@@ -60,9 +60,9 @@ function CPDrawColorTiledRects(
if (sides.length != colors.length)
[CPException raise:CPInvalidArgumentException reason:@"sides (length: " + sides.length + ") and colors (length: " + colors.length + ") must have the same length."];
var resultRect = CGRectMakeCopy(boundsRect),
slice = CGRectMakeZero(),
remainder = CGRectMakeZero(),
var resultRect = _CGRectMakeCopy(boundsRect),
slice = _CGRectMakeZero(),
remainder = _CGRectMakeZero(),
context = [[CPGraphicsContext currentContext] graphicsPort];
CGContextSaveGState(context);
@@ -77,7 +77,7 @@ function CPDrawColorTiledRects(
slice = CGRectIntersection(slice, clipRect);
// Cocoa docs say that only slices that are within the clipRect are actually drawn
if (CGRectIsEmpty(slice))
if (_CGRectIsEmpty(slice))
continue;
var minX,
@@ -88,23 +88,23 @@ function CPDrawColorTiledRects(
if (side == CPMinXEdge || side == CPMaxXEdge)
{
// Make sure we have at least 1 pixel to draw a line
if (CGRectGetWidth(slice) < 1.0)
if (_CGRectGetWidth(slice) < 1.0)
continue;
minX = CGRectGetMinX(slice) + 0.5;
minX = _CGRectGetMinX(slice) + 0.5;
maxX = minX;
minY = CGRectGetMinY(slice);
maxY = CGRectGetMaxY(slice);
minY = _CGRectGetMinY(slice);
maxY = _CGRectGetMaxY(slice);
}
else // CPMinYEdge || CPMaxYEdge
{
// Make sure we have at least 1 pixel to draw a line
if (CGRectGetHeight(slice) < 1.0)
if (_CGRectGetHeight(slice) < 1.0)
continue;
minX = CGRectGetMinX(slice);
maxX = CGRectGetMaxX(slice);
minY = CGRectGetMinY(slice) + 0.5;
minX = _CGRectGetMinX(slice);
maxX = _CGRectGetMaxX(slice);
minY = _CGRectGetMinY(slice) + 0.5;
maxY = minY;
}
+21 -54
View File
@@ -30,20 +30,6 @@
@import "CGGeometry.j"
@import "CPCompatibility.j"
@protocol CPImageDelegate <CPObject>
@optional
- (void)imageDidLoad:(CPImage)anImage;
- (void)imageDidError:(CPImage)anImage;
- (void)imageDidAbort:(CPImage)anImage;
@end
var CPImageDelegate_imageDidLoad_ = 1 << 1,
CPImageDelegate_imageDidError_ = 1 << 2,
CPImageDelegate_imageDidAbort_ = 1 << 3;
CPImageLoadStatusInitialized = 0;
CPImageLoadStatusLoading = 1;
CPImageLoadStatusCompleted = 2;
@@ -62,8 +48,8 @@ var imagesForNames = { },
AppKitImageForNames = { },
ImageDescriptionFormat = "%s {\n filename: \"%s\",\n size: { width:%f, height:%f }\n}";
AppKitImageForNames[CPImageNameColorPanel] = CGSizeMake(26.0, 29.0);
AppKitImageForNames[CPImageNameColorPanelHighlighted] = CGSizeMake(26.0, 29.0);
AppKitImageForNames[CPImageNameColorPanel] = _CGSizeMake(26.0, 29.0);
AppKitImageForNames[CPImageNameColorPanelHighlighted] = _CGSizeMake(26.0, 29.0);
/*!
Returns a resource image with a relative path and size
@@ -86,7 +72,7 @@ function CPImageInBundle()
if (typeof(arguments[1]) === "number")
{
if (arguments[1] !== nil && arguments[1] !== undefined)
size = CGSizeMake(arguments[1], arguments[2]);
size = _CGSizeMake(arguments[1], arguments[2]);
bundle = arguments[3];
}
@@ -133,42 +119,36 @@ function CPAppKitImage(aFilename, aSize)
*/
@implementation CPImage : CPObject
{
CGSize _size;
CPString _filename;
CPString _name;
CGSize _size;
CPString _filename;
CPString _name;
id <CPImageDelegate> _delegate;
unsigned _loadStatus;
unsigned _implementedDelegateMethods;
id _delegate;
unsigned _loadStatus;
Image _image;
Image _image;
}
- (id)init
{
return [self initByReferencingFile:@"" size:CGSizeMake(-1, -1)];
return [self initByReferencingFile:@"" size:_CGSizeMake(-1, -1)];
}
/*!
Initializes the image, by associating it with a filename. The image
denoted in \c aFilename is not actually loaded. It will be loaded
once needed.
denoted in \c aFilename is not actually loaded. It will
be loaded once needed.
@param aFilename the file containing the image
@param aSize the image's size
@return the initialized image
*/
- (id)initByReferencingFile:(CPString)aFilename size:(CGSize)aSize
{
// Quietly return nil like in Cocoa, rather than crashing later.
if (aFilename === undefined || aFilename === nil)
return nil;
self = [super init];
if (self)
{
_size = CGSizeMakeCopy(aSize);
_size = _CGSizeMakeCopy(aSize);
_filename = aFilename;
_loadStatus = CPImageLoadStatusInitialized;
}
@@ -200,7 +180,7 @@ function CPAppKitImage(aFilename, aSize)
*/
- (id)initWithContentsOfFile:(CPString)aFilename
{
self = [self initByReferencingFile:aFilename size:CGSizeMake(-1, -1)];
self = [self initByReferencingFile:aFilename size:_CGSizeMake(-1, -1)];
if (self)
[self load];
@@ -267,7 +247,7 @@ function CPAppKitImage(aFilename, aSize)
*/
- (void)setSize:(CGSize)aSize
{
_size = CGSizeMakeCopy(aSize);
_size = _CGSizeMakeCopy(aSize);
}
/*!
@@ -275,7 +255,7 @@ function CPAppKitImage(aFilename, aSize)
*/
- (CGSize)size
{
return CGSizeMakeCopy(_size);
return _size;
}
+ (id)imageNamed:(CPString)aName
@@ -334,22 +314,9 @@ function CPAppKitImage(aFilename, aSize)
Sets the receiver's delegate.
@param the delegate
*/
- (void)setDelegate:(id <CPImageDelegate>)aDelegate
- (void)setDelegate:(id)aDelegate
{
if (_delegate === aDelegate)
return;
_delegate = aDelegate;
_implementedDelegateMethods = 0;
if ([_delegate respondsToSelector:@selector(imageDidLoad:)])
_implementedDelegateMethods |= CPImageDelegate_imageDidLoad_;
if ([_delegate respondsToSelector:@selector(imageDidError:)])
_implementedDelegateMethods |= CPImageDelegate_imageDidError_;
if ([_delegate respondsToSelector:@selector(imageDidAbort:)])
_implementedDelegateMethods |= CPImageDelegate_imageDidAbort_;
}
/*!
@@ -479,13 +446,13 @@ function CPAppKitImage(aFilename, aSize)
// FIXME: IE is wrong on image sizes????
if (!_size || (_size.width == -1 && _size.height == -1))
_size = CGSizeMake(_image.width, _image.height);
_size = _CGSizeMake(_image.width, _image.height);
[[CPNotificationCenter defaultCenter]
postNotificationName:CPImageDidLoadNotification
object:self];
if (_implementedDelegateMethods & CPImageDelegate_imageDidLoad_)
if ([_delegate respondsToSelector:@selector(imageDidLoad:)])
[_delegate imageDidLoad:self];
}
@@ -494,7 +461,7 @@ function CPAppKitImage(aFilename, aSize)
{
_loadStatus = CPImageLoadStatusReadError;
if (_implementedDelegateMethods & CPImageDelegate_imageDidError_)
if ([_delegate respondsToSelector:@selector(imageDidError:)])
[_delegate imageDidError:self];
}
@@ -503,7 +470,7 @@ function CPAppKitImage(aFilename, aSize)
{
_loadStatus = CPImageLoadStatusCancelled;
if (_implementedDelegateMethods & CPImageDelegate_imageDidAbort_)
if ([_delegate respondsToSelector:@selector(imageDidAbort:)])
[_delegate imageDidAbort:self];
}
+46 -41
View File
@@ -29,7 +29,6 @@
@global CPImagesPboardType
@global appkit_tag_dom_elements
@typedef CPImageAlignment
CPImageAlignCenter = 0;
CPImageAlignTop = 1;
CPImageAlignTopLeft = 2;
@@ -88,37 +87,26 @@ var CPImageViewEmptyPlaceholderImage = nil;
if (self)
{
#if PLATFORM(DOM)
[self _createDOMImageElement];
_DOMImageElement = document.createElement("img");
_DOMImageElement.style.position = "absolute";
_DOMImageElement.style.left = "0px";
_DOMImageElement.style.top = "0px";
if ([CPPlatform supportsDragAndDrop])
{
_DOMImageElement.setAttribute("draggable", "true");
_DOMImageElement.style["-khtml-user-drag"] = "element";
}
CPDOMDisplayServerAppendChild(_DOMElement, _DOMImageElement);
_DOMImageElement.style.visibility = "hidden";
#endif
}
return self;
}
- (void)_createDOMImageElement
{
#if PLATFORM(DOM)
if (_DOMImageElement)
return;
_DOMImageElement = document.createElement("img");
_DOMImageElement.style.position = "absolute";
_DOMImageElement.style.left = "0px";
_DOMImageElement.style.top = "0px";
if ([CPPlatform supportsDragAndDrop])
{
_DOMImageElement.setAttribute("draggable", "true");
_DOMImageElement.style["-khtml-user-drag"] = "element";
}
_DOMImageElement.style.visibility = "hidden";
AppKitTagDOMElement(self, _DOMImageElement);
CPDOMDisplayServerAppendChild(_DOMElement, _DOMImageElement);
#endif
}
/*!
Returns the view's image.
*/
@@ -150,9 +138,6 @@ var CPImageViewEmptyPlaceholderImage = nil;
var newImage = [self objectValue];
#if PLATFORM(DOM)
if (!_DOMImageElement)
[self _createDOMImageElement];
_DOMImageElement.src = newImage ? [newImage filename] : [CPImageViewEmptyPlaceholderImage filename];
#endif
@@ -179,7 +164,6 @@ var CPImageViewEmptyPlaceholderImage = nil;
- (void)imageDidLoad:(CPNotification)aNotification
{
[[CPNotificationCenter defaultCenter] removeObserver:self name:CPImageDidLoadNotification object:[self objectValue]];
[self hideOrDisplayContents];
[self setNeedsLayout];
@@ -269,7 +253,7 @@ var CPImageViewEmptyPlaceholderImage = nil;
[self setNeedsDisplay:YES];
}
- (CPUInteger)imageScaling
- (unsigned)imageScaling
{
return [self currentValueForThemeAttribute:@"image-scaling"];
}
@@ -318,8 +302,8 @@ var CPImageViewEmptyPlaceholderImage = nil;
y = 0.0,
insetWidth = (_hasShadow ? [_shadowView horizontalInset] : 0.0),
insetHeight = (_hasShadow ? [_shadowView verticalInset] : 0.0),
boundsWidth = CGRectGetWidth(bounds),
boundsHeight = CGRectGetHeight(bounds),
boundsWidth = _CGRectGetWidth(bounds),
boundsHeight = _CGRectGetHeight(bounds),
width = boundsWidth - insetWidth,
height = boundsHeight - insetHeight;
@@ -417,10 +401,10 @@ var CPImageViewEmptyPlaceholderImage = nil;
#endif
}
_imageRect = CGRectMake(x, y, width, height);
_imageRect = _CGRectMake(x, y, width, height);
if (_hasShadow)
[_shadowView setFrame:CGRectMake(x - [_shadowView leftInset], y - [_shadowView topInset], width + insetWidth, height + insetHeight)];
[_shadowView setFrame:_CGRectMake(x - [_shadowView leftInset], y - [_shadowView topInset], width + insetWidth, height + insetHeight)];
}
- (void)mouseDown:(CPEvent)anEvent
@@ -504,7 +488,7 @@ var CPImageViewEmptyPlaceholderImage = nil;
[_source setImage:image];
}
- (id)valueForBinding:(CPString)aBinding
- (void)valueForBinding:(CPString)aBinding
{
var image = [_source image];
@@ -533,12 +517,28 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
*/
- (id)initWithCoder:(CPCoder)aCoder
{
#if PLATFORM(DOM)
_DOMImageElement = document.createElement("img");
_DOMImageElement.style.position = "absolute";
_DOMImageElement.style.left = "0px";
_DOMImageElement.style.top = "0px";
_DOMImageElement.style.visibility = "hidden";
if ([CPPlatform supportsDragAndDrop])
{
_DOMImageElement.setAttribute("draggable", "true");
_DOMImageElement.style["-khtml-user-drag"] = "element";
}
if (typeof(appkit_tag_dom_elements) !== "undefined" && !!appkit_tag_dom_elements)
_DOMImageElement.setAttribute("data-cappuccino-view", [self className]);
#endif
self = [super initWithCoder:aCoder];
if (self)
{
#if PLATFORM(DOM)
[self _createDOMImageElement];
_DOMElement.appendChild(_DOMImageElement);
#endif
[self setHasShadow:[aCoder decodeBoolForKey:CPImageViewHasShadowKey]];
@@ -564,12 +564,17 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
// We do this in order to avoid encoding the _shadowView, which
// should just automatically be created programmatically as needed.
if (_shadowView)
[_shadowView removeFromSuperview];
{
var actualSubviews = _subviews;
_subviews = [_subviews copy];
[_subviews removeObjectIdenticalTo:_shadowView];
}
[super encodeWithCoder:aCoder];
if (_shadowView)
[self addSubview:_shadowView];
_subviews = actualSubviews;
[aCoder encodeBool:_hasShadow forKey:CPImageViewHasShadowKey];
[aCoder encodeInt:_imageAlignment forKey:CPImageViewImageAlignmentKey];
@@ -580,7 +585,7 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
@end
@implementation CPImage (CachedImage)
@implementation CPImage (CahedImage)
+ (CPImage)cachedImageWithContentsOfFile:(CPString)aFile
{
@@ -596,4 +601,4 @@ var CPImageViewImageKey = @"CPImageViewImageKey",
return image;
}
@end
@end
+3 -50
View File
@@ -35,7 +35,6 @@
var exposedBindingsMap = @{},
bindingsMap = @{};
@typedef CPBindingOperationKind
var CPBindingOperationAnd = 0,
CPBindingOperationOr = 1;
@@ -71,20 +70,6 @@ var CPBindingOperationAnd = 0,
return [[bindingsMap objectForKey:[anObject UID]] objectForKey:aBinding];
}
+ (void)_reverseSetValueFromExclusiveBinderForObject:(id)anObject
{
var bindersByBindingName = [bindingsMap objectForKey:[anObject UID]];
[bindersByBindingName enumerateKeysAndObjectsUsingBlock:function(binding, binder, stop)
{
if ([binder isKindOfClass:[self class]])
{
[binder reverseSetValueFor:binding];
stop(YES);
}
}];
}
+ (CPDictionary)infoForBinding:(CPString)aBinding forObject:(id)anObject
{
var theBinding = [self getBinding:aBinding forObject:anObject];
@@ -131,7 +116,7 @@ var CPBindingOperationAnd = 0,
count = allKeys.length;
while (count--)
[anObject unbind:allKeys[count]];
[anObject unbind:[bindings objectForKey:allKeys[count]]];
[bindingsMap removeObjectForKey:[anObject UID]];
}
@@ -157,7 +142,7 @@ var CPBindingOperationAnd = 0,
[self _updatePlaceholdersWithOptions:options forBinding:aName];
[aDestination addObserver:self forKeyPath:aKeyPath options:0 context:aBinding];
[aDestination addObserver:self forKeyPath:aKeyPath options:CPKeyValueObservingOptionNew context:aBinding];
var bindings = [bindingsMap objectForKey:[_source UID]];
@@ -174,24 +159,6 @@ var CPBindingOperationAnd = 0,
return self;
}
+ (BOOL)isBindingAllowed:(CPString)aBinding forObject:(id)anObject
{
if ([[anObject class] isBindingExclusive:aBinding])
{
var bindingsForObject = [bindingsMap objectForKey:[anObject UID]],
allBindings = [bindingsForObject allKeys],
count = [allBindings count];
while (count--)
{
if ([[anObject class] isBindingExclusive:allBindings[count]])
return NO;
}
}
return YES;
}
- (void)raiseIfNotApplicable:(id)aValue forKeyPath:(CPString)keyPath options:(CPDictionary)options
{
if (aValue === CPNotApplicableMarker && [options objectForKey:CPRaisesForNotApplicableKeysBindingOption])
@@ -290,11 +257,7 @@ var CPBindingOperationAnd = 0,
if (valueTransformer)
aValue = [valueTransformer transformedValue:aValue];
// If the value is nil AND the source doesn't respond to setPlaceholderString: then
// we set the value to the placeholder. Otherwise, we do not want to short cut the process
// of setting the placeholder that is based on the fact that the value is nil.
if ((aValue === undefined || aValue === nil || aValue === [CPNull null])
&& ![_source respondsToSelector:@selector(setPlaceholderString:)])
if (aValue === undefined || aValue === nil || aValue === [CPNull null])
aValue = [options objectForKey:CPNullPlaceholderBindingOption] || nil;
return aValue;
@@ -420,11 +383,6 @@ var CPBindingOperationAnd = 0,
return [CPBinder class];
}
+ (BOOL)isBindingExclusive:(CPString)aBinding
{
return NO;
}
- (CPArray)exposedBindings
{
var exposedBindings = [],
@@ -453,11 +411,6 @@ var CPBindingOperationAnd = 0,
if (!anObject || !aKeyPath)
return CPLog.error("Invalid object or path on " + self + " for " + aBinding);
if (![CPBinder isBindingAllowed:aBinding forObject:self])
{
CPLog.warn([self description] + " : cannot bind " + aBinding + " because another binding with the same functionality is already in use.");
return;
}
//if (![[self exposedBindings] containsObject:aBinding])
// CPLog.warn("No binding exposed on " + self + " for " + aBinding);
+11 -24
View File
@@ -25,13 +25,11 @@
@global CPApp
@typedef CPTickMarkPosition
CPTickMarkBelow = 0;
CPTickMarkAbove = 1;
CPTickMarkLeft = CPTickMarkAbove;
CPTickMarkRight = CPTickMarkBelow;
@typedef CPLevelIndicatorStyle
CPRelevancyLevelIndicatorStyle = 0;
CPContinuousCapacityLevelIndicatorStyle = 1;
CPDiscreteCapacityLevelIndicatorStyle = 2;
@@ -64,7 +62,7 @@ CPRatingLevelIndicatorStyle = 3;
return "level-indicator";
}
+ (CPDictionary)themeAttributes
+ (id)themeAttributes
{
return @{
@"bezel-color": [CPNull null],
@@ -107,21 +105,10 @@ CPRatingLevelIndicatorStyle = 3;
var filledColor = [self valueForThemeAttribute:@"color-normal"],
value = [self doubleValue];
if (_warningValue < _criticalValue)
{
if (value >= _criticalValue)
filledColor = [self valueForThemeAttribute:@"color-critical"];
else if (value >= _warningValue)
filledColor = [self valueForThemeAttribute:@"color-warning"];
}
else
{
if (value <= _criticalValue)
filledColor = [self valueForThemeAttribute:@"color-critical"];
else if (value <= _warningValue)
filledColor = [self valueForThemeAttribute:@"color-warning"];
}
if (value <= _criticalValue)
filledColor = [self valueForThemeAttribute:@"color-critical"];
else if (value <= _warningValue)
filledColor = [self valueForThemeAttribute:@"color-warning"];
for (var i = 0; i < segmentCount; i++)
{
@@ -135,7 +122,7 @@ CPRatingLevelIndicatorStyle = 3;
- (CPView)createEphemeralSubviewNamed:(CPString)aName
{
return [[CPView alloc] initWithFrame:CGRectMakeZero()];
return [[CPView alloc] initWithFrame:_CGRectMakeZero()];
}
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aViewName
@@ -143,11 +130,11 @@ CPRatingLevelIndicatorStyle = 3;
// TODO Put into theme attributes.
var bezelHeight = 18,
segmentHeight = 17,
bounds = CGRectCreateCopy([self bounds]);
bounds = _CGRectCreateCopy([self bounds]);
if (aViewName == "bezel")
{
bounds.origin.y = (CGRectGetHeight(bounds) - bezelHeight) / 2.0;
bounds.origin.y = (_CGRectGetHeight(bounds) - bezelHeight) / 2.0;
bounds.size.height = bezelHeight;
return bounds;
}
@@ -157,13 +144,13 @@ CPRatingLevelIndicatorStyle = 3;
segmentCount = _maxValue - _minValue;
if (segment >= segmentCount)
return CGRectMakeZero();
return _CGRectMakeZero();
var basicSegmentWidth = bounds.size.width / segmentCount,
segmentFrame = CGRectCreateCopy([self bounds]),
spacing = [self valueForThemeAttribute:@"spacing"];
segmentFrame.origin.y = (CGRectGetHeight(bounds) - bezelHeight) / 2.0;
segmentFrame.origin.y = (_CGRectGetHeight(bounds) - bezelHeight) / 2.0;
segmentFrame.origin.x = FLOOR(segment * basicSegmentWidth);
segmentFrame.size.width = (segment == segmentCount - 1) ? bounds.size.width - segmentFrame.origin.x : FLOOR(((segment + 1) * basicSegmentWidth)) - FLOOR((segment * basicSegmentWidth)) - spacing;
segmentFrame.size.height = segmentHeight;
@@ -171,7 +158,7 @@ CPRatingLevelIndicatorStyle = 3;
return segmentFrame;
}
return CGRectMakeZero();
return _CGRectMakeZero();
}
/*!
+34 -108
View File
@@ -30,17 +30,6 @@
@global CPApp
@protocol CPMenuDelegate <CPObject>
@optional
- (void)menuWillOpen:(CPMenu)aMenu;
- (void)menuDidClose:(CPMenu)aMenu;
@end
var CPMenuDelegate_menuWillOpen_ = 1 << 1,
CPMenuDelegate_menuDidClose_ = 1 << 2;
CPMenuDidAddItemNotification = @"CPMenuDidAddItemNotification";
CPMenuDidChangeItemNotification = @"CPMenuDidChangeItemNotification";
CPMenuDidRemoveItemNotification = @"CPMenuDidRemoveItemNotification";
@@ -61,27 +50,24 @@ var _CPMenuBarVisible = NO,
*/
@implementation CPMenu : CPObject
{
CPMenu _supermenu;
CPMenu _supermenu;
CPString _title;
CPString _name;
CPString _title;
CPString _name;
CPFont _font;
CPFont _font;
float _minimumWidth;
float _minimumWidth;
CPMutableArray _items;
CPMutableArray _items;
BOOL _autoenablesItems;
BOOL _showsStateColumn;
BOOL _autoenablesItems;
BOOL _showsStateColumn;
id <CPMenuDelegate> _delegate;
unsigned _implementedDelegateMethods;
id _delegate;
int _highlightedIndex;
_CPMenuWindow _menuWindow;
CPEvent _lastCloseEvent;
int _highlightedIndex;
_CPMenuWindow _menuWindow;
}
// Managing the Menu Bar
@@ -290,7 +276,7 @@ var _CPMenuBarVisible = NO,
@param aMenuItem the item to insert
@param anIndex the index in the menu to insert the item.
*/
- (void)insertItem:(CPMenuItem)aMenuItem atIndex:(CPUInteger)anIndex
- (void)insertItem:(CPMenuItem)aMenuItem atIndex:(unsigned)anIndex
{
[self insertObject:aMenuItem inItemsAtIndex:anIndex];
}
@@ -303,7 +289,7 @@ var _CPMenuBarVisible = NO,
@param anIndex the index location in the menu for the new item
@return the new menu item
*/
- (CPMenuItem)insertItemWithTitle:(CPString)aTitle action:(SEL)anAction keyEquivalent:(CPString)aKeyEquivalent atIndex:(CPUInteger)anIndex
- (CPMenuItem)insertItemWithTitle:(CPString)aTitle action:(SEL)anAction keyEquivalent:(CPString)aKeyEquivalent atIndex:(unsigned)anIndex
{
var item = [[CPMenuItem alloc] initWithTitle:aTitle action:anAction keyEquivalent:aKeyEquivalent];
@@ -347,7 +333,7 @@ var _CPMenuBarVisible = NO,
Removes the item at the specified index from the menu
@param anIndex the index of the item to remove
*/
- (void)removeItemAtIndex:(CPUInteger)anIndex
- (void)removeItemAtIndex:(unsigned)anIndex
{
[self removeObjectFromItemsAtIndex:anIndex];
}
@@ -367,7 +353,7 @@ var _CPMenuBarVisible = NO,
while (count--)
[_items[count] setMenu:nil];
[self _highlightItemAtIndex:CPNotFound];
_highlightedIndex = CPNotFound;
// Because we are changing _items directly, be sure to notify KVO
[self willChangeValueForKey:@"items"];
@@ -633,7 +619,7 @@ var _CPMenuBarVisible = NO,
*/
- (void)update
{
if (!_autoenablesItems)
if (![self autoenablesItems])
return;
var items = [self itemArray];
@@ -645,25 +631,14 @@ var _CPMenuBarVisible = NO,
if ([item hasSubmenu])
continue;
// If there are enabled bindings for the item, they override anything else
var binder = [CPBinder getBinding:CPEnabledBinding forObject:item];
if (binder)
{
[binder setValueFor:CPEnabledBinding];
[[_menuWindow _menuView] tile];
return;
}
var validator = [CPApp targetForAction:[item action] to:[item target] from:item],
shouldBeEnabled = YES;
var validator = [CPApp targetForAction:[item action] to:[item target] from:item];
if (!validator)
{
// If targetForAction: returns nil, it could be that there is no action.
// If there is an action and nil is returned, no valid target could be found.
if ([item action] || [item target])
shouldBeEnabled = NO;
[item setEnabled:NO];
else
{
// Check to see if there is a target binding with an invalid selector
@@ -678,18 +653,16 @@ var _CPMenuBarVisible = NO,
selector = [options valueForKey:CPSelectorNameBindingOption];
if (target && selector && ![target respondsToSelector:CPSelectorFromString(selector)])
shouldBeEnabled = NO;
[item setEnabled:NO];
}
}
}
else if (![validator respondsToSelector:[item action]])
shouldBeEnabled = NO;
[item setEnabled:NO];
else if ([validator respondsToSelector:@selector(validateMenuItem:)])
shouldBeEnabled = [validator validateMenuItem:item];
[item setEnabled:[validator validateMenuItem:item]];
else if ([validator respondsToSelector:@selector(validateUserInterfaceItem:)])
shouldBeEnabled = [validator validateUserInterfaceItem:item];
[item setEnabled:shouldBeEnabled];
[item setEnabled:[validator validateUserInterfaceItem:item]];
}
[[_menuWindow _menuView] tile];
@@ -868,9 +841,6 @@ var _CPMenuBarVisible = NO,
+ (void)popUpContextMenu:(CPMenu)aMenu withEvent:(CPEvent)anEvent forView:(CPView)aView withFont:(CPFont)aFont
{
// This is needed when we are making several rights click
[[_CPMenuManager sharedMenuManager] cancelActiveMenu];
[aMenu _menuWillOpen];
if (!aFont)
@@ -954,19 +924,9 @@ var _CPMenuBarVisible = NO,
// Managing the Delegate
- (void)setDelegate:(id <CPMenuDelegate>)aDelegate
- (void)setDelegate:(id)aDelegate
{
if (_delegate === aDelegate)
return;
_delegate = aDelegate;
_implementedDelegateMethods = 0;
if ([_delegate respondsToSelector:@selector(menuWillOpen:)])
_implementedDelegateMethods |= CPMenuDelegate_menuWillOpen_;
if ([_delegate respondsToSelector:@selector(menuDidClose:)])
_implementedDelegateMethods |= CPMenuDelegate_menuDidClose_;
}
- (id)delegate
@@ -976,16 +936,18 @@ var _CPMenuBarVisible = NO,
- (void)_menuWillOpen
{
[self _sendDelegateMenuWillOpen];
var delegate = [self delegate];
if ([delegate respondsToSelector:@selector(menuWillOpen:)])
[delegate menuWillOpen:self];
}
- (void)_menuDidClose
{
// Remember which event caused this menu to close, if any. CPPopUpButton uses this to detect
// when a click on the button itself caused the menu to close.
_lastCloseEvent = [CPApp currentEvent];
var delegate = [self delegate];
[self _sendDelegateMenuDidClose];
if ([delegate respondsToSelector:@selector(menuDidClose:)])
[delegate menuDidClose:self];
}
// Handling Tracking
@@ -1001,7 +963,7 @@ var _CPMenuBarVisible = NO,
{
[CPApp sendEvent:[CPEvent
otherEventWithType:CPAppKitDefined
location:CGPointMakeZero()
location:_CGPointMakeZero()
modifierFlags:0
timestamp:0
windowNumber:0
@@ -1078,7 +1040,7 @@ var _CPMenuBarVisible = NO,
Sends the action of the menu item at the specified index.
@param anIndex the index of the item
*/
- (void)performActionForItemAtIndex:(CPUInteger)anIndex
- (void)performActionForItemAtIndex:(unsigned)anIndex
{
var item = _items[anIndex];
@@ -1149,36 +1111,6 @@ var _CPMenuBarVisible = NO,
@end
@implementation CPMenu (CPMenuDelegate)
/*!
@ignore
Call delegate menuWillOpen
*/
- (void)_sendDelegateMenuWillOpen
{
if (!(_implementedDelegateMethods & CPMenuDelegate_menuWillOpen_))
return;
[_delegate menuWillOpen:self];
}
/*!
@ignore
Call delegate menuDidClose
*/
- (void)_sendDelegateMenuDidClose
{
if (!(_implementedDelegateMethods & CPMenuDelegate_menuDidClose_))
return;
[_delegate menuDidClose:self];
}
@end
@implementation CPMenu (CPKeyValueCoding)
- (CPUInteger)countOfItems
@@ -1211,7 +1143,6 @@ var _CPMenuBarVisible = NO,
return;
[aMenuItem setMenu:self];
[self _highlightItemAtIndex:CPNotFound];
[_items insertObject:aMenuItem atIndex:anIndex];
[[CPNotificationCenter defaultCenter]
@@ -1226,7 +1157,6 @@ var _CPMenuBarVisible = NO,
return;
[[_items objectAtIndex:anIndex] setMenu:nil];
[self _highlightItemAtIndex:CPNotFound];
[_items removeObjectAtIndex:anIndex];
[[CPNotificationCenter defaultCenter]
@@ -1240,8 +1170,7 @@ var _CPMenuBarVisible = NO,
var CPMenuTitleKey = @"CPMenuTitleKey",
CPMenuNameKey = @"CPMenuNameKey",
CPMenuItemsKey = @"CPMenuItemsKey",
CPMenuShowsStateColumnKey = @"CPMenuShowsStateColumnKey",
CPMenuAutoEnablesItemsKey = @"CPMenuAutoEnablesItemsKey";
CPMenuShowsStateColumnKey = @"CPMenuShowsStateColumnKey";
@implementation CPMenu (CPCoding)
@@ -1263,7 +1192,7 @@ var CPMenuTitleKey = @"CPMenuTitleKey",
_showsStateColumn = ![aCoder containsValueForKey:CPMenuShowsStateColumnKey] || [aCoder decodeBoolForKey:CPMenuShowsStateColumnKey];
_autoenablesItems = ![aCoder containsValueForKey:CPMenuAutoEnablesItemsKey] || [aCoder decodeBoolForKey:CPMenuAutoEnablesItemsKey];
_autoenablesItems = YES;
[self setMinimumWidth:0];
}
@@ -1286,9 +1215,6 @@ var CPMenuTitleKey = @"CPMenuTitleKey",
if (!_showsStateColumn)
[aCoder encodeBool:_showsStateColumn forKey:CPMenuShowsStateColumnKey];
if (!_autoenablesItems)
[aCoder encodeBool:_autoenablesItems forKey:CPMenuAutoEnablesItemsKey];
}
@end
+4 -10
View File
@@ -24,7 +24,6 @@
@import "_CPMenuManager.j"
@class _CPMenuView
@class CPMenu
@global CPMenuDidAddItemNotification
@global CPMenuDidChangeItemNotification
@@ -32,6 +31,7 @@
@implementation _CPMenuBarWindow : CPPanel
{
CPMenu _menu;
CPView _highlightView;
CPArray _menuItemViews;
@@ -67,8 +67,6 @@
if (self)
{
_constrainsToUsableScreen = NO;
[self setLevel:CPMainMenuWindowLevel];
[self setAutoresizingMask:CPWindowWidthSizable];
@@ -143,7 +141,6 @@
_textColor = aColor;
[_menuItemViews makeObjectsPerformSelector:@selector(setTextColor:) withObject:_textColor];
[_menuItemViews makeObjectsPerformSelector:@selector(setParentMenuTextColor:) withObject:_textColor];
}
- (void)setTitleColor:(CPColor)aColor
@@ -164,7 +161,6 @@
_textShadowColor = aColor;
[_menuItemViews makeObjectsPerformSelector:@selector(setTextShadowColor:) withObject:_textShadowColor];
[_menuItemViews makeObjectsPerformSelector:@selector(setParentMenuTextShadowColor:) withObject:_textShadowColor];
}
- (void)setTitleShadowColor:(CPColor)aColor
@@ -183,8 +179,6 @@
return;
_highlightColor = aColor;
[_menuItemViews makeObjectsPerformSelector:@selector(setParentMenuHighlightColor:) withObject:_highlightColor];
}
- (void)setHighlightTextColor:(CPColor)aColor
@@ -194,7 +188,7 @@
_highlightTextColor = aColor;
[_menuItemViews makeObjectsPerformSelector:@selector(setParentMenuHighlightTextColor:) withObject:_highlightTextColor];
// [_menuItemViews makeObjectsPerformSelector:@selector(setActivateColor:) withObject:_highlightTextColor];
}
- (void)setHighlightTextShadowColor:(CPColor)aColor
@@ -204,7 +198,7 @@
_highlightTextShadowColor = aColor;
[_menuItemViews makeObjectsPerformSelector:@selector(setParentMenuHighlightTextShadowColor:) withObject:_highlightTextShadowColor];
// [_menuItemViews makeObjectsPerformSelector:@selector(setActivateShadowColor:) withObject:_highlightTextShadowColor];
}
- (void)setMenu:(CPMenu)aMenu
@@ -417,7 +411,7 @@
[super setFrame:aRect display:shouldDisplay animate:shouldAnimate];
if (!CGSizeEqualToSize(size, aRect.size))
if (!_CGSizeEqualToSize(size, aRect.size))
[self tile];
}
+25 -31
View File
@@ -45,7 +45,6 @@ var STICKY_TIME_INTERVAL = 0.4,
@implementation _CPMenuManager: CPObject
{
CPTimeInterval _startTime;
CPEvent _openEvent;
BOOL _mouseWasDragged;
int _scrollingState;
CGPoint _lastGlobalLocation;
@@ -104,7 +103,6 @@ var STICKY_TIME_INTERVAL = 0.4,
CPApp._activeMenu = menu;
_startTime = [anEvent timestamp];
_openEvent = anEvent;
_scrollingState = _CPMenuManagerScrollingStateNone;
_constraintRect = aRect;
@@ -185,15 +183,8 @@ var STICKY_TIME_INTERVAL = 0.4,
activeItemIndex = activeMenuContainer ? [activeMenuContainer itemIndexAtPoint:menuLocation] : CPNotFound,
activeItem = activeItemIndex !== CPNotFound ? [activeMenu itemAtIndex:activeItemIndex] : nil;
/*
Click outside the menu structure?
The event which caused the menu to open is not considered even if it's
technically a click outside of an open menu, since this would mean the same
click which opened the menu could also close it. This is actually common.
E.g. you click on a button and it opens a menu below itself.
*/
if (type === CPLeftMouseDown && _openEvent !== anEvent && (!activeMenuContainer || !CGRectContainsPoint([activeMenuContainer globalFrame], globalLocation)))
// Click outside the menu structure?
if (type === CPLeftMouseDown && (!activeMenuContainer || !CGRectContainsPoint([activeMenuContainer globalFrame], globalLocation)))
{
[self completeTracking];
@@ -214,6 +205,15 @@ var STICKY_TIME_INTERVAL = 0.4,
[self _trackAgain];
if (_keyBuffer)
{
if (([anEvent timestamp] - _startTime) > (STICKY_TIME_INTERVAL + [activeMenu numberOfItems] / 2))
[self selectNextItemBeginningWith:_keyBuffer inMenu:menu clearBuffer:YES];
if (type === CPPeriodic)
return;
}
// unhighlight when mouse is moved off the menu
if (_lastGlobalLocation && CGRectContainsPoint([activeMenuContainer globalFrame], _lastGlobalLocation)
&& !CGRectContainsPoint([activeMenuContainer globalFrame], globalLocation))
@@ -250,9 +250,9 @@ var STICKY_TIME_INTERVAL = 0.4,
if (_lastMouseOverMenuView != mouseOverMenuView)
{
[_lastMouseOverMenuView mouseExited:anEvent];
[mouseOverMenuView mouseExited:anEvent];
// FIXME: Possibly multiple of these?
[mouseOverMenuView mouseEntered:anEvent];
[_lastMouseOverMenuView mouseEntered:anEvent];
_lastMouseOverMenuView = mouseOverMenuView;
}
@@ -407,15 +407,6 @@ var STICKY_TIME_INTERVAL = 0.4,
[menu cancelTracking];
}
- (void)cancelActiveMenu
{
if (CPApp._activeMenu)
{
[self completeTracking];
_menuContainerStack = [];
}
}
- (void)completeTracking
{
var trackingMenu = [self trackingMenu];
@@ -466,8 +457,8 @@ var STICKY_TIME_INTERVAL = 0.4,
{
var menuContainer = _menuContainerStack[index],
menuContainerFrame = [menuContainer globalFrame],
menuContainerMinX = CGRectGetMinX(menuContainerFrame),
menuContainerMaxX = CGRectGetMaxX(menuContainerFrame);
menuContainerMinX = _CGRectGetMinX(menuContainerFrame),
menuContainerMaxX = _CGRectGetMaxX(menuContainerFrame);
// If within the x bounds of this menu container, return it.
if (x < menuContainerMaxX && x >= menuContainerMinX)
@@ -563,9 +554,6 @@ var STICKY_TIME_INTERVAL = 0.4,
}
else if (!(modifierFlags & (CPCommandKeyMask | CPControlKeyMask)))
{
if (([anEvent timestamp] - _startTime) > STICKY_TIME_INTERVAL)
_keyBuffer = nil;
if (!_keyBuffer)
{
_startTime = [anEvent timestamp];
@@ -577,12 +565,12 @@ var STICKY_TIME_INTERVAL = 0.4,
else
_keyBuffer += character;
[self selectNextItemBeginningWith:_keyBuffer inMenu:menu];
_lastGlobalLocation = nil;
[self selectNextItemBeginningWith:_keyBuffer inMenu:menu clearBuffer:NO];
_lastGlobalLocation = Nil;
}
}
- (void)selectNextItemBeginningWith:(CPString)characters inMenu:(CPMenu)menu
- (void)selectNextItemBeginningWith:(CPString)characters inMenu:(CPMenu)menu clearBuffer:(BOOL)shouldClear
{
var iter = [[menu itemArray] objectEnumerator],
obj;
@@ -599,7 +587,13 @@ var STICKY_TIME_INTERVAL = 0.4,
}
}
_startTime = [CPEvent currentTimestamp];
if (shouldClear)
{
[CPEvent stopPeriodicEvents];
_keyBuffer = Nil;
}
else
_startTime = [CPEvent currentTimestamp];
}
- (void)scrollToBeginningOfDocument:(CPMenu)menu
+9 -14
View File
@@ -25,8 +25,6 @@
@import "CPWindow.j"
@import "_CPMenuManager.j"
@class _CPMenuView
var _CPMenuWindowPool = [],
_CPMenuWindowPoolCapacity = 5,
@@ -74,8 +72,7 @@ _CPMenuWindowAttachedMenuBackgroundStyle = 2;
+ (void)poolMenuWindow:(_CPMenuWindow)aMenuWindow
{
// FIXME :the poolMenuWindow is called too many times somewhere....
if (!aMenuWindow || _CPMenuWindowPool.length >= _CPMenuWindowPoolCapacity || [_CPMenuWindowPool containsObject:aMenuWindow])
if (!aMenuWindow || _CPMenuWindowPool.length >= _CPMenuWindowPoolCapacity)
return;
_CPMenuWindowPool.push(aMenuWindow);
@@ -83,15 +80,13 @@ _CPMenuWindowAttachedMenuBackgroundStyle = 2;
- (id)initWithContentRect:(CGRect)aRect styleMask:(unsigned)aStyleMask
{
_constraintRect = CGRectMakeZero();
_unconstrainedFrame = CGRectMakeZero();
_constraintRect = _CGRectMakeZero();
_unconstrainedFrame = _CGRectMakeZero();
self = [super initWithContentRect:aRect styleMask:CPBorderlessWindowMask];
if (self)
{
_constrainsToUsableScreen = NO;
[self setLevel:CPPopUpMenuWindowLevel];
[self setHasShadow:YES];
[self setShadowStyle:CPMenuWindowShadowStyle];
@@ -212,26 +207,26 @@ _CPMenuWindowAttachedMenuBackgroundStyle = 2;
- (CGRect)unconstrainedFrame
{
return CGRectMakeCopy(_unconstrainedFrame);
return _CGRectMakeCopy(_unconstrainedFrame);
}
// We need this because if not this will call setFrame: with -frame instead of -unconstrainedFrame, turning
// the constrained frame into the unconstrained frame.
- (void)setFrameOrigin:(CGPoint)aPoint
{
[super setFrame:CGRectMake(aPoint.x, aPoint.y, CGRectGetWidth(_unconstrainedFrame), CGRectGetHeight(_unconstrainedFrame))];
[super setFrame:_CGRectMake(aPoint.x, aPoint.y, _CGRectGetWidth(_unconstrainedFrame), _CGRectGetHeight(_unconstrainedFrame))];
}
- (void)setFrameSize:(CGSize)aSize
{
[super setFrame:CGRectMake(CGRectGetMinX(_unconstrainedFrame), CGRectGetMinY(_unconstrainedFrame), aSize.width, aSize.height)];
[super setFrame:_CGRectMake(_CGRectGetMinX(_unconstrainedFrame), _CGRectGetMinY(_unconstrainedFrame), aSize.width, aSize.height)];
}
- (void)setFrame:(CGRect)aFrame display:(BOOL)shouldDisplay animate:(BOOL)shouldAnimate
{
// FIXME: There are integral window issues with platform windows.
// FIXME: This gets called far too often.
_unconstrainedFrame = CGRectMakeCopy(aFrame);
_unconstrainedFrame = _CGRectMakeCopy(aFrame);
var constrainedFrame = CGRectIntersection(_unconstrainedFrame, _constraintRect),
marginInset = [_menuView valueForThemeAttribute:@"menu-window-margin-inset"],
@@ -412,7 +407,7 @@ _CPMenuWindowAttachedMenuBackgroundStyle = 2;
{
// Don't return indexes of items that aren't visible.
if (!CGRectContainsPoint([_menuClipView bounds], [_menuClipView convertPoint:aPoint fromView:nil]))
return CPNotFound;
return NO;
return [_menuView itemIndexAtPoint:[_menuView convertPoint:aPoint fromView:nil]];
}
@@ -437,7 +432,7 @@ _CPMenuWindowAttachedMenuBackgroundStyle = 2;
return "menu-view";
}
+ (CPDictionary)themeAttributes
+ (id)themeAttributes
{
return @{
@"menu-window-more-above-image": [CPNull null],
-3
View File
@@ -166,9 +166,6 @@ var CPMenuItemStringRepresentationDictionary = @{
if (_isEnabled === isEnabled)
return;
if (!isEnabled && [self isHighlighted])
[_menu _highlightItemAtIndex:CPNotFound];
_isEnabled = !!isEnabled;
[_menuItemView setDirty];
+16 -70
View File
@@ -25,22 +25,16 @@
@class _CPMenuBarWindow
@class _CPMenuView
@class CPMenuItem
@implementation _CPMenuItemMenuBarView : CPView
{
CPColor _highlightColor @accessors(property=highlightColor);
CPColor _textColor @accessors(property=textColor);
CPColor _textShadowColor @accessors(property=textShadowColor);
CPColor _highlightTextColor @accessors(property=highlightTextColor);
CPColor _highlightTextShadowColor @accessors(property=highlightTextShadowColor);
CPMenuItem _menuItem @accessors(property=menuItem);
CPFont _font;
CPColor _textColor;
CPColor _textShadowColor;
BOOL _isDirty;
BOOL _shouldHighlight;
_CPImageAndTextView _imageAndTextView;
}
@@ -50,10 +44,12 @@
return "menu-item-bar-view";
}
+ (CPDictionary)themeAttributes
+ (id)themeAttributes
{
return @{
@"horizontal-margin": 9.0,
@"menu-item-selection-color": [CPNull null],
@"menu-item-text-shadow-color": [CPNull null],
@"horizontal-margin": 12.0,
@"submenu-indicator-margin": 3.0,
@"vertical-margin": 4.0,
};
@@ -85,36 +81,12 @@
return self;
}
- (void)setTextColor:(CPColor)aColor
{
_textColor = aColor;
[self setNeedsLayout];
}
- (void)setTextShadowColor:(CPColor)aColor
{
_textShadowColor = aColor;
[self setNeedsLayout];
}
- (void)setHighlightTextColor:(CPColor)aColor
{
_highlightTextColor = aColor;
[self setNeedsLayout];
}
- (void)setHighlightTextShadowColor:(CPColor)aColor
{
_highlightTextShadowColor = aColor;
[self setNeedsLayout];
}
- (CPColor)textColor
{
if (![_menuItem isEnabled])
return [CPColor lightGrayColor];
return _textColor || [[CPTheme defaultTheme] valueForAttributeWithName:@"menu-bar-text-color" forClass:_CPMenuView];
return _textColor || [CPColor colorWithCalibratedRed:70.0 / 255.0 green:69.0 / 255.0 blue:69.0 / 255.0 alpha:1.0];
}
- (CPColor)textShadowColor
@@ -122,28 +94,7 @@
if (![_menuItem isEnabled])
return [CPColor clearColor];
return _textShadowColor || [[CPTheme defaultTheme] valueForAttributeWithName:@"menu-bar-text-shadow-color" forClass:_CPMenuView];
}
- (CPColor)highlightTextColor
{
if (![_menuItem isEnabled])
return [CPColor lightGrayColor];
return _highlightTextColor || [[CPTheme defaultTheme] valueForAttributeWithName:@"menu-bar-highlight-text-color" forClass:_CPMenuView];
}
- (CPColor)highlightTextShadowColor
{
if (![_menuItem isEnabled])
return [CPColor clearColor];
return _highlightTextShadowColor || [[CPTheme defaultTheme] valueForAttributeWithName:@"menu-bar-highlight-text-shadow-color" forClass:_CPMenuView];
}
- (CPColor)highlightColor
{
return _highlightColor || [[CPTheme defaultTheme] valueForAttributeWithName:@"menu-bar-window-background-selected-color" forClass:_CPMenuView];
return _textShadowColor || [CPColor colorWithWhite:1.0 alpha:0.8];
}
- (void)update
@@ -151,11 +102,13 @@
var x = [self valueForThemeAttribute:@"horizontal-margin"],
height = 0.0;
[_imageAndTextView setText:[_menuItem title]];
[_imageAndTextView setFont:[_menuItem font] || [_CPMenuBarWindow font]];
[_imageAndTextView setVerticalAlignment:CPCenterVerticalTextAlignment];
[_imageAndTextView setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[_imageAndTextView setImage:[_menuItem image]];
[_imageAndTextView setText:[_menuItem title]];
[_imageAndTextView setTextColor:[self textColor]];
[_imageAndTextView setTextShadowColor:[self textShadowColor]];
[_imageAndTextView setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[_imageAndTextView sizeToFit];
var imageAndTextViewFrame = [_imageAndTextView frame];
@@ -170,7 +123,6 @@
[self setAutoresizesSubviews:NO];
[self setFrameSize:CGSizeMake(x + [self valueForThemeAttribute:@"horizontal-margin"], height)];
[self setAutoresizesSubviews:YES];
[self setNeedsLayout];
}
- (void)highlight:(BOOL)shouldHighlight
@@ -179,20 +131,14 @@
if (![_menuItem isEnabled])
shouldHighlight = NO;
_shouldHighlight = shouldHighlight;
[self setNeedsLayout];
}
- (void)layoutSubviews
{
if (_shouldHighlight)
if (shouldHighlight)
{
if (![_menuItem _isMenuBarButton])
[self setBackgroundColor:[self highlightColor]];
[self setBackgroundColor:[[CPTheme defaultTheme] valueForAttributeWithName:@"menu-bar-window-background-selected-color" forClass:_CPMenuView]];
[_imageAndTextView setImage:[_menuItem alternateImage] || [_menuItem image]];
[_imageAndTextView setTextColor:[self highlightTextColor]];
[_imageAndTextView setTextShadowColor:[self highlightTextShadowColor]];
[_imageAndTextView setTextColor:[CPColor whiteColor]];
[_imageAndTextView setTextShadowColor:[self valueForThemeAttribute:@"menu-item-text-shadow-color"]];
}
else
{
+1 -9
View File
@@ -24,9 +24,6 @@
@import "CPImageView.j"
@import "_CPImageAndTextView.j"
@class CPMenuItem
@implementation _CPMenuItemStandardView : CPView
{
CPMenuItem _menuItem @accessors(property=menuItem);
@@ -48,7 +45,7 @@
return "menu-item-standard-view";
}
+ (CPDictionary)themeAttributes
+ (id)themeAttributes
{
return @{
@"submenu-indicator-color": [CPNull null],
@@ -339,11 +336,6 @@
}
}
- (BOOL)isHighlighted
{
return _highlighted;
}
@end
@implementation _CPMenuItemSubmenuIndicatorView : CPView
+3 -33
View File
@@ -26,7 +26,6 @@
@import "_CPMenuItemStandardView.j"
@import "_CPMenuItemMenuBarView.j"
@class CPMenuItem
@global CPApp
/*
@@ -35,7 +34,7 @@
@implementation _CPMenuItemView : CPView
{
CPMenuItem _menuItem;
CPView _view @accessors(property=view, readonly);
CPView _view;
CPFont _font;
CPColor _textColor;
@@ -54,7 +53,7 @@
return "menu-item-view";
}
+ (CPDictionary)themeAttributes
+ (id)themeAttributes
{
return @{};
}
@@ -113,6 +112,7 @@
_view = menuItemView;
}
}
else if ([_menuItem menu] == [CPApp mainMenu])
{
if (![_view isKindOfClass:[_CPMenuItemMenuBarView class]])
@@ -220,36 +220,6 @@
return [_menuItem isEnabled] ? (_textShadowColor ? _textShadowColor : [CPColor colorWithWhite:1.0 alpha:0.8]) : [CPColor colorWithWhite:0.8 alpha:0.8];
}
- (void)setParentMenuHighlightColor:(CPColor)aColor
{
if ([_view respondsToSelector:@selector(setHighlightColor:)])
[_view setHighlightColor:aColor];
}
- (void)setParentMenuHighlightTextColor:(CPColor)aColor
{
if ([_view respondsToSelector:@selector(setHighlightTextColor:)])
[_view setHighlightTextColor:aColor];
}
- (void)setParentMenuHighlightTextShadowColor:(CPColor)aColor
{
if ([_view respondsToSelector:@selector(setHighlightTextShadowColor:)])
[_view setHighlightTextShadowColor:aColor];
}
- (void)setParentMenuTextColor:(CPColor)aColor
{
if ([_view respondsToSelector:@selector(setTextColor:)])
[_view setTextColor:aColor];
}
- (void)setParentMenuTextShadowColor:(CPColor)aColor
{
if ([_view respondsToSelector:@selector(setTextShadowColor:)])
[_view setTextShadowColor:aColor];
}
@end
@implementation _CPMenuItemArrowView : CPView
+18 -23
View File
@@ -51,7 +51,7 @@
CPCountedSet _observedKeys;
}
+ (void)initialize
+ (id)initialize
{
if (self !== [CPObjectController class])
return;
@@ -459,13 +459,13 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
- (BOOL)isEqual:(id)anObject
{
if (self === anObject)
return YES;
if ([anObject class] === [self class])
{
if (anObject._observer === _observer && [anObject._keyPath isEqual:_keyPath] && [anObject._object isEqual:_object])
return YES;
}
if (!anObject || [anObject class] !== [self class] || anObject._observer !== _observer || anObject._keyPath !== _keyPath || anObject._object !== _object)
return NO;
return YES;
return NO;
}
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)change context:(id)context
@@ -572,7 +572,7 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
}
}
- (void)insertObject:(id)anObject atIndex:(CPUInteger)anIndex
- (void)insertObject:(id)anObject atIndex:(unsigned)anIndex
{
for (var i = 0, count = [_observationProxies count]; i < count; i++)
{
@@ -592,7 +592,7 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
[super insertObject:anObject atIndex:anIndex];
}
- (void)removeObjectAtIndex:(CPUInteger)anIndex
- (void)removeObjectAtIndex:(unsigned)anIndex
{
var currentObject = [self objectAtIndex:anIndex];
@@ -614,7 +614,7 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
[super removeObjectAtIndex:anIndex];
}
- (CPArray)objectsAtIndexes:(CPIndexSet)theIndexes
- (_CPObservableArray)objectsAtIndexes:(CPIndexSet)theIndexes
{
return [_CPObservableArray arrayWithArray:[super objectsAtIndexes:theIndexes]];
}
@@ -629,7 +629,7 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
[self removeObjectAtIndex:[self count]];
}
- (void)replaceObjectAtIndex:(CPUInteger)anIndex withObject:(id)anObject
- (void)replaceObjectAtIndex:(unsigned)anIndex withObject:(id)anObject
{
var currentObject = [self objectAtIndex:anIndex];
@@ -749,7 +749,7 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
- (void)setValue:(id)theValue forKey:(CPString)theKeyPath
{
[self setValue:theValue forKeyPath:theKeyPath];
[self setValue:theKeyPath forKeyPath:theKeyPath];
}
- (unsigned)count
@@ -808,20 +808,15 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
- (void)removeObserver:(id)anObject forKeyPath:(CPString)aKeyPath
{
[_observationProxies enumerateObjectsUsingBlock:function(aProxy, idx, stop)
{
if (aProxy._object === self && aProxy._keyPath == aKeyPath && aProxy._observer === anObject)
{
var observedObjects = _observedObjectsByKeyPath[aKeyPath];
var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObject object:self],
index = [_observationProxies indexOfObject:proxy];
[observedObjects removeObserver:aProxy forKeyPath:aKeyPath];
[_observationProxies removeObjectAtIndex:idx];
var observedObjects = _observedObjectsByKeyPath[aKeyPath];
[observedObjects removeObserver:[_observationProxies objectAtIndex:index] forKeyPath:aKeyPath];
_observedObjectsByKeyPath[aKeyPath] = nil;
[_observationProxies removeObjectAtIndex:index];
stop(YES);
}
}];
_observedObjectsByKeyPath[aKeyPath] = nil;
}
@end
+371 -576
View File
File diff suppressed because it is too large Load Diff
+2 -23
View File
@@ -22,13 +22,10 @@
@import "CPWindow.j"
@global CPApp
CPOKButton = 1;
CPCancelButton = 0;
CPDocModalWindowMask = 1 << 6;
/*!
@ingroup appkit
@class CPPanel
@@ -54,6 +51,8 @@ CPDocModalWindowMask = 1 << 6;
@global
@class CPWindow
*/
CPDocModalWindowMask = 1 << 6;
@implementation CPPanel : CPWindow
{
BOOL _becomesKeyOnlyIfNeeded;
@@ -120,24 +119,4 @@ CPDocModalWindowMask = 1 << 6;
return YES;
}
#pragma mark -
#pragma mark Overrides
/*!
@ignore
*/
- (void)cancelOperation:(id)sender
{
if ([[CPApp currentEvent] _couldBeKeyEquivalent] && [self performKeyEquivalent:[CPApp currentEvent]])
return;
[[self firstResponder] tryToPerform:@selector(cancel:) with:self];
}
- (void)cancel:(id)sender
{
[self performClose:sender];
}
@end
+5 -15
View File
@@ -26,9 +26,6 @@
@import <Foundation/CPDictionary.j>
@import <Foundation/CPPropertyListSerialization.j>
@class CPWebScriptObject
@typedef DataTransfer
CPGeneralPboard = @"CPGeneralPboard";
CPFontPboard = @"CPFontPboard";
@@ -69,7 +66,7 @@ var CPPasteboards = nil,
unsigned _changeCount;
CPString _stateUID;
CPWebScriptObject _nativePasteboard;
WebScriptObject _nativePasteboard;
}
/*
@@ -194,12 +191,10 @@ var CPPasteboards = nil,
_owners = @{};
_provided = @{};
if (anOwner)
{
var count = _types.length;
while (count--)
[_owners setObject:anOwner forKey:_types[count]];
}
var count = _types.length;
while (count--)
[_owners setObject:anOwner forKey:_types[count]];
if (_nativePasteboard && shouldUpdate)
{
@@ -210,7 +205,6 @@ var CPPasteboards = nil,
_nativePasteboard.declareTypes_(nativeTypes);
_changeCount = _nativePasteboard.changeCount();
}
return ++_changeCount;
}
@@ -249,10 +243,6 @@ var CPPasteboards = nil,
*/
- (void)setString:(CPString)aString forType:(CPString)aType
{
// Putting a non-string on the string pasteboard can lead to strange crashes.
if (aString && aString.isa && ![aString isKindOfClass:CPString])
[CPException raise:CPInvalidArgumentException reason:"CPPasteboard setString:forType: must be called with a string."];
[self setPropertyList:aString forType:aType];
}
+38 -26
View File
@@ -26,6 +26,8 @@
@import "CPMenu.j"
@import "CPMenuItem.j"
var VISIBLE_MARGIN = 7.0;
CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
/*!
@@ -277,7 +279,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
Selects the item at the specified index
@param anIndex the index of the item to select
*/
- (void)setObjectValue:(id)anIndex
- (void)setObjectValue:(int)anIndex
{
var indexOfSelectedItem = [self objectValue];
@@ -342,7 +344,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
Returns the item at the specified index or \c nil if the item does not exist.
@param anIndex the index of the item to obtain
*/
- (CPMenuItem)itemAtIndex:(CPUInteger)anIndex
- (CPMenuItem)itemAtIndex:(unsigned)anIndex
{
return [[self menu] itemAtIndex:anIndex];
}
@@ -351,7 +353,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
Returns the title of the item at the specified index or \c nil if no item exists.
@param anIndex the index of the item
*/
- (CPString)itemTitleAtIndex:(CPUInteger)anIndex
- (CPString)itemTitleAtIndex:(unsigned)anIndex
{
return [[[self menu] itemAtIndex:anIndex] title];
}
@@ -665,15 +667,10 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
if (![self isEnabled] || ![self numberOfItems])
return;
var menu = [self menu];
// Don't reopen the menu based on the same click which caused it to close, e.g. a click on this button.
if (menu._lastCloseEvent === anEvent)
return;
[self highlight:YES];
var bounds = [self bounds],
var menu = [self menu],
bounds = [self bounds],
minimumWidth = CGRectGetWidth(bounds);
// FIXME: setFont: should set the font on the menu.
@@ -771,6 +768,13 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
[[self selectedItem] setState:CPOffState];
}
- (void)_reverseSetBinding
{
[_CPPopUpButtonSelectionBinder reverseSetValueForObject:self];
[super _reverseSetBinding];
}
@end
@implementation CPPopUpButton (BindingSupport)
@@ -793,20 +797,6 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
return [super _binderClassForBinding:aBinding];
}
+ (BOOL)isBindingExclusive:(CPString)aBinding
{
return (aBinding == CPSelectedIndexBinding ||
aBinding == CPSelectedTagBinding ||
aBinding == CPSelectedValueBinding);
}
- (void)_reverseSetBinding
{
[_CPPopUpButtonSelectionBinder _reverseSetValueFromExclusiveBinderForObject:self];
[super _reverseSetBinding];
}
@end
@implementation _CPPopUpButtonContentBinder : CPBinder
@@ -843,7 +833,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
[self _setContentValuesIfNeeded:contentArray];
}
- (id)valueForBinding:(CPString)aBinding
- (void)valueForBinding:(CPString)aBinding
{
return [self _content];
}
@@ -915,7 +905,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
{
}
- (void)setValue:(CPArray)aValue forBinding:(CPString)aBinding
- (void)setValue:(id)aValue forBinding:(CPString)aBinding
{
[super _setContent:aValue];
}
@@ -936,8 +926,30 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
@end
var binderForObject = {};
@implementation _CPPopUpButtonSelectionBinder : CPBinder
{
CPString _selectionBinding @accessors;
}
- (id)initWithBinding:(CPString)aBinding name:(CPString)aName to:(id)aDestination keyPath:(CPString)aKeyPath options:(CPDictionary)options from:(id)aSource
{
self = [super initWithBinding:aBinding name:aName to:aDestination keyPath:aKeyPath options:options from:aSource];
if (self)
{
binderForObject[[aSource UID]] = self;
_selectionBinding = aName;
}
return self;
}
+ (void)reverseSetValueForObject:(id)aSource
{
var binder = binderForObject[[aSource UID]];
[binder reverseSetValueFor:[binder _selectionBinding]];
}
- (void)setPlaceholderValue:(id)aValue withMarker:(CPString)aMarker forBinding:(CPString)aBinding
+32 -85
View File
@@ -28,19 +28,8 @@
@import "CPImageView.j"
@import "CPResponder.j"
@import "CPView.j"
@import "CPViewController.j"
@import "_CPPopoverWindow.j"
@protocol CPPopoverDelegate <CPObject>
@optional
- (BOOL)popoverShouldClose:(CPPopover)aPopover;
- (void)popoverWillClose:(CPPopover)aPopover;
- (void)popoverDidClose:(CPPopover)aPopover;
- (void)popoverWillShow:(CPPopover)aPopover;
- (void)popoverDidShow:(CPPopover)aPopover;
@end
CPPopoverBehaviorApplicationDefined = 0;
CPPopoverBehaviorTransient = 1;
@@ -71,16 +60,15 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
*/
@implementation CPPopover : CPResponder
{
@outlet CPViewController _contentViewController @accessors(property=contentViewController);
@outlet id <CPPopoverDelegate> _delegate @accessors(getter=delegate);
@outlet CPViewController _contentViewController @accessors(property=contentViewController);
@outlet id _delegate @accessors(getter=delegate);
BOOL _animates @accessors(getter=animates);
int _appearance @accessors(property=appearance);
int _behavior @accessors(getter=behavior);
BOOL _animates @accessors(property=animates);
int _appearance @accessors(property=appearance);
int _behavior @accessors(getter=behavior);
_CPPopoverWindow _popoverWindow;
CPView _positioningView;
int _implementedDelegateMethods;
_CPPopoverWindow _popoverWindow;
int _implementedDelegateMethods;
}
@@ -139,6 +127,9 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
*/
- (CGSize)contentSize
{
if (![_popoverWindow isVisible])
return CGRectMakeZero();
return [[_contentViewController view] frameSize];
}
@@ -149,10 +140,7 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
*/
- (void)setContentSize:(CGSize)aSize
{
if (!_popoverWindow)
[[_contentViewController view] setFrameSize:aSize];
else
[_popoverWindow updateFrameWithSize:aSize];
[[_contentViewController view] setFrameSize:aSize];
}
/*!
@@ -165,20 +153,6 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
return [_popoverWindow isVisible];
}
/*!
Set if the popover should animate for open/close actions.
@param shouldAnimate if YES, the popover will be animated.
*/
- (void)setAnimates:(BOOL)shouldAnimate
{
if (_animates == shouldAnimate)
return;
_animates = shouldAnimate;
[_popoverWindow setAnimates:_animates];
}
/*!
Set the behavior of the CPPopover. It can be:
@@ -193,10 +167,10 @@ Set the behavior of the CPPopover. It can be:
return;
_behavior = aBehavior;
[_popoverWindow setStyleMask:[self _styleMaskForBehavior]];
[_popoverWindow setStyleMask:[self styleMaskForBehavior]];
}
- (void)setDelegate:(id <CPPopoverDelegate>)aDelegate
- (void)setDelegate:(id)aDelegate
{
if (_delegate === aDelegate)
return;
@@ -238,38 +212,33 @@ Set the behavior of the CPPopover. It can be:
if (!_contentViewController)
[CPException raise:CPInternalInconsistencyException reason:@"contentViewController must not be nil"];
// If the popover is currently closing or opening, do nothing. That is what Cocoa does.
if ([_popoverWindow isClosing] || [_popoverWindow isOpening])
// If the popover is currently closing, do nothing. That is what Cocoa does.
if ([_popoverWindow isClosing])
return;
_positioningView = positioningView;
if (_implementedDelegateMethods & CPPopoverDelegate_popover_willShow_)
[_delegate popoverWillShow:self];
if (!_popoverWindow)
_popoverWindow = [[_CPPopoverWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:[self _styleMaskForBehavior]];
{
_popoverWindow = [[_CPPopoverWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:[self styleMaskForBehavior]];
}
[_popoverWindow setPlatformWindow:[[positioningView window] platformWindow]];
[_popoverWindow setAppearance:_appearance];
[_popoverWindow setAnimates:_animates];
[_popoverWindow setDelegate:self];
[_popoverWindow setMovableByWindowBackground:NO];
[_popoverWindow setFrame:[_popoverWindow frameRectForContentRect:[[_contentViewController view] frame]]];
[_popoverWindow setContentView:[_contentViewController view]];
if (![self isShown])
[self _popoverWillShow];
[_popoverWindow positionRelativeToRect:positioningRect ofView:positioningView preferredEdge:preferredEdge];
if (![self isShown])
[self _popoverWindowDidShow];
if (!_animates && _implementedDelegateMethods & CPPopoverDelegate_popover_didShow_)
[_delegate popoverDidShow:self];
}
- (unsigned)_styleMaskForBehavior
- (unsigned)styleMaskForBehavior
{
if (_behavior == CPPopoverBehaviorApplicationDefined)
return 0;
return CPClosableOnBlurWindowMask
return (_behavior == CPPopoverBehaviorTransient) ? CPClosableOnBlurWindowMask : 0;
}
/*!
@@ -288,9 +257,9 @@ Set the behavior of the CPPopover. It can be:
if ([_popoverWindow isClosing] || ![self isShown])
return;
[self _popoverWillClose];
if (_implementedDelegateMethods & CPPopoverDelegate_popover_willClose_)
[_delegate popoverWillClose:self];
_positioningView = nil;
[_popoverWindow close];
// popoverDidClose will be sent from popoverWindowDidClose, since
@@ -311,8 +280,9 @@ Set the behavior of the CPPopover. It can be:
if ([_popoverWindow isClosing])
return;
if (![self _popoverShouldClose])
return;
if (_implementedDelegateMethods & CPPopoverDelegate_popover_shouldClose_)
if (![_delegate popoverShouldClose:self])
return;
[self _close];
}
@@ -322,7 +292,7 @@ Set the behavior of the CPPopover. It can be:
#pragma mark Delegates
/*! @ignore */
- (BOOL)_popoverWindowShouldClose
- (BOOL)popoverWindowShouldClose:(_CPPopoverWindow)aPopoverWindow
{
[self performClose:self];
@@ -333,42 +303,19 @@ Set the behavior of the CPPopover. It can be:
}
/*! @ignore */
- (void)_popoverWindowDidClose
- (void)popoverWindowDidClose:(_CPPopoverWindow)aPopoverWindow
{
if (_implementedDelegateMethods & CPPopoverDelegate_popover_didClose_)
[_delegate popoverDidClose:self];
}
/*! @ignore */
- (void)_popoverWindowDidShow
- (void)popoverWindowDidShow:(_CPPopoverWindow)aPopoverWindow
{
if (_implementedDelegateMethods & CPPopoverDelegate_popover_didShow_)
[_delegate popoverDidShow:self];
}
/*! @ignore */
- (BOOL)_popoverShouldClose
{
if (_implementedDelegateMethods & CPPopoverDelegate_popover_shouldClose_)
return [_delegate popoverShouldClose:self];
return YES;
}
/*! @ignore */
- (void)_popoverWillClose
{
if (_implementedDelegateMethods & CPPopoverDelegate_popover_willClose_)
[_delegate popoverWillClose:self];
}
/*! @ignore */
- (void)_popoverWillShow
{
if (_implementedDelegateMethods & CPPopoverDelegate_popover_willShow_)
[_delegate popoverWillShow:self];
}
@end
@implementation CPPopover (Deprecated)
+2 -58
View File
@@ -26,7 +26,6 @@
@import "CPWindow_Constants.j"
@typedef CPProgressIndicatorStyle
/*
@global
@group CPProgressIndicatorStyle
@@ -86,9 +85,6 @@ var CPProgressIndicatorSpinningStyleColors = [];
@"spinning-mini-gif": [CPNull null],
@"spinning-small-gif": [CPNull null],
@"spinning-regular-gif": [CPNull null],
@"circular-border-color": [CPNull null],
@"circular-border-size": 1,
@"circular-color": [CPNull null]
};
}
@@ -371,12 +367,11 @@ var CPProgressIndicatorSpinningStyleColors = [];
- (void)drawBar
{
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
- (CPView)createEphemeralSubviewNamed:(CPString)aName
{
return [[CPView alloc] initWithFrame:CGRectMakeZero()];
return [[CPView alloc] initWithFrame:_CGRectMakeZero()];
}
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aViewName
@@ -392,7 +387,7 @@ var CPProgressIndicatorSpinningStyleColors = [];
if (_indeterminate)
barWidth = width;
return CGRectMake(0, 0, barWidth, [self valueForThemeAttribute:@"default-height"]);
return _CGRectMake(0, 0, barWidth, [self valueForThemeAttribute:@"default-height"]);
}
return nil;
@@ -417,9 +412,6 @@ var CPProgressIndicatorSpinningStyleColors = [];
{
if (_style == CPProgressIndicatorSpinningStyle)
{
if (!_indeterminate)
return;
// This will cause the bar view to go away due to having a nil rect when _style == CPProgressIndicatorSpinningStyle.
[self layoutEphemeralSubviewNamed:"bar-view"
positioned:CPWindowBelow
@@ -445,54 +437,6 @@ var CPProgressIndicatorSpinningStyleColors = [];
[self setBackgroundColor:nil];
}
- (void)drawRect:(CGRect)aRect
{
if (_style == CPProgressIndicatorSpinningStyle && !_indeterminate)
{
var context = [[CPGraphicsContext currentContext] graphicsPort],
rect = CGRectMakeCopy(aRect),
borderSize = [self currentValueForThemeAttribute:@"circular-border-size"];
rect.origin.x += borderSize;
rect.origin.y += borderSize;
rect.size.width = rect.size.width - borderSize * 2;
rect.size.height = rect.size.height - borderSize * 2;
if ([self doubleValue] > [self minValue] && [self doubleValue] < [self maxValue])
{
var midX = CGRectGetMidX(rect),
midY = CGRectGetMidY(rect),
endAngle = Math.PI * 2 * (([self doubleValue] - [self minValue]) / ([self maxValue] - [self minValue])) - Math.PI / 2,
radius = MIN(rect.size.width / 2, rect.size.height / 2)
CGContextBeginPath(context);
CGContextSetLineWidth(context, borderSize);
CGContextSetFillColor(context, [self currentValueForThemeAttribute:@"circular-color"])
CGContextMoveToPoint(context, midX, midY);
CGContextAddArc(context, midX, midY, radius, 3 * Math.PI / 2, endAngle, YES)
CGContextAddLineToPoint(context, midX, midY);
CGContextClosePath(context);
CGContextFillPath(context);
CGContextStrokePath(context);
}
else if ([self doubleValue] == [self maxValue])
{
CGContextBeginPath(context);
CGContextSetFillColor(context, [self currentValueForThemeAttribute:@"circular-color"])
CGContextAddEllipseInRect(context, rect);
CGContextClosePath(context);
CGContextFillPath(context);
}
CGContextBeginPath(context);
CGContextSetStrokeColor(context , [self currentValueForThemeAttribute:@"circular-border-color"]);
CGContextSetLineWidth(context, borderSize);
CGContextAddEllipseInRect(context, rect);
CGContextClosePath(context);
CGContextStrokePath(context);
}
}
@end
+30 -15
View File
@@ -25,11 +25,8 @@
@import "CPButton.j"
@class CPRadioGroup
@global CPApp
CPRadioImageOffset = 4.0;
/*!
@ingroup appkit
@@ -68,6 +65,9 @@ CPRadioImageOffset = 4.0;
option.
*/
CPRadioImageOffset = 4.0;
@implementation CPRadio : CPButton
{
CPRadioGroup _radioGroup;
@@ -152,7 +152,7 @@ CPRadioImageOffset = 4.0;
[_radioGroup _setSelectedRadio:self];
}
- (BOOL)sendAction:(SEL)anAction to:(id)anObject
- (void)sendAction:(SEL)anAction to:(id)anObject
{
[super sendAction:anAction to:anObject];
@@ -267,9 +267,9 @@ var CPRadioRadioGroupKey = @"CPRadioRadioGroupKey";
- (BOOL)selectRadioWithTag:(int)tag
{
var index = [_radios indexOfObjectPassingTest:function(radio)
{
return [radio tag] === tag;
}];
{
return [radio tag] === tag;
}];
if (index !== CPNotFound)
{
@@ -356,7 +356,7 @@ var CPRadioRadioGroupKey = @"CPRadioRadioGroupKey";
[_selectedRadio setState:CPOffState];
_selectedRadio = aRadio;
[_CPRadioGroupSelectionBinder _reverseSetValueFromExclusiveBinderForObject:self];
[_CPRadioGroupSelectionBinder reverseSetValueForObject:self];
}
@end
@@ -407,17 +407,32 @@ var CPRadioGroupRadiosKey = @"CPRadioGroupRadiosKey",
return [super _binderClassForBinding:aBinding];
}
+ (BOOL)isBindingExclusive:(CPString)aBinding
{
return (aBinding == CPSelectedIndexBinding ||
aBinding == CPSelectedTagBinding ||
aBinding == CPSelectedValueBinding);
}
@end
var binderForObject = {};
@implementation _CPRadioGroupSelectionBinder : CPBinder
{
CPString _selectionBinding @accessors;
}
- (id)initWithBinding:(CPString)aBinding name:(CPString)aName to:(id)aDestination keyPath:(CPString)aKeyPath options:(CPDictionary)options from:(id)aSource
{
self = [super initWithBinding:aBinding name:aName to:aDestination keyPath:aKeyPath options:options from:aSource];
if (self)
{
binderForObject[[aSource UID]] = self;
_selectionBinding = aName;
}
return self;
}
+ (void)reverseSetValueForObject:(id)aSource
{
var binder = binderForObject[[aSource UID]];
[binder reverseSetValueFor:[binder _selectionBinding]];
}
- (void)setPlaceholderValue:(id)aValue withMarker:(CPString)aMarker forBinding:(CPString)aBinding
+1 -15
View File
@@ -24,10 +24,8 @@
@import <Foundation/CPObjJRuntime.j>
@import "CPEvent.j"
@import "CPCursor.j"
@class CPKeyBinding
@class CPMenu
CPDeleteKeyCode = 8;
CPTabKeyCode = 9;
@@ -201,18 +199,6 @@ CPDeleteForwardKeyCode = 46;
[_nextResponder performSelector:_cmd withObject:anEvent];
}
/*!
Notifies the receiver that the mouse entered the receiver's area and that it can adapt the cursor.
@param anEvent contains information about the exit
*/
- (void)cursorUpdate:(CPEvent)anEvent
{
if (_nextResponder)
[_nextResponder performSelector:_cmd withObject:anEvent];
else
[[CPCursor arrowCursor] set];
}
/*!
Notifies the receiver that the mouse scroll wheel has moved.
@param anEvent information about the scroll
@@ -370,7 +356,7 @@ CPDeleteForwardKeyCode = 46;
var CPResponderNextResponderKey = @"CPResponderNextResponderKey",
CPResponderMenuKey = @"CPResponderMenuKey";
@implementation CPResponder (CPCoding) <CPCoding>
@implementation CPResponder (CPCoding)
/*!
Initializes the responder with data from a coder.
+5 -5
View File
@@ -484,7 +484,7 @@
#pragma mark RuleEditor delegate methods
- (int)_queryNumberOfChildrenOfItem:(id)rowItem withRowType:(CPRuleEditorRowType)type
- (int)_queryNumberOfChildrenOfItem:(id)rowItem withRowType:(int)type
{
if (rowItem == nil)
{
@@ -494,7 +494,7 @@
return [[rowItem children] count];
}
- (id)_queryChild:(int)childIndex ofItem:(id)rowItem withRowType:(CPRuleEditorRowType)type
- (id)_queryChild:(int)childIndex ofItem:(id)rowItem withRowType:(int)type
{
if (rowItem == nil)
{
@@ -505,7 +505,7 @@
return [[rowItem children] objectAtIndex:childIndex];
}
- (id)_queryValueForItem:(id)rowItem inRow:(CPInteger)rowIndex
- (id)_queryValueForItem:(id)rowItem inRow:(int)rowIndex
{
return [rowItem displayValue];
}
@@ -516,7 +516,7 @@ var CPPredicateTemplatesKey = @"CPPredicateTemplates";
@implementation CPPredicateEditor (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
- (id)initWithCoder:(id)aCoder
{
self = [super initWithCoder:aCoder];
@@ -531,7 +531,7 @@ var CPPredicateTemplatesKey = @"CPPredicateTemplates";
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
- (void)encodeWithCoder:(id)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_allTemplates forKey:CPPredicateTemplatesKey];
@@ -27,7 +27,8 @@
@import "CPMenuItem.j"
@import "CPTextField.j"
@import "CPDatePicker.j"
// NOTE: CPDatePicker is not implemented yet
@class CPDatePicker
CPUndefinedAttributeType = 0;
@@ -487,36 +488,7 @@ CPTransformableAttributeType = 1800;
- (id)copy
{
var views = [CPArray array],
copy = [[[self class] alloc] init];
[copy _setTemplateType:_templateType];
[copy _setOptions:_predicateOptions];
[copy _setModifier:_predicateModifier];
[copy _setLeftAttributeType:_leftAttributeType];
[copy _setRightAttributeType:_rightAttributeType];
[copy setLeftIsWildcard:_leftIsWildcard];
[copy setRightIsWildcard:_rightIsWildcard];
[_views enumerateObjectsUsingBlock:function(aView, idx, stop)
{
var vcopy;
if ([aView implementsSelector:@selector(copy)])
{
vcopy = [aView copy];
}
else
{
vcopy = [CPKeyedUnarchiver unarchiveObjectWithData:[CPKeyedArchiver archivedDataWithRootObject:aView]];
}
[views addObject:vcopy];
}];
[copy setTemplateViews:views];
return copy;
return [CPKeyedUnarchiver unarchiveObjectWithData:[CPKeyedArchiver archivedDataWithRootObject:self]];
}
+ (id)_operatorsForAttributeType:(CPAttributeType)attributeType
@@ -708,10 +680,7 @@ CPTransformableAttributeType = 1800;
view = [[CPCheckBox alloc] initWithFrame:CGRectMake(0, 0, 50, 26)];
}
else if (attributeType == CPDateAttributeType)
{
view = [[CPDatePicker alloc] initWithFrame:CGRectMake(0, 0, 180, 26)];
[view setDatePickerElements:CPYearMonthDayDatePickerElementFlag];
}
view = [[CPDatePicker alloc] initWithFrame:CGRectMake(0, 0, 150, 26)];
else
return nil;
@@ -733,12 +702,12 @@ CPTransformableAttributeType = 1800;
return textField;
}
- (void)_setOptions:(unsigned)options
- (void)_setOptions:(unsigned int)options
{
_predicateOptions = options;
}
- (void)_setModifier:(unsigned)modifier
- (void)_setModifier:(unsigned int)modifier
{
_predicateModifier = modifier;
}
@@ -828,31 +797,5 @@ var CPPredicateTemplateTypeKey = @"CPPredicateTemplateType",
[coder encodeObject:_views forKey:CPPredicateTemplateViewsKey];
}
@end
// Copy support for built-in types
@implementation CPDatePicker (CPCopying)
- (id)copy
{
var ret = [[[self class] alloc] initWithFrame:[self frame]];
[ret setTextFont:[self textFont]];
[ret setMinDate:[self minDate]];
[ret setMaxDate:[self maxDate]];
[ret setTimeInterval:[self timeInterval]];
[ret setDatePickerMode:[self datePickerMode]];
[ret setDatePickerElements:[self datePickerElements]];
[ret setDatePickerStyle:[self datePickerStyle]];
[ret setLocale:[self locale]];
[ret setDateValue:[self dateValue]];
[ret setBackgroundColor:[self backgroundColor]];
[ret setDrawsBackground:[self drawsBackground]];
[ret setBordered:[self isBordered]];
[ret _init];
return ret;
}
@end
/*! @endcond */
+70 -139
View File
@@ -41,21 +41,6 @@
@global CPCaseInsensitivePredicateOption
@global CPOrPredicateType
@protocol CPRuleEditorDelegate <CPObject>
@required
- (id)ruleEditor:(CPRuleEditor)editor child:(CPInteger)index forCriterion:(id)criterion withRowType:(CPRuleEditorRowType)rowType;
- (id)ruleEditor:(CPRuleEditor)editor displayValueForCriterion:(id)criterion inRow:(CPInteger)row;
- (CPInteger)ruleEditor:(CPRuleEditor)editor numberOfChildrenForCriterion:(id)criterion withRowType:(CPRuleEditorRowType)rowType;
@optional
- (CPDictionary)ruleEditor:(CPRuleEditor)editor predicatePartsForCriterion:(id)criterion withDisplayValue:(id)value inRow:(CPInteger)row;
- (void)ruleEditorRowsDidChange:(CPNotification)notification;
@end
var CPRuleEditorDelegate_ruleEditor_predicatePartsForCriterion_withDisplayValue_inRow_ = 1 << 1;
var CPRuleEditorItemPBoardType = @"CPRuleEditorItemPBoardType",
itemsContext = "items",
valuesContext = "values",
@@ -84,51 +69,50 @@ var CPRuleEditorItemPBoardType = @"CPRuleEditorItemPBoardType",
@implementation CPRuleEditor : CPControl
{
BOOL _suppressKeyDownHandling;
BOOL _allowsEmptyCompoundRows;
BOOL _disallowEmpty;
BOOL _delegateWantsValidation;
BOOL _editable;
BOOL _sendAction;
BOOL _suppressKeyDownHandling;
BOOL _allowsEmptyCompoundRows;
BOOL _disallowEmpty;
BOOL _delegateWantsValidation;
BOOL _editable;
BOOL _sendAction;
Class _rowClass;
Class _rowClass;
CPIndexSet _draggingRows;
CPInteger _subviewIndexOfDropLine;
CPView _dropLineView;
CPIndexSet _draggingRows;
CPInteger _subviewIndexOfDropLine;
CPView _dropLineView;
CPMutableArray _rowCache;
CPMutableArray _slices;
CPMutableArray _rowCache;
CPMutableArray _slices;
CPPredicate _predicate;
CPPredicate _predicate;
CPString _itemsKeyPath;
CPString _subrowsArrayKeyPath;
CPString _typeKeyPath;
CPString _valuesKeyPath;
CPString _boundArrayKeyPath @accessors(property=boundArrayKeyPath);
CPString _itemsKeyPath;
CPString _subrowsArrayKeyPath;
CPString _typeKeyPath;
CPString _valuesKeyPath;
CPString _boundArrayKeyPath @accessors(property=boundArrayKeyPath);
CPView _slicesHolder;
CPViewAnimation _currentAnimation;
CPView _slicesHolder;
CPViewAnimation _currentAnimation;
CPInteger _lastRow;
CPInteger _nestingMode;
CPInteger _lastRow;
CPInteger _nestingMode;
float _alignmentGridWidth;
float _sliceHeight;
float _alignmentGridWidth;
float _sliceHeight;
id _ruleDataSource;
id <CPRuleEditorDelegate> _ruleDelegate;
id _boundArrayOwner;
unsigned _implementedDelegateMethods;
id _ruleDataSource;
id _ruleDelegate;
id _boundArrayOwner;
CPString _stringsFilename;
CPString _stringsFilename;
BOOL _isKeyDown;
BOOL _nestingModeDidChange;
BOOL _isKeyDown;
BOOL _nestingModeDidChange;
_CPRuleEditorLocalizer _standardLocalizer @accessors(property=standardLocalizer);
CPDictionary _itemsAndValuesToAddForRowType;
_CPRuleEditorLocalizer _standardLocalizer @accessors(property=standardLocalizer);
CPDictionary _itemsAndValuesToAddForRowType;
}
/*! @cond */
@@ -138,7 +122,7 @@ var CPRuleEditorItemPBoardType = @"CPRuleEditorItemPBoardType",
return @"rule-editor";
}
+ (CPDictionary)themeAttributes
+ (id)themeAttributes
{
return @{
@"alternating-row-colors": [CPNull null],
@@ -147,10 +131,8 @@ var CPRuleEditorItemPBoardType = @"CPRuleEditorItemPBoardType",
@"slice-bottom-border-color": [CPNull null],
@"slice-last-bottom-border-color": [CPNull null],
@"font": [CPNull null],
@"font-color": [CPNull null],
@"add-image": [CPNull null],
@"remove-image": [CPNull null],
@"vertical-alignment": [CPNull null]
};
}
@@ -161,7 +143,7 @@ var CPRuleEditorItemPBoardType = @"CPRuleEditorItemPBoardType",
{
_slices = [[CPMutableArray alloc] init];
_sliceHeight = 26.0;
_sliceHeight = 26.;
_nestingMode = CPRuleEditorNestingModeSimple; // 10.5 default is CPRuleEditorNestingModeCompound
_editable = YES;
_allowsEmptyCompoundRows = NO;
@@ -231,24 +213,19 @@ var CPRuleEditorItemPBoardType = @"CPRuleEditorItemPBoardType",
@discussion CPRuleEditor requires a delegate that implements the required delegate methods to function.
@see delegate
*/
- (void)setDelegate:(id <CPRuleEditorDelegate>)aDelegate
- (void)setDelegate:(id)aDelegate
{
if (_ruleDelegate === aDelegate)
return;
var nc = [CPNotificationCenter defaultCenter];
if (_ruleDelegate)
[nc removeObserver:_ruleDelegate name:nil object:self];
_ruleDelegate = aDelegate;
_implementedDelegateMethods = 0;
if ([_ruleDelegate respondsToSelector:@selector(ruleEditorRowsDidChange:)])
[nc addObserver:_ruleDelegate selector:@selector(ruleEditorRowsDidChange:) name:CPRuleEditorRowsDidChangeNotification object:nil];
if ([_ruleDelegate respondsToSelector:@selector(ruleEditor:predicatePartsForCriterion:withDisplayValue:inRow:)])
_implementedDelegateMethods |= CPRuleEditorDelegate_ruleEditor_predicatePartsForCriterion_withDisplayValue_inRow_;
}
/*!
@brief Returns a Boolean value that indicates whether the receiver is editable.
@@ -484,7 +461,7 @@ var CPRuleEditorItemPBoardType = @"CPRuleEditorItemPBoardType",
@param row The index of a row in the receiver.
@return The currently chosen items for row @a row.
*/
- (id)criteriaForRow:(CPInteger)row
- (id)criteriaForRow:(int)row
{
var rowcache = [self _rowCacheForIndex:row];
if (rowcache)
@@ -503,7 +480,7 @@ var CPRuleEditorItemPBoardType = @"CPRuleEditorItemPBoardType",
@return The chosen values (strings, views, or menu items) for row row.
@discussion The values returned are the same as those returned from the delegate method -#ruleEditor:displayValueForCriterion:inRow:
*/
- (CPMutableArray)displayValuesForRow:(CPInteger)row
- (CPMutableArray)displayValuesForRow:(int)row
{
var rowcache = [self _rowCacheForIndex:row];
if (rowcache)
@@ -526,7 +503,7 @@ var CPRuleEditorItemPBoardType = @"CPRuleEditorItemPBoardType",
@param rowIndex The index of a row in the receiver.
@return The index of the parent of the row at @a rowIndex. If the row at @a rowIndex is a root row, returns @c -1.
*/
- (int)parentRowForRow:(CPInteger)rowIndex
- (int)parentRowForRow:(int)rowIndex
{
if (rowIndex < 0 || rowIndex >= [self numberOfRows])
[CPException raise:CPRangeException reason:_cmd + @" row " + rowIndex + " is out of range"];
@@ -567,7 +544,7 @@ TODO: implement
@return The type of the row at @a rowIndex.
@warning Raises a @c CPRangeException if rowIndex is less than @c 0 or greater than or equal to the number of rows.
*/
- (CPRuleEditorRowType)rowTypeForRow:(CPInteger)rowIndex
- (CPRuleEditorRowType)rowTypeForRow:(int)rowIndex
{
if (rowIndex < 0 || rowIndex > [self numberOfRows])
[CPException raise:CPRangeException reason:_cmd + @"row " + rowIndex + " is out of range"];
@@ -588,7 +565,7 @@ TODO: implement
@return The immediate subrows of the row at @a rowIndex.
@discussion Rows are numbered starting at @c 0.
*/
- (CPIndexSet)subrowIndexesForRow:(CPInteger)rowIndex
- (CPIndexSet)subrowIndexesForRow:(int)rowIndex
{
var object;
@@ -714,7 +691,7 @@ TODO: implement
@note Currently, @a shouldAnimate has no effect, rows are always animated when calling this method.
@see addRow:
*/
- (void)insertRowAtIndex:(int)rowIndex withType:(unsigned int)rowType asSubrowOfRow:(CPInteger)parentRow animate:(BOOL)shouldAnimate
- (void)insertRowAtIndex:(int)rowIndex withType:(unsigned int)rowType asSubrowOfRow:(int)parentRow animate:(BOOL)shouldAnimate
{
/*
TODO: raise exceptions if parentRow is greater than or equal to rowIndex, or if rowIndex would fall amongst the children of some other parent, or if the nesting mode forbids this configuration.
@@ -833,7 +810,7 @@ TODO: implement
var item = [items objectAtIndex:i],
//var displayValue = [self _queryValueForItem:item inRow:aRow]; Ask the delegate or get cached value ?.
displayValue = [[self displayValuesForRow:aRow] objectAtIndex:i],
predpart = [self _sendDelegateRuleEditorPredicatePartsForCriterion:item withDisplayValue:displayValue inRow:aRow];
predpart = [_ruleDelegate ruleEditor:self predicatePartsForCriterion:item withDisplayValue:displayValue inRow:aRow];
if (predpart)
[predicateParts addEntriesFromDictionary:predpart];
@@ -1336,7 +1313,7 @@ TODO: implement
return [_boundArrayOwner mutableArrayValueForKey:_boundArrayKeyPath];
}
- (BOOL)_nextUnusedItems:(CPArray)items andValues:(CPArray)values forRow:(CPInteger)rowIndex forRowType:(unsigned int)type
- (BOOL)_nextUnusedItems:(CPArray)items andValues:(CPArray)values forRow:(int)rowIndex forRowType:(unsigned int)type
{
var parentItem = [items lastObject], // if empty items array, this is NULL aka the root item;
childrenCount = [self _queryNumberOfChildrenOfItem:parentItem withRowType:type],
@@ -1398,7 +1375,7 @@ TODO: implement
return YES;
}
- (CPMutableArray)_getItemsAndValuesToAddForRow:(CPInteger)rowIndex ofType:(CPRuleEditorRowType)type
- (CPMutableArray)_getItemsAndValuesToAddForRow:(int)rowIndex ofType:(CPRuleEditorRowType)type
{
//var cachedItemsAndValues = _itemsAndValuesToAddForRowType[type];
//if (cachedItemsAndValues)
@@ -1441,7 +1418,7 @@ TODO: implement
[self insertRowAtIndex:insertIndex withType:type asSubrowOfRow:parentRowIndex animate:YES];
}
- (id)_insertNewRowAtIndex:(int)insertIndex ofType:(CPRuleEditorRowType)rowtype withParentRow:(CPInteger)parentRowIndex
- (id)_insertNewRowAtIndex:(int)insertIndex ofType:(CPRuleEditorRowType)rowtype withParentRow:(int)parentRowIndex
{
var row = [[[self rowClass] alloc] init],
itemsandvalues = [self _getItemsAndValuesToAddForRow:insertIndex ofType:rowtype],
@@ -1543,7 +1520,7 @@ TODO: implement
}
}
- (void)_changedItem:(id)fromItem toItem:(id)toItem inRow:(CPInteger)aRow atCriteriaIndex:(int)fromItemIndex
- (void)_changedItem:(id)fromItem toItem:(id)toItem inRow:(int)aRow atCriteriaIndex:(int)fromItemIndex
{
var criteria = [self criteriaForRow:aRow],
displayValues = [self displayValuesForRow:aRow],
@@ -1707,7 +1684,7 @@ TODO: implement
[super bind:aBinding toObject:observableController withKeyPath:aKeyPath options:options];
}
- (void)unbind:(CPString)object
- (void)unbind:(id)object
{
_rowClass = [_CPRuleEditorRowObject class];
[super unbind:object];
@@ -1739,7 +1716,8 @@ TODO: implement
{
if (_delegateWantsValidation)
{
if (![self _delegateRespondsToRuleEditorPredicatePartsForCriterionWithDisplayValueInRow])
var selector = @selector(ruleEditor:predicatePartsForCriterion:withDisplayValue:inRow:);
if (![_ruleDelegate respondsToSelector:selector])
return;
_delegateWantsValidation = NO;
@@ -1887,34 +1865,14 @@ TODO: implement
return [self valueForThemeAttribute:@"font"];
}
- (CPColor)_fontColor
- (CPImage)_addImage
{
return [self valueForThemeAttribute:@"font-color"];
return [self valueForThemeAttribute:@"add-image"];
}
- (CPImage)_imageAdd
- (CPImage)_removeImage
{
return [self valueForThemeAttribute:@"add-image" inState:CPThemeStateNormal];
}
- (CPImage)_imageAddHighlighted
{
return [self valueForThemeAttribute:@"add-image" inState:CPThemeStateHighlighted];
}
- (CPImage)_imageRemove
{
return [self valueForThemeAttribute:@"remove-image" inState:CPThemeStateNormal];
}
- (CPImage)_imageRemoveHighlighted
{
return [self valueForThemeAttribute:@"remove-image" inState:CPThemeStateHighlighted];
}
- (CPVerticalTextAlignment)_verticalAlignment
{
return [self valueForThemeAttribute:@"vertical-alignment"];
return [self valueForThemeAttribute:@"remove-image"];
}
- (CPString)_toolTipForAddCompoundRowButton
@@ -2047,7 +2005,7 @@ TODO: implement
return [_ruleDelegate ruleEditor:self child:childIndex forCriterion:item withRowType:type];
}
- (id)_queryValueForItem:(id)item inRow:(CPInteger)row
- (id)_queryValueForItem:(id)item inRow:(int)row
{
return [_ruleDelegate ruleEditor:self displayValueForCriterion:item inRow:row];
}
@@ -2068,12 +2026,12 @@ TODO: implement
_alignmentGridWidth = width;
}
- (BOOL)_validateItem:(id)item value:(id)value inRow:(CPInteger)row
- (BOOL)_validateItem:(id)item value:(id)value inRow:(int)row
{
return [self _queryCanSelectItem:item displayValue:value inRow:row];
}
- (BOOL)_queryCanSelectItem:(id)item displayValue:(id)value inRow:(CPInteger)row
- (BOOL)_queryCanSelectItem:(id)item displayValue:(id)value inRow:(int)row
{
return YES;
}
@@ -2121,7 +2079,7 @@ TODO: implement
return;
var point = [self convertPoint:[event locationInWindow] fromView:nil],
view = [_slices objectAtIndex:FLOOR(MAX(0, point.y) / _sliceHeight)];
view = [_slices objectAtIndex:FLOOR(point.y / _sliceHeight)];
if ([self _dragShouldBeginFromMouseDown:view])
[self _performDragForSlice:view withEvent:event];
@@ -2170,7 +2128,7 @@ TODO: implement
return YES;
}
- (CPDragOperation)draggingEntered:(id /*< CPDraggingInfo >*/)sender
- (CPDragOperation)draggingEntered:(id < CPDraggingInfo >)sender
{
if ([sender draggingSource] === self)
{
@@ -2200,14 +2158,14 @@ TODO: implement
_subviewIndexOfDropLine = CPNotFound;
}
- (CPDragOperation)draggingUpdated:(id /*<CPDraggingInfo>*/)sender
- (CPDragOperation)draggingUpdated:(id <CPDraggingInfo>)sender
{
var point = [self convertPoint:[sender draggingLocation] fromView:nil],
y = point.y + _sliceHeight / 2,
indexOfDropLine = FLOOR(y / _sliceHeight),
numberOfRows = [self numberOfRows];
if (indexOfDropLine <= 0 || indexOfDropLine > numberOfRows || (indexOfDropLine >= [_draggingRows firstIndex] && indexOfDropLine <= [_draggingRows lastIndex] + 1))
if (indexOfDropLine < 0 || indexOfDropLine > numberOfRows || (indexOfDropLine >= [_draggingRows firstIndex] && indexOfDropLine <= [_draggingRows lastIndex] + 1))
{
if (_subviewIndexOfDropLine !== CPNotFound && indexOfDropLine !== _subviewIndexOfDropLine)
[self _clearDropLine];
@@ -2237,12 +2195,12 @@ TODO: implement
return CPDragOperationMove;
}
- (BOOL)prepareForDragOperation:(id /*< CPDraggingInfo >*/)sender
- (BOOL)prepareForDragOperation:(id < CPDraggingInfo >)sender
{
return (_subviewIndexOfDropLine !== CPNotFound);
}
- (BOOL)performDragOperation:(id /*< CPDraggingInfo >*/)info
- (BOOL)performDragOperation:(id < CPDraggingInfo >)info
{
var aboveInsertIndexCount = 0,
object,
@@ -2304,7 +2262,7 @@ TODO: implement
{
}
- (void)_setWindow:(CPWindow)window
- (void)_setWindow:(id)window
{
[super _setWindow:window];
}
@@ -2321,7 +2279,7 @@ TODO: implement
- (void)_postRowCountChangedNotificationOfType:(CPString)notificationName indexes:indexes
{
var userInfo = indexes === nil ? @{} : @{ "indexes": indexes };
var userInfo = @{ "indexes": indexes };
[[CPNotificationCenter defaultCenter] postNotificationName:notificationName object:self userInfo:userInfo];
}
@@ -2367,7 +2325,7 @@ TODO: implement
return YES;
}
- (void)_getAllAvailableItems:(id)items values:(id)values asChildrenOfItem:(id)parentItem inRow:(CPInteger)aRow
- (void)_getAllAvailableItems:(id)items values:(id)values asChildrenOfItem:(id)parentItem inRow:(int)aRow
{
var type,
indexofCriterion,
@@ -2419,33 +2377,6 @@ TODO: implement
@end
@implementation CPRuleEditor (CPRuleEditorDelegate)
/*!
@ignore
Check if the delegate responds to ruleEditor:predicatePartsForCriterion:withDisplayValue:inRow:
*/
- (BOOL)_delegateRespondsToRuleEditorPredicatePartsForCriterionWithDisplayValueInRow
{
return _implementedDelegateMethods & CPRuleEditorDelegate_ruleEditor_predicatePartsForCriterion_withDisplayValue_inRow_;
}
/*!
@ignore
Call delegate ruleEditor:predicatePartsForCriterion:withDisplayValue:inRow:
*/
- (CPDictionary)_sendDelegateRuleEditorPredicatePartsForCriterion:(id)criterion withDisplayValue:(id)value inRow:(CPInteger)row
{
if (!(_implementedDelegateMethods & CPRuleEditorDelegate_ruleEditor_predicatePartsForCriterion_withDisplayValue_inRow_))
return @{};
return [_ruleDelegate ruleEditor:self predicatePartsForCriterion:criterion withDisplayValue:value inRow:row];
}
@end
var CPRuleEditorAlignmentGridWidthKey = @"CPRuleEditorAlignmentGridWidth",
CPRuleEditorSliceHeightKey = @"CPRuleEditorSliceHeight",
CPRuleEditorStringsFilenameKey = @"CPRuleEditorStringsFilename",
@@ -2495,7 +2426,7 @@ var CPRuleEditorAlignmentGridWidthKey = @"CPRuleEditorAlignmentGridWidth",
return self;
}
- (void)encodeWithCoder:(CPCoder)coder
- (void)encodeWithCoder:(id)coder
{
[super encodeWithCoder:coder];
@@ -2550,7 +2481,7 @@ var CriteriaKey = @"criteria",
return "<" + [self className] + ">\nsubrows = " + [subrows description] + "\ncriteria = " + [criteria description] + "\ndisplayValues = " + [displayValues description];
}
- (id)initWithCoder:(CPCoder)coder
- (id)initWithCoder:(id)coder
{
self = [super init];
if (self !== nil)
@@ -2564,7 +2495,7 @@ var CriteriaKey = @"criteria",
return self;
}
- (void)encodeWithCoder:(CPCoder)coder
- (void)encodeWithCoder:(id)coder
{
[coder encodeObject:subrows forKey:SubrowsKey];
[coder encodeObject:criteria forKey:CriteriaKey];
@@ -2603,7 +2534,7 @@ var CPBoundArrayKey = @"CPBoundArray";
return self;
}
- (id)initWithCoder:(CPCoder)coder
- (id)initWithCoder:(id)coder
{
if (self = [super init])
boundArray = [coder decodeObjectForKey:CPBoundArrayKey];
@@ -2611,7 +2542,7 @@ var CPBoundArrayKey = @"CPBoundArray";
return self;
}
- (void)encodeWithCoder:(CPCoder)coder
- (void)encodeWithCoder:(id)coder
{
[coder encodeObject:boundArray forKey:CPBoundArrayKey];
}
@@ -20,7 +20,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
CPRuleEditorPredicateLeftExpression = "CPRuleEditorPredicateLeftExpression";
CPRuleEditorPredicateRightExpression = "CPRuleEditorPredicateRightExpression";
CPRuleEditorPredicateComparisonModifier = "CPRuleEditorPredicateComparisonModifier";
@@ -37,6 +36,5 @@ CPRuleEditorNestingModeList = 1; // Allows a single list, with no nes
CPRuleEditorNestingModeCompound = 2; // Unlimited nesting and compound rows; this is the default
CPRuleEditorNestingModeSimple = 3; // One compound row at the top with subrows beneath it, and no further nesting allowed
@typedef CPRuleEditorRowType
CPRuleEditorRowTypeSimple = 0;
CPRuleEditorRowTypeCompound = 1;
@@ -20,8 +20,6 @@
@import <Foundation/CPObject.j>
@import <Foundation/CPString.j>
@class CPPredicateEditorRowTemplate
@implementation _CPPredicateEditorTree : CPObject
{
CPPredicateEditorRowTemplate template @accessors;
@@ -0,0 +1,203 @@
/*
* Created by cacaodev@gmail.com.
* Copyright (c) 2011 Pear, Inc. All rights reserved.
*
* 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 "CPBezierPath.j"
@import "CPPopUpButton.j"
@class _CPRuleEditorViewSlice
var GRADIENT_START_COLOR = "#fcfcfc",
GRADIENT_END_COLOR = "#dfdfdf",
BORDER_COLOR = "#BDBDBD";
var GRADIENT_NORMAL,
GRADIENT_HIGHLIGHTED,
GRADIENT_PROPERTY;
if (CPBrowserIsEngine(CPWebKitBrowserEngine))
{
GRADIENT_NORMAL = "-webkit-gradient(linear, left top, left bottom, from(" + GRADIENT_START_COLOR + "), to(" + GRADIENT_END_COLOR + "))",
GRADIENT_HIGHLIGHTED = "-webkit-gradient(linear, left top, left bottom, from(" + GRADIENT_END_COLOR + "), to(" + GRADIENT_START_COLOR + "))";
GRADIENT_PROPERTY = "background";
}
else if (CPBrowserIsEngine(CPGeckoBrowserEngine))
{
GRADIENT_NORMAL = "-moz-linear-gradient(top, " + GRADIENT_START_COLOR + ", " + GRADIENT_END_COLOR + ")",
GRADIENT_HIGHLIGHTED = "-moz-linear-gradient(top, " + GRADIENT_END_COLOR + ", " + GRADIENT_START_COLOR + ")";
GRADIENT_PROPERTY = "background";
}
else if (CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
{
GRADIENT_NORMAL = "progid:DXImageTransform.Microsoft.gradient(startColorstr='" + GRADIENT_START_COLOR + "', endColorstr='" + GRADIENT_END_COLOR + "')";
GRADIENT_HIGHLIGHTED = "progid:DXImageTransform.Microsoft.gradient(startColorstr='" + GRADIENT_END_COLOR + "', endColorstr='" + GRADIENT_START_COLOR + "')";
GRADIENT_PROPERTY = "filter";
}else
{
GRADIENT_NORMAL = GRADIENT_START_COLOR;
GRADIENT_HIGHLIGHTED = GRADIENT_END_COLOR;
GRADIENT_PROPERTY = "background";
}
@implementation _CPRuleEditorPopUpButton : CPPopUpButton
{
CPInteger radius;
}
- (void)_sharedInit
{
[self setBordered:NO];
#if PLATFORM(DOM)
var style = _DOMElement.style;
style.border = "1px solid " + BORDER_COLOR;
style[GRADIENT_PROPERTY] = GRADIENT_NORMAL;
#endif
}
- (id)initWithFrame:(CGRect)aFrame
{
if (self = [super initWithFrame:aFrame])
[self _sharedInit];
return self;
}
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
[self _sharedInit];
return self;
}
- (id)hitTest:(CGPoint)point
{
if (!CGRectContainsPoint([self frame], point) || ![self sliceIsEditable])
return nil;
return self;
}
- (BOOL)sliceIsEditable
{
var superview = [self superview];
return ![superview isKindOfClass:[_CPRuleEditorViewSlice]] || [superview isEditable];
}
- (BOOL)trackMouse:(CPEvent)theEvent
{
if (![self sliceIsEditable])
return NO;
return [super trackMouse:theEvent];
}
- (CGRect)contentRectForBounds:(CGRect)bounds
{
var contentRect = [super contentRectForBounds:bounds];
contentRect.origin.x += radius;
contentRect.size.width -= 2 * radius;
return contentRect;
}
- (void)layoutSubviews
{
#if PLATFORM(DOM)
radius = FLOOR(CGRectGetHeight([self bounds]) / 2);
var style = _DOMElement.style,
radiusCSS = radius + "px";
style.borderRadius = radiusCSS;
#endif
[super layoutSubviews];
}
- (void)drawRect:(CGRect)aRect
{
var context = [[CPGraphicsContext currentContext] graphicsPort],
bounds = [self bounds],
arrow_width = FLOOR(CGRectGetHeight(bounds) / 3.5);
CGContextTranslateCTM(context, CGRectGetWidth(bounds) - radius - arrow_width, CGRectGetHeight(bounds) / 2);
var arrowsPath = [CPBezierPath bezierPath];
[arrowsPath moveToPoint:CGPointMake(0, 1)];
[arrowsPath lineToPoint:CGPointMake(arrow_width, 1)];
[arrowsPath lineToPoint:CGPointMake(arrow_width / 2, arrow_width + 1)];
[arrowsPath closePath];
CGContextSetFillColor(context, [CPColor colorWithWhite:101 / 255 alpha:1]);
[arrowsPath fill];
CGContextScaleCTM(context, 1 , -1);
[arrowsPath fill];
}
@end
@implementation _CPRuleEditorButton : CPButton
{
CPInteger radius;
}
- (void)_sharedInit
{
[self setBordered:NO];
#if PLATFORM(DOM)
var style = _DOMElement.style;
style.border = "1px solid " + BORDER_COLOR;
style[GRADIENT_PROPERTY] = GRADIENT_NORMAL;
#endif
}
- (id)initWithFrame:(CGRect)aFrame
{
if (self = [super initWithFrame:aFrame])
[self _sharedInit];
return self;
}
- (id)initWithCoder:(CPCoder)aCoder
{
self = [super initWithCoder:aCoder];
[self _sharedInit];
return self;
}
- (void)layoutSubviews
{
#if PLATFORM(DOM)
radius = FLOOR(CGRectGetHeight([self bounds]) / 2);
var style = _DOMElement.style,
radiusCSS = radius + "px";
style.borderRadius = radiusCSS;
style[GRADIENT_PROPERTY] = ([self isHighlighted]) ? GRADIENT_HIGHLIGHTED : GRADIENT_NORMAL;
#endif
[super layoutSubviews];
}
@end
+6 -7
View File
@@ -19,8 +19,6 @@
@import "CPView.j"
@class CPRuleEditor
@implementation _CPRuleEditorViewSlice : CPView
{
CPRuleEditor _ruleEditor;
@@ -29,6 +27,7 @@
CGRect _animationTargetRect @accessors(property=_animationTargetRect);
BOOL _selected @accessors(getter=_isSelected, setter=_setSelected:);
BOOL _lastSelected @accessors(getter=_isLastSelected, setter=_setLastSelected:);
CPColor _backgroundColor @accessors(property=backgroundColor);
BOOL _editable @accessors(getter=isEditable, setter=setEditable:);
}
@@ -54,17 +53,17 @@
if (select == _selected)
return;
var selector = select ? @selector(setThemeState:) : @selector(unsetThemeState:);
[[self subviews] makeObjectsPerformSelector:selector withObject:CPThemeStateSelectedDataView];
var selector = select ? @"setThemeState:" : @"unsetThemeState:";
[[self subviews] makeObjectsPerformSelector:CPSelectorFromString(selector) withObject:CPThemeStateSelectedDataView];
_selected = select;
}
- (void)drawRect:(CGRect)rect
{
var context = [[CPGraphicsContext currentContext] graphicsPort],
bounds = [self bounds],
maxX = CGRectGetWidth(bounds),
maxY = CGRectGetHeight(bounds);
bounds = [self bounds],
maxX = CGRectGetWidth(bounds),
maxY = CGRectGetHeight(bounds);
// Draw background
if ([self _isSelected])
+87 -97
View File
@@ -19,27 +19,24 @@
@import "CPRuleEditor_Constants.j"
@import "_CPRuleEditorViewSlice.j"
@import "CPButton.j"
@import "CPDatePicker.j"
@import "CPPopUpButton.j"
@import "_CPRuleEditorPopUpButton.j"
@global CPApp
@global CPMiniControlSize
@global CPSmallControlSize
var CONTROL_HEIGHT = 16.,
BUTTON_HEIGHT = 16.;
@implementation _CPRuleEditorViewSliceRow : _CPRuleEditorViewSlice
{
CPButton _addButton;
CPButton _subtractButton;
CPMutableArray _correspondingRuleItems;
CPMutableArray _ruleOptionFrames;
CPMutableArray _ruleOptionInitialViewFrames;
CPMutableArray _ruleOptionViews;
CPMutableArray _ruleOptionViews;
CPMutableArray _ruleOptionFrames;
CPMutableArray _correspondingRuleItems;
CPMutableArray _ruleOptionInitialViewFrames;
CPButton _addButton;
CPButton _subtractButton;
CPRuleEditorRowType _rowType @accessors;
CPRuleEditorRowType _plusButtonRowType;
CPRuleEditorRowType _rowType @accessors;
CPRuleEditorRowType _plusButtonRowType;
}
- (id)initWithFrame:(CGRect)frame ruleEditorView:(id)editor
@@ -52,33 +49,34 @@
- (void)_initShared
{
_correspondingRuleItems = [[CPMutableArray alloc] init];
_ruleOptionFrames = [[CPMutableArray alloc] init];
_ruleOptionInitialViewFrames = [[CPMutableArray alloc] init];
_ruleOptionViews = [[CPMutableArray alloc] init];
_editable = [_ruleEditor isEditable];
_addButton = [self _createAddRowButton];
_subtractButton = [self _createDeleteRowButton];
_correspondingRuleItems = [[CPMutableArray alloc] init];
_ruleOptionFrames = [[CPMutableArray alloc] init];
_ruleOptionInitialViewFrames = [[CPMutableArray alloc] init];
_ruleOptionViews = [[CPMutableArray alloc] init];
_editable = [_ruleEditor isEditable];
_addButton = [self _createAddRowButton];
_subtractButton = [self _createDeleteRowButton];
[_addButton setToolTip:[_ruleEditor _toolTipForAddSimpleRowButton]];
[_subtractButton setToolTip:[_ruleEditor _toolTipForDeleteRowButton]];
[_addButton setHidden:!_editable];
[_subtractButton setHidden:!_editable];
[self addSubview:_addButton];
[self addSubview:_subtractButton];
[self setAutoresizingMask:CPViewWidthSizable];
var center = [CPNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(_textDidChange:) name:CPControlTextDidChangeNotification object:nil];
}
- (CPButton)_createRowButton
{
var button = [[CPButton alloc] initWithFrame:CGRectMakeZero()];
[button setFont:[_ruleEditor font]];
[button setTextColor:[_ruleEditor _fontColor]];
var button = [[_CPRuleEditorButton alloc] initWithFrame:CGRectMakeZero()];
[button setFont:[CPFont boldFontWithName:@"Apple Symbol" size:12.0]];
[button setTextColor:[CPColor colorWithWhite:150 / 255 alpha:1]];
[button setAlignment:CPCenterTextAlignment];
[button setAutoresizingMask:CPViewMinXMargin];
[button setButtonType:CPMomentaryChangeButton];
[button setBordered:NO];
[button setHidden:!_editable];
[button setImagePosition:CPImageOnly];
return button;
@@ -88,10 +86,7 @@
{
var button = [self _createRowButton];
[button setToolTip:[_ruleEditor _toolTipForAddSimpleRowButton]];
[button setValue:[_ruleEditor _imageAdd] forThemeAttribute:@"image" inState:CPThemeStateNormal];
[button setValue:[_ruleEditor _imageAddHighlighted] forThemeAttribute:@"image" inState:CPThemeStateHighlighted];
[button setImage:[_ruleEditor _addImage]];
[button setAction:@selector(_addOption:)];
[button setTarget:self];
@@ -102,10 +97,7 @@
{
var button = [self _createRowButton];
[button setToolTip:[_ruleEditor _toolTipForDeleteRowButton]];
[button setValue:[_ruleEditor _imageRemove] forThemeAttribute:@"image" inState:CPThemeStateNormal];
[button setValue:[_ruleEditor _imageRemoveHighlighted] forThemeAttribute:@"image" inState:CPThemeStateHighlighted];
[button setImage:[_ruleEditor _removeImage]];
[button setAction:@selector(_deleteOption:)];
[button setTarget:self];
@@ -115,17 +107,20 @@
- (CPMenuItem)_createMenuItemWithTitle:(CPString )title
{
title = [[_ruleEditor standardLocalizer] localizedStringForString:title];
return [[CPMenuItem alloc] initWithTitle:title action:nil keyEquivalent:@""];
var mItem = [[CPMenuItem alloc] initWithTitle:title action:nil keyEquivalent:@""];
return mItem;
}
- (CPPopUpButton)_createPopUpButtonWithItems:(CPArray)itemsArray selectedItemIndex:(int)index
{
var title = [[itemsArray objectAtIndex:index] title],
font = [_ruleEditor font],
width = [title sizeWithFont:font].width + 35, // 35 for right arrows + margins
rect = CGRectMake(0, 0, width, [_ruleEditor rowHeight]),
popup = [[CPPopUpButton alloc] initWithFrame:rect];
var title = [[itemsArray objectAtIndex:index] title],
font = [_ruleEditor font],
width = [title sizeWithFont:font].width + 20,
rect = CGRectMake(0, 0, (width - width % 40) + 80, CONTROL_HEIGHT),
popup = [[_CPRuleEditorPopUpButton alloc] initWithFrame:rect];
[popup setTextColor:[CPColor colorWithWhite:101 / 255 alpha:1]];
[popup setValue:font forThemeAttribute:@"font"];
var count = [itemsArray count];
@@ -142,17 +137,17 @@
return [CPMenuItem separatorItem];
}
- (CPTextField)_createStaticTextFieldWithStringValue:(CPString)text
- (_CPRuleEditorTextField)_createStaticTextFieldWithStringValue:(CPString)text
{
var textField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()],
ruleEditorFont = [_ruleEditor font],
font = [CPFont fontWithName:[ruleEditorFont familyName] size:[ruleEditorFont size] + 2],
localizedText = [[_ruleEditor standardLocalizer] localizedStringForString:text],
size = [localizedText sizeWithFont:font];
var textField = [[_CPRuleEditorTextField alloc] initWithFrame:CGRectMakeZero()],
ruleEditorFont = [_ruleEditor font],
font = [CPFont fontWithName:[ruleEditorFont familyName] size:[ruleEditorFont size] + 2],
localizedText = [[_ruleEditor standardLocalizer] localizedStringForString:text],
size = [localizedText sizeWithFont:font];
[textField setFrameSize:CGSizeMake(size.width + 4, CONTROL_HEIGHT + 2)];
[textField setFrameSize:CGSizeMake(size.width + 4, [_ruleEditor rowHeight])];
[textField setValue:font forThemeAttribute:@"font"];
[textField setValue:[_ruleEditor _verticalAlignment] forThemeAttribute:@"vertical-alignment"];
[textField setStringValue:localizedText];
return textField;
@@ -164,7 +159,6 @@
[self setNeedsDisplay:YES];
var type = _plusButtonRowType;
if ([_ruleEditor nestingMode] == CPRuleEditorNestingModeCompound && ([[CPApp currentEvent] modifierFlags] & CPAlternateKeyMask))
type = CPRuleEditorRowTypeCompound;
@@ -176,12 +170,12 @@
[_ruleEditor _deleteSlice:self];
}
- (void)_ruleOptionPopupChangedAction:(CPMenuItem)sender
- (void)_ruleOptionPopupChangedAction:(CPMenuItem )sender
{
var layoutdict = [sender representedObject],
newItem = [layoutdict objectForKey:@"item"],
var layoutdict = [sender representedObject],
newItem = [layoutdict objectForKey:@"item"],
indexInCriteria = [layoutdict objectForKey:@"indexInCriteria"],
oldItem = [_correspondingRuleItems objectAtIndex:indexInCriteria];
oldItem = [_correspondingRuleItems objectAtIndex:indexInCriteria];
if (![newItem isEqual:oldItem])
{
@@ -313,16 +307,8 @@
if (ruleView != nil)
{
[ruleView setControlSize:CPSmallControlSize];
var minSize = [ruleView currentValueForThemeAttribute:@"min-size"],
frame = [ruleView frame];
// Force controls to their minimum size
frame.size.height = minSize.height;
[ruleView setFrame:frame];
[_ruleOptionViews addObject:ruleView];
var frame = [ruleView frame];
[_ruleOptionInitialViewFrames addObject:frame];
[_ruleOptionFrames addObject:frame];
@@ -345,6 +331,8 @@
var aView = [_ruleOptionViews objectAtIndex:firstResponderIndex];
[[self window] makeFirstResponder:aView]; // This is not working. bug in CPPopUpButton firstResponder ?
}
//[self setNeedsDisplay:YES];
}
- (void)_updateEnabledStateForSubviews
@@ -362,15 +350,14 @@
var optionViewOriginX,
leftHorizontalPadding,
leftButtonMinX,
rowHeight = [_ruleEditor rowHeight],
count = [_ruleOptionViews count],
sliceFrame = [self frame],
image = [_ruleEditor _imageAdd],
rowHeight = [_ruleEditor rowHeight],
count = [_ruleOptionViews count],
sliceFrame = [self frame],
buttonFrame = CGRectMake(CGRectGetWidth(sliceFrame) - [image size].width - [self _rowButtonsRightHorizontalPadding], ([_ruleEditor rowHeight] - [image size].height) / 2 - 1, [image size].width, [image size].height);
buttonFrame = CGRectMake(CGRectGetWidth(sliceFrame) - BUTTON_HEIGHT - [self _rowButtonsRightHorizontalPadding], ([_ruleEditor rowHeight] - BUTTON_HEIGHT) / 2 - 2, BUTTON_HEIGHT, BUTTON_HEIGHT);
[_addButton setFrame:buttonFrame];
buttonFrame.origin.x -= [image size].width + [self _rowButtonsInterviewHorizontalPadding];
buttonFrame.origin.x -= BUTTON_HEIGHT + [self _rowButtonsInterviewHorizontalPadding];
[_subtractButton setFrame:buttonFrame];
if (widthChanged)
@@ -385,8 +372,7 @@
var ruleOptionView = _ruleOptionViews[i],
optionFrame = _ruleOptionFrames[i];
// Use a pixel correction to align controls
optionFrame.origin.y = (rowHeight - CGRectGetHeight(optionFrame)) / 2;
optionFrame.origin.y = (rowHeight - CGRectGetHeight(optionFrame)) / 2 - 2;
if (widthChanged)
{
@@ -495,26 +481,6 @@
[self layoutSubviews];
}
- (void)_addObservers
{
if (_isObserving)
return;
[super _addObservers];
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_textDidChange:) name:CPControlTextDidChangeNotification object:nil];
}
- (void)_removeObservers
{
if (!_isObserving)
return;
[super _removeObservers];
[[CPNotificationCenter defaultCenter] removeObserver:self name:CPControlTextDidChangeNotification object:nil];
}
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
@@ -522,9 +488,8 @@
- (BOOL)_isRulePopup:(CPView)view
{
if ([view isKindOfClass:[CPPopUpButton class]])
if ([view isKindOfClass:[_CPRuleEditorPopUpButton class]])
return YES;
return NO;
}
@@ -541,3 +506,28 @@
}
@end
@implementation _CPRuleEditorTextField : CPTextField
{
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
[self setDrawsBackground:NO];
}
return self;
}
- (id)hitTest:(CGPoint)point
{
if (!CGRectContainsPoint([self frame], point))
return nil;
return [self superview];
}
@end
+2 -2
View File
@@ -43,9 +43,9 @@
- (CGRect)visibleFrame
{
#if PLATFORM(DOM)
return CGRectMake(window.screen.availLeft, window.screen.availTop, window.screen.availWidth, window.screen.availHeight);
return _CGRectMake(window.screen.availLeft, window.screen.availTop, window.screen.availWidth, window.screen.availHeight);
#else
return CGRectMakeZero();
return _CGRectMakeZero();
#endif
}
+104 -162
View File
@@ -33,59 +33,49 @@
#define SHOULD_SHOW_CORNER_VIEW() (_scrollerStyle === CPScrollerStyleLegacy && _verticalScroller && ![_verticalScroller isHidden])
@protocol CPScrollViewDelegate <CPObject>
@optional
- (void)scrollViewWillScroll:(CPScrollView)aScrollView;
- (void)scrollViewDidScroll:(CPScrollView)aScrollView;
@end
/*! @ignore */
var _isBrowserUsingOverlayScrollers = function()
var _isSystemUsingOverlayScrollers = function()
{
#if PLATFORM(DOM)
/*
Even if the system supports overlay (Lion) scrollers,
the browser (e.g. FireFox *cough*) may not.
var inner = document.createElement('p'),
outer = document.createElement('div');
To determine if the browser is using overlay scrollbars,
we put a <p> element inside a shorter <div> and set its
overflow to scroll. If the browser is using visible scrollers,
the outer div's clientWidth will less than the offsetWidth, because
clientWidth does not include scrollbars, whereas offsetWidth does.
So if clientWidth === offsetWidth, the scrollers must be overlay.
Even IE gets this right.
*/
var outer = document.createElement('div'),
inner = document.createElement('p');
inner.style.width = "100%";
inner.style.height = "200px";
// position it absolute so it doesn't affect existing DOM elements
outer.style.position = "absolute";
outer.style.top = "0px";
outer.style.left = "0px";
outer.style.visibility = "hidden";
outer.style.width = "200px";
outer.style.height = "150px";
outer.style.overflow = "scroll";
outer.style.overflow = "hidden";
outer.appendChild (inner);
inner.style.width = "100%";
inner.style.height = "200px";
outer.appendChild(inner);
document.body.appendChild (outer);
var w1 = inner.offsetWidth;
outer.style.overflow = 'scroll';
var w2 = inner.offsetWidth;
if (w1 == w2)
w2 = outer.clientWidth;
document.body.appendChild(outer);
document.body.removeChild (outer);
var usingOverlayScrollers = outer.clientWidth === outer.offsetWidth;
document.body.removeChild(outer);
return usingOverlayScrollers;
return (w1 - w2 == 0);
#else
return NO;
#endif
};
/*!
@ingroup appkit
@class CPScrollView
Used to display views that are too large for the viewing area. the CPScrollView
places scroll bars on the side of the view to allow the user to scroll and see the entire
contents of the view.
*/
var TIMER_INTERVAL = 0.2,
CPScrollViewDelegate_scrollViewWillScroll_ = 1 << 0,
CPScrollViewDelegate_scrollViewDidScroll_ = 1 << 1,
@@ -95,45 +85,38 @@ var TIMER_INTERVAL = 0.2,
var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
CPScrollerStyleGlobalChangeNotification = @"CPScrollerStyleGlobalChangeNotification";
/*!
@ingroup appkit
@class CPScrollView
Used to display views that are too large for the viewing area. the CPScrollView
places scroll bars on the side of the view to allow the user to scroll and see the entire
contents of the view.
*/
@implementation CPScrollView : CPView
{
CPClipView _contentView;
CPClipView _headerClipView;
CPView _cornerView;
CPView _bottomCornerView;
CPClipView _contentView;
CPClipView _headerClipView;
CPView _cornerView;
CPView _bottomCornerView;
id <CPScrollViewDelegate> _delegate;
CPTimer _scrollTimer;
id _delegate;
CPTimer _scrollTimer;
BOOL _hasVerticalScroller;
BOOL _hasHorizontalScroller;
BOOL _autohidesScrollers;
BOOL _hasVerticalScroller;
BOOL _hasHorizontalScroller;
BOOL _autohidesScrollers;
CPScroller _verticalScroller;
CPScroller _horizontalScroller;
CPScroller _verticalScroller;
CPScroller _horizontalScroller;
CPInteger _recursionCount;
CPInteger _implementedDelegateMethods;
CPInteger _recursionCount;
CPInteger _implementedDelegateMethods;
float _verticalLineScroll;
float _verticalPageScroll;
float _horizontalLineScroll;
float _horizontalPageScroll;
float _verticalLineScroll;
float _verticalPageScroll;
float _horizontalLineScroll;
float _horizontalPageScroll;
CPBorderType _borderType;
CPBorderType _borderType;
CPTimer _timerScrollersHide;
CPTimer _timerScrollersHide;
int _scrollerStyle;
int _scrollerKnobStyle;
int _scrollerStyle;
int _scrollerKnobStyle;
}
@@ -147,8 +130,8 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
var globalValue = [[CPBundle mainBundle] objectForInfoDictionaryKey:@"CPScrollersGlobalStyle"];
if (globalValue === nil || globalValue === -1)
CPScrollerStyleGlobal = _isBrowserUsingOverlayScrollers() ? CPScrollerStyleOverlay : CPScrollerStyleLegacy
if (globalValue == nil || globalValue == -1)
CPScrollerStyleGlobal = _isSystemUsingOverlayScrollers() ? CPScrollerStyleOverlay : CPScrollerStyleLegacy
else
CPScrollerStyleGlobal = globalValue;
}
@@ -168,7 +151,7 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
+ (CGSize)contentSizeForFrameSize:(CGSize)frameSize hasHorizontalScroller:(BOOL)hFlag hasVerticalScroller:(BOOL)vFlag borderType:(CPBorderType)borderType
{
var bounds = [self _insetBounds:CGRectMake(0.0, 0.0, frameSize.width, frameSize.height) borderType:borderType],
var bounds = [self _insetBounds:_CGRectMake(0.0, 0.0, frameSize.width, frameSize.height) borderType:borderType],
scrollerWidth = [CPScroller scrollerWidth];
if (hFlag)
@@ -182,10 +165,10 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
+ (CGSize)frameSizeForContentSize:(CGSize)contentSize hasHorizontalScroller:(BOOL)hFlag hasVerticalScroller:(BOOL)vFlag borderType:(CPBorderType)borderType
{
var bounds = [self _insetBounds:CGRectMake(0.0, 0.0, contentSize.width, contentSize.height) borderType:borderType],
var bounds = [self _insetBounds:_CGRectMake(0.0, 0.0, contentSize.width, contentSize.height) borderType:borderType],
widthInset = contentSize.width - bounds.size.width,
heightInset = contentSize.height - bounds.size.height,
frameSize = CGSizeMake(contentSize.width + widthInset, contentSize.height + heightInset),
frameSize = _CGSizeMake(contentSize.width + widthInset, contentSize.height + heightInset),
scrollerWidth = [CPScroller scrollerWidth];
if (hFlag)
@@ -203,10 +186,10 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
{
case CPLineBorder:
case CPBezelBorder:
return CGRectInset(bounds, 1.0, 1.0);
return _CGRectInset(bounds, 1.0, 1.0);
case CPGrooveBorder:
bounds = CGRectInset(bounds, 2.0, 2.0);
bounds = _CGRectInset(bounds, 2.0, 2.0);
++bounds.origin.y;
--bounds.size.height;
return bounds;
@@ -271,6 +254,11 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
_delegate = nil;
_scrollTimer = nil;
_implementedDelegateMethods = 0;
[[CPNotificationCenter defaultCenter] addObserver:self
selector:@selector(_didReceiveDefaultStyleChange:)
name:CPScrollerStyleGlobalChangeNotification
object:nil];
}
return self;
@@ -303,7 +291,7 @@ Notifies the delegate when the scroll view has finished scrolling.
@endcode
*/
- (void)setDelegate:(id <CPScrollViewDelegate>)aDelegate
- (void)setDelegate:(id)aDelegate
{
if (aDelegate === _delegate)
return;
@@ -529,8 +517,8 @@ Notifies the delegate when the scroll view has finished scrolling.
{
var bounds = [self _insetBounds];
[self setHorizontalScroller:[[CPScroller alloc] initWithFrame:CGRectMake(0.0, 0.0, MAX(CGRectGetWidth(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle] + 1), [CPScroller scrollerWidthInStyle:_scrollerStyle])]];
[[self horizontalScroller] setFrameSize:CGSizeMake(CGRectGetWidth(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle])];
[self setHorizontalScroller:[[CPScroller alloc] initWithFrame:CGRectMake(0.0, 0.0, MAX(_CGRectGetWidth(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle] + 1), [CPScroller scrollerWidthInStyle:_scrollerStyle])]];
[[self horizontalScroller] setFrameSize:CGSizeMake(_CGRectGetWidth(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle])];
}
[self reflectScrolledClipView:_contentView];
@@ -594,8 +582,8 @@ Notifies the delegate when the scroll view has finished scrolling.
{
var bounds = [self _insetBounds];
[self setVerticalScroller:[[CPScroller alloc] initWithFrame:CGRectMake(0.0, 0.0, [CPScroller scrollerWidthInStyle:_scrollerStyle], MAX(CGRectGetHeight(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle] + 1))]];
[[self verticalScroller] setFrameSize:CGSizeMake([CPScroller scrollerWidthInStyle:_scrollerStyle], CGRectGetHeight(bounds))];
[self setVerticalScroller:[[CPScroller alloc] initWithFrame:_CGRectMake(0.0, 0.0, [CPScroller scrollerWidthInStyle:_scrollerStyle], MAX(_CGRectGetHeight(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle] + 1))]];
[[self verticalScroller] setFrameSize:CGSizeMake([CPScroller scrollerWidthInStyle:_scrollerStyle], _CGRectGetHeight(bounds))];
}
[self reflectScrolledClipView:_contentView];
@@ -871,13 +859,13 @@ Notifies the delegate when the scroll view has finished scrolling.
- (CGRect)_cornerViewFrame
{
if (!_cornerView)
return CGRectMakeZero();
return _CGRectMakeZero();
var bounds = [self _insetBounds],
frame = [_cornerView frame];
frame.origin.x = CGRectGetMaxX(bounds) - CGRectGetWidth(frame);
frame.origin.y = CGRectGetMinY(bounds);
frame.origin.x = _CGRectGetMaxX(bounds) - _CGRectGetWidth(frame);
frame.origin.y = _CGRectGetMinY(bounds);
return frame;
}
@@ -888,14 +876,14 @@ Notifies the delegate when the scroll view has finished scrolling.
var headerView = [self _headerView];
if (!headerView)
return CGRectMakeZero();
return _CGRectMakeZero();
var frame = [self _insetBounds];
frame.size.height = CGRectGetHeight([headerView frame]);
frame.size.height = _CGRectGetHeight([headerView frame]);
if (SHOULD_SHOW_CORNER_VIEW())
frame.size.width -= CGRectGetWidth([self _cornerViewFrame]);
frame.size.width -= _CGRectGetWidth([self _cornerViewFrame]);
return frame;
}
@@ -936,18 +924,18 @@ Notifies the delegate when the scroll view has finished scrolling.
break;
case CPScrollerDecrementPage:
contentBounds.origin.y -= CGRectGetHeight(contentBounds) - _verticalPageScroll;
contentBounds.origin.y -= _CGRectGetHeight(contentBounds) - _verticalPageScroll;
break;
case CPScrollerIncrementPage:
contentBounds.origin.y += CGRectGetHeight(contentBounds) - _verticalPageScroll;
contentBounds.origin.y += _CGRectGetHeight(contentBounds) - _verticalPageScroll;
break;
// We want integral bounds!
case CPScrollerKnobSlot:
case CPScrollerKnob:
default:
contentBounds.origin.y = ROUND(value * (CGRectGetHeight(documentFrame) - CGRectGetHeight(contentBounds)));
contentBounds.origin.y = ROUND(value * (_CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentBounds)));
}
[self _sendDelegateMessages];
@@ -973,18 +961,18 @@ Notifies the delegate when the scroll view has finished scrolling.
break;
case CPScrollerDecrementPage:
contentBounds.origin.x -= CGRectGetWidth(contentBounds) - _horizontalPageScroll;
contentBounds.origin.x -= _CGRectGetWidth(contentBounds) - _horizontalPageScroll;
break;
case CPScrollerIncrementPage:
contentBounds.origin.x += CGRectGetWidth(contentBounds) - _horizontalPageScroll;
contentBounds.origin.x += _CGRectGetWidth(contentBounds) - _horizontalPageScroll;
break;
// We want integral bounds!
case CPScrollerKnobSlot:
case CPScrollerKnob:
default:
contentBounds.origin.x = ROUND(value * (CGRectGetWidth(documentFrame) - CGRectGetWidth(contentBounds)));
contentBounds.origin.x = ROUND(value * (_CGRectGetWidth(documentFrame) - _CGRectGetWidth(contentBounds)));
}
[self _sendDelegateMessages];
@@ -1108,7 +1096,7 @@ Notifies the delegate when the scroll view has finished scrolling.
}
[_contentView setFrame:[self _insetBounds]];
[_headerClipView setFrame:CGRectMakeZero()];
[_headerClipView setFrame:_CGRectMakeZero()];
--_recursionCount;
@@ -1118,12 +1106,12 @@ Notifies the delegate when the scroll view has finished scrolling.
var documentFrame = [documentView frame], // the size of the whole document
contentFrame = [self _insetBounds], // assume it takes up the entire size of the scrollview (no scrollers)
headerClipViewFrame = [self _headerClipViewFrame],
headerClipViewHeight = CGRectGetHeight(headerClipViewFrame);
headerClipViewHeight = _CGRectGetHeight(headerClipViewFrame);
contentFrame.origin.y += headerClipViewHeight;
contentFrame.size.height -= headerClipViewHeight;
var difference = CGSizeMake(CGRectGetWidth(documentFrame) - CGRectGetWidth(contentFrame), CGRectGetHeight(documentFrame) - CGRectGetHeight(contentFrame)),
var difference = _CGSizeMake(_CGRectGetWidth(documentFrame) - _CGRectGetWidth(contentFrame), _CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentFrame)),
verticalScrollerWidth = [CPScroller scrollerWidthInStyle:[_verticalScroller style]],
horizontalScrollerHeight = [CPScroller scrollerWidthInStyle:[_horizontalScroller style]],
hasVerticalScroll = difference.height > 0.0,
@@ -1174,18 +1162,18 @@ Notifies the delegate when the scroll view has finished scrolling.
if (shouldShowVerticalScroller)
{
var verticalScrollerY =
MAX(CGRectGetMinY(contentFrame), MAX(CGRectGetMaxY([self _cornerViewFrame]), CGRectGetMaxY(headerClipViewFrame)));
MAX(_CGRectGetMinY(contentFrame), MAX(_CGRectGetMaxY([self _cornerViewFrame]), _CGRectGetMaxY(headerClipViewFrame)));
var verticalScrollerHeight = CGRectGetMaxY(contentFrame) - verticalScrollerY;
var verticalScrollerHeight = _CGRectGetMaxY(contentFrame) - verticalScrollerY;
// Make a gap at the bottom of the vertical scroller so that the horizontal and vertical can't overlap.
if (_scrollerStyle === CPScrollerStyleOverlay && hasHorizontalScroll)
verticalScrollerHeight -= horizontalScrollerHeight;
var documentHeight = CGRectGetHeight(documentFrame);
var documentHeight = _CGRectGetHeight(documentFrame);
[_verticalScroller setFloatValue:(difference.height <= 0.0) ? 0.0 : scrollPoint.y / difference.height];
[_verticalScroller setKnobProportion:documentHeight > 0 ? CGRectGetHeight(contentFrame) / documentHeight : 1.0];
[_verticalScroller setFrame:CGRectMake(CGRectGetMaxX(contentFrame) - overlay, verticalScrollerY, verticalScrollerWidth, verticalScrollerHeight)];
[_verticalScroller setKnobProportion:documentHeight > 0 ? _CGRectGetHeight(contentFrame) / documentHeight : 1.0];
[_verticalScroller setFrame:_CGRectMake(_CGRectGetMaxX(contentFrame) - overlay, verticalScrollerY, verticalScrollerWidth, verticalScrollerHeight)];
}
else if (wasShowingVerticalScroller)
{
@@ -1195,16 +1183,16 @@ Notifies the delegate when the scroll view has finished scrolling.
if (shouldShowHorizontalScroller)
{
var horizontalScrollerWidth = CGRectGetWidth(contentFrame);
var horizontalScrollerWidth = _CGRectGetWidth(contentFrame);
// Make a gap at the bottom of the vertical scroller so that the horizontal and vertical can't overlap.
if (_scrollerStyle === CPScrollerStyleOverlay && hasVerticalScroll)
horizontalScrollerWidth -= verticalScrollerWidth;
var documentWidth = CGRectGetWidth(documentFrame);
var documentWidth = _CGRectGetWidth(documentFrame);
[_horizontalScroller setFloatValue:(difference.width <= 0.0) ? 0.0 : scrollPoint.x / difference.width];
[_horizontalScroller setKnobProportion:documentWidth > 0 ? CGRectGetWidth(contentFrame) / documentWidth : 1.0];
[_horizontalScroller setFrame:CGRectMake(CGRectGetMinX(contentFrame), CGRectGetMaxY(contentFrame) - overlay, horizontalScrollerWidth, horizontalScrollerHeight)];
[_horizontalScroller setKnobProportion:documentWidth > 0 ? _CGRectGetWidth(contentFrame) / documentWidth : 1.0];
[_horizontalScroller setFrame:_CGRectMake(_CGRectGetMinX(contentFrame), _CGRectGetMaxY(contentFrame) - overlay, horizontalScrollerWidth, horizontalScrollerHeight)];
}
else if (wasShowingHorizontalScroller)
{
@@ -1264,45 +1252,10 @@ Notifies the delegate when the scroll view has finished scrolling.
[self reflectScrolledClipView:_contentView];
}
- (CGRect)documentVisibleRect
{
return [_contentView documentVisibleRect];
}
#pragma mark -
#pragma mark Overrides
- (void)_removeObservers
{
if (!_isObserving)
return;
[[CPNotificationCenter defaultCenter] removeObserver:self
name:CPScrollerStyleGlobalChangeNotification
object:nil];
[super _removeObservers];
}
- (void)_addObservers
{
if (_isObserving)
return;
//Make sure to have the last global style for the scroller
[self _didReceiveDefaultStyleChange:nil];
[[CPNotificationCenter defaultCenter] addObserver:self
selector:@selector(_didReceiveDefaultStyleChange:)
name:CPScrollerStyleGlobalChangeNotification
object:nil];
[super _addObservers];
}
- (void)drawRect:(CGRect)aRect
{
[super drawRect:aRect];
@@ -1319,7 +1272,7 @@ Notifies the delegate when the scroll view has finished scrolling.
{
case CPLineBorder:
CGContextSetStrokeColor(context, [self currentValueForThemeAttribute:@"border-color"]);
CGContextStrokeRect(context, CGRectInset(strokeRect, 0.5, 0.5));
CGContextStrokeRect(context, _CGRectInset(strokeRect, 0.5, 0.5));
break;
case CPBezelBorder:
@@ -1337,10 +1290,10 @@ Notifies the delegate when the scroll view has finished scrolling.
- (void)_drawGrayBezelInContext:(CGContext)context bounds:(CGRect)aRect
{
var minX = CGRectGetMinX(aRect),
maxX = CGRectGetMaxX(aRect),
minY = CGRectGetMinY(aRect),
maxY = CGRectGetMaxY(aRect),
var minX = _CGRectGetMinX(aRect),
maxX = _CGRectGetMaxX(aRect),
minY = _CGRectGetMinY(aRect),
maxY = _CGRectGetMaxY(aRect),
y = minY + 0.5;
// Slightly darker line on top.
@@ -1371,10 +1324,10 @@ Notifies the delegate when the scroll view has finished scrolling.
- (void)_drawGrooveInContext:(CGContext)context bounds:(CGRect)aRect
{
var minX = CGRectGetMinX(aRect),
maxX = CGRectGetMaxX(aRect),
minY = CGRectGetMinY(aRect),
maxY = CGRectGetMaxY(aRect);
var minX = _CGRectGetMinX(aRect),
maxX = _CGRectGetMaxX(aRect),
minY = _CGRectGetMinY(aRect),
maxY = _CGRectGetMaxY(aRect);
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor colorWithWhite:159.0 / 255.0 alpha:1.0]);
@@ -1404,11 +1357,11 @@ Notifies the delegate when the scroll view has finished scrolling.
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor whiteColor]);
var rect = CGRectOffset(aRect, 1.0, 1.0);
var rect = _CGRectOffset(aRect, 1.0, 1.0);
rect.size.width -= 1.0;
rect.size.height -= 1.0;
CGContextStrokeRect(context, CGRectInset(rect, 0.5, 0.5));
CGContextStrokeRect(context, _CGRectInset(rect, 0.5, 0.5));
CGContextBeginPath(context);
CGContextSetStrokeColor(context, [CPColor colorWithWhite:192.0 / 255.0 alpha:1.0]);
@@ -1436,44 +1389,35 @@ Notifies the delegate when the scroll view has finished scrolling.
if (![_horizontalScroller isHidden] || ![_verticalScroller isHidden])
_timerScrollersHide = [CPTimer scheduledTimerWithTimeInterval:CPScrollViewFadeOutTime target:self selector:@selector(_hideScrollers:) userInfo:nil repeats:NO];
var deltaX = [anEvent scrollingDeltaX],
deltaY = [anEvent scrollingDeltaY];
if (![anEvent hasPreciseScrollingDeltas])
{
deltaX *= (_horizontalLineScroll || 1.0);
deltaY *= (_verticalLineScroll || 1.0);
}
[self _respondToScrollWheelEventWithDeltaX:deltaX deltaY:deltaY];
[self _respondToScrollWheelEventWithDeltaX:[anEvent deltaX] deltaY:[anEvent deltaY]];
}
- (void)scrollPageUp:(id)sender
{
var contentBounds = [_contentView bounds];
[self moveByOffset:CGSizeMake(0.0, -(CGRectGetHeight(contentBounds) - _verticalPageScroll))];
[self moveByOffset:CGSizeMake(0.0, -(_CGRectGetHeight(contentBounds) - _verticalPageScroll))];
}
- (void)scrollPageDown:(id)sender
{
var contentBounds = [_contentView bounds];
[self moveByOffset:CGSizeMake(0.0, CGRectGetHeight(contentBounds) - _verticalPageScroll)];
[self moveByOffset:CGSizeMake(0.0, _CGRectGetHeight(contentBounds) - _verticalPageScroll)];
}
- (void)scrollToBeginningOfDocument:(id)sender
{
[_contentView scrollToPoint:CGPointMakeZero()];
[_headerClipView scrollToPoint:CGPointMakeZero()];
[_contentView scrollToPoint:_CGPointMakeZero()];
[_headerClipView scrollToPoint:_CGPointMakeZero()];
}
- (void)scrollToEndOfDocument:(id)sender
{
var contentBounds = [_contentView bounds],
documentFrame = [[self documentView] frame],
scrollPoint = CGPointMake(0.0, CGRectGetHeight(documentFrame) - CGRectGetHeight(contentBounds));
scrollPoint = _CGPointMake(0.0, _CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentBounds));
[_contentView scrollToPoint:scrollPoint];
[_headerClipView scrollToPoint:CGPointMakeZero()];
[_headerClipView scrollToPoint:_CGPointMakeZero()];
}
- (void)moveLeft:(id)sender
@@ -1582,8 +1526,6 @@ var CPScrollViewContentViewKey = @"CPScrollViewContentView",
*/
- (void)awakeFromCib
{
[super awakeFromCib];
[self _updateScrollerStyle];
[self _updateCornerAndHeaderView];
}
+74 -46
View File
@@ -33,7 +33,6 @@
@global CPApp
// CPScroller Constants
@typedef CPScrollerPart
CPScrollerNoPart = 0;
CPScrollerDecrementPage = 1;
CPScrollerKnob = 2;
@@ -45,11 +44,15 @@ CPScrollerKnobSlot = 6;
CPScrollerIncrementArrow = 0;
CPScrollerDecrementArrow = 1;
@typedef CPUsableScrollerParts
CPNoScrollerParts = 0;
CPOnlyScrollerArrows = 1;
CPAllScrollerParts = 2;
/*!
@ingroup appkit
@class CPScroller
*/
var PARTS_ARRANGEMENT = [CPScrollerKnobSlot, CPScrollerDecrementLine, CPScrollerIncrementLine, CPScrollerKnob],
NAMES_FOR_PARTS = {},
PARTS_FOR_NAMES = {};
@@ -73,13 +76,9 @@ CPThemeStateScrollViewLegacy = CPThemeState("scroller-style-legacy");
CPThemeStateScrollerKnobLight = CPThemeState("scroller-knob-light");
CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
/*!
@ingroup appkit
@class CPScroller
*/
@implementation CPScroller : CPControl
{
CPControlSize _controlSize;
CPUsableScrollerParts _usableParts;
CPArray _partRects;
@@ -109,7 +108,7 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
return "scroller";
}
+ (CPDictionary)themeAttributes
+ (id)themeAttributes
{
return @{
@"scroller-width": 7.0,
@@ -117,11 +116,11 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
@"decrement-line-color": [CPNull null],
@"increment-line-color": [CPNull null],
@"knob-color": [CPNull null],
@"decrement-line-size": CGSizeMakeZero(),
@"increment-line-size": CGSizeMakeZero(),
@"track-inset": CGInsetMakeZero(),
@"knob-inset": CGInsetMakeZero(),
@"minimum-knob-length": 21.0,
@"decrement-line-size":_CGSizeMakeZero(),
@"increment-line-size":_CGSizeMakeZero(),
@"track-inset":_CGInsetMakeZero(),
@"knob-inset": _CGInsetMakeZero(),
@"minimum-knob-length":21.0,
@"track-border-overlay": 9.0
};
}
@@ -173,6 +172,7 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
{
if (self = [super initWithFrame:aFrame])
{
_controlSize = CPRegularControlSize;
_partRects = [];
[self setFloatValue:0.0];
@@ -182,7 +182,6 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
_allowFadingOut = YES;
_isMouseOver = NO;
_style = CPScrollerStyleOverlay;
var paramAnimFadeOut = @{
CPViewAnimationTargetKey: self,
CPViewAnimationEffectKey: CPViewAnimationFadeOutEffect,
@@ -195,7 +194,7 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
// We have to choose an orientation. If for some bizarre reason width === height,
// punt and choose vertical.
[self _setIsVertical:CGRectGetHeight(aFrame) >= CGRectGetWidth(aFrame)];
[self _setIsVertical:_CGRectGetHeight(aFrame) >= _CGRectGetWidth(aFrame)];
}
return self;
@@ -243,6 +242,29 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
[super setObjectValue:MIN(1.0, MAX(0.0, +aValue))];
}
/*!
Returns the scroller's control size
*/
- (CPControlSize)controlSize
{
return _controlSize;
}
/*!
Sets the scroller's size.
@param aControlSize the scroller's size
*/
- (void)setControlSize:(CPControlSize)aControlSize
{
if (_controlSize == aControlSize)
return;
_controlSize = aControlSize;
[self setNeedsLayout];
[self setNeedsDisplay:YES];
}
/*!
Return's the knob's proportion
*/
@@ -299,7 +321,7 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
- (CGRect)rectForPart:(CPScrollerPart)aPart
{
if (aPart == CPScrollerNoPart)
return CGRectMakeZero();
return _CGRectMakeZero();
return _partRects[aPart];
}
@@ -369,8 +391,8 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
var knobInset = [self currentValueForThemeAttribute:@"knob-inset"],
trackInset = [self currentValueForThemeAttribute:@"track-inset"],
width = CGRectGetWidth(bounds),
height = CGRectGetHeight(bounds);
width = _CGRectGetWidth(bounds),
height = _CGRectGetHeight(bounds);
if ([self isVertical])
{
@@ -384,21 +406,21 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
knobHeight = MAX(minimumKnobLength, (slotSize * _knobProportion)),
knobLocation = effectiveDecrementLineHeight + (slotSize - knobHeight) * [self floatValue];
_partRects[CPScrollerDecrementPage] = CGRectMake(0.0, effectiveDecrementLineHeight, width, knobLocation - effectiveDecrementLineHeight);
_partRects[CPScrollerKnob] = CGRectMake(knobInset.left, knobLocation, knobWidth, knobHeight);
_partRects[CPScrollerIncrementPage] = CGRectMake(0.0, knobLocation + knobHeight, width, height - (knobLocation + knobHeight) - effectiveIncrementLineHeight);
_partRects[CPScrollerKnobSlot] = CGRectMake(trackInset.left, effectiveDecrementLineHeight, width - trackInset.left - trackInset.right, slotSize);
_partRects[CPScrollerDecrementLine] = CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height);
_partRects[CPScrollerIncrementLine] = CGRectMake(0.0, height - incrementLineSize.height, incrementLineSize.width, incrementLineSize.height);
_partRects[CPScrollerDecrementPage] = _CGRectMake(0.0, effectiveDecrementLineHeight, width, knobLocation - effectiveDecrementLineHeight);
_partRects[CPScrollerKnob] = _CGRectMake(knobInset.left, knobLocation, knobWidth, knobHeight);
_partRects[CPScrollerIncrementPage] = _CGRectMake(0.0, knobLocation + knobHeight, width, height - (knobLocation + knobHeight) - effectiveIncrementLineHeight);
_partRects[CPScrollerKnobSlot] = _CGRectMake(trackInset.left, effectiveDecrementLineHeight, width - trackInset.left - trackInset.right, slotSize);
_partRects[CPScrollerDecrementLine] = _CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height);
_partRects[CPScrollerIncrementLine] = _CGRectMake(0.0, height - incrementLineSize.height, incrementLineSize.width, incrementLineSize.height);
if (height < knobHeight + decrementLineSize.height + incrementLineSize.height + trackInset.top + trackInset.bottom)
_partRects[CPScrollerKnob] = CGRectMakeZero();
_partRects[CPScrollerKnob] = _CGRectMakeZero();
if (height < decrementLineSize.height + incrementLineSize.height - 2)
{
_partRects[CPScrollerIncrementLine] = CGRectMakeZero();
_partRects[CPScrollerDecrementLine] = CGRectMakeZero();
_partRects[CPScrollerKnobSlot] = CGRectMake(trackInset.left, 0, width - trackInset.left - trackInset.right, height);
_partRects[CPScrollerIncrementLine] = _CGRectMakeZero();
_partRects[CPScrollerDecrementLine] = _CGRectMakeZero();
_partRects[CPScrollerKnobSlot] = _CGRectMake(trackInset.left, 0, width - trackInset.left - trackInset.right, height);
}
}
else
@@ -413,21 +435,21 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
knobHeight = height - knobInset.top - knobInset.bottom,
knobLocation = effectiveDecrementLineWidth + (slotSize - knobWidth) * [self floatValue];
_partRects[CPScrollerDecrementPage] = CGRectMake(effectiveDecrementLineWidth, 0.0, knobLocation - effectiveDecrementLineWidth, height);
_partRects[CPScrollerKnob] = CGRectMake(knobLocation, knobInset.top, knobWidth, knobHeight);
_partRects[CPScrollerIncrementPage] = CGRectMake(knobLocation + knobWidth, 0.0, width - (knobLocation + knobWidth) - effectiveIncrementLineWidth, height);
_partRects[CPScrollerKnobSlot] = CGRectMake(effectiveDecrementLineWidth, trackInset.top, slotSize, height - trackInset.top - trackInset.bottom);
_partRects[CPScrollerDecrementLine] = CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height);
_partRects[CPScrollerIncrementLine] = CGRectMake(width - incrementLineSize.width, 0.0, incrementLineSize.width, incrementLineSize.height);
_partRects[CPScrollerDecrementPage] = _CGRectMake(effectiveDecrementLineWidth, 0.0, knobLocation - effectiveDecrementLineWidth, height);
_partRects[CPScrollerKnob] = _CGRectMake(knobLocation, knobInset.top, knobWidth, knobHeight);
_partRects[CPScrollerIncrementPage] = _CGRectMake(knobLocation + knobWidth, 0.0, width - (knobLocation + knobWidth) - effectiveIncrementLineWidth, height);
_partRects[CPScrollerKnobSlot] = _CGRectMake(effectiveDecrementLineWidth, trackInset.top, slotSize, height - trackInset.top - trackInset.bottom);
_partRects[CPScrollerDecrementLine] = _CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height);
_partRects[CPScrollerIncrementLine] = _CGRectMake(width - incrementLineSize.width, 0.0, incrementLineSize.width, incrementLineSize.height);
if (width < knobWidth + decrementLineSize.width + incrementLineSize.width + trackInset.left + trackInset.right)
_partRects[CPScrollerKnob] = CGRectMakeZero();
_partRects[CPScrollerKnob] = _CGRectMakeZero();
if (width < decrementLineSize.width + incrementLineSize.width - 2)
{
_partRects[CPScrollerIncrementLine] = CGRectMakeZero();
_partRects[CPScrollerDecrementLine] = CGRectMakeZero();
_partRects[CPScrollerKnobSlot] = CGRectMake(0.0, 0.0, width, slotSize);
_partRects[CPScrollerIncrementLine] = _CGRectMakeZero();
_partRects[CPScrollerDecrementLine] = _CGRectMakeZero();
_partRects[CPScrollerKnobSlot] = _CGRectMake(0.0, 0.0, width, slotSize);
}
}
}
@@ -495,7 +517,7 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
- (CPView)createViewForPart:(CPScrollerPart)aPart
{
var view = [[CPView alloc] initWithFrame:CGRectMakeZero()];
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
[view setHitTests:NO];
@@ -509,7 +531,7 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
- (CPView)createEphemeralSubviewNamed:(CPString)aName
{
var view = [[CPView alloc] initWithFrame:CGRectMakeZero()];
var view = [[CPView alloc] initWithFrame:_CGRectMakeZero()];
[view setHitTests:NO];
@@ -584,7 +606,7 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
{
var knobRect = [self rectForPart:CPScrollerKnob],
knobSlotRect = [self rectForPart:CPScrollerKnobSlot],
remainder = ![self isVertical] ? (CGRectGetWidth(knobSlotRect) - CGRectGetWidth(knobRect)) : (CGRectGetHeight(knobSlotRect) - CGRectGetHeight(knobRect));
remainder = ![self isVertical] ? (_CGRectGetWidth(knobSlotRect) - _CGRectGetWidth(knobRect)) : (_CGRectGetHeight(knobSlotRect) - _CGRectGetHeight(knobRect));
if (remainder <= 0)
[self setFloatValue:0.0];
@@ -638,11 +660,11 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
else if (_trackingPart === CPScrollerDecrementPage || _trackingPart === CPScrollerIncrementPage)
{
var knobRect = [self rectForPart:CPScrollerKnob],
knobWidth = ![self isVertical] ? CGRectGetWidth(knobRect) : CGRectGetHeight(knobRect),
knobWidth = ![self isVertical] ? _CGRectGetWidth(knobRect) : _CGRectGetHeight(knobRect),
knobSlotRect = [self rectForPart:CPScrollerKnobSlot],
remainder = (![self isVertical] ? CGRectGetWidth(knobSlotRect) : CGRectGetHeight(knobSlotRect)) - knobWidth;
remainder = (![self isVertical] ? _CGRectGetWidth(knobSlotRect) : _CGRectGetHeight(knobSlotRect)) - knobWidth;
[self setFloatValue:((![self isVertical] ? _trackingStartPoint.x - CGRectGetMinX(knobSlotRect) : _trackingStartPoint.y - CGRectGetMinY(knobSlotRect)) - knobWidth / 2.0) / remainder];
[self setFloatValue:((![self isVertical] ? _trackingStartPoint.x - _CGRectGetMinX(knobSlotRect) : _trackingStartPoint.y - _CGRectGetMinY(knobSlotRect)) - knobWidth / 2.0) / remainder];
_hitPart = CPScrollerKnob;
@@ -710,7 +732,7 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
var themeState = _themeState;
if (NAMES_FOR_PARTS[_hitPart] + "-color" !== anAttributeName)
themeState = themeState.without(CPThemeStateHighlighted);
themeState &= ~CPThemeStateHighlighted;
return [self valueForThemeAttribute:anAttributeName inState:themeState];
}
@@ -779,7 +801,8 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
@end
var CPScrollerIsVerticalKey = @"CPScrollerIsVerticalKey",
var CPScrollerControlSizeKey = @"CPScrollerControlSize",
CPScrollerIsVerticalKey = @"CPScrollerIsVerticalKey",
CPScrollerKnobProportionKey = @"CPScrollerKnobProportion",
CPScrollerStyleKey = @"CPScrollerStyleKey";
@@ -789,6 +812,10 @@ var CPScrollerIsVerticalKey = @"CPScrollerIsVerticalKey",
{
if (self = [super initWithCoder:aCoder])
{
_controlSize = CPRegularControlSize;
if ([aCoder containsValueForKey:CPScrollerControlSizeKey])
_controlSize = [aCoder decodeIntForKey:CPScrollerControlSizeKey];
_knobProportion = 1.0;
if ([aCoder containsValueForKey:CPScrollerKnobProportionKey])
@@ -823,6 +850,7 @@ var CPScrollerIsVerticalKey = @"CPScrollerIsVerticalKey",
{
[super encodeWithCoder:aCoder];
[aCoder encodeInt:_controlSize forKey:CPScrollerControlSizeKey];
[aCoder encodeInt:_isVertical forKey:CPScrollerIsVerticalKey];
[aCoder encodeFloat:_knobProportion forKey:CPScrollerKnobProportionKey];
[aCoder encodeInt:_style forKey:CPScrollerStyleKey];
+22 -37
View File
@@ -34,8 +34,9 @@ CPSearchFieldRecentsMenuItemTag = 1001;
CPSearchFieldClearRecentsMenuItemTag = 1002;
CPSearchFieldNoRecentsMenuItemTag = 1003;
var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotification",
RECENT_SEARCH_PREFIX = @" ";
var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotification";
var RECENT_SEARCH_PREFIX = @" ";
/*!
@ingroup appkit
@@ -72,9 +73,7 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
@"image-search": [CPNull null],
@"image-find": [CPNull null],
@"image-cancel": [CPNull null],
@"image-cancel-pressed": [CPNull null],
@"image-search-inset" : CGInsetMake(0, 0, 0, 5),
@"image-cancel-inset" : CGInsetMake(0, 5, 0, 0)
@"image-cancel-pressed": [CPNull null]
};
}
@@ -120,28 +119,16 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
_canResignFirstResponder = YES;
}
#pragma mark -
#pragma mark Override observers
- (void)_removeObservers
- (void)viewWillMoveToSuperview:(CPView)aView
{
if (!_isObserving)
return;
[super _removeObservers];
[super viewWillMoveToSuperview:aView];
// First we remove any observer that may have been in place to avoid memory leakage.
[[CPNotificationCenter defaultCenter] removeObserver:self name:CPControlTextDidChangeNotification object:self];
}
- (void)_addObservers
{
if (_isObserving)
return;
[super _addObservers];
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_searchFieldTextDidChange:) name:CPControlTextDidChangeNotification object:self];
// Register the observe here if we need to.
if (aView)
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_searchFieldTextDidChange:) name:CPControlTextDidChangeNotification object:self];
}
// Managing Buttons
@@ -242,22 +229,22 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
- (CGRect)searchTextRectForBounds:(CGRect)rect
{
var leftOffset = 0,
width = CGRectGetWidth(rect),
width = _CGRectGetWidth(rect),
bounds = [self bounds];
if (_searchButton)
{
var searchBounds = [self searchButtonRectForBounds:bounds];
leftOffset = CGRectGetMaxX(searchBounds) + 2;
leftOffset = _CGRectGetMaxX(searchBounds) + 2;
}
if (_cancelButton)
{
var cancelRect = [self cancelButtonRectForBounds:bounds];
width = CGRectGetMinX(cancelRect) - leftOffset;
width = _CGRectGetMinX(cancelRect) - leftOffset;
}
return CGRectMake(leftOffset, CGRectGetMinY(rect), width, CGRectGetHeight(rect));
return _CGRectMake(leftOffset, _CGRectGetMinY(rect), width, _CGRectGetHeight(rect));
}
/*!
@@ -267,10 +254,9 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
*/
- (CGRect)searchButtonRectForBounds:(CGRect)rect
{
var size = [[self currentValueForThemeAttribute:@"image-search"] size] || CGSizeMakeZero(),
inset = [self currentValueForThemeAttribute:@"image-search-inset"];
var size = [[self valueForThemeAttribute:@"image-search"] size] || CGSizeMakeZero();
return CGRectMake(inset.left - inset.right, inset.top - inset.bottom + (CGRectGetHeight(rect) - size.height) / 2, size.width, size.height);
return _CGRectMake(5, (_CGRectGetHeight(rect) - size.height) / 2, size.width, size.height);
}
/*!
@@ -280,10 +266,9 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
*/
- (CGRect)cancelButtonRectForBounds:(CGRect)rect
{
var size = [[self currentValueForThemeAttribute:@"image-cancel"] size] || CGSizeMakeZero(),
inset = [self currentValueForThemeAttribute:@"image-cancel-inset"];
var size = [[self valueForThemeAttribute:@"image-cancel"] size] || CGSizeMakeZero();
return CGRectMake(CGRectGetWidth(rect) - size.width + inset.left - inset.right, inset.top - inset.bottom + (CGRectGetHeight(rect) - size.width) / 2, size.height, size.height);
return _CGRectMake(_CGRectGetWidth(rect) - size.width - 5, (_CGRectGetHeight(rect) - size.width) / 2, size.height, size.height);
}
// Managing Menu Templates
@@ -473,7 +458,7 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
[self sendAction:[self action] to:[self target]];
}
- (BOOL)sendAction:(SEL)anAction to:(id)anObject
- (void)sendAction:(SEL)anAction to:(id)anObject
{
[super sendAction:anAction to:anObject];
@@ -497,7 +482,7 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
- (CPView)hitTest:(CGPoint)aPoint
{
// Make sure a hit anywhere within the search field returns the search field itself
if (CGRectContainsPoint([self frame], aPoint))
if (_CGRectContainsPoint([self frame], aPoint))
return self;
else
return nil;
@@ -513,7 +498,7 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
var location = [anEvent locationInWindow],
point = [self convertPoint:location fromView:nil];
if (CGRectContainsPoint([self searchButtonRectForBounds:[self bounds]], point))
if (_CGRectContainsPoint([self searchButtonRectForBounds:[self bounds]], point))
{
if (_searchMenuTemplate == nil)
{
@@ -525,7 +510,7 @@ var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotificat
else
[self _showMenu];
}
else if (CGRectContainsPoint([self cancelButtonRectForBounds:[self bounds]], point))
else if (_CGRectContainsPoint([self cancelButtonRectForBounds:[self bounds]], point))
[_cancelButton mouseDown:anEvent];
else
[super mouseDown:anEvent];
+204 -303
View File
@@ -25,11 +25,9 @@
@import "CPControl.j"
@import "CPWindow_Constants.j"
@import "_CPImageAndTextView.j"
@import "CPMenu.j"
@global CPApp
@typedef CPSegmentSwitchTracking
CPSegmentSwitchTrackingSelectOne = 0;
CPSegmentSwitchTrackingSelectAny = 1;
CPSegmentSwitchTrackingMomentary = 2;
@@ -42,7 +40,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
@implementation CPSegmentedControl : CPControl
{
CPArray _segments @accessors(getter=segments);
CPArray _segments;
CPArray _themeStates;
int _selectedSegment;
@@ -58,23 +56,37 @@ CPSegmentSwitchTrackingMomentary = 2;
return "segmented-control";
}
+ (CPDictionary)themeAttributes
+ (id)themeAttributes
{
return @{
@"alignment": CPCenterTextAlignment,
@"vertical-alignment": CPCenterVerticalTextAlignment,
@"image-position": CPImageLeft,
@"image-scaling": CPImageScaleNone,
@"bezel-inset": CGInsetMakeZero(),
@"content-inset": CGInsetMakeZero(),
@"bezel-inset": _CGInsetMakeZero(),
@"content-inset": _CGInsetMakeZero(),
@"left-segment-bezel-color": [CPNull null],
@"right-segment-bezel-color": [CPNull null],
@"center-segment-bezel-color": [CPNull null],
@"divider-bezel-color": [CPNull null],
@"divider-thickness": 1.0,
@"default-height": 24.0,
};
}
+ (Class)_binderClassForBinding:(CPString)aBinding
{
if ([self _isSelectionBinding:aBinding])
return [_CPSegmentedControlBinder class];
return [super _binderClassForBinding:aBinding];
}
+ (BOOL)_isSelectionBinding:(CPString)aBinding
{
return (aBinding === CPSelectedIndexBinding || aBinding === CPSelectedLabelBinding || aBinding === CPSelectedTagBinding);
}
- (id)initWithFrame:(CGRect)aRect
{
_segments = [];
@@ -87,21 +99,22 @@ CPSegmentSwitchTrackingMomentary = 2;
_selectedSegment = -1;
_trackingMode = CPSegmentSwitchTrackingSelectOne;
_trackingHighlighted = NO;
_trackingSegment = -1;
}
return self;
}
/*!
Sets the control's size.
@param aControlSize the control's size
*/
- (void)setControlSize:(CPControlSize)aControlSize
- (void)bind:(CPString)aBinding toObject:(id)anObject withKeyPath:(CPString)aKeyPath options:(CPDictionary)options
{
[super setControlSize:aControlSize];
[self _sizeToControlSize];
if ([[self class] _isSelectionBinding:aBinding] && _trackingMode !== CPSegmentSwitchTrackingSelectOne)
CPLog.warn("Binding " + aBinding + " needs CPSegmentSwitchTrackingSelectOne tracking mode");
else
[super bind:aBinding toObject:anObject withKeyPath:aKeyPath options:options];
}
- (void)_reverseSetBinding
{
[_CPSegmentedControlBinder reverseSetValueForObject:self];
}
/*!
@@ -109,54 +122,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (int)selectedTag
{
return [[_segments objectAtIndex:_selectedSegment] tag];
}
/*! @ignore */
- (void)setSegments:(CPArray)segments
{
[self removeSegmentsAtIndexes:[CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self segmentCount])]];
[self insertSegments:segments atIndexes:[CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [segments count])]];
}
/*! @ignore */
- (void)insertSegments:(CPArray)segments atIndexes:(CPIndexSet)indices
{
if ([segments count] == 0)
return;
var newStates = @[],
count = [indices count];
while (count--)
[newStates addObject:CPThemeStateNormal];
[_segments insertObjects:segments atIndexes:indices];
[_themeStates insertObjects:newStates atIndexes:indices];
if (_selectedSegment >= [indices firstIndex])
_selectedSegment += [indices count];
}
/*! @ignore */
- (void)removeSegmentsAtIndexes:(CPIndexSet)indices
{
if ([indices count] == 0)
return;
[indices enumerateIndexesUsingBlock:function(idx, stop)
{
[[_segments objectAtIndex:idx] setSelected:NO];
}];
if ([indices containsIndex:_selectedSegment])
_selectedSegment = -1;
else if ([indices lastIndex] < _selectedSegment)
_selectedSegment -= [indices count];
[_segments removeObjectsAtIndexes:indices];
[_themeStates removeObjectsAtIndexes:indices];
return [_segments[_selectedSegment] tag];
}
// Specifying the number of segments
@@ -166,32 +132,41 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (void)setSegmentCount:(unsigned)aCount
{
var prevCount = [_segments count];
if (aCount == prevCount)
if (_segments.length == aCount)
return;
if (aCount > prevCount)
var height = CGRectGetHeight([self bounds]),
dividersBefore = MAX(0, _segments.length - 1),
dividersAfter = MAX(0, aCount - 1);
if (_segments.length < aCount)
{
var count = aCount - prevCount,
segments = @[];
while (count--)
[segments addObject:[[_CPSegmentItem alloc] init]];
[self insertSegments:segments atIndexes:[CPIndexSet indexSetWithIndexesInRange:CPMakeRange(prevCount, aCount - prevCount)]];
for (var index = _segments.length; index < aCount; ++index)
{
_segments[index] = [[_CPSegmentItem alloc] init];
_themeStates[index] = CPThemeStateNormal;
}
}
else if (aCount < _segments.length)
{
_segments.length = aCount;
_themeStates.length = aCount;
}
else
[self removeSegmentsAtIndexes:[CPIndexSet indexSetWithIndexesInRange:CPMakeRange(aCount, prevCount - aCount)]];
[self _updateSelectionIfNeeded];
[self tileWithChangedSegment:MAX(MIN(prevCount, aCount) - 1, 0)];
}
- (void)_updateSelectionIfNeeded
{
if (_selectedSegment >= [self segmentCount])
if (_selectedSegment >= _segments.length)
_selectedSegment = -1;
var thickness = [self currentValueForThemeAttribute:@"divider-thickness"],
frame = [self frame],
widthOfAllSegments = 0,
dividerExtraSpace = ([_segments count] - 1) * thickness;
for (var i = 0; i < [_segments count]; i++)
widthOfAllSegments += [_segments[i] width];
[self setFrameSize:CGSizeMake(widthOfAllSegments + dividerExtraSpace, frame.size.height)];
[self tileWithChangedSegment:0];
}
/*!
@@ -199,7 +174,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (unsigned)segmentCount
{
return [_segments count];
return _segments.length;
}
// Specifying Selected Segment
@@ -211,20 +186,7 @@ CPSegmentSwitchTrackingMomentary = 2;
- (void)setSelectedSegment:(unsigned)aSegment
{
// setSelected:forSegment throws the exception for us (if necessary)
if (_selectedSegment == aSegment)
return;
if (aSegment == -1)
{
var count = [self segmentCount];
while (count--)
[self setSelected:NO forSegment:count];
_selectedSegment = -1;
}
else
[self setSelected:YES forSegment:aSegment];
[self setSelected:YES forSegment:aSegment];
}
/*!
@@ -242,8 +204,8 @@ CPSegmentSwitchTrackingMomentary = 2;
{
var index = 0;
for (; index < [_segments count]; ++index)
if ([[_segments objectAtIndex:index] tag] == aTag)
for (; index < _segments.length; ++index)
if (_segments[index].tag == aTag)
{
[self setSelectedSegment:index];
@@ -257,8 +219,8 @@ CPSegmentSwitchTrackingMomentary = 2;
{
var index = 0;
for (; index < [_segments count]; ++index)
if ([[_segments objectAtIndex:index] label] == aLabel)
for (; index < _segments.length; ++index)
if (_segments[index].label == aLabel)
{
[self setSelectedSegment:index];
@@ -269,7 +231,7 @@ CPSegmentSwitchTrackingMomentary = 2;
}
// Specifying Tracking Mode
/*! @ignore */
- (BOOL)isTracking
{
@@ -287,7 +249,7 @@ CPSegmentSwitchTrackingMomentary = 2;
var index = 0,
selected = NO;
for (; index < [self segmentCount]; ++index)
for (; index < _segments.length; ++index)
if ([_segments[index] selected])
if (selected)
[self setSelected:NO forSegment:index];
@@ -299,7 +261,7 @@ CPSegmentSwitchTrackingMomentary = 2;
{
var index = 0;
for (; index < [self segmentCount]; ++index)
for (; index < _segments.length; ++index)
if ([_segments[index] selected])
[self setSelected:NO forSegment:index];
}
@@ -322,7 +284,8 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (void)setWidth:(float)aWidth forSegment:(unsigned)aSegment
{
[[_segments objectAtIndex:aSegment] setWidth:aWidth];
[_segments[aSegment] setWidth:aWidth];
[self tileWithChangedSegment:aSegment];
}
@@ -333,7 +296,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (float)widthForSegment:(unsigned)aSegment
{
return [[_segments objectAtIndex:aSegment] width];
return [_segments[aSegment] width];
}
/*!
@@ -344,7 +307,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (void)setImage:(CPImage)anImage forSegment:(unsigned)aSegment
{
[[_segments objectAtIndex:aSegment] setImage:anImage];
[_segments[aSegment] setImage:anImage];
[self tileWithChangedSegment:aSegment];
}
@@ -356,7 +319,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (CPImage)imageForSegment:(unsigned)aSegment
{
return [[_segments objectAtIndex:aSegment] image];
return [_segments[aSegment] image];
}
/*!
@@ -367,7 +330,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (void)setLabel:(CPString)aLabel forSegment:(unsigned)aSegment
{
[[_segments objectAtIndex:aSegment] setLabel:aLabel];
[_segments[aSegment] setLabel:aLabel];
[self tileWithChangedSegment:aSegment];
}
@@ -379,7 +342,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (CPString)labelForSegment:(unsigned)aSegment
{
return [[_segments objectAtIndex:aSegment] label];
return [_segments[aSegment] label];
}
/*!
@@ -390,7 +353,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (void)setMenu:(CPMenu)aMenu forSegment:(unsigned)aSegment
{
[[_segments objectAtIndex:aSegment] setMenu:aMenu];
[_segments[aSegment] setMenu:aMenu];
}
/*!
@@ -400,7 +363,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (CPMenu)menuForSegment:(unsigned)aSegment
{
return [[_segments objectAtIndex:aSegment] menu];
return [_segments[aSegment] menu];
}
/*!
@@ -412,7 +375,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (void)setSelected:(BOOL)isSelected forSegment:(unsigned)aSegment
{
var segment = [_segments objectAtIndex:aSegment];
var segment = _segments[aSegment];
// If we're already in this state, bail.
if ([segment selected] == isSelected)
@@ -429,7 +392,7 @@ CPSegmentSwitchTrackingMomentary = 2;
_selectedSegment = aSegment;
if (_trackingMode == CPSegmentSwitchTrackingSelectOne && oldSelectedSegment != aSegment && oldSelectedSegment != -1 && oldSelectedSegment < _segments.length)
if (_trackingMode == CPSegmentSwitchTrackingSelectOne && oldSelectedSegment != aSegment && oldSelectedSegment != -1)
{
[_segments[oldSelectedSegment] setSelected:NO];
_themeStates[oldSelectedSegment] = CPThemeStateNormal;
@@ -452,7 +415,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (BOOL)isSelectedForSegment:(unsigned)aSegment
{
return [[_segments objectAtIndex:aSegment] selected];
return [_segments[aSegment] selected];
}
/*!
@@ -463,17 +426,15 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (void)setEnabled:(BOOL)shouldBeEnabled forSegment:(unsigned)aSegment
{
var segment = [_segments objectAtIndex:aSegment];
if ([segment enabled] === shouldBeEnabled)
if ([_segments[aSegment] enabled] === shouldBeEnabled)
return;
[segment setEnabled:shouldBeEnabled];
[_segments[aSegment] setEnabled:shouldBeEnabled];
if (shouldBeEnabled)
_themeStates[aSegment] = _themeStates[aSegment].without(CPThemeStateDisabled);
_themeStates[aSegment] &= ~CPThemeStateDisabled;
else
_themeStates[aSegment] = _themeStates[aSegment].and(CPThemeStateDisabled);
_themeStates[aSegment] |= CPThemeStateDisabled;
[self setNeedsLayout];
[self setNeedsDisplay:YES];
@@ -486,7 +447,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (BOOL)isEnabledForSegment:(unsigned)aSegment
{
return [[_segments objectAtIndex:aSegment] enabled];
return [_segments[aSegment] enabled];
}
/*!
@@ -496,7 +457,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (void)setTag:(int)aTag forSegment:(unsigned)aSegment
{
[[_segments objectAtIndex:aSegment] setTag:aTag];
[_segments[aSegment] setTag:aTag];
}
/*!
@@ -505,7 +466,7 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (int)tagForSegment:(unsigned)aSegment
{
return [[_segments objectAtIndex:aSegment] tag];
return [_segments[aSegment] tag];
}
// Drawings
@@ -516,13 +477,10 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (void)drawSegmentBezel:(int)aSegment highlight:(BOOL)shouldHighlight
{
if (aSegment < _themeStates.length)
{
if (shouldHighlight)
_themeStates[aSegment] = _themeStates[aSegment].and(CPThemeStateHighlighted);
else
_themeStates[aSegment] = _themeStates[aSegment].without(CPThemeStateHighlighted);
}
if (shouldHighlight)
_themeStates[aSegment] |= CPThemeStateHighlighted;
else
_themeStates[aSegment] &= ~CPThemeStateHighlighted;
[self setNeedsLayout];
[self setNeedsDisplay:YES];
@@ -530,12 +488,14 @@ CPSegmentSwitchTrackingMomentary = 2;
- (float)_leftOffsetForSegment:(unsigned)segment
{
var bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"];
if (segment == 0)
return [self currentValueForThemeAttribute:@"bezel-inset"].left;
return bezelInset.left;
var thickness = [self currentValueForThemeAttribute:@"divider-thickness"];
return [self _leftOffsetForSegment:segment - 1] + CGRectGetWidth([self frameForSegment:segment - 1]) + thickness;
return [self _leftOffsetForSegment:segment - 1] + [self widthForSegment:segment - 1] + thickness;
}
- (unsigned)_indexOfLastSegment
@@ -550,7 +510,7 @@ CPSegmentSwitchTrackingMomentary = 2;
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aName
{
var height = [self currentValueForThemeAttribute:@"min-size"].height,
var height = [self currentValueForThemeAttribute:@"default-height"],
contentInset = [self currentValueForThemeAttribute:@"content-inset"],
bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"],
bounds = [self bounds];
@@ -569,7 +529,7 @@ CPSegmentSwitchTrackingMomentary = 2;
else if (aName.indexOf("segment-bezel") === 0)
{
var segment = parseInt(aName.substring("segment-bezel-".length), 10),
frame = CGRectCreateCopy([self frameForSegment:segment]);
frame = CGRectCreateCopy([_segments[segment] frame]);
if (segment === 0)
{
@@ -577,7 +537,7 @@ CPSegmentSwitchTrackingMomentary = 2;
frame.size.width -= contentInset.left;
}
if (segment === [self segmentCount] - 1)
if (segment === _segments.length - 1)
frame.size.width = CGRectGetWidth([self bounds]) - contentInset.right - frame.origin.x;
return frame;
@@ -585,7 +545,7 @@ CPSegmentSwitchTrackingMomentary = 2;
else if (aName.indexOf("divider-bezel") === 0)
{
var segment = parseInt(aName.substring("divider-bezel-".length), 10),
width = CGRectGetWidth([self frameForSegment:segment]),
width = [self widthForSegment:segment],
left = [self _leftOffsetForSegment:segment],
thickness = [self currentValueForThemeAttribute:@"divider-thickness"];
@@ -604,27 +564,19 @@ CPSegmentSwitchTrackingMomentary = 2;
- (CPView)createEphemeralSubviewNamed:(CPString)aName
{
if ([aName hasPrefix:@"segment-content"])
return [[_CPImageAndTextView alloc] initWithFrame:CGRectMakeZero()];
return [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()];
return [[CPView alloc] initWithFrame:CGRectMakeZero()];
return [[CPView alloc] initWithFrame:_CGRectMakeZero()];
}
- (void)layoutSubviews
{
if ([self segmentCount] <= 0)
if (_segments.length <= 0)
return;
var themeState = _themeStates[0],
isDisabled = [self hasThemeState:CPThemeStateDisabled],
isControlSizeSmall = [self hasThemeState:CPThemeStateControlSizeSmall],
isControlSizeMini = [self hasThemeState:CPThemeStateControlSizeMini];
var themeState = _themeStates[0];
themeState = isDisabled ? themeState.and(CPThemeStateDisabled) : themeState;
if (isControlSizeSmall)
themeState = themeState.and(CPThemeStateControlSizeSmall);
else if (isControlSizeMini)
themeState = themeState.and(CPThemeStateControlSizeMini);
themeState |= _themeState & CPThemeStateDisabled;
var leftCapColor = [self valueForThemeAttribute:@"left-segment-bezel-color"
inState:themeState],
@@ -637,12 +589,7 @@ CPSegmentSwitchTrackingMomentary = 2;
var themeState = _themeStates[_themeStates.length - 1];
themeState = isDisabled ? themeState.and(CPThemeStateDisabled) : themeState;
if (isControlSizeSmall)
themeState = themeState.and(CPThemeStateControlSizeSmall);
else if (isControlSizeMini)
themeState = themeState.and(CPThemeStateControlSizeMini);
themeState |= _themeState & CPThemeStateDisabled;
var rightCapColor = [self valueForThemeAttribute:@"right-segment-bezel-color"
inState:themeState],
@@ -657,12 +604,7 @@ CPSegmentSwitchTrackingMomentary = 2;
{
var themeState = _themeStates[i];
themeState = isDisabled ? themeState.and(CPThemeStateDisabled) : themeState;
if (isControlSizeSmall)
themeState = themeState.and(CPThemeStateControlSizeSmall);
else if (isControlSizeMini)
themeState = themeState.and(CPThemeStateControlSizeMini);
themeState |= _themeState & CPThemeStateDisabled;
var bezelColor = [self valueForThemeAttribute:@"center-segment-bezel-color"
inState:themeState],
@@ -673,6 +615,7 @@ CPSegmentSwitchTrackingMomentary = 2;
[bezelView setBackgroundColor:bezelColor];
// layout image/title views
var segment = _segments[i],
contentView = [self layoutEphemeralSubviewNamed:@"segment-content-" + i
@@ -699,15 +642,11 @@ CPSegmentSwitchTrackingMomentary = 2;
if (i == count - 1)
continue;
var borderState = _themeStates[i] | _themeStates[i + 1];
var borderState = _themeStates[i].and(_themeStates[i + 1]);
borderState = (borderState & CPThemeStateSelected & ~CPThemeStateHighlighted) ? CPThemeStateSelected : CPThemeStateNormal;
borderState = isDisabled ? borderState.and(CPThemeStateDisabled) : borderState;
if (isControlSizeSmall)
borderState = borderState.and(CPThemeStateControlSizeSmall);
else if (isControlSizeMini)
borderState = borderState.and(CPThemeStateControlSizeMini);
borderState |= _themeState & CPThemeStateDisabled;
var borderColor = [self valueForThemeAttribute:@"divider-bezel-color"
inState:borderState],
@@ -730,33 +669,61 @@ CPSegmentSwitchTrackingMomentary = 2;
{
}
/*! @ignore */
- (void)tile
- (void)tileWithChangedSegment:(unsigned)aSegment
{
[self tileWithChangedSegment:0];
}
/*! @ignore */
- (void)tileWithChangedSegment:(CPInteger)aSegment
{
var segmentCount = [self segmentCount];
// Corner case: when segmentCount == 0 and aSegment == 0, we do not return here because we still need to set the new frameSize bellow.
if (aSegment < 0 || (segmentCount > 0 && aSegment >= segmentCount))
if (aSegment >= _segments.length)
return;
var width = 0;
var segment = _segments[aSegment],
segmentWidth = [segment width],
themeState = _themeStates[aSegment] | (_themeState & CPThemeStateDisabled),
contentInset = [self valueForThemeAttribute:@"content-inset" inState:themeState],
font = [self font];
if (segmentCount > 0)
if (!segmentWidth)
{
// Invalidate frames for segments on the right. They will be lazily computed by -frameForSegment:.
for (var i = aSegment; i < segmentCount; i++)
[_segments[i] setFrame:CGRectMakeZero()];
width = CGRectGetMaxX([self frameForSegment:(segmentCount - 1)]);
if ([segment image] && [segment label])
segmentWidth = [[segment label] sizeWithFont:font].width + [[segment image] size].width + contentInset.left + contentInset.right;
else if (segment.image)
segmentWidth = [[segment image] size].width + contentInset.left + contentInset.right;
else if (segment.label)
segmentWidth = [[segment label] sizeWithFont:font].width + contentInset.left + contentInset.right;
else
segmentWidth = 0.0;
}
[self setFrameSize:CGSizeMake(width, CGRectGetHeight([self frame]))];
var delta = segmentWidth - CGRectGetWidth([segment frame]);
if (!delta)
{
[self setNeedsLayout];
[self setNeedsDisplay:YES];
return;
}
// Update control size
var frame = [self frame];
[self setFrameSize:CGSizeMake(CGRectGetWidth(frame) + delta, CGRectGetHeight(frame))];
// Update segment width
[segment setWidth:segmentWidth];
[segment setFrame:[self frameForSegment:aSegment]];
// Update following segments widths
var index = aSegment + 1;
for (; index < _segments.length; ++index)
{
[_segments[index] frame].origin.x += delta;
[self drawSegmentBezel:index highlight:NO];
[self drawSegment:index highlight:NO];
}
[self drawSegmentBezel:aSegment highlight:NO];
[self drawSegment:aSegment highlight:NO];
[self setNeedsLayout];
[self setNeedsDisplay:YES];
@@ -768,57 +735,29 @@ CPSegmentSwitchTrackingMomentary = 2;
*/
- (CGRect)frameForSegment:(unsigned)aSegment
{
var segment = [_segments objectAtIndex:aSegment],
frame = [segment frame];
if (CGRectEqualToRect(frame, CGRectMakeZero()))
{
frame = [self bezelFrameForSegment:aSegment];
[segment setFrame:frame];
}
return frame;
return [self bezelFrameForSegment:aSegment];
}
- (CGRect)bezelFrameForSegment:(unsigned)aSegment
{
var left = [self _leftOffsetForSegment:aSegment],
top = [self currentValueForThemeAttribute:@"bezel-inset"].top,
var height = [self currentValueForThemeAttribute:@"default-height"],
bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"],
width = [self widthForSegment:aSegment],
height = [self currentValueForThemeAttribute:@"min-size"].height;
left = [self _leftOffsetForSegment:aSegment];
if (width == 0)
{
var themeState = _themeState.hasThemeState(CPThemeStateDisabled) ? _themeStates[aSegment].and(CPThemeStateDisabled) : _themeStates[aSegment],
contentInset = [self valueForThemeAttribute:@"content-inset" inState:themeState],
contentInsetWidth = contentInset.left + contentInset.right,
segment = _segments[aSegment],
label = [segment label],
image = [segment image];
width = (label ? [label sizeWithFont:[self font]].width : 4.0) + (image ? [image size].width : 0) + contentInsetWidth;
}
return CGRectMake(left, top, width, height);
return CGRectMake(left, bezelInset.top, width, height);
}
- (CGRect)contentFrameForSegment:(unsigned)aSegment
{
var height = [self currentValueForThemeAttribute:@"min-size"].height,
var height = [self currentValueForThemeAttribute:@"default-height"],
contentInset = [self currentValueForThemeAttribute:@"content-inset"],
width = CGRectGetWidth([self frameForSegment:aSegment]),
width = [self widthForSegment:aSegment],
left = [self _leftOffsetForSegment:aSegment];
return CGRectMake(left + contentInset.left, contentInset.top, width - contentInset.left - contentInset.right, height - contentInset.top - contentInset.bottom);
}
- (CGSize)_minimumFrameSize
{
// The current width is always the minimum width.
return CGSizeMake(CGRectGetWidth([self frame]), [self currentValueForThemeAttribute:@"min-size"].height);
}
/*!
Returns the segment that is hit by the specified point.
@param aPoint the point to test for a segment hit
@@ -827,19 +766,19 @@ CPSegmentSwitchTrackingMomentary = 2;
- (unsigned)testSegment:(CGPoint)aPoint
{
var location = [self convertPoint:aPoint fromView:nil],
count = [self segmentCount];
count = _segments.length;
while (count--)
if (CGRectContainsPoint([self frameForSegment:count], aPoint))
if (CGRectContainsPoint([_segments[count] frame], aPoint))
return count;
if ([self segmentCount])
if (_segments.length)
{
var adjustedLastFrame = CGRectCreateCopy([self frameForSegment:(_segments.length - 1)]);
var adjustedLastFrame = CGRectCreateCopy([_segments[_segments.length - 1] frame]);
adjustedLastFrame.size.width = CGRectGetWidth([self bounds]) - adjustedLastFrame.origin.x;
if (CGRectContainsPoint(adjustedLastFrame, aPoint))
return [self segmentCount] - 1;
return _segments.length - 1;
}
return -1;
@@ -890,7 +829,7 @@ CPSegmentSwitchTrackingMomentary = 2;
{
[self setSelected:NO forSegment:_trackingSegment];
_selectedSegment = CPNotFound;
_selectedSegment = -1;
}
}
@@ -934,7 +873,7 @@ CPSegmentSwitchTrackingMomentary = 2;
{
[super setFont:aFont];
[self tile];
[self tileWithChangedSegment:0];
}
@end
@@ -966,49 +905,28 @@ var CPSegmentedControlSegmentsKey = "CPSegmentedControlSegmentsKey",
if ([aCoder containsValueForKey:CPSegmentedControlSelectedKey])
_selectedSegment = [aCoder decodeIntForKey:CPSegmentedControlSelectedKey];
else
_selectedSegment = CPNotFound;
_selectedSegment = -1;
if ([aCoder containsValueForKey:CPSegmentedControlTrackingModeKey])
_trackingMode = [aCoder decodeIntForKey:CPSegmentedControlTrackingModeKey];
else
_trackingMode = CPSegmentSwitchTrackingSelectOne;
// Here we update the themeStates array for each segments to know if there are selected or not
for (var i = 0; i < [self segmentCount]; i++)
// HACK
for (var i = 0; i < _segments.length; i++)
{
_themeStates[i] = [_segments[i] selected] ? CPThemeStateSelected : CPThemeStateNormal;
[self tile];
var thickness = [self currentValueForThemeAttribute:@"divider-thickness"],
dividerExtraSpace = ([_segments count] - 1) * thickness,
difference = MAX(originalWidth - [self frame].size.width - dividerExtraSpace, 0.0),
remainingWidth = FLOOR(difference / [self segmentCount]),
widthOfAllSegments = 0;
// We do this in a second loop because it relies on all the themeStates being set first
for (var i = 0; i < [self segmentCount]; i++)
{
var frame = [_segments[i] frame];
frame.size.width += remainingWidth;
widthOfAllSegments += CGRectGetWidth(frame);
[self tileWithChangedSegment:i];
}
// Here we handle the leftovers pixel, and we will add one pixel to each segment cell till we have the same size as the originalSize.
// This is needed to have a perfect/same alignment between our application and xCode.
var leftOversPixel = originalWidth - (widthOfAllSegments + dividerExtraSpace);
var difference = MAX(originalWidth - [self frame].size.width, 0.0),
remainingWidth = FLOOR(difference / _segments.length);
// Make sure we don't make an out of range
if (leftOversPixel < [self segmentCount] - 1)
{
for (var i = 0; i < leftOversPixel; i++)
{
[_segments[i] frame].size.width += 1;
}
}
for (var i = 0; i < _segments.length; i++)
[self setWidth:[_segments[i] width] + remainingWidth forSegment:i];
[self setFrameSize:CGSizeMake(originalWidth, CGRectGetHeight([self frame]))];
[self tile];
[self tileWithChangedSegment:0];
}
return self;
@@ -1026,48 +944,31 @@ var CPSegmentedControlSegmentsKey = "CPSegmentedControlSegmentsKey",
@end
@implementation CPSegmentedControl (BindingSupport)
+ (Class)_binderClassForBinding:(CPString)aBinding
{
if ([self _isSelectionBinding:aBinding])
return [_CPSegmentedControlBinder class];
return [super _binderClassForBinding:aBinding];
}
+ (BOOL)_isSelectionBinding:(CPString)aBinding
{
return (aBinding === CPSelectedIndexBinding || aBinding === CPSelectedLabelBinding || aBinding === CPSelectedTagBinding);
}
+ (BOOL)isBindingExclusive:(CPString)aBinding
{
return [self _isSelectionBinding:aBinding];
}
- (void)bind:(CPString)aBinding toObject:(id)anObject withKeyPath:(CPString)aKeyPath options:(CPDictionary)options
{
if ([[self class] _isSelectionBinding:aBinding] && _trackingMode !== CPSegmentSwitchTrackingSelectOne)
{
CPLog.warn("Binding " + aBinding + " needs CPSegmentSwitchTrackingSelectOne tracking mode");
return;
}
[super bind:aBinding toObject:anObject withKeyPath:aKeyPath options:options];
}
- (void)_reverseSetBinding
{
[_CPSegmentedControlBinder _reverseSetValueFromExclusiveBinderForObject:self];
}
@end
var CPSegmentedControlNoSelectionPlaceholder = "CPSegmentedControlNoSelectionPlaceholder";
var CPSegmentedControlBindersMap = {},
CPSegmentedControlNoSelectionPlaceholder = "CPSegmentedControlNoSelectionPlaceholder";
@implementation _CPSegmentedControlBinder : CPBinder
{
CPString _selectionBinding @accessors(readonly, getter=selectionBinding);
}
+ (void)reverseSetValueForObject:(id)aSource
{
var binder = CPSegmentedControlBindersMap[[aSource UID]];
[binder reverseSetValueFor:[binder selectionBinding]];
}
- (id)initWithBinding:(CPString)aBinding name:(CPString)aName to:(id)aDestination keyPath:(CPString)aKeyPath options:(CPDictionary)options from:(id)aSource
{
self = [super initWithBinding:aBinding name:aName to:aDestination keyPath:aKeyPath options:options from:aSource];
if (self)
{
CPSegmentedControlBindersMap[[aSource UID]] = self;
_selectionBinding = aName;
}
return self;
}
- (void)_updatePlaceholdersWithOptions:(CPDictionary)options
+2 -5
View File
@@ -22,9 +22,6 @@
@import <Foundation/CPObject.j>
@import "CGGeometry.j"
@import "CPColor.j"
@import "CPGraphicsContext.j"
/*!
@deprecated
@@ -34,9 +31,9 @@
*/
@implementation CPShadow : CPObject
{
CGSize _offset @accessors(property=shadowOffset);
CGSize _offset @accessors(property=shadowOffset);
float _blurRadius @accessors(property=shadowBlurRadius);
CPColor _color @accessors(property=shadowColor);
CPColor _color @accessors(property=shadowColor);
}
/*!
+3 -3
View File
@@ -26,7 +26,7 @@
@import "CPImage.j"
@import "CPView.j"
@typedef CPShadowWeight
CPLightShadow = 0;
CPHeavyShadow = 1;
@@ -47,7 +47,7 @@ CPThemeStateShadowViewHeavy = CPThemeState("shadowview-style-heavy");
return "shadow-view";
}
+ (CPDictionary)themeAttributes
+ (id)themeAttributes
{
return @{
@"bezel-color": [CPNull null],
@@ -60,7 +60,7 @@ CPThemeStateShadowViewHeavy = CPThemeState("shadowview-style-heavy");
var shadowView = [CPShadowView new],
inset = [shadowView valueForThemeAttribute:@"content-inset" inState:(aWeight == CPLightShadow) ? CPThemeStateShadowViewLight : CPThemeStateShadowViewHeavy];
return CGRectMake(CGRectGetMinX(aFrame) - inset.left, CGRectGetMinY(aFrame) - inset.top, CGRectGetWidth(aFrame) + inset.left + inset.right, CGRectGetHeight(aFrame) + inset.top + inset.bottom);
return CGRectMake(_CGRectGetMinX(aFrame) - inset.left, _CGRectGetMinY(aFrame) - inset.top, _CGRectGetWidth(aFrame) + inset.left + inset.right, _CGRectGetHeight(aFrame) + inset.top + inset.bottom);
}
+ (id)shadowViewEnclosingView:(CPView)aView
+27 -27
View File
@@ -49,11 +49,11 @@ CPCircularSlider = 1;
return "slider";
}
+ (CPDictionary)themeAttributes
+ (id)themeAttributes
{
return @{
@"knob-color": [CPNull null],
@"knob-size": CGSizeMakeZero(),
@"knob-size": _CGSizeMakeZero(),
@"track-width": 0.0,
@"track-color": [CPNull null],
};
@@ -162,16 +162,16 @@ CPCircularSlider = 1;
var trackWidth = [self currentValueForThemeAttribute:@"track-width"];
if (trackWidth <= 0)
return CGRectMakeZero();
return _CGRectMakeZero();
if ([self isVertical])
{
bounds.origin.x = (CGRectGetWidth(bounds) - trackWidth) / 2.0;
bounds.origin.x = (_CGRectGetWidth(bounds) - trackWidth) / 2.0;
bounds.size.width = trackWidth;
}
else
{
bounds.origin.y = (CGRectGetHeight(bounds) - trackWidth) / 2.0;
bounds.origin.y = (_CGRectGetHeight(bounds) - trackWidth) / 2.0;
bounds.size.height = trackWidth;
}
}
@@ -184,13 +184,13 @@ CPCircularSlider = 1;
var knobSize = [self currentValueForThemeAttribute:@"knob-size"];
if (knobSize.width <= 0 || knobSize.height <= 0)
return CGRectMakeZero();
return _CGRectMakeZero();
var knobRect = CGRectMake(0.0, 0.0, knobSize.width, knobSize.height),
var knobRect = _CGRectMake(0.0, 0.0, knobSize.width, knobSize.height),
trackRect = [self trackRectForBounds:bounds];
// No track, do our best to approximate a place for this thing.
if (!trackRect || CGRectIsEmpty(trackRect))
if (!trackRect || _CGRectIsEmpty(trackRect))
trackRect = bounds;
if ([self hasThemeState:CPThemeStateCircular])
@@ -203,13 +203,13 @@ CPCircularSlider = 1;
}
else if ([self isVertical])
{
knobRect.origin.x = CGRectGetMidX(trackRect) - knobSize.width / 2.0;
knobRect.origin.y = ((_maxValue - [self doubleValue]) / (_maxValue - _minValue)) * (CGRectGetHeight(trackRect) - knobSize.height);
knobRect.origin.x = _CGRectGetMidX(trackRect) - knobSize.width / 2.0;
knobRect.origin.y = ((_maxValue - [self doubleValue]) / (_maxValue - _minValue)) * (_CGRectGetHeight(trackRect) - knobSize.height);
}
else
{
knobRect.origin.x = (([self doubleValue] - _minValue) / (_maxValue - _minValue)) * (CGRectGetWidth(trackRect) - knobSize.width);
knobRect.origin.y = CGRectGetMidY(trackRect) - knobSize.height / 2.0;
knobRect.origin.x = (([self doubleValue] - _minValue) / (_maxValue - _minValue)) * (_CGRectGetWidth(trackRect) - knobSize.width);
knobRect.origin.y = _CGRectGetMidY(trackRect) - knobSize.height / 2.0;
}
return knobRect;
@@ -260,8 +260,8 @@ CPCircularSlider = 1;
{
// Recalculate isVertical.
var bounds = [self bounds],
width = CGRectGetWidth(bounds),
height = CGRectGetHeight(bounds);
width = _CGRectGetWidth(bounds),
height = _CGRectGetHeight(bounds);
_isVertical = width < height ? 1 : (width > height ? 0 : -1);
@@ -306,55 +306,55 @@ CPCircularSlider = 1;
if ([self hasThemeState:CPThemeStateCircular])
{
var knobWidth = CGRectGetWidth(knobRect);
var knobWidth = _CGRectGetWidth(knobRect);
trackRect.origin.x += knobWidth / 2;
trackRect.size.width -= knobWidth;
var minValue = [self minValue],
dx = aPoint.x - CGRectGetMidX(trackRect),
dy = aPoint.y - CGRectGetMidY(trackRect);
dx = aPoint.x - _CGRectGetMidX(trackRect),
dy = aPoint.y - _CGRectGetMidY(trackRect);
return MAX(0.0, MIN(1.0, 1.0 - (3 * PI_2 - ATAN2(dy, dx)) % PI2 / PI2)) * ([self maxValue] - minValue) + minValue;
}
else if ([self isVertical])
{
var knobHeight = CGRectGetHeight(knobRect);
var knobHeight = _CGRectGetHeight(knobRect);
trackRect.origin.y += knobHeight / 2;
trackRect.size.height -= knobHeight;
var minValue = [self minValue];
return MAX(0.0, MIN(1.0, (CGRectGetMaxY(trackRect) - aPoint.y) / CGRectGetHeight(trackRect))) * ([self maxValue] - minValue) + minValue;
return MAX(0.0, MIN(1.0, (_CGRectGetMaxY(trackRect) - aPoint.y) / _CGRectGetHeight(trackRect))) * ([self maxValue] - minValue) + minValue;
}
else
{
var knobWidth = CGRectGetWidth(knobRect);
var knobWidth = _CGRectGetWidth(knobRect);
trackRect.origin.x += knobWidth / 2;
trackRect.size.width -= knobWidth;
var minValue = [self minValue];
return MAX(0.0, MIN(1.0, (aPoint.x - CGRectGetMinX(trackRect)) / CGRectGetWidth(trackRect))) * ([self maxValue] - minValue) + minValue;
return MAX(0.0, MIN(1.0, (aPoint.x - _CGRectGetMinX(trackRect)) / _CGRectGetWidth(trackRect))) * ([self maxValue] - minValue) + minValue;
}
}
- (BOOL)startTrackingAt:(CGPoint)aPoint
{
var bounds = [self bounds],
knobRect = [self knobRectForBounds:CGRectMakeCopy(bounds)];
knobRect = [self knobRectForBounds:_CGRectMakeCopy(bounds)];
if (CGRectContainsPoint(knobRect, aPoint))
_dragOffset = CGSizeMake(CGRectGetMidX(knobRect) - aPoint.x, CGRectGetMidY(knobRect) - aPoint.y);
if (_CGRectContainsPoint(knobRect, aPoint))
_dragOffset = _CGSizeMake(_CGRectGetMidX(knobRect) - aPoint.x, _CGRectGetMidY(knobRect) - aPoint.y);
else
{
var trackRect = [self trackRectForBounds:bounds];
if (trackRect && CGRectContainsPoint(trackRect, aPoint))
if (trackRect && _CGRectContainsPoint(trackRect, aPoint))
{
_dragOffset = CGSizeMakeZero();
_dragOffset = _CGSizeMakeZero();
[self setObjectValue:[self _valueAtPoint:aPoint]];
}
@@ -373,7 +373,7 @@ CPCircularSlider = 1;
- (BOOL)continueTracking:(CGPoint)lastPoint at:(CGPoint)aPoint
{
[self setObjectValue:[self _valueAtPoint:CGPointMake(aPoint.x + _dragOffset.width, aPoint.y + _dragOffset.height)]];
[self setObjectValue:[self _valueAtPoint:_CGPointMake(aPoint.x + _dragOffset.width, aPoint.y + _dragOffset.height)]];
return YES;
}
+10 -12
View File
@@ -55,6 +55,7 @@
CPTextField _hexLabel;
CPTextField _hexValue;
CPTextField _hexValue;
CPTextField _redValue;
CPTextField _greenValue;
CPTextField _blueValue;
@@ -145,7 +146,7 @@
[_hueLabel setTextColor:[CPColor blackColor]];
_hueSlider = [[CPSlider alloc] initWithFrame:CGRectMake(15, 143, aFrame.size.width - 70, 20)];
[_hueSlider setMaxValue:0.999];
[_hueSlider setMaxValue:359.0];
[_hueSlider setMinValue:0.0];
[_hueSlider setTarget:self];
[_hueSlider setAction:@selector(sliderChanged:)];
@@ -164,7 +165,7 @@
[_saturationLabel setTextColor:[CPColor blackColor]];
_saturationSlider = [[CPSlider alloc] initWithFrame:CGRectMake(15, 168, aFrame.size.width - 70, 20)];
[_saturationSlider setMaxValue:1.0];
[_saturationSlider setMaxValue:100.0];
[_saturationSlider setMinValue:0.0];
[_saturationSlider setTarget:self];
[_saturationSlider setAction:@selector(sliderChanged:)];
@@ -183,7 +184,7 @@
[_brightnessLabel setTextColor:[CPColor blackColor]];
_brightnessSlider = [[CPSlider alloc] initWithFrame:CGRectMake(15, 194, aFrame.size.width - 70, 20)];
[_brightnessSlider setMaxValue:1.0];
[_brightnessSlider setMaxValue:100.0];
[_brightnessSlider setMinValue:0.0];
[_brightnessSlider setTarget:self];
[_brightnessSlider setAction:@selector(sliderChanged:)];
@@ -281,9 +282,6 @@
- (void)setColor:(CPColor)aColor
{
if (!aColor)
[CPException raise:CPInvalidArgumentException reason:"aColor can't be nil"];
[self updateRGBSliders:aColor];
[self updateHSBSliders:aColor];
[self updateHex:aColor];
@@ -315,9 +313,9 @@
- (void)updateLabels
{
[_hueValue setStringValue:ROUND([_hueSlider floatValue] * 360.0)];
[_saturationValue setStringValue:ROUND([_saturationSlider floatValue] * 100.0)];
[_brightnessValue setStringValue:ROUND([_brightnessSlider floatValue] * 100.0)];
[_hueValue setStringValue:ROUND([_hueSlider floatValue])];
[_saturationValue setStringValue:ROUND([_saturationSlider floatValue])];
[_brightnessValue setStringValue:ROUND([_brightnessSlider floatValue])];
[_redValue setStringValue:ROUND([_redSlider floatValue] * 255)];
[_greenValue setStringValue:ROUND([_greenSlider floatValue] * 255)];
@@ -365,15 +363,15 @@
[self sliderChanged:_blueSlider];
break;
case _hueValue: [_hueSlider setFloatValue:MAX(MIN(ROUND(value), 360) / 360.0, 0)];
case _hueValue: [_hueSlider setFloatValue:MAX(MIN(ROUND(value), 360), 0)];
[self sliderChanged:_hueSlider];
break;
case _saturationValue: [_saturationSlider setFloatValue:MAX(MIN(ROUND(value), 100) / 100.0, 0)];
case _saturationValue: [_saturationSlider setFloatValue:MAX(MIN(ROUND(value), 100), 0)];
[self sliderChanged:_saturationSlider];
break;
case _brightnessValue: [_brightnessSlider setFloatValue:MAX(MIN(ROUND(value), 100) / 100.0, 0)];
case _brightnessValue: [_brightnessSlider setFloatValue:MAX(MIN(ROUND(value), 100), 0)];
[self sliderChanged:_brightnessSlider];
break;
}
+2 -50
View File
@@ -23,18 +23,6 @@
@import <Foundation/CPObject.j>
@import <Foundation/CPRunLoop.j>
@typedef HTMLAudioElement
@protocol CPSoundDelegate <CPObject>
@optional
- (void)sound:(CPSound)aSound didFinishPlaying:(BOOL)finishedLoading;
@end
var CPSoundDelegate_sound_didFinishPlaying_ = 1 << 1;
CPSoundLoadStateEmpty = 0;
CPSoundLoadStateLoading = 1;
CPSoundLoadStateCanBePlayed = 2;
@@ -62,7 +50,6 @@ CPSoundPlayBackStatePause = 2;
HTMLAudioElement _audioTag;
int _loadStatus;
int _playBackStatus;
unsigned _implementedDelegateMethods;
}
#pragma mark -
@@ -146,25 +133,6 @@ CPSoundPlayBackStatePause = 2;
}
#pragma mark -
#pragma mark Delegate methods
/*!
Sets the sound's delegate.
@param aDelegate the new delegate
*/
- (void)setDelegate:(id)aDelegate
{
if (_delegate === aDelegate)
return;
_delegate = aDelegate;
_implementedDelegateMethods = 0;
if ([_delegate respondsToSelector:@selector(sound:didFinishPlaying:)])
_implementedDelegateMethods |= CPSoundDelegate_sound_didFinishPlaying_;
}
#pragma mark -
#pragma mark Events listener
@@ -239,7 +207,8 @@ CPSoundPlayBackStatePause = 2;
_audioTag.currentTime = 0.0;
_playBackStatus = CPSoundPlayBackStateStop;
[self _sendDelegateSoundDidFinishPlaying:YES];
if (_delegate && [_delegate respondsToSelector:@selector(sound:didFinishPlaying:)])
[_delegate sound:self didFinishPlaying:YES];
return YES;
}
@@ -347,20 +316,3 @@ CPSoundPlayBackStatePause = 2;
}
@end
@implementation CPSound (CPSoundDelegate)
/*!
@ignore
Call delegate sound:didFinishPlaying:
*/
- (void)_sendDelegateSoundDidFinishPlaying:(BOOL)finishedPlaying
{
if (!(_implementedDelegateMethods & CPSoundDelegate_sound_didFinishPlaying_))
return;
[_delegate sound:self didFinishPlaying:finishedPlaying];
}
@end
+128 -323
View File
@@ -26,40 +26,10 @@
@import "CPImage.j"
@import "CPView.j"
@import "CPCursor.j"
@import "CPTrackingArea.j"
@class CPUserDefaults
@global CPApp
@protocol CPSplitViewDelegate <CPObject>
@optional
- (BOOL)splitView:(CPSplitView)splitView canCollapseSubview:(CPView)subview;
- (BOOL)splitView:(CPSplitView)splitView shouldAdjustSizeOfSubview:(CPView)subview;
- (BOOL)splitView:(CPSplitView)splitView shouldCollapseSubview:(CPView)subview forDoubleClickOnDividerAtIndex:(CPInteger)dividerIndex;
- (CGRect)splitView:(CPSplitView)splitView additionalEffectiveRectOfDividerAtIndex:(CPInteger)dividerIndex;
- (CGRect)splitView:(CPSplitView)splitView effectiveRect:(CGRect)proposedEffectiveRect forDrawnRect:(CGRect)drawnRect ofDividerAtIndex:(CPInteger)dividerIndex;
- (float)splitView:(CPSplitView)splitView constrainMaxCoordinate:(float)proposedMax ofSubviewAt:(CPInteger)dividerIndex;
- (float)splitView:(CPSplitView)splitView constrainMinCoordinate:(float)proposedMin ofSubviewAt:(CPInteger)dividerIndex;
- (float)splitView:(CPSplitView)splitView constrainSplitPosition:(float)proposedPosition ofSubviewAt:(CPInteger)dividerIndex;
- (void)splitView:(CPSplitView)splitView resizeSubviewsWithOldSize:(CGSize)oldSize;
- (void)splitViewDidResizeSubviews:(CPNotification)aNotification;
- (void)splitViewWillResizeSubviews:(CPNotification)aNotification;
@end
var CPSplitViewDelegate_splitView_canCollapseSubview_ = 1 << 0,
CPSplitViewDelegate_splitView_shouldAdjustSizeOfSubview_ = 1 << 1,
CPSplitViewDelegate_splitView_shouldCollapseSubview_forDoubleClickOnDividerAtIndex_ = 1 << 2,
CPSplitViewDelegate_splitView_additionalEffectiveRectOfDividerAtIndex_ = 1 << 3,
CPSplitViewDelegate_splitView_effectiveRect_forDrawnRect_ofDividerAtIndex_ = 1 << 4,
CPSplitViewDelegate_splitView_constrainMaxCoordinate_ofSubviewAt_ = 1 << 5,
CPSplitViewDelegate_splitView_constrainMinCoordinate_ofSubviewAt_ = 1 << 6,
CPSplitViewDelegate_splitView_constrainSplitPosition_ofSubviewAt_ = 1 << 7,
CPSplitViewDelegate_splitView_resizeSubviewsWithOldSize_ = 1 << 8,
CPSplitViewDelegate_splitViewDidResizeSubviews_ = 1 << 9,
CPSplitViewDelegate_splitViewWillResizeSubviews_ = 1 << 10;
#define SPLIT_VIEW_MAYBE_POST_WILL_RESIZE() \
if ((_suppressResizeNotificationsMask & DidPostWillResizeNotification) === 0) \
{ \
@@ -103,31 +73,29 @@ var ShouldSuppressResizeNotifications = 1,
@implementation CPSplitView : CPView
{
id <CPSplitViewDelegate> _delegate;
BOOL _isVertical;
BOOL _isPaneSplitter;
id _delegate;
BOOL _isVertical;
BOOL _isPaneSplitter;
int _currentDivider;
float _initialOffset;
CPDictionary _preCollapsePositions;
int _currentDivider;
float _initialOffset;
CPDictionary _preCollapsePositions;
CPString _originComponent;
CPString _sizeComponent;
CPString _originComponent;
CPString _sizeComponent;
CPArray _DOMDividerElements;
CPString _dividerImagePath;
int _drawingDivider;
CPArray _DOMDividerElements;
CPString _dividerImagePath;
int _drawingDivider;
CPString _autosaveName;
BOOL _shouldAutosave;
CGSize _shouldRestoreFromAutosaveUnlessFrameSize;
CPString _autosaveName;
BOOL _shouldAutosave;
CGSize _shouldRestoreFromAutosaveUnlessFrameSize;
BOOL _needsResizeSubviews;
int _suppressResizeNotificationsMask;
BOOL _needsResizeSubviews;
int _suppressResizeNotificationsMask;
CPArray _buttonBars;
unsigned _implementedDelegateMethods;
CPArray _buttonBars;
}
+ (CPString)defaultThemeClass
@@ -135,7 +103,7 @@ var ShouldSuppressResizeNotifications = 1,
return @"splitview";
}
+ (CPDictionary)themeAttributes
+ (id)themeAttributes
{
return @{
@"divider-thickness": 1.0,
@@ -366,8 +334,8 @@ var ShouldSuppressResizeNotifications = 1,
}
[self _setupDOMDivider];
CPDOMDisplayServerSetStyleLeftTop(_DOMDividerElements[_drawingDivider], NULL, CGRectGetMinX(aRect), CGRectGetMinY(aRect));
CPDOMDisplayServerSetStyleSize(_DOMDividerElements[_drawingDivider], CGRectGetWidth(aRect), CGRectGetHeight(aRect));
CPDOMDisplayServerSetStyleLeftTop(_DOMDividerElements[_drawingDivider], NULL, _CGRectGetMinX(aRect), _CGRectGetMinY(aRect));
CPDOMDisplayServerSetStyleSize(_DOMDividerElements[_drawingDivider], _CGRectGetWidth(aRect), _CGRectGetHeight(aRect));
#endif
}
@@ -438,8 +406,11 @@ var ShouldSuppressResizeNotifications = 1,
buttonBarRect.origin = [self convertPoint:buttonBarRect.origin fromView:buttonBar];
}
effectiveRect = [self _sendDelegateSplitViewEffectiveRect:effectiveRect forDrawnRect:effectiveRect ofDividerAtIndex:anIndex];
additionalRect = [self _sendDelegateSplitViewAdditionalEffectiveRectOfDividerAtIndex:anIndex];
if ([_delegate respondsToSelector:@selector(splitView:effectiveRect:forDrawnRect:ofDividerAtIndex:)])
effectiveRect = [_delegate splitView:self effectiveRect:effectiveRect forDrawnRect:effectiveRect ofDividerAtIndex:anIndex];
if ([_delegate respondsToSelector:@selector(splitView:additionalEffectiveRectOfDividerAtIndex:)])
additionalRect = [_delegate splitView:self additionalEffectiveRectOfDividerAtIndex:anIndex];
return CGRectContainsPoint(effectiveRect, aPoint) ||
(additionalRect && CGRectContainsPoint(additionalRect, aPoint)) ||
@@ -501,21 +472,21 @@ var ShouldSuppressResizeNotifications = 1,
if ([self cursorAtPoint:point hitDividerAtIndex:i])
{
if ([anEvent clickCount] == 2 &&
[self _delegateRespondsToSplitViewCanCollapseSubview] &&
[self _delegateRespondsToSplitViewshouldCollapseSubviewForDoubleClickOnDividerAtIndex])
[_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)] &&
[_delegate respondsToSelector:@selector(splitView:shouldCollapseSubview:forDoubleClickOnDividerAtIndex:)])
{
var minPosition = [self minPossiblePositionOfDividerAtIndex:i],
maxPosition = [self maxPossiblePositionOfDividerAtIndex:i],
preCollapsePosition = [_preCollapsePositions objectForKey:"" + i] || 0;
if ([self _sendDelegateSplitViewCanCollapseSubview:_subviews[i]] && [self _sendDelegateSplitViewShouldCollapseSubview:_subviews[i] forDoubleClickOnDividerAtIndex:i])
if ([_delegate splitView:self canCollapseSubview:_subviews[i]] && [_delegate splitView:self shouldCollapseSubview:_subviews[i] forDoubleClickOnDividerAtIndex:i])
{
if ([self isSubviewCollapsed:_subviews[i]])
[self setPosition:preCollapsePosition ? preCollapsePosition : (minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i];
else
[self setPosition:minPosition ofDividerAtIndex:i];
}
else if ([self _sendDelegateSplitViewCanCollapseSubview:_subviews[i + 1]] && [self _sendDelegateSplitViewShouldCollapseSubview:_subviews[i + 1] forDoubleClickOnDividerAtIndex:i])
else if ([_delegate splitView:self canCollapseSubview:_subviews[i + 1]] && [_delegate splitView:self shouldCollapseSubview:_subviews[i + 1] forDoubleClickOnDividerAtIndex:i])
{
if ([self isSubviewCollapsed:_subviews[i + 1]])
[self setPosition:preCollapsePosition ? preCollapsePosition : (minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i];
@@ -563,6 +534,26 @@ var ShouldSuppressResizeNotifications = 1,
//[[self window] setAcceptsMouseMovedEvents:YES];
}
- (void)mouseEntered:(CPEvent)anEvent
{
// Tracking code handles cursor by itself.
if (_currentDivider == CPNotFound)
[self _updateResizeCursor:anEvent];
}
- (void)mouseMoved:(CPEvent)anEvent
{
if (_currentDivider == CPNotFound)
[self _updateResizeCursor:anEvent];
}
- (void)mouseExited:(CPEvent)anEvent
{
if (_currentDivider == CPNotFound)
// FIXME: we should use CPCursor push/pop (if previous currentCursor != arrow).
[[CPCursor arrowCursor] set];
}
- (void)_updateResizeCursor:(CPEvent)anEvent
{
var point = [self convertPoint:[anEvent locationInWindow] fromView:nil];
@@ -589,8 +580,12 @@ var ShouldSuppressResizeNotifications = 1,
if (sizeA === 0)
canGrow = YES; // Subview is collapsed.
else if (!canShrink && [self _sendDelegateSplitViewCanCollapseSubview:_subviews[i]])
else if (!canShrink &&
[_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)] &&
[_delegate splitView:self canCollapseSubview:_subviews[i]])
{
canShrink = YES; // Subview is collapsible.
}
if (sizeB === 0)
{
@@ -599,7 +594,9 @@ var ShouldSuppressResizeNotifications = 1,
// It's safe to assume it can always be uncollapsed.
canShrink = YES;
}
else if (!canGrow && [self _sendDelegateSplitViewCanCollapseSubview:_subviews[i + 1]])
else if (!canGrow &&
[_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)] &&
[_delegate splitView:self canCollapseSubview:_subviews[i + 1]])
{
canGrow = YES; // Right/lower subview is collapsible.
}
@@ -660,38 +657,53 @@ var ShouldSuppressResizeNotifications = 1,
- (int)_realPositionForPosition:(float)position ofDividerAtIndex:(int)dividerIndex
{
// not sure where this should override other positions?
var proposedPosition = [self _sendDelegateSplitViewConstrainSplitPosition:position ofSubviewAt:dividerIndex];
if ([_delegate respondsToSelector:@selector(splitView:constrainSplitPosition:ofSubviewAt:)])
{
var proposedPosition = [_delegate splitView:self constrainSplitPosition:position ofSubviewAt:dividerIndex];
// Silently ignore bad positions which could result from odd delegate responses. We don't want these
// bad results to go into the system and cause havoc with frame sizes as the split view tries to resize
// its subviews.
if (_IS_NUMERIC(proposedPosition))
position = proposedPosition;
// Silently ignore bad positions which could result from odd delegate responses. We don't want these
// bad results to go into the system and cause havoc with frame sizes as the split view tries to resize
// its subviews.
if (_IS_NUMERIC(proposedPosition))
position = proposedPosition;
}
var proposedMax = [self maxPossiblePositionOfDividerAtIndex:dividerIndex],
proposedMin = [self minPossiblePositionOfDividerAtIndex:dividerIndex],
actualMax = proposedMax,
actualMin = proposedMin,
proposedActualMin = [self _sendDelegateSplitViewConstrainMinCoordinate:proposedMin ofSubviewAt:dividerIndex],
proposedActualMax = [self _sendDelegateSplitViewConstrainMaxCoordinate:proposedMax ofSubviewAt:dividerIndex];
actualMin = proposedMin;
if (_IS_NUMERIC(proposedActualMin))
actualMin = proposedActualMin;
if ([_delegate respondsToSelector:@selector(splitView:constrainMinCoordinate:ofSubviewAt:)])
{
var proposedActualMin = [_delegate splitView:self constrainMinCoordinate:proposedMin ofSubviewAt:dividerIndex];
if (_IS_NUMERIC(proposedActualMax))
actualMax = proposedActualMax;
if (_IS_NUMERIC(proposedActualMin))
actualMin = proposedActualMin;
}
if ([_delegate respondsToSelector:@selector(splitView:constrainMaxCoordinate:ofSubviewAt:)])
{
var proposedActualMax = [_delegate splitView:self constrainMaxCoordinate:proposedMax ofSubviewAt:dividerIndex];
if (_IS_NUMERIC(proposedActualMax))
actualMax = proposedActualMax;
}
var viewA = _subviews[dividerIndex],
viewB = _subviews[dividerIndex + 1],
realPosition = MAX(MIN(position, actualMax), actualMin);
// Is this position past the halfway point to collapse?
if ((position < proposedMin + (actualMin - proposedMin) / 2) && [self _sendDelegateSplitViewCanCollapseSubview:viewA])
realPosition = proposedMin;
if (position < proposedMin + (actualMin - proposedMin) / 2)
if ([_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)])
if ([_delegate splitView:self canCollapseSubview:viewA])
realPosition = proposedMin;
// We can also collapse to the right.
if ((position > proposedMax - (proposedMax - actualMax) / 2) && [self _sendDelegateSplitViewCanCollapseSubview:viewB])
realPosition = proposedMax;
if (position > proposedMax - (proposedMax - actualMax) / 2)
if ([_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)])
if ([_delegate splitView:self canCollapseSubview:viewB])
realPosition = proposedMax;
return realPosition;
}
@@ -775,9 +787,9 @@ var ShouldSuppressResizeNotifications = 1,
- (void)resizeSubviewsWithOldSize:(CGSize)oldSize
{
if ([self _delegateRespondsToSplitViewResizeSubviewsWithOldSize])
if ([_delegate respondsToSelector:@selector(splitView:resizeSubviewsWithOldSize:)])
{
[self _sendDelegateSplitViewResizeSubviewsWithOldSize:oldSize];
[_delegate splitView:self resizeSubviewsWithOldSize:oldSize];
return;
}
@@ -803,7 +815,8 @@ var ShouldSuppressResizeNotifications = 1,
oldFlexibleSpace = 0,
totalSizablePanes = 0,
isSizableMap = {},
viewSizes = [];
viewSizes = [],
delegateRespondsToShouldAdjust = [_delegate respondsToSelector:@selector(splitView:shouldAdjustSizeOfSubview:)];
// What we want to do is to preserve non resizable sizes first, and then to preserve the ratio of size to available
// non fixed space for every other subview. E.g. assume fixed space was 20 pixels initially, view 1 was 20 and
@@ -819,7 +832,7 @@ var ShouldSuppressResizeNotifications = 1,
for (index = 0; index < count; ++index)
{
var view = _subviews[index],
isSizable = [self _sendDelegateSplitViewShouldAdjustSizeOfSubview:view],
isSizable = !delegateRespondsToShouldAdjust || [_delegate splitView:self shouldAdjustSizeOfSubview:view],
size = [view frame].size[_sizeComponent];
isSizableMap[index] = isSizable;
@@ -945,47 +958,25 @@ The sum of the views and the sum of the dividers should be equal to the size of
@param delegate - The delegate of the splitview.
*/
- (void)setDelegate:(id <CPSplitViewDelegate>)aDelegate
- (void)setDelegate:(id)delegate
{
if (_delegate === aDelegate)
return;
_delegate = aDelegate;
_implementedDelegateMethods = 0;
if ([_delegate respondsToSelector:@selector(splitViewWillResizeSubviews:)])
_implementedDelegateMethods |= CPSplitViewDelegate_splitViewWillResizeSubviews_;
if ([_delegate respondsToSelector:@selector(splitViewDidResizeSubviews:)])
_implementedDelegateMethods |= CPSplitViewDelegate_splitViewDidResizeSubviews_;
[[CPNotificationCenter defaultCenter] removeObserver:_delegate name:CPSplitViewDidResizeSubviewsNotification object:self];
if ([_delegate respondsToSelector:@selector(splitViewWillResizeSubviews:)])
[[CPNotificationCenter defaultCenter] removeObserver:_delegate name:CPSplitViewWillResizeSubviewsNotification object:self];
if ([_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)])
_implementedDelegateMethods |= CPSplitViewDelegate_splitView_canCollapseSubview_;
if ([_delegate respondsToSelector:@selector(splitView:shouldAdjustSizeOfSubview:)])
_implementedDelegateMethods |= CPSplitViewDelegate_splitView_shouldAdjustSizeOfSubview_;
if ([_delegate respondsToSelector:@selector(splitView:shouldCollapseSubview:forDoubleClickOnDividerAtIndex:)])
_implementedDelegateMethods |= CPSplitViewDelegate_splitView_shouldCollapseSubview_forDoubleClickOnDividerAtIndex_;
if ([_delegate respondsToSelector:@selector(splitView:additionalEffectiveRectOfDividerAtIndex:)])
_implementedDelegateMethods |= CPSplitViewDelegate_splitView_additionalEffectiveRectOfDividerAtIndex_;
if ([_delegate respondsToSelector:@selector(splitView:effectiveRect:forDrawnRect:ofDividerAtIndex:)])
_implementedDelegateMethods |= CPSplitViewDelegate_splitView_effectiveRect_forDrawnRect_ofDividerAtIndex_;
if ([_delegate respondsToSelector:@selector(splitView:constrainMaxCoordinate:ofSubviewAt:)])
_implementedDelegateMethods |= CPSplitViewDelegate_splitView_constrainMaxCoordinate_ofSubviewAt_;
if ([_delegate respondsToSelector:@selector(splitView:constrainMinCoordinate:ofSubviewAt:)])
_implementedDelegateMethods |= CPSplitViewDelegate_splitView_constrainMinCoordinate_ofSubviewAt_;
if ([_delegate respondsToSelector:@selector(splitView:constrainSplitPosition:ofSubviewAt:)])
_implementedDelegateMethods |= CPSplitViewDelegate_splitView_constrainSplitPosition_ofSubviewAt_;
if ([_delegate respondsToSelector:@selector(splitView:resizeSubviewsWithOldSize:)])
_implementedDelegateMethods |= CPSplitViewDelegate_splitView_resizeSubviewsWithOldSize_;
_delegate = delegate;
if ([_delegate respondsToSelector:@selector(splitViewDidResizeSubviews:)])
[[CPNotificationCenter defaultCenter] addObserver:_delegate
selector:@selector(splitViewDidResizeSubviews:)
name:CPSplitViewDidResizeSubviewsNotification
object:self];
if ([_delegate respondsToSelector:@selector(splitViewWillResizeSubviews:)])
[[CPNotificationCenter defaultCenter] addObserver:_delegate
selector:@selector(splitViewWillResizeSubviews:)
name:CPSplitViewWillResizeSubviewsNotification
object:self];
}
/*!
@@ -1004,7 +995,7 @@ The sum of the views and the sum of the dividers should be equal to the size of
@param unsigned int - The divider index the button bar will be assigned to.
*/
// FIXME Should be renamed to setButtonBar:ofDividerAtIndex:.
- (void)setButtonBar:(CPButtonBar)aButtonBar forDividerAtIndex:(CPUInteger)dividerIndex
- (void)setButtonBar:(CPButtonBar)aButtonBar forDividerAtIndex:(unsigned)dividerIndex
{
if (!aButtonBar)
{
@@ -1035,12 +1026,27 @@ The sum of the views and the sum of the dividers should be equal to the size of
- (void)_postNotificationWillResize
{
[self _sendDelegateSplitViewWillResizeSubviews];
var userInfo = nil;
if (_currentDivider !== CPNotFound)
userInfo = @{ @"CPSplitViewDividerIndex": _currentDivider };
[[CPNotificationCenter defaultCenter] postNotificationName:CPSplitViewWillResizeSubviewsNotification
object:self
userInfo:userInfo];
}
- (void)_postNotificationDidResize
{
[self _sendDelegateSplitViewDidResizeSubviews];
var userInfo = nil;
if (_currentDivider !== CPNotFound)
userInfo = @{ @"CPSplitViewDividerIndex": _currentDivider };
[[CPNotificationCenter defaultCenter] postNotificationName:CPSplitViewDidResizeSubviewsNotification
object:self
userInfo:userInfo];
// TODO Cocoa always autosaves on "viewDidEndLiveResize". If Cappuccino adds support for this we
// should do the same.
@@ -1104,7 +1110,7 @@ The sum of the views and the sum of the dividers should be equal to the size of
*/
- (void)_restoreFromAutosaveIfNeeded
{
if (_shouldRestoreFromAutosaveUnlessFrameSize && !CGSizeEqualToSize([self frameSize], _shouldRestoreFromAutosaveUnlessFrameSize))
if (_shouldRestoreFromAutosaveUnlessFrameSize && !_CGSizeEqualToSize([self frameSize], _shouldRestoreFromAutosaveUnlessFrameSize))
{
[self _restoreFromAutosave];
}
@@ -1186,207 +1192,6 @@ The sum of the views and the sum of the dividers should be equal to the size of
@end
@implementation CPSplitView (CPTrackingArea)
- (void)updateTrackingAreas
{
[self removeAllTrackingAreas];
var options = CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow;
for (var i = 0; i < _subviews.length - 1; i++)
[self addTrackingArea:[[CPTrackingArea alloc] initWithRect:[self effectiveRectOfDividerAtIndex:i]
options:options
owner:self
userInfo:nil]];
}
- (void)cursorUpdate:(CPEvent)anEvent
{
if (_currentDivider === CPNotFound)
[self _updateResizeCursor:anEvent];
}
@end
@implementation CPSplitView (CPSplitViewDelegate)
/*!
@ignore
Return YES if the delegate implements splitView:resizeSubviewsWithOldSize:
*/
- (BOOL)_delegateRespondsToSplitViewResizeSubviewsWithOldSize
{
return _implementedDelegateMethods & CPSplitViewDelegate_splitView_resizeSubviewsWithOldSize_;
}
/*!
@ignore
Return YES if the delegate implements splitView:canCollapseSubview:
*/
- (BOOL)_delegateRespondsToSplitViewCanCollapseSubview
{
return _implementedDelegateMethods & CPSplitViewDelegate_splitView_canCollapseSubview_;
}
/*!
@ignore
Return YES if the delegate implements splitView:shouldCollapseSubview:forDoubleClickOnDividerAtIndex
*/
- (BOOL)_delegateRespondsToSplitViewshouldCollapseSubviewForDoubleClickOnDividerAtIndex
{
return _implementedDelegateMethods & CPSplitViewDelegate_splitView_shouldCollapseSubview_forDoubleClickOnDividerAtIndex_;
}
/*!
@ignore
Call the delegate splitView:canCollapseSubview:
*/
- (BOOL)_sendDelegateSplitViewCanCollapseSubview:(CPView)aView
{
if (!(_implementedDelegateMethods & CPSplitViewDelegate_splitView_canCollapseSubview_))
return NO;
return [_delegate splitView:self canCollapseSubview:aView];
}
/*!
@ignore
Call the delegate splitView:shouldAdjustSizeOfSubview:
*/
- (BOOL)_sendDelegateSplitViewShouldAdjustSizeOfSubview:(CPView)aView
{
if (!(_implementedDelegateMethods & CPSplitViewDelegate_splitView_shouldAdjustSizeOfSubview_))
return YES;
return [_delegate splitView:self shouldAdjustSizeOfSubview:aView];
}
/*!
@ignore
Call the delegate splitView:shouldCollapseSubview:forDoubleClickOnDividerAtIndex:
*/
- (BOOL)_sendDelegateSplitViewShouldCollapseSubview:(CPView)aView forDoubleClickOnDividerAtIndex:(int)anIndex
{
if (!(_implementedDelegateMethods & CPSplitViewDelegate_splitView_shouldCollapseSubview_forDoubleClickOnDividerAtIndex_))
return NO;
return [_delegate splitView:self shouldCollapseSubview:aView forDoubleClickOnDividerAtIndex:anIndex];
}
/*!
@ignore
Call the delegate splitView:additionalEffectiveRectOfDividerAtIndex:
*/
- (CGRect)_sendDelegateSplitViewAdditionalEffectiveRectOfDividerAtIndex:(int)anIndex
{
if (!(_implementedDelegateMethods & CPSplitViewDelegate_splitView_additionalEffectiveRectOfDividerAtIndex_))
return nil;
return [_delegate splitView:self additionalEffectiveRectOfDividerAtIndex:anIndex];
}
/*!
@ignore
Call the delegate splitView:effectiveRect:forDrawnRect:ofDividerAtIndex:
*/
- (CGRect)_sendDelegateSplitViewEffectiveRect:(CGRect)proposedEffectiveRect forDrawnRect:(CGRect)drawnRect ofDividerAtIndex:(CPInteger)dividerIndex
{
if (!(_implementedDelegateMethods & CPSplitViewDelegate_splitView_effectiveRect_forDrawnRect_ofDividerAtIndex_))
return proposedEffectiveRect;
return [_delegate splitView:self effectiveRect:proposedEffectiveRect forDrawnRect:drawnRect ofDividerAtIndex:dividerIndex];
}
/*!
@ignore
Call the delegate splitView:constrainMaxCoordinate:ofSubviewAt:
*/
- (float)_sendDelegateSplitViewConstrainMaxCoordinate:(float)proposedMax ofSubviewAt:(CPInteger)dividerIndex
{
if (!(_implementedDelegateMethods & CPSplitViewDelegate_splitView_constrainMaxCoordinate_ofSubviewAt_))
return nil;
return [_delegate splitView:self constrainMaxCoordinate:proposedMax ofSubviewAt:dividerIndex];
}
/*!
@ignore
Call the delegate splitView:constrainMinCoordinate:ofSubviewAt:
*/
- (float)_sendDelegateSplitViewConstrainMinCoordinate:(float)proposedMin ofSubviewAt:(CPInteger)dividerIndex
{
if (!(_implementedDelegateMethods & CPSplitViewDelegate_splitView_constrainMinCoordinate_ofSubviewAt_))
return nil;
return [_delegate splitView:self constrainMinCoordinate:proposedMin ofSubviewAt:dividerIndex];
}
/*!
@ignore
Call the delegate splitView:constrainSplitPosition:ofSubviewAt:
*/
- (float)_sendDelegateSplitViewConstrainSplitPosition:(float)proposedMax ofSubviewAt:(CPInteger)dividerIndex
{
if (!(_implementedDelegateMethods & CPSplitViewDelegate_splitView_constrainSplitPosition_ofSubviewAt_))
return nil;
return [_delegate splitView:self constrainSplitPosition:proposedMax ofSubviewAt:dividerIndex];
}
/*!
@ignore
Call the delegate splitView:resizeSubviewsWithOldSize:
*/
- (void)_sendDelegateSplitViewResizeSubviewsWithOldSize:(CGSize)oldSize
{
if (!(_implementedDelegateMethods & CPSplitViewDelegate_splitView_resizeSubviewsWithOldSize_))
return;
[_delegate splitView:self resizeSubviewsWithOldSize:oldSize];
}
/*!
@ignore
Call the delegate splitViewWillResizeSubviews:
*/
- (void)_sendDelegateSplitViewWillResizeSubviews
{
var userInfo = nil;
if (_currentDivider !== CPNotFound)
userInfo = @{ @"CPSplitViewDividerIndex": _currentDivider };
if (_implementedDelegateMethods & CPSplitViewDelegate_splitViewWillResizeSubviews_)
[_delegate splitViewWillResizeSubviews:[[CPNotification alloc] initWithName:CPSplitViewWillResizeSubviewsNotification object:self userInfo:userInfo]];
[[CPNotificationCenter defaultCenter] postNotificationName:CPSplitViewWillResizeSubviewsNotification object:self userInfo:userInfo];
}
/*!
@ignore
Call the delegate splitViewDidResizeSubviews:
*/
- (void)_sendDelegateSplitViewDidResizeSubviews
{
var userInfo = nil;
if (_currentDivider !== CPNotFound)
userInfo = @{ @"CPSplitViewDividerIndex": _currentDivider };
if (_implementedDelegateMethods & CPSplitViewDelegate_splitViewDidResizeSubviews_)
[_delegate splitViewDidResizeSubviews:[[CPNotification alloc] initWithName:CPSplitViewDidResizeSubviewsNotification object:self userInfo:userInfo]];
[[CPNotificationCenter defaultCenter] postNotificationName:CPSplitViewDidResizeSubviewsNotification object:self userInfo:userInfo];
[self updateTrackingAreas];
}
@end
var CPSplitViewDelegateKey = "CPSplitViewDelegateKey",
CPSplitViewIsVerticalKey = "CPSplitViewIsVerticalKey",
CPSplitViewIsPaneSplitterKey = "CPSplitViewIsPaneSplitterKey",
+29 -36
View File
@@ -25,6 +25,7 @@
@import "CPTextField.j"
/*!
CPStepper is an implementation of Cocoa NSStepper.
@@ -52,9 +53,9 @@
@param maxValue the maximal acceptable value of the stepper
@return Initialized CPStepper
*/
+ (id)stepperWithInitialValue:(float)aValue minValue:(float)aMinValue maxValue:(float)aMaxValue
+ (CPStepper)stepperWithInitialValue:(float)aValue minValue:(float)aMinValue maxValue:(float)aMaxValue
{
var stepper = [[self alloc] initWithFrame:CGRectMakeZero()];
var stepper = [[CPStepper alloc] initWithFrame:_CGRectMakeZero()];
[stepper setDoubleValue:aValue];
[stepper setMinValue:aMinValue];
@@ -74,14 +75,14 @@
@return Initialized CPStepper
*/
+ (id)stepper
+ (CPStepper)stepper
{
return [CPStepper stepperWithInitialValue:0.0 minValue:0.0 maxValue:59.0];
}
+ (Class)_binderClassForBinding:(CPString)aBinding
{
if (aBinding === CPValueBinding || aBinding === CPMinValueBinding || aBinding === CPMaxValueBinding)
if (aBinding == CPValueBinding || aBinding == CPMinValueBinding || aBinding == CPMaxValueBinding)
return [_CPStepperValueBinder class];
return [super _binderClassForBinding:aBinding];
@@ -89,7 +90,7 @@
- (CPString)_replacementKeyPathForBinding:(CPString)aBinding
{
if (aBinding === CPValueBinding)
if (aBinding == CPValueBinding)
return @"doubleValue";
return [super _replacementKeyPathForBinding:aBinding];
@@ -121,14 +122,14 @@
- (void)_init
{
_buttonUp = [[CPButton alloc] initWithFrame:CGRectMakeZero()];
_buttonUp = [[CPButton alloc] initWithFrame:_CGRectMakeZero()];
[_buttonUp setContinuous:_autorepeat];
[_buttonUp setTarget:self];
[_buttonUp setAction:@selector(_buttonDidClick:)];
[_buttonUp setAutoresizingMask:CPViewNotSizable];
[self addSubview:_buttonUp];
_buttonDown = [[CPButton alloc] initWithFrame:CGRectMakeZero()];
_buttonDown = [[CPButton alloc] initWithFrame:_CGRectMakeZero()];
[_buttonDown setContinuous:_autorepeat];
[_buttonDown setTarget:self];
[_buttonDown setAction:@selector(_buttonDidClick:)];
@@ -137,16 +138,9 @@
[self setContinuous:_autorepeat];
[self addSubview:_buttonDown];
[self _sizeToFit];
[self setNeedsLayout];
}
- (void)setControlSize:(CPControlSize)aControlSize
{
[super setControlSize:aControlSize];
[self _sizeToFit];
}
#pragma mark -
#pragma mark Superclass overrides
@@ -165,10 +159,10 @@
- (void)setFrame:(CGRect)aFrame
{
var upSize = [self currentValueForThemeAttribute:@"up-button-size"],
downSize = [self currentValueForThemeAttribute:@"down-button-size"],
minSize = CGSizeMake(upSize.width, upSize.height + downSize.height),
frame = CGRectMakeCopy(aFrame);
var upSize = [self valueForThemeAttribute:@"up-button-size"],
downSize = [self valueForThemeAttribute:@"down-button-size"],
minSize = _CGSizeMake(upSize.width, upSize.height + downSize.height),
frame = _CGRectMakeCopy(aFrame);
frame.size.width = MAX(minSize.width, frame.size.width);
frame.size.height = MAX(minSize.height, frame.size.height);
@@ -178,22 +172,21 @@
/*! @ignore */
- (void)layoutSubviews
{
var controlSizeThemeState = [self _controlSizeThemeState],
aFrame = [self frame],
upSize = [self valueForThemeAttribute:@"up-button-size" inState:controlSizeThemeState],
downSize = [self valueForThemeAttribute:@"down-button-size" inState:controlSizeThemeState],
upFrame = CGRectMake(0, 0, upSize.width, upSize.height),
downFrame = CGRectMake(0, upSize.height, downSize.width, downSize.height);
var aFrame = [self frame],
upSize = [self valueForThemeAttribute:@"up-button-size"],
downSize = [self valueForThemeAttribute:@"down-button-size"],
upFrame = _CGRectMake(aFrame.size.width - upSize.width, 0, upSize.width, upSize.height),
downFrame = _CGRectMake(aFrame.size.width - downSize.width, upSize.height, downSize.width, downSize.height);
[_buttonUp setFrame:upFrame];
[_buttonDown setFrame:downFrame];
[_buttonUp setValue:[self valueForThemeAttribute:@"bezel-color-up-button" inStates:[controlSizeThemeState, CPThemeStateBordered]] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered];
[_buttonUp setValue:[self valueForThemeAttribute:@"bezel-color-up-button" inStates:[controlSizeThemeState, CPThemeStateBordered, CPThemeStateDisabled]] forThemeAttribute:@"bezel-color" inStates:[CPThemeStateBordered, CPThemeStateDisabled]];
[_buttonUp setValue:[self valueForThemeAttribute:@"bezel-color-up-button" inStates:[controlSizeThemeState, CPThemeStateBordered, CPThemeStateHighlighted]] forThemeAttribute:@"bezel-color" inStates:[CPThemeStateBordered, CPThemeStateHighlighted]];
[_buttonDown setValue:[self valueForThemeAttribute:@"bezel-color-down-button" inStates:[controlSizeThemeState, CPThemeStateBordered]] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered];
[_buttonDown setValue:[self valueForThemeAttribute:@"bezel-color-down-button" inStates:[controlSizeThemeState, CPThemeStateBordered, CPThemeStateDisabled]] forThemeAttribute:@"bezel-color" inStates:[CPThemeStateBordered, CPThemeStateDisabled]];
[_buttonDown setValue:[self valueForThemeAttribute:@"bezel-color-down-button" inStates:[controlSizeThemeState, CPThemeStateBordered, CPThemeStateHighlighted]] forThemeAttribute:@"bezel-color" inStates:[CPThemeStateBordered, CPThemeStateHighlighted]];
[_buttonUp setValue:[self valueForThemeAttribute:@"bezel-color-up-button" inState:CPThemeStateBordered] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered];
[_buttonUp setValue:[self valueForThemeAttribute:@"bezel-color-up-button" inState:CPThemeStateBordered | CPThemeStateDisabled] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered | CPThemeStateDisabled];
[_buttonUp setValue:[self valueForThemeAttribute:@"bezel-color-up-button" inState:CPThemeStateBordered | CPThemeStateHighlighted] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered | CPThemeStateHighlighted];
[_buttonDown setValue:[self valueForThemeAttribute:@"bezel-color-down-button" inState:CPThemeStateBordered] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered];
[_buttonDown setValue:[self valueForThemeAttribute:@"bezel-color-down-button" inState:CPThemeStateBordered | CPThemeStateDisabled] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered | CPThemeStateDisabled];
[_buttonDown setValue:[self valueForThemeAttribute:@"bezel-color-down-button" inState:CPThemeStateBordered | CPThemeStateHighlighted] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered | CPThemeStateHighlighted];
}
- (void)_sizeToFit
@@ -220,7 +213,7 @@
Set the current value of the stepper.
@param aValue a float containing the value
*/
- (void)setDoubleValue:(double)aValue
- (void)setDoubleValue:(float)aValue
{
if (aValue > _maxValue)
[super setDoubleValue:_valueWraps ? _minValue : _maxValue];
@@ -239,7 +232,7 @@
if (![self isEnabled])
return;
if (aSender === _buttonUp)
if (aSender == _buttonUp)
[self setDoubleValue:([self doubleValue] + _increment)];
else
[self setDoubleValue:([self doubleValue] - _increment)];
@@ -274,13 +267,13 @@
return @"stepper";
}
+ (CPDictionary)themeAttributes
+ (id)themeAttributes
{
return @{
@"bezel-color-up-button": [CPNull null],
@"bezel-color-down-button": [CPNull null],
@"up-button-size": CGSizeMakeZero(),
@"down-button-size": CGSizeMakeZero(),
@"up-button-size": _CGSizeMakeZero(),
@"down-button-size": _CGSizeMakeZero(),
};
}
@@ -292,7 +285,7 @@
- (void)_updatePlaceholdersWithOptions:(CPDictionary)options forBinding:(CPString)aBinding
{
var placeholder = (aBinding === CPMaxValueBinding) ? [_source maxValue] : [_source minValue];
var placeholder = (aBinding == CPMaxValueBinding) ? [_source maxValue] : [_source minValue];
[super _updatePlaceholdersWithOptions:options];
+105 -407
View File
@@ -25,7 +25,6 @@
@import "CPTabViewItem.j"
@import "CPView.j"
@typedef CPTabViewType
CPTopTabsBezelBorder = 0;
//CPLeftTabsBezelBorder = 1;
CPBottomTabsBezelBorder = 2;
@@ -34,24 +33,10 @@ CPNoTabsBezelBorder = 4; //Displays no tabs and has a bezeled border.
CPNoTabsLineBorder = 5; //Has no tabs and displays a line border.
CPNoTabsNoBorder = 6; //Displays no tabs and no border.
@class _CPTabViewBox
var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
CPTabViewShouldSelectTabViewItemSelector = 1 << 2,
CPTabViewWillSelectTabViewItemSelector = 1 << 3,
CPTabViewDidChangeNumberOfTabViewItemsSelector = 1 << 4;
@protocol CPTabViewDelegate <CPObject>
@optional
- (BOOL)tabView:(CPTabView)tabView shouldSelectTabViewItem:(CPTabViewItem)tabViewItem;
- (void)tabView:(CPTabView)tabView didSelectTabViewItem:(CPTabViewItem)tabViewItem;
- (void)tabView:(CPTabView)tabView willSelectTabViewItem:(CPTabViewItem)tabViewItem;
- (void)tabViewDidChangeNumberOfTabViewItems:(CPTabView)tabView;
@end
var CPTabViewDidSelectTabViewItemSelector = 1,
CPTabViewShouldSelectTabViewItemSelector = 2,
CPTabViewWillSelectTabViewItemSelector = 4,
CPTabViewDidChangeNumberOfTabViewItemsSelector = 8;
/*!
@ingroup appkit
@@ -63,27 +48,27 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
*/
@implementation CPTabView : CPView
{
CPArray _items;
CPArray _items;
CPSegmentedControl _tabs;
_CPTabViewBox _box;
CPView _placeHolderView;
CPSegmentedControl _tabs;
CPBox _box;
CPTabViewItem _selectedTabViewItem;
CPNumber _selectedIndex;
CPTabViewType _type;
CPFont _font;
CPTabViewType _type;
CPFont _font;
id <CPTabViewDelegate> _delegate;
unsigned _delegateSelectors;
id _delegate;
unsigned _delegateSelectors;
}
- (id)initWithFrame:(CGRect)aFrame
{
if (self = [super initWithFrame:aFrame])
{
_items = [CPArray array];
[self _init];
_selectedTabViewItem = nil;
[self setTabViewType:CPTopTabsBezelBorder];
}
@@ -92,26 +77,19 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
- (void)_init
{
_tabs = [[CPSegmentedControl alloc] initWithFrame:CGRectMakeZero()];
_selectedIndex = CPNotFound;
_tabs = [[CPSegmentedControl alloc] initWithFrame:_CGRectMake(0, 0, 0, 0)];
[_tabs setHitTests:NO];
[_tabs setSegments:[CPArray array]];
var height = [_tabs valueForThemeAttribute:@"min-size"].height;
[_tabs setFrameSize:CGSizeMake(0, height)];
var height = [_tabs valueForThemeAttribute:@"default-height"];
[_tabs setFrameSize:_CGSizeMake(0, height)];
_box = [[_CPTabViewBox alloc] initWithFrame:[self bounds]];
[_box setTabView:self];
_box = [[CPBox alloc] initWithFrame:[self bounds]];
[self setBackgroundColor:[CPColor colorWithCalibratedWhite:0.95 alpha:1.0]];
[self addSubview:_box];
[self addSubview:_tabs];
_placeHolderView = nil;
}
- (CPArray)items
{
return [_tabs segments];
}
// Adding and Removing Tabs
@@ -121,7 +99,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
*/
- (void)addTabViewItem:(CPTabViewItem)aTabViewItem
{
[self insertTabViewItem:aTabViewItem atIndex:[self numberOfTabViewItems]];
[self insertTabViewItem:aTabViewItem atIndex:[_items count]];
}
/*!
@@ -129,20 +107,17 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
@param aTabViewItem the item to insert
@param anIndex the index for the item
*/
- (void)insertTabViewItem:(CPTabViewItem)aTabViewItem atIndex:(CPUInteger)anIndex
- (void)insertTabViewItem:(CPTabViewItem)aTabViewItem atIndex:(unsigned)anIndex
{
[self _insertTabViewItems:[aTabViewItem] atIndexes:[CPIndexSet indexSetWithIndex:anIndex]];
}
[_items insertObject:aTabViewItem atIndex:anIndex];
- (void)_insertTabViewItems:(CPArray)tabViewItems atIndexes:(CPIndexSet)indexes
{
[_tabs insertSegments:tabViewItems atIndexes:indexes];
[tabViewItems makeObjectsPerformSelector:@selector(_setTabView:) withObject:self];
[self _updateItems];
[self _repositionTabs];
[self tileWithChangedItem:[tabViewItems firstObject]];
[self _reverseSetContent];
[aTabViewItem _setTabView:self];
[self _sendDelegateTabViewDidChangeNumberOfTabViewItems];
if (_delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector)
[_delegate tabViewDidChangeNumberOfTabViewItems:self];
}
/*!
@@ -151,39 +126,23 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
*/
- (void)removeTabViewItem:(CPTabViewItem)aTabViewItem
{
var idx = [[self items] indexOfObjectIdenticalTo:aTabViewItem];
var count = [_items count];
for (var i = 0; i < count; i++)
{
if ([_items objectAtIndex:i] === aTabViewItem)
{
[_items removeObjectAtIndex:i];
break;
}
}
if (idx == CPNotFound)
return;
[self _updateItems];
[self _repositionTabs];
[_tabs removeSegmentsAtIndexes:[CPIndexSet indexSetWithIndex:idx]];
[aTabViewItem _setTabView:nil];
[self tileWithChangedItem:nil];
[self _didRemoveTabViewItem:aTabViewItem atIndex:idx];
[self _reverseSetContent];
[self _sendDelegateTabViewDidChangeNumberOfTabViewItems];
}
- (void)_didRemoveTabViewItem:(CPTabViewItem)aTabViewItem atIndex:(CPInteger)idx
{
// If the selection is managed by bindings, let the binder do that.
if ([self binderForBinding:CPSelectionIndexesBinding] || [self binderForBinding:CPSelectedIndexBinding])
return;
if (_selectedTabViewItem == aTabViewItem)
{
var didSelect = NO;
if (idx > 0)
didSelect = [self selectTabViewItemAtIndex:idx - 1];
else if ([self numberOfTabViewItems] > 0)
didSelect = [self selectTabViewItemAtIndex:0];
if (didSelect == NO)
_selectedTabViewItem == nil;
}
if (_delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector)
[_delegate tabViewDidChangeNumberOfTabViewItems:self];
}
// Accessing Tabs
@@ -194,7 +153,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
*/
- (int)indexOfTabViewItem:(CPTabViewItem)aTabViewItem
{
return [[self items] indexOfObjectIdenticalTo:aTabViewItem];
return [_items indexOfObjectIdenticalTo:aTabViewItem];
}
/*!
@@ -204,10 +163,11 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
*/
- (int)indexOfTabViewItemWithIdentifier:(CPString)anIdentifier
{
return [[self items] indexOfObjectPassingTest:function(item, idx, stop)
{
return [[item identifier] isEqual:anIdentifier];
}];
for (var index = [_items count]; index >= 0; index--)
if ([[_items[index] identifier] isEqual:anIdentifier])
return index;
return CPNotFound;
}
/*!
@@ -216,16 +176,16 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
*/
- (unsigned)numberOfTabViewItems
{
return [[self items] count];
return [_items count];
}
/*!
Returns the CPTabViewItem at the specified index.
@return a tab view item, or nil
*/
- (CPTabViewItem)tabViewItemAtIndex:(CPUInteger)anIndex
- (CPTabViewItem)tabViewItemAtIndex:(unsigned)anIndex
{
return [[self items] objectAtIndex:anIndex];
return [_items objectAtIndex:anIndex];
}
/*!
@@ -234,7 +194,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
*/
- (CPArray)tabViewItems
{
return [[self items] copy]; // Copy?
return [_items copy]; // Copy?
}
// Selecting a Tab
@@ -244,7 +204,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
*/
- (void)selectFirstTabViewItem:(id)aSender
{
if ([self numberOfTabViewItems] === 0)
if ([_items count] === 0)
return; // throw?
[self selectTabViewItemAtIndex:0];
@@ -256,10 +216,10 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
*/
- (void)selectLastTabViewItem:(id)aSender
{
if ([self numberOfTabViewItems] === 0)
if ([_items count] === 0)
return; // throw?
[self selectTabViewItemAtIndex:[self numberOfTabViewItems] - 1];
[self selectTabViewItemAtIndex:[_items count] - 1];
}
/*!
@@ -268,12 +228,12 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
*/
- (void)selectNextTabViewItem:(id)aSender
{
if (_selectedTabViewItem === nil)
if (_selectedIndex === CPNotFound)
return;
var nextIndex = [self indexOfTabViewItem:_selectedTabViewItem] + 1;
var nextIndex = _selectedIndex + 1;
if (nextIndex === [self numberOfTabViewItems])
if (nextIndex === [_items count])
// does nothing. According to spec at (http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Reference/ApplicationKit/Classes/NSTabView_Class/Reference/Reference.html#//apple_ref/occ/instm/NSTabView/selectNextTabViewItem:)
return;
@@ -286,10 +246,10 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
*/
- (void)selectPreviousTabViewItem:(id)aSender
{
if (_selectedTabViewItem === nil)
if (_selectedIndex === CPNotFound)
return;
var previousIndex = [self indexOfTabViewItem:_selectedTabViewItem] - 1;
var previousIndex = _selectedIndex - 1;
if (previousIndex < 0)
return; // does nothing. See above.
@@ -310,34 +270,24 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
Selects the item at the specified index.
@param anIndex the index of the item to display.
*/
- (BOOL)selectTabViewItemAtIndex:(CPUInteger)anIndex
- (BOOL)selectTabViewItemAtIndex:(unsigned)anIndex
{
if (![self _selectTabViewItemAtIndex:anIndex])
return NO;
if (anIndex === _selectedIndex)
return;
[self _reverseSetSelectedIndex];
return YES;
}
// Like selectTabViewItemAtIndex: but without bindings interaction
- (BOOL)_selectTabViewItemAtIndex:(CPUInteger)anIndex
{
var aTabViewItem = [self tabViewItemAtIndex:anIndex];
if (aTabViewItem == _selectedTabViewItem)
if ((_delegateSelectors & CPTabViewShouldSelectTabViewItemSelector) && ![_delegate tabView:self shouldSelectTabViewItem:aTabViewItem])
return NO;
if (![self _sendDelegateShouldSelectTabViewItem:aTabViewItem])
return NO;
if (_delegateSelectors & CPTabViewWillSelectTabViewItemSelector)
[_delegate tabView:self willSelectTabViewItem:aTabViewItem];
[self _sendDelegateWillSelectTabViewItem:aTabViewItem];
[_tabs selectSegmentWithTag:anIndex];
[self _setSelectedIndex:anIndex];
[_tabs setSelectedSegment:anIndex];
_selectedTabViewItem = aTabViewItem;
[self _displayItemView:[aTabViewItem view]];
[self _sendDelegateDidSelectTabViewItem:aTabViewItem];
if (_delegateSelectors & CPTabViewDidSelectTabViewItemSelector)
[_delegate tabView:self didSelectTabViewItem:aTabViewItem];
return YES;
}
@@ -348,7 +298,10 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
*/
- (CPTabViewItem)selectedTabViewItem
{
return _selectedTabViewItem;
if (_selectedIndex != CPNotFound)
return [_items objectAtIndex:_selectedIndex];
return nil;
}
// Modifying the font
@@ -409,14 +362,6 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
[self setNeedsLayout];
}
- (void)tileWithChangedItem:(CPTabViewItem)aTabViewItem
{
var segment = aTabViewItem ? [self indexOfTabViewItem:aTabViewItem] : 0;
[_tabs tileWithChangedSegment:segment];
[self setNeedsLayout];
}
- (void)layoutSubviews
{
// Even if CPTabView's autoresizesSubviews is NO, _tabs and _box has to be laid out.
@@ -428,11 +373,11 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
else
{
var aFrame = [self frame],
segmentedHeight = CGRectGetHeight([_tabs frame]),
segmentedHeight = _CGRectGetHeight([_tabs frame]),
origin = _type === CPTopTabsBezelBorder ? segmentedHeight / 2 : 0;
[_box setFrame:CGRectMake(0, origin, CGRectGetWidth(aFrame),
CGRectGetHeight(aFrame) - segmentedHeight / 2)];
[_box setFrame:_CGRectMake(0, origin, _CGRectGetWidth(aFrame),
_CGRectGetHeight(aFrame) - segmentedHeight / 2)];
[self _repositionTabs];
}
@@ -460,7 +405,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
Sets the delegate for this tab view.
@param aDelegate the tab view's delegate
*/
- (void)setDelegate:(id <CPTabViewDelegate>)aDelegate
- (void)setDelegate:(id)aDelegate
{
if (_delegate == aDelegate)
return;
@@ -502,247 +447,39 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
- (void)_repositionTabs
{
var horizontalCenterOfSelf = CGRectGetWidth([self bounds]) / 2,
verticalCenterOfTabs = CGRectGetHeight([_tabs bounds]) / 2;
var horizontalCenterOfSelf = _CGRectGetWidth([self bounds]) / 2,
verticalCenterOfTabs = _CGRectGetHeight([_tabs bounds]) / 2;
if (_type === CPBottomTabsBezelBorder)
[_tabs setCenter:CGPointMake(horizontalCenterOfSelf, CGRectGetHeight([self bounds]) - verticalCenterOfTabs)];
[_tabs setCenter:_CGPointMake(horizontalCenterOfSelf, _CGRectGetHeight([self bounds]) - verticalCenterOfTabs)];
else
[_tabs setCenter:CGPointMake(horizontalCenterOfSelf, verticalCenterOfTabs)];
[_tabs setCenter:_CGPointMake(horizontalCenterOfSelf, verticalCenterOfTabs)];
}
- (void)_displayItemView:(CPView)aView
- (void)_setSelectedIndex:(CPNumber)index
{
[_box setContentView:aView];
_selectedIndex = index;
[self _setContentViewFromItem:[_items objectAtIndex:_selectedIndex]];
}
// DELEGATE METHODS
- (BOOL)_sendDelegateShouldSelectTabViewItem:(CPTabViewItem)aTabViewItem
- (void)_setContentViewFromItem:(CPTabViewItem)anItem
{
if (_delegateSelectors & CPTabViewShouldSelectTabViewItemSelector)
return [_delegate tabView:self shouldSelectTabViewItem:aTabViewItem];
return YES;
[_box setContentView:[anItem view]];
}
- (void)_sendDelegateWillSelectTabViewItem:(CPTabViewItem)aTabViewItem
- (void)_updateItems
{
if (_delegateSelectors & CPTabViewWillSelectTabViewItemSelector)
[_delegate tabView:self willSelectTabViewItem:aTabViewItem];
}
var count = [_items count];
[_tabs setSegmentCount:count];
- (void)_sendDelegateDidSelectTabViewItem:(CPTabViewItem)aTabViewItem
{
if (_delegateSelectors & CPTabViewDidSelectTabViewItemSelector)
[_delegate tabView:self didSelectTabViewItem:aTabViewItem];
}
- (void)_sendDelegateTabViewDidChangeNumberOfTabViewItems
{
if (_delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector)
[_delegate tabViewDidChangeNumberOfTabViewItems:self];
}
@end
@implementation CPTabView (BindingSupport)
+ (Class)_binderClassForBinding:(CPString)aBinding
{
if (aBinding == CPContentBinding)
return [_CPTabViewContentBinder class];
else if (aBinding == CPSelectionIndexesBinding || aBinding == CPSelectedIndexBinding)
return [_CPTabViewSelectionBinder class];
return [super _binderClassForBinding:aBinding];
}
+ (BOOL)isBindingExclusive:(CPString)aBinding
{
return (aBinding == CPSelectionIndexesBinding || aBinding == CPSelectedIndexBinding);
}
- (void)_reverseSetContent
{
var theBinder = [self binderForBinding:CPContentBinding];
[theBinder reverseSetValueFor:@"items"];
}
- (void)_reverseSetSelectedIndex
{
var theBinder = [self binderForBinding:CPSelectionIndexesBinding];
if (theBinder !== nil)
[theBinder reverseSetValueFor:@"selectionIndexes"];
else
for (var i = 0; i < count; i++)
{
theBinder = [self binderForBinding:CPSelectedIndexBinding];
[theBinder reverseSetValueFor:@"selectedIndex"];
}
}
- (CPBinder)binderForBinding:(CPString)aBinding
{
var cls = [[self class] _binderClassForBinding:aBinding]
return [cls getBinding:aBinding forObject:self];
}
- (void)setItems:(CPArray)tabViewItems
{
if ([tabViewItems isEqualToArray:[_tabs segments]])
return;
[[self items] makeObjectsPerformSelector:@selector(_setTabView:) withObject:nil];
[_tabs setSegments:tabViewItems];
[tabViewItems makeObjectsPerformSelector:@selector(_setTabView:) withObject:self];
[self tileWithChangedItem:nil];
// Update the selection because setSegments: did remove all previous segments AND the selection.
[_tabs setSelectedSegment:[self indexOfTabViewItem:_selectedTabViewItem]];
// should we send delegate methods in bindings mode ?
//[self _delegateTabViewDidChangeNumberOfTabViewItems:self];
}
- (void)_deselectAll
{
[_tabs setSelectedSegment:-1];
_selectedTabViewItem = nil;
}
- (void)_displayPlaceholder:(CPString)aPlaceholder
{
if (_placeHolderView == nil)
{
_placeHolderView = [[CPView alloc] initWithFrame:CGRectMakeZero()];
var textField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
[textField setTag:1000];
[textField setTextColor:[CPColor whiteColor]];
[textField setFont:[CPFont boldFontWithName:@"Geneva" size:18 italic:YES]];
[_placeHolderView addSubview:textField];
[_tabs setLabel:[[_items objectAtIndex:i] label] forSegment:i];
[_tabs setTag:i forSegment:i];
}
var textField = [_placeHolderView viewWithTag:1000];
[textField setStringValue:aPlaceholder];
[textField sizeToFit];
var boxBounds = [_box bounds],
textFieldBounds = [textField bounds],
origin = CGPointMake(CGRectGetWidth(boxBounds)/2 - CGRectGetWidth(textFieldBounds)/2, CGRectGetHeight(boxBounds)/2 - CGRectGetHeight(textFieldBounds));
[textField setFrameOrigin:origin];
[self _displayItemView:_placeHolderView];
}
#pragma mark -
#pragma mark Override
/*!
Enabled controls accept first mouse by default.
*/
- (BOOL)acceptsFirstMouse:(CPEvent)anEvent
{
return YES;
}
@end
var _CPTabViewContentBinderNull = @"NO CONTENT";
@implementation _CPTabViewContentBinder : CPBinder
{
}
- (void)_updatePlaceholdersWithOptions:(CPDictionary)options
{
[super _updatePlaceholdersWithOptions:options];
[self _setPlaceholder:_CPTabViewContentBinderNull forMarker:CPNullMarker isDefault:YES];
}
- (void)setPlaceholderValue:(id)aValue withMarker:(CPString)aMarker forBinding:(CPString)aBinding
{
[_source setItems:@[]];
[_source _setPlaceholderView:aValue];
}
- (void)setValue:(id)aValue forBinding:(CPString)aBinding
{
[_source setItems:aValue];
}
- (id)valueForBinding:(CPString)aBinding
{
return [_source items];
}
@end
var _CPTabViewSelectionBinderMultipleValues = @"Multiple Selection",
_CPTabViewSelectionBinderNoSelection = @"No Selection";
@implementation _CPTabViewSelectionBinder : CPBinder
{
}
- (void)_updatePlaceholdersWithOptions:(CPDictionary)options
{
[super _updatePlaceholdersWithOptions:options];
[self _setPlaceholder:_CPTabViewSelectionBinderMultipleValues forMarker:CPMultipleValuesMarker isDefault:YES];
[self _setPlaceholder:_CPTabViewSelectionBinderNoSelection forMarker:CPNoSelectionMarker isDefault:YES];
}
- (void)setPlaceholderValue:(id)aValue withMarker:(CPString)aMarker forBinding:(CPString)aBinding
{
if (aMarker == CPNoSelectionMarker || aMarker == CPNullMarker)
[_source _deselectAll];
[_source _displayPlaceholder:aValue];
}
- (void)setValue:(id)aValue forBinding:(CPString)aBinding
{
if (aBinding == CPSelectionIndexesBinding)
{
if (aValue == nil || [aValue count] == 0)
{
[_source _deselectAll];
[_source _displayPlaceholder:_CPTabViewSelectionBinderNoSelection];
}
else if ([aValue count] > 1)
[_source _displayPlaceholder:_CPTabViewSelectionBinderMultipleValues];
else if ([aValue firstIndex] < [_source numberOfTabViewItems])
[_source _selectTabViewItemAtIndex:[aValue firstIndex]];
}
else if (aBinding == CPSelectedIndexBinding)
{
if (aValue == CPNotFound)
{
[_source _deselectAll];
[_source _displayPlaceholder:_CPTabViewSelectionBinderNoSelection];
}
else if (aValue < [_source numberOfTabViewItems])
[_source _selectTabViewItemAtIndex:aValue];
}
}
- (id)valueForBinding:(CPString)aBinding
{
if (aBinding == CPSelectionIndexesBinding)
{
var result = [CPIndexSet indexSet],
idx = [_source indexOfTabViewItem:[_source selectedTabViewItem]];
if (idx !== CPNotFound)
[result addIndex:idx];
return result;
}
else if (aBinding == CPSelectedIndexBinding)
return [_source indexOfTabViewItem:[_source selectedTabViewItem]];
if (_selectedIndex === CPNotFound)
[self selectFirstTabViewItem:self];
}
@end
@@ -764,13 +501,14 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
_font = [aCoder decodeObjectForKey:CPTabViewFontKey];
[_tabs setFont:_font];
var items = [aCoder decodeObjectForKey:CPTabViewItemsKey] || [CPArray array];
[self _insertTabViewItems:items atIndexes:[CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [items count])]];
_items = [aCoder decodeObjectForKey:CPTabViewItemsKey];
[_items makeObjectsPerformSelector:@selector(_setTabView:) withObject:self];
[self _updateItems];
[self setDelegate:[aCoder decodeObjectForKey:CPTabViewDelegateKey]];
_selectedTabViewItem = [aCoder decodeObjectForKey:CPTabViewSelectedItemKey];
self.selectOnAwake = [aCoder decodeObjectForKey:CPTabViewSelectedItemKey];
_type = [aCoder decodeIntForKey:CPTabViewTypeKey];
}
@@ -779,23 +517,10 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
- (void)awakeFromCib
{
[super awakeFromCib];
// This cannot be run in initWithCoder because it might call selectTabViewItem:, which is
// not safe to call before the views of the tab views items are fully decoded.
if (_selectedTabViewItem)
if (self.selectOnAwake)
{
var idx = [self indexOfTabViewItem:_selectedTabViewItem];
if (idx !== CPNotFound)
{
// Temporarily set the selected item to not selected.
// It allows the initial selection to be made correctly.
_selectedTabViewItem = nil;
[self selectTabViewItemAtIndex:idx];
}
[self selectTabViewItem:self.selectOnAwake];
delete self.selectOnAwake;
}
var type = _type;
@@ -807,17 +532,13 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
- (void)encodeWithCoder:(CPCoder)aCoder
{
// Don't bother to encode the CPBox. We will recreate it on decode and its content view is already
// stored by the tab view item. Not encoding _box makes the resulting archive smaller and reduces
// the surface for decoding bugs (of which we've had many in tab view).
var subviews = [self subviews];
[_box removeFromSuperview];
[super encodeWithCoder:aCoder];
[self setSubviews:subviews];
[aCoder encodeObject:_items forKey:CPTabViewItemsKey];
[aCoder encodeConditionalObject:_selectedTabViewItem forKey:CPTabViewSelectedItemKey];
var selected = [self selectedTabViewItem];
if (selected)
[aCoder encodeObject:selected forKey:CPTabViewSelectedItemKey];
[aCoder encodeInt:_type forKey:CPTabViewTypeKey];
[aCoder encodeObject:_font forKey:CPTabViewFontKey];
@@ -826,26 +547,3 @@ var CPTabViewItemsKey = "CPTabViewItemsKey",
}
@end
@implementation _CPTabViewBox : CPBox
{
CPTabView _tabView @accessors(property=tabView);
}
#pragma mark -
#pragma mark Override
- (CPView)hitTest:(CGPoint)aPoint
{
// Here we check if we have clicked on the segmentedControl of the tabView or not
// If YES, the CPBox should not handle the click
var segmentIndex = [_tabView._tabs testSegment:[_tabView._tabs convertPoint:aPoint fromView:[self superview]]];
if (segmentIndex != CPNotFound)
return nil;
return [super hitTest:aPoint];
}
@end
+10 -103
View File
@@ -23,8 +23,7 @@
@import <Foundation/CPObject.j>
@import "CPView.j"
@class CPTabView
@class CPViewController
/*
The tab is currently selected.
@@ -54,34 +53,14 @@ CPPressedTab = 2;
*/
@implementation CPTabViewItem : CPObject
{
id _identifier;
CPString _label;
CPInteger _tag @accessors(property=tag);
id _identifier;
CPString _label;
CPView _view;
CPView _auxiliaryView;
CPView _view;
CPView _auxiliaryView;
CPTabView _tabView;
unsigned _tabState; // Looks like it is not yet implemented
CPImage _image @accessors(property=image);
CPViewController _viewController @accessors(getter=viewController);
BOOL _enabled @accessors(property=enabled);
BOOL _selected @accessors(property=selected);
CGRect _tabRect @accessors(property=frame);
float _width @accessors(property=width);
}
/*
*/
+ (CPTabViewItem)tabViewItemWithViewController:(CPViewController)aViewController
{
var item = [[CPTabViewItem alloc] init];
[item setViewController:aViewController];
return item;
CPTabView _tabView;
unsigned _tabState; // Looks like it is not yet implemented
}
- (id)init
@@ -89,19 +68,6 @@ CPPressedTab = 2;
return [self initWithIdentifier:@""];
}
- (void)_init
{
_tag = 0;
_viewController = nil;
_image = nil;
_tabState = 0;
_tabView = nil;
_enabled = YES;
_selected = NO;
_tabRect = CGRectMakeZero();
_width = 0;
}
/*!
Initializes the tab view item with the specified identifier.
@return the initialized CPTabViewItem
@@ -110,12 +76,8 @@ CPPressedTab = 2;
{
self = [super init];
[self _init];
_identifier = anIdentifier;
_label = nil;
_view = nil;
//_auxiliaryView = nil;
if (self)
_identifier = anIdentifier;
return self;
}
@@ -127,11 +89,7 @@ CPPressedTab = 2;
*/
- (void)setLabel:(CPString)aLabel
{
if ([aLabel isEqualToString:_label])
return;
_label = aLabel;
[_tabView tileWithChangedItem:self];
}
/*!
@@ -142,28 +100,6 @@ CPPressedTab = 2;
return _label;
}
// Working With Images
/*!
Sets the CPTabViewItem's image.
@param anImage the image for the item
*/
- (void)setImage:(CPImage)anImage
{
if ([anImage isEqual:_image])
return;
_image = anImage;
[_tabView tileWithChangedItem:self];
}
/*!
Returns the CPTabViewItem's image
*/
- (CPImage)image
{
return _image;
}
// Checking the Tab Display State
/*!
Returns the tab's current state.
@@ -203,7 +139,7 @@ CPPressedTab = 2;
_view = aView;
if ([_tabView selectedTabViewItem] == self)
[_tabView _displayItemView:_view];
[_tabView _setContentViewFromItem:self];
}
/*!
@@ -211,9 +147,6 @@ CPPressedTab = 2;
*/
- (CPView)view
{
if (!_view && _viewController)
return [_viewController view]; // The view controller loads here.
return _view;
}
@@ -252,32 +185,10 @@ CPPressedTab = 2;
_tabView = aView;
}
/*!
Sets the specified view controller for the tab view item.
@param aViewController an instance of CPViewController.
*/
- (void)setViewController:(CPViewController)aViewController
{
_viewController = aViewController;
var identifier = [aViewController cibName],
title = [_viewController title];
if (identifier)
_identifier = identifier;
if (title)
[self setLabel:title];
if ([_tabView selectedTabViewItem] == self)
[_tabView _displayItemView:[_viewController view]];
}
@end
var CPTabViewItemIdentifierKey = "CPTabViewItemIdentifierKey",
CPTabViewItemLabelKey = "CPTabViewItemLabelKey",
CPTabViewItemImageKey = "CPTabViewItemImageKey",
CPTabViewItemViewKey = "CPTabViewItemViewKey",
CPTabViewItemAuxViewKey = "CPTabViewItemAuxViewKey";
@@ -290,11 +201,8 @@ var CPTabViewItemIdentifierKey = "CPTabViewItemIdentifierKey",
if (self)
{
[self _init];
_identifier = [aCoder decodeObjectForKey:CPTabViewItemIdentifierKey];
_label = [aCoder decodeObjectForKey:CPTabViewItemLabelKey];
_image = [aCoder decodeObjectForKey:CPTabViewItemImageKey];
_view = [aCoder decodeObjectForKey:CPTabViewItemViewKey];
_auxiliaryView = [aCoder decodeObjectForKey:CPTabViewItemAuxViewKey];
@@ -307,7 +215,6 @@ var CPTabViewItemIdentifierKey = "CPTabViewItemIdentifierKey",
{
[aCoder encodeObject:_identifier forKey:CPTabViewItemIdentifierKey];
[aCoder encodeObject:_label forKey:CPTabViewItemLabelKey];
[aCoder encodeObject:_image forKey:CPTabViewItemImageKey];
[aCoder encodeObject:_view forKey:CPTabViewItemViewKey];
[aCoder encodeObject:_auxiliaryView forKey:CPTabViewItemAuxViewKey];
+28 -25
View File
@@ -28,8 +28,9 @@
@import "CPTextField.j"
@global CPTableViewColumnDidResizeNotification
@class _CPTableColumnHeaderView
@class CPTableView
CPTableColumnNoResizing = 0;
CPTableColumnAutoresizingMask = 1 << 0;
@@ -180,11 +181,11 @@ CPTableColumnUserResizingMask = 1 << 1;
columns = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(index, [tableView._exposedColumns lastIndex] - index + 1)];
// FIXME: Would be faster with some sort of -setNeedsDisplayInColumns: that updates a dirtyTableColumnForDisplay cache; then marked columns would relayout their data views at display time.
[tableView _layoutViewsForRowIndexes:rows columnIndexes:columns];
[tableView _layoutDataViewsInRows:rows columns:columns];
[tableView tile];
if (!_disableResizingPosting)
[[self tableView] _didResizeTableColumn:self oldWidth:oldWidth];
[self _postDidResizeNotificationWithOldWidth:oldWidth];
}
}
@@ -282,7 +283,7 @@ CPTableColumnUserResizingMask = 1 << 1;
*/
- (void)sizeToFit
{
var width = CGRectGetWidth([_headerView frame]);
var width = _CGRectGetWidth([_headerView frame]);
if (width < [self minWidth])
[self setMinWidth:width];
@@ -393,8 +394,8 @@ CPTableColumnUserResizingMask = 1 << 1;
*/
- (void)setDataView:(CPView)aView
{
if (_dataView === aView)
return;
if (_dataView)
_dataViewData = nil;
[aView setThemeState:CPThemeStateTableDataView];
@@ -415,7 +416,7 @@ CPTableColumnUserResizingMask = 1 << 1;
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.
*/
- (id)dataViewForRow:(CPInteger)aRowIndex
- (id)dataViewForRow:(int)aRowIndex
{
return [self dataView];
}
@@ -537,6 +538,19 @@ CPTableColumnUserResizingMask = 1 << 1;
return _headerToolTip;
}
/*!
@ignore
*/
- (void)_postDidResizeNotificationWithOldWidth:(float)oldWidth
{
[[self tableView] _didResizeTableColumn:self];
[[CPNotificationCenter defaultCenter]
postNotificationName:CPTableViewColumnDidResizeNotification
object:[self tableView]
userInfo:@{ @"CPTableColumn": self, @"CPOldWidth": oldWidth }];
}
@end
@implementation CPTableColumnValueBinder : CPBinder
@@ -546,22 +560,11 @@ CPTableColumnUserResizingMask = 1 << 1;
- (void)setValueFor:(CPString)aBinding
{
var tableView = [_source tableView],
newNumberOfRows = [tableView _numberOfRows];
column = [[tableView tableColumns] indexOfObjectIdenticalTo:_source],
rowIndexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [tableView numberOfRows])],
columnIndexes = [CPIndexSet indexSetWithIndex:column];
if ([tableView numberOfRows] == newNumberOfRows)
{
var rowIndexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, newNumberOfRows)],
column = [[tableView tableColumns] indexOfObjectIdenticalTo:_source],
columnIndexes = [CPIndexSet indexSetWithIndex:column];
// Reloads objectValues only, not the views.
// FIXME: reload data for all rows or just rows intersecting exposed rows ?
[tableView _reloadDataForRowIndexes:rowIndexes columnIndexes:columnIndexes];
}
else
{
[tableView reloadData];
}
[tableView reloadDataForRowIndexes:rowIndexes columnIndexes:columnIndexes];
}
- (CPSortDescriptor)_defaultSortDescriptorPrototype
@@ -592,7 +595,7 @@ CPTableColumnUserResizingMask = 1 << 1;
@implementation CPTableColumn (Bindings)
+ (Class)_binderClassForBinding:(CPString)aBinding
+ (id)_binderClassForBinding:(CPString)aBinding
{
if (aBinding == CPValueBinding)
return [CPTableColumnValueBinder class];
@@ -601,7 +604,7 @@ CPTableColumnUserResizingMask = 1 << 1;
}
/*!
Binds the receiver to an object. Note that unlike Cocoa, this works only *after* the receiver has been added to a \c CPTableView.
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.
@@ -825,7 +828,7 @@ var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
/*!
@ignore
*/
- (id)dataCellForRow:(CPInteger)row
- (id)dataCellForRow:(int)row
{
[CPException raise:CPUnsupportedMethodException
reason:@"dataCellForRow: is not supported. Use -dataViewForRow:row instead."];
+360 -404
View File
File diff suppressed because it is too large Load Diff
+1219 -2091
View File
File diff suppressed because it is too large Load Diff
-23
View File
@@ -28,26 +28,3 @@ CPFormFeedCharacter = "\u000c";
CPCarriageReturnCharacter = "\u000d";
CPBackTabCharacter = "\u0019";
CPDeleteCharacter = "\u007f";
CPIllegalTextMovement = 0;
CPOtherTextMovement = 0;
CPReturnTextMovement = 16;
CPTabTextMovement = 17;
CPBacktabTextMovement = 18;
CPLeftTextMovement = 19;
CPRightTextMovement = 20;
CPUpTextMovement = 21;
CPDownTextMovement = 22;
CPCancelTextMovement = 23;
@typedef CPWritingDirection
CPWritingDirectionNatural = -1;
CPWritingDirectionLeftToRight = 0;
CPWritingDirectionRightToLeft = 1;
@typedef CPTextAlignment
CPLeftTextAlignment = 0;
CPRightTextAlignment = 1;
CPCenterTextAlignment = 2;
CPJustifiedTextAlignment = 3;
CPNaturalTextAlignment = 4;
+323 -843
View File
File diff suppressed because it is too large Load Diff
+198 -340
View File
@@ -26,7 +26,6 @@
@import <Foundation/CPKeyedUnarchiver.j>
@class CPView
@class _CPThemeAttribute
var CPThemesByName = { },
CPThemeDefaultTheme = nil,
@@ -36,6 +35,7 @@ var CPThemesByName = { },
/*!
@ingroup appkit
*/
@implementation CPTheme : CPObject
{
CPString _name;
@@ -141,19 +141,20 @@ var CPThemesByName = { },
if (!className)
{
if ([aClass respondsToSelector:@selector(defaultThemeClass)])
if ([aClass isKindOfClass:[CPView class]])
{
className = [aClass defaultThemeClass];
}
else if ([aClass respondsToSelector:@selector(themeClass)])
{
CPLog.warn(@"%@ themeClass is deprecated in favor of defaultThemeClass", CPStringFromClass(aClass));
className = [aClass themeClass];
if ([aClass respondsToSelector:@selector(defaultThemeClass)])
className = [aClass defaultThemeClass];
else if ([aClass respondsToSelector:@selector(themeClass)])
{
CPLog.warn(@"%@ themeClass is deprecated in favor of defaultThemeClass", CPStringFromClass(aClass));
className = [aClass themeClass];
}
else
return nil;
}
else
{
return nil;
}
[CPException raise:CPInvalidArgumentException reason:@"aClass must be a class object or a string."];
}
return [_attributes objectForKey:className];
@@ -239,7 +240,7 @@ var CPThemesByName = { },
@param aClass The themed class in which to look for the attribute
@return A value or nil
*/
- (id)valueForAttributeWithName:(CPString)aName inState:(ThemeState)aState forClass:(id)aClass
- (id)valueForAttributeWithName:(CPString)aName inState:(CPThemeState)aState forClass:(id)aClass
{
var attribute = [self attributeWithName:aName forClass:aClass];
@@ -313,213 +314,6 @@ var CPThemeNameKey = @"CPThemeNameKey",
@end
/*!
* ThemeStates are immutable objects representing a particular ThemeState. Applications should never be creating
* ThemeStates directly but should instead use the CPThemeState function.
*/
function ThemeState(stateNames)
{
var stateNameKeys = [];
this._stateNames = {};
for (key in stateNames)
{
if (!stateNames.hasOwnProperty(key))
continue;
if (key !== 'normal')
{
this._stateNames[key] = true;
stateNameKeys.push(key);
}
}
if (stateNameKeys.length === 0)
{
stateNameKeys.push('normal');
this._stateNames['normal'] = true;
}
stateNameKeys.sort();
this._stateNameString = stateNameKeys[0];
var stateNameLength = stateNameKeys.length;
for (var stateIndex = 1; stateIndex < stateNameLength; stateIndex++)
this._stateNameString = this._stateNameString + "+" + stateNameKeys[stateIndex];
this._stateNameCount = stateNameLength;
}
ThemeState.prototype.toString = function()
{
return this._stateNameString;
}
ThemeState.prototype.hasThemeState = function(aState)
{
if (!aState || !aState._stateNames)
return false;
// We can do this in O(n) because both states have their stateNames already sorted.
for (var stateName in aState._stateNames)
{
if (!aState._stateNames.hasOwnProperty(stateName))
continue;
if (!this._stateNames[stateName])
return false;
}
return true;
}
ThemeState.prototype.isSubsetOf = function(aState)
{
if (aState._stateNameCount < this._stateNameCount)
return false;
for (var key in this._stateNames)
{
if (!this._stateNames.hasOwnProperty(key))
continue;
if (!aState._stateNames[key])
return false;
}
return true;
}
ThemeState.prototype.without = function(aState)
{
if (!aState || aState === [CPNull null])
return this;
var firstTransform = CPThemeWithoutTransform[this._stateNameString],
result;
if (firstTransform)
{
result = firstTransform[aState._stateNameString];
if (result)
return result;
}
var newStates = {};
for (var stateName in this._stateNames)
{
if (!this._stateNames.hasOwnProperty(stateName))
continue;
if (!aState._stateNames[stateName])
newStates[stateName] = true;
}
result = ThemeState._cacheThemeState(new ThemeState(newStates));
if (!firstTransform)
firstTransform = CPThemeWithoutTransform[this._stateNameString] = {};
firstTransform[aState._stateNameString] = result;
return result;
}
ThemeState.prototype.and = function(aState)
{
var firstTransform = CPThemeAndTransform[this._stateNameString],
result;
if (firstTransform)
{
result = firstTransform[aState._stateNameString];
if (result)
return result;
}
result = CPThemeState(this, aState);
if (!firstTransform)
firstTransform = CPThemeAndTransform[this._stateNameString] = {};
firstTransform[aState._stateNameString] = result;
return result;
}
var CPThemeStates = {},
CPThemeWithoutTransform = {},
CPThemeAndTransform = {};
ThemeState._cacheThemeState = function(aState)
{
// We do this caching so themeState equality works. Basically, doing CPThemeState('foo+bar') === CPThemeState('bar', 'foo') will return true.
var themeState = CPThemeStates[String(aState)];
if (themeState === undefined)
{
themeState = aState;
CPThemeStates[String(themeState)] = themeState;
}
return themeState;
}
/*!
* This method can be called in multiple ways:
* CPThemeState('state1') - creates a new CPThemeState that corresponds to the string 'state1'
* CPThemeState('state1', 'state2') - creates a new composite CPThemeState made up of both 'state1' or 'state2'
* CPThemeState('state1+state2') - The same as CPThemeState('state1', 'state2')
* CPThemeState(state1, state2) - creates a new composite CPThemeState made up of state1 and state2
* where state1 and state2 are not strings but are themselves CPThemeStates.
*/
function CPThemeState()
{
if (arguments.length < 1)
throw "CPThemeState() must be called with at least one string argument";
var themeState;
if (arguments.length === 1 && typeof arguments[0] === 'string')
{
themeState = CPThemeStates[arguments[0]];
if (themeState !== undefined)
return themeState;
}
var stateNames = {};
for (var argIndex = 0; argIndex < arguments.length; argIndex++)
{
if (arguments[argIndex] === [CPNull null] || !arguments[argIndex])
continue;
if (typeof arguments[argIndex] === 'object')
{
for (var stateName in arguments[argIndex]._stateNames)
{
if (!arguments[argIndex]._stateNames.hasOwnProperty(stateName))
continue;
stateNames[stateName] = true;
}
}
else
{
var allNames = arguments[argIndex].split('+');
for (var nameIndex = 0; nameIndex < allNames.length; nameIndex++)
stateNames[allNames[nameIndex]] = true;
}
}
themeState = ThemeState._cacheThemeState(new ThemeState(stateNames));
return themeState;
}
@implementation _CPThemeKeyedUnarchiver : CPKeyedUnarchiver
{
CPBundle _bundle;
@@ -547,31 +341,88 @@ function CPThemeState()
@end
CPThemeStateNormal = CPThemeState("normal");
CPThemeStateDisabled = CPThemeState("disabled");
CPThemeStateHovered = CPThemeState("hovered");
CPThemeStateHighlighted = CPThemeState("highlighted");
CPThemeStateSelected = CPThemeState("selected");
CPThemeStateTableDataView = CPThemeState("tableDataView");
CPThemeStateSelectedDataView = CPThemeState("selectedTableDataView");
CPThemeStateGroupRow = CPThemeState("CPThemeStateGroupRow");
CPThemeStateBezeled = CPThemeState("bezeled");
CPThemeStateBordered = CPThemeState("bordered");
CPThemeStateEditable = CPThemeState("editable");
CPThemeStateEditing = CPThemeState("editing");
CPThemeStateVertical = CPThemeState("vertical");
CPThemeStateDefault = CPThemeState("default");
CPThemeStateCircular = CPThemeState("circular");
CPThemeStateAutocompleting = CPThemeState("autocompleting");
CPThemeStateFirstResponder = CPThemeState("firstResponder");
CPThemeStateMainWindow = CPThemeState("mainWindow");
CPThemeStateKeyWindow = CPThemeState("keyWindow");
CPThemeStateControlSizeRegular = CPThemeState("controlSizeRegular");
CPThemeStateControlSizeSmall = CPThemeState("controlSizeSmall");
CPThemeStateControlSizeMini = CPThemeState("controlSizeMini");
var CPThemeStates = {},
CPThemeStateNames = {},
CPThemeStateCount = 0;
CPThemeStateNormalString = String(CPThemeStateNormal);
function CPThemeState(aStateName)
{
var state = CPThemeStates[aStateName];
if (state === undefined)
{
if (aStateName.indexOf('+') === -1)
state = 1 << CPThemeStateCount++;
else
{
var state = 0,
states = aStateName.split('+'),
count = states.length;
while (count--)
{
var stateName = states[count],
individualState = CPThemeStates[stateName];
if (individualState === undefined)
{
individualState = 1 << CPThemeStateCount++;
CPThemeStates[stateName] = individualState;
CPThemeStateNames[individualState] = stateName;
}
state |= individualState;
}
}
CPThemeStates[aStateName] = state;
CPThemeStateNames[state] = aStateName;
}
return state;
}
function CPThemeStateName(aState)
{
var name = CPThemeStateNames[aState];
if (name !== undefined)
return name;
if (!(aState & (aState - 1)))
return "";
var state = 1,
name = "";
for (; state < aState; state <<= 1)
if (aState & state)
name += (name.length === 0 ? '' : '+') + CPThemeStateNames[state];
CPThemeStateNames[aState] = name;
return name;
}
CPThemeStateNames[0] = "normal";
CPThemeStateNormal = CPThemeStates["normal"] = 0;
CPThemeStateDisabled = CPThemeState("disabled");
CPThemeStateHovered = CPThemeState("hovered");
CPThemeStateHighlighted = CPThemeState("highlighted");
CPThemeStateSelected = CPThemeState("selected");
CPThemeStateTableDataView = CPThemeState("tableDataView");
CPThemeStateSelectedDataView = CPThemeStateSelectedTableDataView = CPThemeState("selectedTableDataView");
CPThemeStateGroupRow = CPThemeState("CPThemeStateGroupRow");
CPThemeStateBezeled = CPThemeState("bezeled");
CPThemeStateBordered = CPThemeState("bordered");
CPThemeStateEditable = CPThemeState("editable");
CPThemeStateEditing = CPThemeState("editing");
CPThemeStateVertical = CPThemeState("vertical");
CPThemeStateDefault = CPThemeState("default");
CPThemeStateCircular = CPThemeState("circular");
CPThemeStateAutocompleting = CPThemeState("autocompleting");
CPThemeStateMainWindow = CPThemeState("mainWindow");
CPThemeStateKeyWindow = CPThemeState("keyWindow");
@implementation _CPThemeAttribute : CPObject
{
@@ -580,10 +431,10 @@ CPThemeStateNormalString = String(CPThemeStateNormal);
CPDictionary _values @accessors(readonly, getter=values);
JSObject _cache;
_CPThemeAttribute _themeDefaultAttribute;
_CPThemeAttribute _parentAttribute;
}
- (id)initWithName:(CPString)aName defaultValue:(id)aDefaultValue defaultAttribute:(_CPThemeAttribute)aDefaultAttribute
- (id)initWithName:(CPString)aName defaultValue:(id)aDefaultValue
{
self = [super init];
@@ -592,9 +443,7 @@ CPThemeStateNormalString = String(CPThemeStateNormal);
_cache = { };
_name = aName;
_defaultValue = aDefaultValue;
if (aDefaultAttribute)
_themeDefaultAttribute = aDefaultAttribute;
_values = @{};
}
return self;
@@ -615,41 +464,29 @@ CPThemeStateNormalString = String(CPThemeStateNormal);
return [_values count] > 0;
}
- (_CPThemeAttribute)attributeBySettingValue:(id)aValue
- (BOOL)isTrivial
{
var attribute = [[_CPThemeAttribute alloc] initWithName:_name defaultValue:_defaultValue defaultAttribute:_themeDefaultAttribute];
if (aValue !== undefined && aValue !== nil)
attribute._values = @{ CPThemeStateNormalString: aValue };
return attribute;
return ([_values count] === 1) && (Number([_values allKeys][0]) === CPThemeStateNormal);
}
- (_CPThemeAttribute)attributeBySettingValue:(id)aValue forState:(ThemeState)aState
- (void)setValue:(id)aValue
{
var shouldRemoveValue = aValue === undefined || aValue === nil,
attribute = [[_CPThemeAttribute alloc] initWithName:_name defaultValue:_defaultValue defaultAttribute:_themeDefaultAttribute],
values = _values;
_cache = {};
if (values != null)
{
values = [values copy];
if (aValue === undefined || aValue === nil)
_values = @{};
else
_values = @{ String(CPThemeStateNormal): aValue };
}
if (shouldRemoveValue)
[values removeObjectForKey:String(aState)];
else
[values setObject:aValue forKey:String(aState)];
- (void)setValue:(id)aValue forState:(CPThemeState)aState
{
_cache = { };
attribute._values = values;
}
else if (!shouldRemoveValue)
{
values = [[CPDictionary alloc] init];
[values setObject:aValue forKey:String(aState)];
attribute._values = values;
}
return attribute;
if ((aValue === undefined) || (aValue === nil))
[_values removeObjectForKey:String(aState)];
else
[_values setObject:aValue forKey:String(aState)];
}
- (id)value
@@ -657,34 +494,44 @@ CPThemeStateNormalString = String(CPThemeStateNormal);
return [self valueForState:CPThemeStateNormal];
}
- (id)valueForState:(ThemeState)aState
- (id)valueForState:(CPThemeState)aState
{
var stateName = String(aState),
value = _cache[stateName];
var value = _cache[aState];
// This can be nil.
if (value !== undefined)
return value;
value = [_values objectForKey:stateName];
value = [_values objectForKey:String(aState)];
if (value === undefined || value === nil)
// If we don't have a value, and we have a non-normal state...
if ((value === undefined || value === nil) && aState !== CPThemeStateNormal)
{
// If this is a composite state, find the closest partial subset match.
if (aState._stateNameCount > 1)
// If this is a composite state (not a power of 2), find the closest partial subset match.
if (aState & (aState - 1))
{
var states = [_values allKeys],
count = states ? states.length : 0,
largestThemeState = 0;
var highestOneCount = 0,
states = [_values allKeys],
count = states.length;
while (count--)
{
var stateObject = CPThemeState(states[count]);
// states[count] is a string!
var state = Number(states[count]);
if (stateObject.isSubsetOf(aState) && stateObject._stateNameCount > largestThemeState)
// A & B = A iff A < B
if ((state & aState) === state)
{
value = [_values objectForKey:states[count]];
largestThemeState = stateObject._stateNameCount;
var oneCount = cachedNumberOfOnes[state];
if (oneCount === undefined)
oneCount = numberOfOnes(state);
if (oneCount > highestOneCount)
{
highestOneCount = oneCount;
value = [_values objectForKey:String(state)];
}
}
}
}
@@ -695,58 +542,37 @@ CPThemeStateNormalString = String(CPThemeStateNormal);
}
if (value === undefined || value === nil)
value = [_themeDefaultAttribute valueForState:aState];
value = [_parentAttribute valueForState:aState];
if (value === undefined || value === nil)
{
value = _defaultValue;
// Class theme attributes cannot use nil because it's a dictionary.
// So transform CPNull into nil.
if (value === [CPNull null])
value = nil;
}
_cache[stateName] = value;
_cache[aState] = value;
return value;
}
- (_CPThemeAttribute)attributeBySettingParentAttribute:(_CPThemeAttribute)anAttribute
- (void)setParentAttribute:(_CPThemeAttribute)anAttribute
{
if (_themeDefaultAttribute === anAttribute)
return self;
if (_parentAttribute === anAttribute)
return;
var attribute = [[_CPThemeAttribute alloc] initWithName:_name defaultValue:_defaultValue defaultAttribute:anAttribute];
attribute._values = [_values copy];
return attribute;
_cache = { };
_parentAttribute = anAttribute;
}
- (_CPThemeAttribute)attributeMergedWithAttribute:(_CPThemeAttribute)anAttribute
{
var mergedAttribute = [[_CPThemeAttribute alloc] initWithName:_name defaultValue:_defaultValue defaultAttribute:_themeDefaultAttribute];
var mergedAttribute = [[_CPThemeAttribute alloc] initWithName:_name defaultValue:_defaultValue];
mergedAttribute._values = [_values copy];
if (anAttribute._values)
mergedAttribute._values ? [mergedAttribute._values addEntriesFromDictionary:anAttribute._values] : [anAttribute._values copy];
[mergedAttribute._values addEntriesFromDictionary:anAttribute._values];
return mergedAttribute;
}
- (CPString)description
{
return [super description] + @" Name: " + _name + @", defaultAttribute: " + _themeDefaultAttribute + @", defaultValue: " + _defaultValue + @", values: " + _values;
}
@end
// This is used to pass 'parrentAttribute' to the coder
var ParentAttributeForCoder = nil;
@implementation _CPThemeAttribute (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
@@ -760,16 +586,13 @@ var ParentAttributeForCoder = nil;
_name = [aCoder decodeObjectForKey:@"name"];
_defaultValue = [aCoder decodeObjectForKey:@"defaultValue"];
_values = @{};
_themeDefaultAttribute = ParentAttributeForCoder;
if ([aCoder containsValueForKey:@"value"])
{
var state;
var state = CPThemeStateNormal;
if ([aCoder containsValueForKey:@"state"])
state = [aCoder decodeObjectForKey:@"state"];
else
state = CPThemeStateNormalString
state = CPThemeState([aCoder decodeObjectForKey:@"state"]);
[_values setObject:[aCoder decodeObjectForKey:"value"] forKey:state];
}
@@ -783,7 +606,7 @@ var ParentAttributeForCoder = nil;
{
var key = keys[count];
[_values setObject:[encodedValues objectForKey:key] forKey:key];
[_values setObject:[encodedValues objectForKey:key] forKey:CPThemeState(key)];
}
}
}
@@ -797,14 +620,14 @@ var ParentAttributeForCoder = nil;
[aCoder encodeObject:_defaultValue forKey:@"defaultValue"];
var keys = [_values allKeys],
count = keys ? keys.length : 0;
count = keys.length;
if (count === 1)
{
var onlyKey = keys[0];
if (onlyKey !== String(CPThemeStateNormal))
[aCoder encodeObject:onlyKey forKey:@"state"];
if (Number(onlyKey) !== CPThemeStateNormal)
[aCoder encodeObject:CPThemeStateName(Number(onlyKey)) forKey:@"state"];
[aCoder encodeObject:[_values objectForKey:onlyKey] forKey:@"value"];
}
@@ -816,7 +639,7 @@ var ParentAttributeForCoder = nil;
{
var key = keys[count];
[encodedValues setObject:[_values objectForKey:key] forKey:key];
[encodedValues setObject:[_values objectForKey:key] forKey:CPThemeStateName(Number(key))];
}
[aCoder encodeObject:encodedValues forKey:@"values"];
@@ -825,6 +648,35 @@ var ParentAttributeForCoder = nil;
@end
var cachedNumberOfOnes = [ 0 /*000000*/, 1 /*000001*/, 1 /*000010*/, 2 /*000011*/, 1 /*000100*/, 2 /*000101*/, 2 /*000110*/,
3 /*000111*/, 1 /*001000*/, 2 /*001001*/, 2 /*001010*/, 3 /*001011*/, 2 /*001100*/, 3 /*001101*/,
3 /*001110*/, 4 /*001111*/, 1 /*010000*/, 2 /*010001*/, 2 /*010010*/, 3 /*010011*/, 2 /*010100*/,
3 /*010101*/, 3 /*010110*/, 4 /*010111*/, 2 /*011000*/, 3 /*011001*/, 3 /*011010*/, 4 /*011011*/,
3 /*011100*/, 4 /*011101*/, 4 /*011110*/, 5 /*011111*/, 1 /*100000*/, 2 /*100001*/, 2 /*100010*/,
3 /*100011*/, 2 /*100100*/, 3 /*100101*/, 3 /*100110*/, 4 /*100111*/, 2 /*101000*/, 3 /*101001*/,
3 /*101010*/, 4 /*101011*/, 3 /*101100*/, 4 /*101101*/, 4 /*101110*/, 5 /*101111*/, 2 /*110000*/,
3 /*110001*/, 3 /*110010*/, 4 /*110011*/, 3 /*110100*/, 4 /*110101*/, 4 /*110110*/, 5 /*110111*/,
3 /*111000*/, 4 /*111001*/, 4 /*111010*/, 5 /*111011*/, 4 /*111100*/, 5 /*111101*/, 5 /*111110*/,
6 /*111111*/ ];
var numberOfOnes = function(aNumber)
{
var count = 0,
slot = aNumber;
while (aNumber)
{
++count;
aNumber &= (aNumber - 1);
}
cachedNumberOfOnes[slot] = count;
return count;
};
numberOfOnes.displayName = "numberOfOnes";
function CPThemeAttributeEncode(aCoder, aThemeAttribute)
{
var values = aThemeAttribute._values,
@@ -835,7 +687,7 @@ function CPThemeAttributeEncode(aCoder, aThemeAttribute)
{
var state = [values allKeys][0];
if (state === CPThemeStateNormalString)
if (Number(state) === 0)
{
[aCoder encodeObject:[values objectForKey:state] forKey:key];
@@ -853,24 +705,30 @@ function CPThemeAttributeEncode(aCoder, aThemeAttribute)
return NO;
}
function CPThemeAttributeDecode(aCoder, attribute)
function CPThemeAttributeDecode(aCoder, anAttributeName, aDefaultValue, aTheme, aClass)
{
var key = "$a" + attribute._name;
var key = "$a" + anAttributeName;
if ([aCoder containsValueForKey:key])
if (![aCoder containsValueForKey:key])
var attribute = [[_CPThemeAttribute alloc] initWithName:anAttributeName defaultValue:aDefaultValue];
else
{
ParentAttributeForCoder = attribute._themeDefaultAttribute;
var attribute = [aCoder decodeObjectForKey:key];
var decodedAttribute = [aCoder decodeObjectForKey:key];
if (!attribute.isa || ![attribute isKindOfClass:[_CPThemeAttribute class]])
{
var themeAttribute = [[_CPThemeAttribute alloc] initWithName:anAttributeName defaultValue:aDefaultValue];
ParentAttributeForCoder = nil;
[themeAttribute setValue:attribute];
if (!decodedAttribute || !decodedAttribute.isa || ![decodedAttribute isKindOfClass:[_CPThemeAttribute class]])
attribute = [attribute attributeBySettingValue:decodedAttribute];
else
attribute = decodedAttribute;
attribute = themeAttribute;
}
}
if (aTheme && aClass)
[attribute setParentAttribute:[aTheme attributeWithName:anAttributeName forClass:aClass]];
return attribute;
}
Regular → Executable
+91 -187
View File
@@ -20,6 +20,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#import "../Foundation/CPRange.h"
@import <Foundation/CPCharacterSet.j>
@import <Foundation/CPIndexSet.j>
@import <Foundation/CPTimer.j>
@@ -33,34 +35,7 @@
@import "CPTextField.j"
@import "CPWindow_Constants.j"
@class _CPTokenFieldTokenCloseButton
@class _CPTokenFieldTokenDisclosureButton
@global CPApp
@global CPTextFieldDidFocusNotification
@global CPTextFieldDidBlurNotification
// TODO: should be conform to protocol CPTextFieldDelegate
@protocol CPTokenFieldDelegate <CPObject>
@optional
- (BOOL)tokenField:(CPTokenField)tokenField hasMenuForRepresentedObject:(id)representedObject;
- (CPArray)tokenField:(CPTokenField)tokenField completionsForSubstring:(CPString)substring indexOfToken:(CPInteger)tokenIndex indexOfSelectedItem:(CPInteger)selectedIndex;
- (CPArray)tokenField:(CPTokenField)tokenField shouldAddObjects:(CPArray)tokens atIndex:(CPUInteger)index;
- (CPMenu)tokenField:(CPTokenField)tokenField menuForRepresentedObject:(id)representedObject;
- (CPString )tokenField:(CPTokenField)tokenField displayStringForRepresentedObject:(id)representedObject;
- (id)tokenField:(CPTokenField)tokenField representedObjectForEditingString:(CPString)editingString;
@end
var CPTokenFieldDelegate_tokenField_hasMenuForRepresentedObject_ = 1 << 1,
CPTokenFieldDelegate_tokenField_completionsForSubstring_indexOfToken_indexOfSelectedItem_ = 1 << 2,
CPTokenFieldDelegate_tokenField_shouldAddObjects_atIndex_ = 1 << 3,
CPTokenFieldDelegate_tokenField_menuForRepresentedObject_ = 1 << 4,
CPTokenFieldDelegate_tokenField_displayStringForRepresentedObject_ = 1 << 5,
CPTokenFieldDelegate_tokenField_representedObjectForEditingString_ = 1 << 6;
#if PLATFORM(DOM)
@@ -89,26 +64,23 @@ CPTokenFieldDeleteButtonType = 1;
@implementation CPTokenField : CPTextField
{
CPScrollView _tokenScrollView;
int _shouldScrollTo;
CPScrollView _tokenScrollView;
int _shouldScrollTo;
CPRange _selectedRange;
CPRange _selectedRange;
_CPAutocompleteMenu _autocompleteMenu;
CGRect _inputFrame;
_CPAutocompleteMenu _autocompleteMenu;
CGRect _inputFrame;
CPTimeInterval _completionDelay;
CPTimeInterval _completionDelay;
CPCharacterSet _tokenizingCharacterSet @accessors(property=tokenizingCharacterSet);
CPCharacterSet _tokenizingCharacterSet @accessors(property=tokenizingCharacterSet);
CPEvent _mouseDownEvent;
CPEvent _mouseDownEvent;
BOOL _shouldNotifyTarget;
BOOL _shouldNotifyTarget;
int _buttonType @accessors(property=buttonType);
id <CPTokenFieldDelegate> _tokenFieldDelegate;
unsigned _implementedTokenFieldDelegateMethods;
int _buttonType @accessors(property=buttonType);
}
+ (CPCharacterSet)defaultTokenizingCharacterSet
@@ -126,9 +98,9 @@ CPTokenFieldDeleteButtonType = 1;
return "tokenfield";
}
+ (CPDictionary)themeAttributes
+ (id)themeAttributes
{
return @{ @"editor-inset": CGInsetMakeZero() };
return @{ @"editor-inset": _CGInsetMakeZero() };
}
- (id)initWithFrame:(CGRect)frame
@@ -152,7 +124,7 @@ CPTokenFieldDeleteButtonType = 1;
- (void)_init
{
_selectedRange = CPMakeRange(0, 0);
_selectedRange = _CPMakeRange(0, 0);
var frame = [self frame];
@@ -168,41 +140,6 @@ CPTokenFieldDeleteButtonType = 1;
[self addSubview:_tokenScrollView];
}
#pragma mark -
#pragma mark Delegate methods
/*!
Set the delegate of the receiver
*/
- (void)setDelegate:(id <CPTokenFieldDelegate>)aDelegate
{
if (_tokenFieldDelegate === aDelegate)
return;
_tokenFieldDelegate = aDelegate;
_implementedTokenFieldDelegateMethods = 0;
if ([_tokenFieldDelegate respondsToSelector:@selector(tokenField:hasMenuForRepresentedObject:)])
_implementedTokenFieldDelegateMethods |= CPTokenFieldDelegate_tokenField_hasMenuForRepresentedObject_;
if ([_tokenFieldDelegate respondsToSelector:@selector(tokenField:completionsForSubstring:indexOfToken:indexOfSelectedItem:)])
_implementedTokenFieldDelegateMethods |= CPTokenFieldDelegate_tokenField_completionsForSubstring_indexOfToken_indexOfSelectedItem_;
if ([_tokenFieldDelegate respondsToSelector:@selector(tokenField:shouldAddObjects:atIndex:)])
_implementedTokenFieldDelegateMethods |= CPTokenFieldDelegate_tokenField_shouldAddObjects_atIndex_;
if ([_tokenFieldDelegate respondsToSelector:@selector(tokenField:menuForRepresentedObject:)])
_implementedTokenFieldDelegateMethods |= CPTokenFieldDelegate_tokenField_menuForRepresentedObject_;
if ([_tokenFieldDelegate respondsToSelector:@selector(tokenField:displayStringForRepresentedObject:)])
_implementedTokenFieldDelegateMethods |= CPTokenFieldDelegate_tokenField_displayStringForRepresentedObject_;
if ([_tokenFieldDelegate respondsToSelector:@selector(tokenField:representedObjectForEditingString:)])
_implementedTokenFieldDelegateMethods |= CPTokenFieldDelegate_tokenField_representedObjectForEditingString_;
[super setDelegate:_tokenFieldDelegate];
}
- (_CPAutocompleteMenu)_autocompleteMenu
{
if (!_autocompleteMenu)
@@ -277,7 +214,7 @@ CPTokenFieldDeleteButtonType = 1;
if (delegateApprovedObjectsCount)
location += delegateApprovedObjectsCount;
_selectedRange = CPMakeRange(location, 0);
_selectedRange = _CPMakeRange(location, 0);
[self _inputElement].value = @"";
[self setNeedsLayout];
@@ -297,12 +234,12 @@ CPTokenFieldDeleteButtonType = 1;
if (indexOfToken == CPNotFound)
{
if (!extend)
_selectedRange = CPMakeRange([[self _tokens] count], 0);
_selectedRange = _CPMakeRange([[self _tokens] count], 0);
}
else if (extend)
_selectedRange = CPUnionRange(_selectedRange, CPMakeRange(indexOfToken, 1));
_selectedRange = CPUnionRange(_selectedRange, _CPMakeRange(indexOfToken, 1));
else
_selectedRange = CPMakeRange(indexOfToken, 1);
_selectedRange = _CPMakeRange(indexOfToken, 1);
[self setNeedsLayout];
}
@@ -312,7 +249,7 @@ CPTokenFieldDeleteButtonType = 1;
var indexOfToken = [[self _tokens] indexOfObject:token];
if (CPLocationInRange(indexOfToken, _selectedRange))
_selectedRange = CPMakeRange(MAX(indexOfToken, _selectedRange.location), MIN(_selectedRange.length, indexOfToken - _selectedRange.location));
_selectedRange = _CPMakeRange(MAX(indexOfToken, _selectedRange.location), MIN(_selectedRange.length, indexOfToken - _selectedRange.location));
[self setNeedsLayout];
}
@@ -365,7 +302,7 @@ CPTokenFieldDeleteButtonType = 1;
[self setObjectValue:tokens];
// setObjectValue moves the cursor to the end of the selection. We want it to stay
// where the selected tokens were.
_selectedRange = CPMakeRange(collapsedSelection, 0);
_selectedRange = _CPMakeRange(collapsedSelection, 0);
[self _controlTextDidChange];
}
@@ -384,9 +321,6 @@ CPTokenFieldDeleteButtonType = 1;
- (BOOL)becomeFirstResponder
{
if (![super becomeFirstResponder])
return NO;
#if PLATFORM(DOM)
if (CPTokenFieldInputOwner && [CPTokenFieldInputOwner window] !== [self window])
[[CPTokenFieldInputOwner window] makeFirstResponder:nil];
@@ -398,18 +332,13 @@ CPTokenFieldDeleteButtonType = 1;
[self scrollRectToVisible:[self bounds]];
if ([[self window] isKeyWindow])
return [self _becomeFirstKeyResponder];
[self _becomeFirstKeyResponder];
return YES;
}
- (BOOL)_becomeFirstKeyResponder
- (void)_becomeFirstKeyResponder
{
// If the token field is still not completely on screen, refuse to become
// first responder, because the browser will scroll it into view out of our control.
if (![self _isWithinUsablePlatformRect])
return NO;
[self setThemeState:CPThemeStateEditing];
[self _updatePlaceholderState];
@@ -429,16 +358,11 @@ CPTokenFieldDeleteButtonType = 1;
switch ([self alignment])
{
case CPCenterTextAlignment:
element.style.textAlign = "center";
break;
case CPRightTextAlignment:
element.style.textAlign = "right";
break;
default:
element.style.textAlign = "left";
case CPCenterTextAlignment: element.style.textAlign = "center";
break;
case CPRightTextAlignment: element.style.textAlign = "right";
break;
default: element.style.textAlign = "left";
}
var contentRect = [self contentRectForBounds:[self bounds]];
@@ -448,27 +372,19 @@ CPTokenFieldDeleteButtonType = 1;
element.style.width = CGRectGetWidth(contentRect) + "px";
element.style.height = [font defaultLineHeightForFont] + "px";
[[CPRunLoop mainRunLoop] performBlock:function()
window.setTimeout(function()
{
[_tokenScrollView documentView]._DOMElement.appendChild(element);
//post CPControlTextDidBeginEditingNotification
[self textDidBeginEditing:[CPNotification notificationWithName:CPControlTextDidBeginEditingNotification object:self userInfo:nil]];
[[CPRunLoop mainRunLoop] performBlock:function()
window.setTimeout(function()
{
// This will prevent to jump to the focused element
var previousScrollingOrigin = [self _scrollToVisibleRectAndReturnPreviousOrigin];
element.focus();
[self _restorePreviousScrollingOrigin:previousScrollingOrigin];
CPTokenFieldInputOwner = self;
} argument:nil order:0 modes:[CPDefaultRunLoopMode]];
[self textDidFocus:[CPNotification notificationWithName:CPTextFieldDidFocusNotification object:self userInfo:nil]];
} argument:nil order:0 modes:[CPDefaultRunLoopMode]];
}, 0.0);
}, 0.0);
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
@@ -484,8 +400,6 @@ CPTokenFieldDeleteButtonType = 1;
}
#endif
return YES;
}
- (BOOL)resignFirstResponder
@@ -500,14 +414,12 @@ CPTokenFieldDeleteButtonType = 1;
if (_shouldNotifyTarget)
{
_shouldNotifyTarget = NO;
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:@{"CPTextMovement": [self _currentTextMovement]}]];
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:nil]];
if ([self sendsActionOnEndEditing])
[self sendAction:[self action] to:[self target]];
}
[self textDidBlur:[CPNotification notificationWithName:CPTextFieldDidBlurNotification object:self userInfo:nil]];
return YES;
}
@@ -569,7 +481,7 @@ CPTokenFieldDeleteButtonType = 1;
- (void)_mouseUpOnToken:(_CPTokenFieldToken)aToken withEvent:(CPEvent)anEvent
{
if (_mouseDownEvent && CGPointEqualToPoint([_mouseDownEvent locationInWindow], [anEvent locationInWindow]))
if (_mouseDownEvent && _CGPointEqualToPoint([_mouseDownEvent locationInWindow], [anEvent locationInWindow]))
{
[self _selectToken:aToken byExtendingSelection:[anEvent modifierFlags] & CPShiftKeyMask];
[[self window] makeFirstResponder:self];
@@ -717,7 +629,7 @@ CPTokenFieldDeleteButtonType = 1;
[[self _tokens] makeObjectsPerformSelector:@selector(setEditable:) withObject:shouldBeEditable];
}
- (BOOL)sendAction:(SEL)anAction to:(id)anObject
- (void)sendAction:(SEL)anAction to:(id)anObject
{
_shouldNotifyTarget = NO;
[super sendAction:anAction to:anObject];
@@ -725,7 +637,7 @@ CPTokenFieldDeleteButtonType = 1;
// Incredible hack to disable supers implementation
// so it cannot change our object value and break the tokenfield
- (BOOL)_setStringValue:(CPString)aValue
- (void)_setStringValue:(id)aValue
{
}
@@ -781,7 +693,11 @@ CPTokenFieldDeleteButtonType = 1;
{
if (![self hasThemeState:CPThemeStateEditing])
return @"";
#if PLATFORM(DOM)
return [self _inputElement].value;
#else
return @"";
#endif
}
- (void)moveUp:(id)sender
@@ -905,7 +821,7 @@ CPTokenFieldDeleteButtonType = 1;
if (_selectedRange.length)
{
// Place the cursor at the end of the selection and collapse.
_selectedRange.location = CPMaxRange(_selectedRange);
_selectedRange.location = _CPMaxRange(_selectedRange);
_selectedRange.length = 0;
}
else
@@ -926,7 +842,7 @@ CPTokenFieldDeleteButtonType = 1;
- (void)moveRightAndModifySelection:(id)sender
{
if (CPMaxRange(_selectedRange) < [[self _tokens] count] && [self _editorValue] == "")
if (_CPMaxRange(_selectedRange) < [[self _tokens] count] && [self _editorValue] == "")
{
// Leave the selection location in place but include the next token to the right.
_selectedRange.length++;
@@ -1005,7 +921,7 @@ CPTokenFieldDeleteButtonType = 1;
// Finish any editing.
[self _autocomplete];
_selectedRange = CPMakeRange(0, [[self _tokens] count]);
_selectedRange = _CPMakeRange(0, [[self _tokens] count]);
[self setNeedsLayout];
}
@@ -1039,21 +955,6 @@ CPTokenFieldDeleteButtonType = 1;
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
}
- (BOOL)performKeyEquivalent:(CPEvent)anEvent
{
var characters = [anEvent characters];
// Here we handle the event when getting a CPNewlineCharacter or CPCarriageReturnCharacter when the menu is open
// We don't want that the application dispatches the event to the other controls
if ([self hasThemeState:CPThemeStateAutocompleting] && (characters === CPNewlineCharacter || characters === CPCarriageReturnCharacter))
{
[self keyDown:anEvent];
return YES;
}
return [super performKeyEquivalent:anEvent];
}
- (void)textDidChange:(CPNotification)aNotification
{
if ([aNotification object] !== self)
@@ -1112,7 +1013,7 @@ CPTokenFieldDeleteButtonType = 1;
return;
// Move each token into the right position.
var contentRect = CGRectMakeCopy([contentView bounds]),
var contentRect = _CGRectMakeCopy([contentView bounds]),
contentOrigin = contentRect.origin,
contentSize = contentRect.size,
offset = CGPointMake(contentOrigin.x, contentOrigin.y),
@@ -1129,11 +1030,11 @@ CPTokenFieldDeleteButtonType = 1;
// Get the height of a typical token, or a token token if you will.
[tokenToken sizeToFit];
var tokenHeight = CGRectGetHeight([tokenToken bounds]);
var tokenHeight = _CGRectGetHeight([tokenToken bounds]);
var fitAndFrame = function(width, height)
{
var r = CGRectMake(0, 0, width, height);
var r = _CGRectMake(0, 0, width, height);
if (offset.x + width >= contentSize.width && offset.x > contentOrigin.x)
{
@@ -1146,8 +1047,8 @@ CPTokenFieldDeleteButtonType = 1;
// Make sure the frame fits.
var scrollHeight = offset.y + tokenHeight + CEIL(spaceBetweenTokens.height / 2.0);
if (CGRectGetHeight([contentView bounds]) < scrollHeight)
[contentView setFrameSize:CGSizeMake(CGRectGetWidth([_tokenScrollView bounds]), scrollHeight)];
if (_CGRectGetHeight([contentView bounds]) < scrollHeight)
[contentView setFrameSize:_CGSizeMake(_CGRectGetWidth([_tokenScrollView bounds]), scrollHeight)];
offset.x += width + spaceBetweenTokens.width;
@@ -1181,12 +1082,12 @@ CPTokenFieldDeleteButtonType = 1;
// When editing, always scroll to the cursor.
if (_selectedRange.length == 0)
[[_tokenScrollView documentView] scrollPoint:CGPointMake(0, _inputFrame.origin.y)];
[[_tokenScrollView documentView] scrollPoint:_CGPointMake(0, _inputFrame.origin.y)];
};
for (var i = 0, count = [tokens count]; i < count; i++)
{
if (isEditing && !_selectedRange.length && i == CPMaxRange(_selectedRange))
if (isEditing && !_selectedRange.length && i == _CPMaxRange(_selectedRange))
placeEditor(false);
var tokenView = [tokens objectAtIndex:i];
@@ -1207,7 +1108,7 @@ CPTokenFieldDeleteButtonType = 1;
[tokenView setButtonType:_buttonType];
}
if (isEditing && !_selectedRange.length && CPMaxRange(_selectedRange) >= [tokens count])
if (isEditing && !_selectedRange.length && _CPMaxRange(_selectedRange) >= [tokens count])
placeEditor(true);
// Hide the editor if there are selected tokens, but still keep it active
@@ -1228,8 +1129,8 @@ CPTokenFieldDeleteButtonType = 1;
// Trim off any excess height downwards (in case we shrank).
var scrollHeight = offset.y + tokenHeight;
if (CGRectGetHeight([contentView bounds]) > scrollHeight)
[contentView setFrameSize:CGSizeMake(CGRectGetWidth([_tokenScrollView bounds]), scrollHeight)];
if (_CGRectGetHeight([contentView bounds]) > scrollHeight)
[contentView setFrameSize:_CGSizeMake(_CGRectGetWidth([_tokenScrollView bounds]), scrollHeight)];
if (_shouldScrollTo !== CPScrollDestinationNone)
{
@@ -1241,7 +1142,7 @@ CPTokenFieldDeleteButtonType = 1;
if (scrollToToken === CPScrollDestinationLeft)
scrollToToken = tokens[_selectedRange.location]
else if (scrollToToken === CPScrollDestinationRight)
scrollToToken = tokens[MAX(0, CPMaxRange(_selectedRange) - 1)];
scrollToToken = tokens[MAX(0, _CPMaxRange(_selectedRange) - 1)];
[self _scrollTokenViewToVisible:scrollToToken];
}
@@ -1254,7 +1155,7 @@ CPTokenFieldDeleteButtonType = 1;
if (!aToken)
return;
return [[_tokenScrollView documentView] scrollPoint:CGPointMake(0, [aToken frameOrigin].y)];
return [[_tokenScrollView documentView] scrollPoint:_CGPointMake(0, [aToken frameOrigin].y)];
}
@end
@@ -1272,10 +1173,12 @@ CPTokenFieldDeleteButtonType = 1;
*/
- (CPArray)_completionsForSubstring:(CPString)substring indexOfToken:(int)tokenIndex indexOfSelectedItem:(int)selectedIndex
{
if (!(_implementedTokenFieldDelegateMethods & CPTokenFieldDelegate_tokenField_completionsForSubstring_indexOfToken_indexOfSelectedItem_))
return [];
if ([[self delegate] respondsToSelector:@selector(tokenField:completionsForSubstring:indexOfToken:indexOfSelectedItem:)])
{
return [[self delegate] tokenField:self completionsForSubstring:substring indexOfToken:tokenIndex indexOfSelectedItem:selectedIndex];
}
return [_tokenFieldDelegate tokenField:self completionsForSubstring:substring indexOfToken:tokenIndex indexOfSelectedItem:selectedIndex];
return [];
}
/*!
@@ -1284,8 +1187,7 @@ CPTokenFieldDeleteButtonType = 1;
- (CGPoint)_completionOrigin:(_CPAutocompleteMenu)anAutocompleteMenu
{
var relativeFrame = _inputFrame ? [[_tokenScrollView documentView] convertRect:_inputFrame toView:self ] : [self bounds];
return CGPointMake(CGRectGetMinX(relativeFrame), CGRectGetMaxY(relativeFrame));
return _CGPointMake(_CGRectGetMinX(relativeFrame), _CGRectGetMaxY(relativeFrame));
}
/*!
@@ -1298,12 +1200,13 @@ CPTokenFieldDeleteButtonType = 1;
*/
- (CPString)_displayStringForRepresentedObject:(id)representedObject
{
if (_implementedTokenFieldDelegateMethods & CPTokenFieldDelegate_tokenField_displayStringForRepresentedObject_)
if ([[self delegate] respondsToSelector:@selector(tokenField:displayStringForRepresentedObject:)])
{
var stringForRepresentedObject = [_tokenFieldDelegate tokenField:self displayStringForRepresentedObject:representedObject];
var stringForRepresentedObject = [[self delegate] tokenField:self displayStringForRepresentedObject:representedObject];
if (stringForRepresentedObject !== nil)
{
return stringForRepresentedObject;
}
}
return representedObject;
@@ -1320,10 +1223,10 @@ CPTokenFieldDeleteButtonType = 1;
*/
- (CPArray)_shouldAddObjects:(CPArray)tokens atIndex:(int)index
{
if (_implementedTokenFieldDelegateMethods & CPTokenFieldDelegate_tokenField_shouldAddObjects_atIndex_)
var delegate = [self delegate];
if ([delegate respondsToSelector:@selector(tokenField:shouldAddObjects:atIndex:)])
{
var approvedObjects = [_tokenFieldDelegate tokenField:self shouldAddObjects:tokens atIndex:index];
var approvedObjects = [delegate tokenField:self shouldAddObjects:tokens atIndex:index];
if (approvedObjects !== nil)
return approvedObjects;
}
@@ -1342,10 +1245,10 @@ CPTokenFieldDeleteButtonType = 1;
*/
- (id)_representedObjectForEditingString:(CPString)aString
{
if (_implementedTokenFieldDelegateMethods & CPTokenFieldDelegate_tokenField_representedObjectForEditingString_)
var delegate = [self delegate];
if ([delegate respondsToSelector:@selector(tokenField:representedObjectForEditingString:)])
{
var token = [_tokenFieldDelegate tokenField:self representedObjectForEditingString:aString];
var token = [delegate tokenField:self representedObjectForEditingString:aString];
if (token !== nil && token !== undefined)
return token;
// If nil was returned, assume the string is the represented object. The alternative would have been
@@ -1357,22 +1260,23 @@ CPTokenFieldDeleteButtonType = 1;
- (BOOL)_hasMenuForRepresentedObject:(id)aRepresentedObject
{
if ((_implementedTokenFieldDelegateMethods & CPTokenFieldDelegate_tokenField_hasMenuForRepresentedObject_) &&
(_implementedTokenFieldDelegateMethods & CPTokenFieldDelegate_tokenField_menuForRepresentedObject_))
return [_tokenFieldDelegate tokenField:self hasMenuForRepresentedObject:aRepresentedObject];
var delegate = [self delegate];
if ([delegate respondsToSelector:@selector(tokenField:hasMenuForRepresentedObject:)] &&
[delegate respondsToSelector:@selector(tokenField:menuForRepresentedObject:)])
return [delegate tokenField:self hasMenuForRepresentedObject:aRepresentedObject];
return NO;
}
- (CPMenu)_menuForRepresentedObject:(id)aRepresentedObject
{
if ((_implementedTokenFieldDelegateMethods & CPTokenFieldDelegate_tokenField_hasMenuForRepresentedObject_) &&
(_implementedTokenFieldDelegateMethods & CPTokenFieldDelegate_tokenField_menuForRepresentedObject_))
var delegate = [self delegate];
if ([delegate respondsToSelector:@selector(tokenField:hasMenuForRepresentedObject:)] &&
[delegate respondsToSelector:@selector(tokenField:menuForRepresentedObject:)])
{
var hasMenu = [_tokenFieldDelegate tokenField:self hasMenuForRepresentedObject:aRepresentedObject];
var hasMenu = [delegate tokenField:self hasMenuForRepresentedObject:aRepresentedObject];
if (hasMenu)
return [_tokenFieldDelegate tokenField:self menuForRepresentedObject:aRepresentedObject] || nil;
return [delegate tokenField:self menuForRepresentedObject:aRepresentedObject] || nil;
}
return nil;
@@ -1473,12 +1377,12 @@ CPTokenFieldDeleteButtonType = 1;
[self setNeedsLayout];
}
- (BOOL)setThemeState:(ThemeState)aState
- (BOOL)setThemeState:(CPThemeState)aState
{
var r = [super setThemeState:aState];
// Share hover state with the disclosure and delete buttons.
if (aState.hasThemeState(CPThemeStateHovered))
if (aState & CPThemeStateHovered)
{
[_disclosureButton setThemeState:CPThemeStateHovered];
[_deleteButton setThemeState:CPThemeStateHovered];
@@ -1487,12 +1391,12 @@ CPTokenFieldDeleteButtonType = 1;
return r;
}
- (BOOL)unsetThemeState:(ThemeState)aState
- (BOOL)unsetThemeState:(CPThemeState)aState
{
var r = [super unsetThemeState:aState];
// Share hover state with the disclosure and delete button.
if (aState.hasThemeState(CPThemeStateHovered))
if (aState & CPThemeStateHovered)
{
[_disclosureButton unsetThemeState:CPThemeStateHovered];
[_deleteButton unsetThemeState:CPThemeStateHovered];
@@ -1503,7 +1407,7 @@ CPTokenFieldDeleteButtonType = 1;
- (CGSize)_minimumFrameSize
{
var size = CGSizeMakeZero(),
var size = _CGSizeMakeZero(),
minSize = [self currentValueForThemeAttribute:@"min-size"],
contentInset = [self currentValueForThemeAttribute:@"content-inset"];
@@ -1578,7 +1482,7 @@ CPTokenFieldDeleteButtonType = 1;
buttonOffset = [_disclosureButton currentValueForThemeAttribute:@"offset"],
buttonSize = [_disclosureButton currentValueForThemeAttribute:@"min-size"];
[_disclosureButton setFrame:CGRectMake(CGRectGetMaxX(frame) - buttonOffset.x, CGRectGetMinY(frame) + buttonOffset.y, buttonSize.width, buttonSize.height)];
[_disclosureButton setFrame:_CGRectMake(CGRectGetMaxX(frame) - buttonOffset.x, CGRectGetMinY(frame) + buttonOffset.y, buttonSize.width, buttonSize.height)];
break;
case CPTokenFieldDeleteButtonType:
[_deleteButton setEnabled:[self isEditable] && [self isEnabled]];
@@ -1587,7 +1491,7 @@ CPTokenFieldDeleteButtonType = 1;
buttonOffset = [_deleteButton currentValueForThemeAttribute:@"offset"],
buttonSize = [_deleteButton currentValueForThemeAttribute:@"min-size"];
[_deleteButton setFrame:CGRectMake(CGRectGetMaxX(frame) - buttonOffset.x, CGRectGetMinY(frame) + buttonOffset.y, buttonSize.width, buttonSize.height)];
[_deleteButton setFrame:_CGRectMake(CGRectGetMaxX(frame) - buttonOffset.x, CGRectGetMinY(frame) + buttonOffset.y, buttonSize.width, buttonSize.height)];
break;
}
}
@@ -1625,11 +1529,11 @@ CPTokenFieldDeleteButtonType = 1;
{
}
+ (CPDictionary)themeAttributes
+ (id)themeAttributes
{
var attributes = [CPButton themeAttributes];
[attributes setObject:CGPointMake(15, 5) forKey:@"offset"];
[attributes setObject:_CGPointMake(15, 5) forKey:@"offset"];
return attributes;
}
@@ -1655,11 +1559,11 @@ CPTokenFieldDeleteButtonType = 1;
{
}
+ (CPDictionary)themeAttributes
+ (id)themeAttributes
{
var attributes = [CPButton themeAttributes];
[attributes setObject:CGPointMake(15, 5) forKey:@"offset"];
[attributes setObject:_CGPointMake(15, 5) forKey:@"offset"];
return attributes;
}
+41 -162
View File
@@ -30,15 +30,6 @@
@global CPApp
var CPToolbarDelegate_toolbar_itemForItemIdentifier_willBeInsertedIntoToolbar_ = 1 << 0,
CPToolbarDelegate_toolbarAllowedItemIdentifiers_ = 1 << 1,
CPToolbarDelegate_toolbarDefaultItemIdentifiers_ = 1 << 2,
CPToolbarDelegate_toolbarDidRemoveItem_ = 1 << 3,
CPToolbarDelegate_toolbarSelectableItemIdentifiers_ = 1 << 4,
CPToolbarDelegate_toolbarWillAddItem_ = 1 << 5;
@typedef CPToolbarDisplayMode
/*
@global
@group CPToolbarDisplayMode
@@ -60,7 +51,7 @@ CPToolbarDisplayModeIconOnly = 2;
*/
CPToolbarDisplayModeLabelOnly = 3;
@typedef CPToolbarSizeMode
CPToolbarSizeModeDefault = 0;
CPToolbarSizeModeRegular = 1;
CPToolbarSizeModeSmall = 2;
@@ -68,20 +59,6 @@ CPToolbarSizeModeSmall = 2;
var CPToolbarsByIdentifier = nil,
CPToolbarConfigurationsByIdentifier = nil;
@protocol CPToolbarDelegate <CPObject>
@optional
- (CPToolbarItem)toolbar:(CPToolbar)toolbar itemForItemIdentifier:(CPString)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag;
- (CPArray)toolbarAllowedItemIdentifiers:(CPToolbar)toolbar;
- (CPArray)toolbarDefaultItemIdentifiers:(CPToolbar)toolbar;
- (void)toolbarDidRemoveItem:(CPNotification)notification;
- (CPArray)toolbarSelectableItemIdentifiers:(CPToolbar)toolbar;
- (void)toolbarWillAddItem:(CPNotification)notification;
@end
/*!
@ingroup appkit
@class CPToolbar
@@ -112,15 +89,14 @@ var CPToolbarsByIdentifier = nil,
@implementation CPToolbar : CPObject
{
CPString _identifier;
CPToolbarDisplayMode _displayMode @accessors(property=displayMode);
CPToolbarDisplayMode _displayMode @accessors(property=displayMode);
BOOL _showsBaselineSeparator;
BOOL _allowsUserCustomization;
BOOL _isVisible;
CPToolbarSizeMode _sizeMode @accessors(property=sizeMode);
int _sizeMode @accessors(property=sizeMode);
int _desiredHeight;
id <CPToolbarDelegate> _delegate;
unsigned _implementedDelegateMethods;
id _delegate;
CPArray _itemIdentifiers;
@@ -189,6 +165,15 @@ var CPToolbarsByIdentifier = nil,
return self;
}
/*!
Sets the toolbar's display mode. NOT YET IMPLEMENTED.
*/
- (void)setDisplayMode:(CPToolbarDisplayMode)aDisplayMode
{
}
/*!
Returns the toolbar's identifier
*/
@@ -263,25 +248,6 @@ var CPToolbarsByIdentifier = nil,
return;
_delegate = aDelegate;
_implementedDelegateMethods = 0;
if ([_delegate respondsToSelector:@selector(toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:)])
_implementedDelegateMethods |= CPToolbarDelegate_toolbar_itemForItemIdentifier_willBeInsertedIntoToolbar_;
if ([_delegate respondsToSelector:@selector(toolbarAllowedItemIdentifiers:)])
_implementedDelegateMethods |= CPToolbarDelegate_toolbarAllowedItemIdentifiers_;
if ([_delegate respondsToSelector:@selector(toolbarDefaultItemIdentifiers:)])
_implementedDelegateMethods |= CPToolbarDelegate_toolbarDefaultItemIdentifiers_;
if ([_delegate respondsToSelector:@selector(toolbarDidRemoveItem:)])
_implementedDelegateMethods |= CPToolbarDelegate_toolbarDidRemoveItem_;
if ([_delegate respondsToSelector:@selector(toolbarSelectableItemIdentifiers:)])
_implementedDelegateMethods |= CPToolbarDelegate_toolbarSelectableItemIdentifiers_;
if ([_delegate respondsToSelector:@selector(toolbarWillAddItem:)])
_implementedDelegateMethods |= CPToolbarDelegate_toolbarWillAddItem_;
[self _reloadToolbarItems];
}
@@ -332,9 +298,9 @@ var CPToolbarsByIdentifier = nil,
// _defaultItems may have been loaded from Cib
_itemIdentifiers = [_defaultItems valueForKey:@"itemIdentifier"] || [];
if ([self _delegateRespondsToToolbarDefaultItemIdentifiers])
if ([_delegate respondsToSelector:@selector(toolbarDefaultItemIdentifiers:)])
{
var itemIdentifiersFromDelegate = [self _sendDelegateToolbarDefaultItemIdentifiers];
var itemIdentifiersFromDelegate = [_delegate toolbarDefaultItemIdentifiers:self];
// If we get items both from the Cib and from the delegate method, put the delegate items before the
// Cib ones.
@@ -359,7 +325,7 @@ var CPToolbarsByIdentifier = nil,
item = [_identifiedItems objectForKey:identifier];
if (!item && _delegate)
item = [self _sendDelegateItemForItemIdentifier:identifier willBeInsertedIntoToolbar:YES];
item = [_delegate toolbar:self itemForItemIdentifier:identifier willBeInsertedIntoToolbar:YES];
item = [item copy];
@@ -437,14 +403,12 @@ var CPToolbarsByIdentifier = nil,
- (id)_itemForItemIdentifier:(CPString)identifier willBeInsertedIntoToolbar:(BOOL)toolbar
{
var item = [_identifiedItems objectForKey:identifier];
if (!item)
{
item = [CPToolbarItem _standardItemWithItemIdentifier:identifier];
if (_delegate && !item)
{
item = [[self _sendDelegateItemForItemIdentifier:identifier willBeInsertedIntoToolbar:toolbar] copy];
item = [[_delegate toolbar:self itemForItemIdentifier:identifier willBeInsertedIntoToolbar:toolbar] copy];
if (!item)
[CPException raise:CPInvalidArgumentException
reason:@"Toolbar delegate " + _delegate + " returned nil toolbar item for identifier " + identifier];
@@ -469,11 +433,11 @@ var CPToolbarsByIdentifier = nil,
/* @ignore */
- (id)_defaultToolbarItems
{
if (!_defaultItems && [self _delegateRespondsToToolbarDefaultItemIdentifiers])
if (!_defaultItems && [_delegate respondsToSelector:@selector(toolbarDefaultItemIdentifiers:)])
{
_defaultItems = [];
var identifiers = [self _sendDelegateToolbarDefaultItemIdentifiers],
var identifiers = [_delegate toolbarDefaultItemIdentifiers:self],
index = 0,
count = [identifiers count];
@@ -639,14 +603,14 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
return @"toolbar-view";
}
+ (CPDictionary)themeAttributes
+ (id)themeAttributes
{
return @{
@"item-margin": 10.0,
@"extra-item-width": 20.0,
@"extra-item-extra-image": [CPNull null],
@"extra-item-extra-alternate-image": [CPNull null],
@"content-inset": CGInsetMake(4.0, 4.0, 4.0, 10),
@"content-inset": _CGInsetMake(4.0, 4.0, 4.0, 10),
@"regular-size-height": 59.0,
@"small-size-height": 46.0,
@"image-item-separator-color": [CPNull null],
@@ -665,7 +629,7 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
_labelColor = [CPColor blackColor];
_labelShadowColor = [CPColor colorWithWhite:1.0 alpha:0.75];
_additionalItemsButton = [[CPPopUpButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 10.0, 15.0) pullsDown:YES];
_additionalItemsButton = [[CPPopUpButton alloc] initWithFrame:_CGRectMake(0.0, 0.0, 10.0, 15.0) pullsDown:YES];
[_additionalItemsButton setBordered:NO];
[_additionalItemsButton setImagePosition:CPImageOnly];
@@ -715,7 +679,7 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
{
// We begin by recalculating the visible items.
var items = [_toolbar items],
itemsWidth = CGRectGetWidth([self bounds]),
itemsWidth = _CGRectGetWidth([self bounds]),
minWidth = _minWidth,
// FIXME: This should be a CPSet.
invisibleItemsSortedByPriority = [];
@@ -802,7 +766,7 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
// static width (min==max). This handles the case where the user did setView:
// with a view of a different size than minSize/maxSize
else
[view setFrameSize:CGSizeMake(minSize.width, height)];
[view setFrameSize:_CGSizeMake(minSize.width, height)];
[view setHidden:NO];
}
@@ -837,7 +801,7 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
remainingSpace += proposedWidth - constrainedWidth;
}
[view setFrameSize:CGSizeMake(constrainedWidth, height)];
[view setFrameSize:_CGSizeMake(constrainedWidth, height)];
}
}
@@ -845,14 +809,15 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
var index = 0,
count = _visibleItems.length,
x = contentInset.left,
contentInset = [self valueForThemeAttribute:@"content-inset"],
y = contentInset.top;
for (; index < count; ++index)
{
var view = [self viewForItem:_visibleItems[index]],
viewWidth = CGRectGetWidth([view frame]);
viewWidth = _CGRectGetWidth([view frame]);
[view setFrame:CGRectMake(x, y, viewWidth, height)];
[view setFrame:_CGRectMake(x, y, viewWidth, height)];
x += viewWidth + [self valueForThemeAttribute:@"item-margin"];
}
@@ -886,7 +851,7 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
if (needsAdditionalItemsButton)
{
[_additionalItemsButton setFrameOrigin:CGPointMake(itemsWidth + 5.0, (CGRectGetHeight([self bounds]) - CGRectGetHeight([_additionalItemsButton frame])) / 2.0)];
[_additionalItemsButton setFrameOrigin:_CGPointMake(itemsWidth + 5.0, (_CGRectGetHeight([self bounds]) - _CGRectGetHeight([_additionalItemsButton frame])) / 2.0)];
[self addSubview:_additionalItemsButton];
@@ -1029,12 +994,12 @@ var LABEL_MARGIN = 2.0;
{
_toolbarItem = aToolbarItem;
_labelField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
_labelField = [[CPTextField alloc] initWithFrame:_CGRectMakeZero()];
[_labelField setFont:[CPFont systemFontOfSize:11.0]];
[_labelField setTextColor:[self FIXME_labelColor]];
[_labelField setTextShadowColor:[self FIXME_labelShadowColor]];
[_labelField setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[_labelField setTextShadowOffset:_CGSizeMake(0.0, 1.0)];
[_labelField setAutoresizingMask:CPViewWidthSizable | CPViewMinXMargin];
[self addSubview:_labelField];
@@ -1136,8 +1101,8 @@ var LABEL_MARGIN = 2.0;
[_labelField setHidden:iconOnly];
[_view setHidden:labelOnly];
_minSize = CGSizeMake(MAX(_labelSize.width, minSize.width), (labelOnly ? 0 : minSize.height) + (iconOnly ? 0 : _labelSize.height + LABEL_MARGIN));
_maxSize = CGSizeMake(MAX(_labelSize.width, maxSize.width), 100000000.0);
_minSize = _CGSizeMake(MAX(_labelSize.width, minSize.width), (labelOnly ? 0 : minSize.height) + (iconOnly ? 0 : _labelSize.height + LABEL_MARGIN));
_maxSize = _CGSizeMake(MAX(_labelSize.width, maxSize.width), 100000000.0);
[_toolbar tile];
}
@@ -1151,14 +1116,14 @@ var LABEL_MARGIN = 2.0;
return;
var bounds = [self bounds],
width = CGRectGetWidth(bounds);
width = _CGRectGetWidth(bounds);
if (identifier === CPToolbarSeparatorItemIdentifier)
{
var itemSeparatorColor = [_toolbar valueForThemeAttribute:@"image-item-separator-color"],
itemSeparatorSize = [_toolbar valueForThemeAttribute:@"image-item-separator-size"];
[_view setFrame:CGRectMake(ROUND((width - itemSeparatorSize.size.width) / 2.0), 0.0, itemSeparatorSize.size.width, CGRectGetHeight(bounds))];
[_view setFrame:_CGRectMake(ROUND((width - itemSeparatorSize.size.width) / 2.0), 0.0, itemSeparatorSize.size.width, _CGRectGetHeight(bounds))];
[_view setBackgroundColor:itemSeparatorColor];
return;
@@ -1168,17 +1133,17 @@ var LABEL_MARGIN = 2.0;
var view = _view || _imageView,
itemMaxSize = [_toolbarItem maxSize],
iconOnly = [[_toolbarItem toolbar] displayMode] === CPToolbarDisplayModeIconOnly,
height = CGRectGetHeight(bounds) - (iconOnly ? 0 : _labelSize.height),
height = _CGRectGetHeight(bounds) - (iconOnly ? 0 : _labelSize.height),
viewWidth = MIN(itemMaxSize.width, width),
viewHeight = MIN(itemMaxSize.height, height);
[view setFrame:CGRectMake(ROUND((width - viewWidth) / 2.0),
[view setFrame:_CGRectMake(ROUND((width - viewWidth) / 2.0),
ROUND((height - viewHeight) / 2.0),
viewWidth,
viewHeight)];
// Label is always drawn at the bottom of the view. So if the view is really tall but the icon is tiny, the icon is centred above the label while the label remains on the bottom.
[_labelField setFrameOrigin:CGPointMake(ROUND((width - _labelSize.width) / 2.0), CGRectGetHeight(bounds) - _labelSize.height)];
[_labelField setFrameOrigin:_CGPointMake(ROUND((width - _labelSize.width) / 2.0), _CGRectGetHeight(bounds) - _labelSize.height)];
}
- (void)mouseDown:(CPEvent)anEvent
@@ -1245,7 +1210,7 @@ var LABEL_MARGIN = 2.0;
if (alternateImage)
[_imageView setImage:alternateImage];
[_labelField setTextShadowOffset:CGSizeMakeZero()];
[_labelField setTextShadowOffset:_CGSizeMakeZero()];
}
else
{
@@ -1254,13 +1219,13 @@ var LABEL_MARGIN = 2.0;
if (image)
[_imageView setImage:image];
[_labelField setTextShadowOffset:CGSizeMake(0.0, 1.0)];
[_labelField setTextShadowOffset:_CGSizeMake(0.0, 1.0)];
}
[_labelField setTextShadowColor:[self FIXME_labelShadowColor]];
}
- (BOOL)sendAction:(SEL)anAction to:(id)aSender
- (void)sendAction:(SEL)anAction to:(id)aSender
{
[CPApp sendAction:anAction to:aSender from:_toolbarItem];
}
@@ -1284,89 +1249,3 @@ var LABEL_MARGIN = 2.0;
}
@end
@implementation CPToolbar (CPToolbarDelegate)
/*
@ignore
Return YES if the delegate implements toolbarDefaultItemIdentifiers:
*/
- (BOOL)_delegateRespondsToToolbarDefaultItemIdentifiers
{
return _implementedDelegateMethods & CPToolbarDelegate_toolbarDefaultItemIdentifiers_;
}
/*!
@ignore
Call the delegate toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:
*/
- (CPToolbarItem)_sendDelegateItemForItemIdentifier:(CPString)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag
{
if (!(_implementedDelegateMethods & CPToolbarDelegate_toolbar_itemForItemIdentifier_willBeInsertedIntoToolbar_))
return nil;
return [_delegate toolbar:self itemForItemIdentifier:itemIdentifier willBeInsertedIntoToolbar:flag];
}
/*!
@ignore
Call the delegate toolbarAllowedItemIdentifiers:
*/
- (CPArray)_sendDelegateToolbarAllowedItemIdentifiers
{
if (!(_implementedDelegateMethods & CPToolbarDelegate_toolbarAllowedItemIdentifiers_))
return [];
return [_delegate toolbarAllowedItemIdentifiers:self];
}
/*!
@ignore
Call the delegate toolbarDefaultItemIdentifiers:
*/
- (CPArray)_sendDelegateToolbarDefaultItemIdentifiers
{
if (!(_implementedDelegateMethods & CPToolbarDelegate_toolbarDefaultItemIdentifiers_))
return [];
return [_delegate toolbarDefaultItemIdentifiers:self];
}
/*!
@ignore
Call the delegate toolbarDidRemoveItem:
*/
- (void)_sendDelegateToolbarDidRemoveItem:(CPNotification)notification
{
if (!(_delegate & CPToolbarDelegate_toolbarDidRemoveItem_))
return;
[_delegate toolbarDidRemoveItem:notification];
}
/*!
@ignore
Call the delegate toolbarSelectableItemIdentifiers:
*/
- (CPArray)_sendDelegateToolbarSelectableItemIdentifiers
{
if (!(_implementedDelegateMethods & CPToolbarDelegate_toolbarSelectableItemIdentifiers_))
return [];
return [_delegate toolbarSelectableItemIdentifiers:self];
}
/*!
@ignore
Call the delegate toolbarWillAddItem:
*/
- (void)_sendDelegateToolbarWillAddItem:(CPNotification)notification
{
if (!(_delegate & CPToolbarDelegate_toolbarWillAddItem_))
return;
[_delegate toolbarWillAddItem:notification];
}
@end
-164
View File
@@ -1,164 +0,0 @@
/*
* CPTrackingArea.j
* AppKit
*
* Created by Didier Korthoudt.
* Copyright 2015, Cappuccino Project.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/Foundation.j>
@class CPView
/* @group CPTrackingAreaOptions */
@typedef CPTrackingAreaOptions
CPTrackingMouseEnteredAndExited = 1 << 1;
CPTrackingMouseMoved = 1 << 2;
CPTrackingCursorUpdate = 1 << 3;
CPTrackingActiveWhenFirstResponder = 1 << 4;
CPTrackingActiveInKeyWindow = 1 << 5;
CPTrackingActiveInActiveApp = 1 << 6;
CPTrackingActiveAlways = 1 << 7;
CPTrackingAssumeInside = 1 << 8;
CPTrackingInVisibleRect = 1 << 9;
CPTrackingEnabledDuringMouseDrag = 1 << 10;
var CPTrackingAreaViewRectKey = @"CPTrackinkAreaViewRectKey",
CPTrackingAreaOptionsKey = @"CPTrackingAreaOptionsKey",
CPTrackingAreaOwnerKey = @"CPTrackingAreaOwnerKey",
CPTrackingAreaUserInfoKey = @"CPTrackingAreaUserInfoKey",
CPTrackingAreaReferencingViewKey = @"CPTrackingAreaReferencingViewKey",
CPTrackingAreaWindowRect = @"CPTrackingAreaWindowRect";
CPTrackingOwnerImplementsMouseEntered = 1 << 1;
CPTrackingOwnerImplementsMouseExited = 1 << 2;
CPTrackingOwnerImplementsMouseMoved = 1 << 3;
CPTrackingOwnerImplementsCursorUpdate = 1 << 4;
/*!
@ingroup appkit
A CPTrackingArea defines a region of view that generates mouse-tracking and
cursor-update events when the mouse is over that region.
*/
@implementation CPTrackingArea : CPObject
{
CGRect _viewRect @accessors(getter=rect);
CPTrackingAreaOptions _options @accessors(getter=options);
id _owner @accessors(getter=owner);
CPDictionary _userInfo @accessors(getter=userInfo);
CPView _referencingView @accessors(property=view);
CGRect _windowRect @accessors(getter=windowRect);
unsigned _implementedOwnerMethods @accessors(getter=implementedOwnerMethods);
}
#pragma mark -
#pragma mark Initialization
/*!
Initializes and returns an object defining a region of a view to receive mouse-tracking events, mouse-moved events, cursor-update events, or possibly
all these events.
*/
- (CPTrackingArea)initWithRect:(CGRect)aRect options:(CPTrackingAreaOptions)options owner:(id)owner userInfo:(CPDictionary)userInfo
{
if (owner === nil)
[CPException raise:CPInternalInconsistencyException reason:"No owner specified"];
if (options === 0)
[CPException raise:CPInternalInconsistencyException reason:"Invalid CPTrackingArea options"];
// Check options:
// - at least one of CPTrackingMouseEnteredAndExited, CPTrackingMouseMoved, CPTrackingCursorUpdate
// - exactly one of CPTrackingActiveWhenFirstResponder, CPTrackingActiveInKeyWindow, CPTrackingActiveInActiveApp, CPTrackingActiveAlways
// - no check on CPTrackingAssumeInside, CPTrackingInVisibleRect, CPTrackingEnableDuringMouseDrag
if (!((options & CPTrackingMouseEnteredAndExited) || (options & CPTrackingMouseMoved) || (options & CPTrackingCursorUpdate)))
[CPException raise:CPInternalInconsistencyException reason:"Invalid CPTrackingAreaOptions: must use at least one of [CPTrackingMouseEnteredAndExited | CPTrackingMouseMoved | CPTrackingCursorUpdate]"];
if ((((options & CPTrackingActiveWhenFirstResponder) > 0) + ((options & CPTrackingActiveInKeyWindow) > 0) + ((options & CPTrackingActiveInActiveApp) > 0) + ((options & CPTrackingActiveAlways) > 0)) !== 1)
[CPException raise:CPInternalInconsistencyException reason:"Tracking area options may only specify one of [CPTrackingActiveWhenFirstResponder | CPTrackingActiveInKeyWindow | CPTrackingActiveInActiveApp | CPTrackingActiveAlways]."];
if (self = [super init])
{
_viewRect = aRect;
_options = options;
_owner = owner;
_userInfo = userInfo;
// Cache owner implemented methods
if ([_owner respondsToSelector:@selector(mouseEntered:)])
_implementedOwnerMethods |= CPTrackingOwnerImplementsMouseEntered;
if ([_owner respondsToSelector:@selector(mouseExited:)])
_implementedOwnerMethods |= CPTrackingOwnerImplementsMouseExited;
if ([_owner respondsToSelector:@selector(mouseMoved:)])
_implementedOwnerMethods |= CPTrackingOwnerImplementsMouseMoved;
if ([_owner respondsToSelector:@selector(cursorUpdate:)])
_implementedOwnerMethods |= CPTrackingOwnerImplementsCursorUpdate;
}
return self;
}
#pragma mark -
#pragma mark Implementation
- (void)_updateWindowRect
{
_windowRect = [_referencingView convertRect:((_options & CPTrackingInVisibleRect) ? [_referencingView visibleRect] : _viewRect) toView:[[_referencingView window] _windowView]];
}
@end
#pragma mark -
#pragma mark CPCoding
@implementation CPTrackingArea (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super init])
{
_viewRect = [aCoder decodeObjectForKey:CPTrackingAreaViewRectKey];
_options = [aCoder decodeObjectForKey:CPTrackingAreaOptionsKey];
_owner = [aCoder decodeObjectForKey:CPTrackingAreaOwnerKey];
_userInfo = [aCoder decodeObjectForKey:CPTrackingAreaUserInfoKey];
_referencingView = [aCoder decodeObjectForKey:CPTrackingAreaReferencingViewKey];
_windowRect = [aCoder decodeObjectForKey:CPTrackingAreaWindowRect];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:_viewRect forKey:CPTrackingAreaViewRectKey];
[aCoder encodeObject:_options forKey:CPTrackingAreaOptionsKey];
[aCoder encodeObject:_owner forKey:CPTrackingAreaOwnerKey];
[aCoder encodeObject:_userInfo forKey:CPTrackingAreaUserInfoKey];
[aCoder encodeObject:_referencingView forKey:CPTrackingAreaReferencingViewKey];
[aCoder encodeObject:_windowRect forKey:CPTrackingAreaWindowRect];
}
@end
+443 -1053
View File
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -105,7 +105,7 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOutEffect";
[super startAnimation];
}
- (void)setCurrentProgress:(float)progress
- (void)setCurrentProgress:(CPAnimationProgress)progress
{
[super setCurrentProgress:progress];
@@ -116,7 +116,7 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOutEffect";
view = [self _targetView:dictionary],
startFrame = [self _startFrame:dictionary],
endFrame = [self _endFrame:dictionary],
differenceFrame = CGRectMakeZero(),
differenceFrame = _CGRectMakeZero(),
value = [super currentValue];
differenceFrame.origin.x = endFrame.origin.x - startFrame.origin.x;
@@ -124,7 +124,7 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOutEffect";
differenceFrame.size.width = endFrame.size.width - startFrame.size.width;
differenceFrame.size.height = endFrame.size.height - startFrame.size.height;
var intermediateFrame = CGRectMakeZero();
var intermediateFrame = _CGRectMakeZero();
intermediateFrame.origin.x = startFrame.origin.x + differenceFrame.origin.x * value;
intermediateFrame.origin.y = startFrame.origin.y + differenceFrame.origin.y * value;
intermediateFrame.size.width = startFrame.size.width + differenceFrame.size.width * value;
@@ -140,7 +140,7 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOutEffect";
[view setAlphaValue:1.0 + ( 0.0 - 1.0 ) * value];
if (progress === 1.0)
[self _targetView:view setHidden:CGRectIsEmpty(endFrame) || [view alphaValue] === 0.0];
[self _targetView:view setHidden:_CGRectIsNull(endFrame) || [view alphaValue] === 0.0];
}
}
@@ -161,7 +161,7 @@ CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOutEffect";
else if (effect === CPViewAnimationFadeOutEffect)
[view setAlphaValue:0.0];
[self _targetView:view setHidden:CGRectIsEmpty(endFrame) || [view alphaValue] === 0.0];
[self _targetView:view setHidden:_CGRectIsNull(endFrame) || [view alphaValue] === 0.0];
}
[super stopAnimation];
-1
View File
@@ -210,7 +210,6 @@ var CPViewControllerCachedCibs;
[cibOwner viewControllerDidLoadCib:self];
_isLoading = NO;
_isLazy = NO;
[self _viewDidLoad];
}
else if (_isLazy)
-186
View File
@@ -1,186 +0,0 @@
/*
* CPVisualEffectView.j
* AppKit
*
* Created by Antoine Mercadal.
* Copyright 2015, 280 Cappuccino Project.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/Foundation.j>
@import "CPAppearance.j"
@import "CPView.j"
@typedef CPVisualEffectMaterial
CPVisualEffectMaterialAppearanceBased = 0;
CPVisualEffectMaterialLight = 1;
CPVisualEffectMaterialDark = 2;
CPVisualEffectMaterialTitlebar = 3;
@typedef CPVisualEffectBlendingMode
CPVisualEffectBlendingModeBehindWindow = 0;
CPVisualEffectBlendingModeWithinWindow = 1;
@typedef CPVisualEffectState
CPVisualEffectStateFollowsWindowActiveState = 0;
CPVisualEffectStateActive = 1;
CPVisualEffectStateInactive = 2;
/*! @ingroup appkit
Very naive implementation of CPVisualEffectView. This view allows
to use vibrancy effect. This is only working with Safari 9+ and the
support in Chrome/ium should come quite soon.
Using this class with a browser that doesn't support backdrop-filter
While still work, but you will not get the blurry effect.
*/
@implementation CPVisualEffectView : CPView
{
CPImage _maskImage @accessors(property=maskImage);
CPVisualEffectBlendingMode _blendingMode @accessors(property=blendingMode);
CPVisualEffectMaterial _material @accessors(property=material);
CPVisualEffectState _state @accessors(property=state);
}
#pragma mark -
#pragma mark Initialization
- (id)initWithFrame:(CGRect)aFrame
{
if (self = [super initWithFrame:aFrame])
{
_material = CPVisualEffectMaterialAppearanceBased;
_blendingMode = CPVisualEffectBlendingModeWithinWindow;
_state = CPVisualEffectStateFollowsWindowActiveState;
_appearance = [CPAppearance appearanceNamed:CPAppearanceNameVibrantDark];
}
return self;
}
#pragma mark -
#pragma mark CPVisualEffectView API
/*! Sets the appearance of the CPVisualEffectView.
Only CPAppearance named CPAppearanceNameVibrantDark or CPAppearanceNameVibrantLight are valid
@param anAppearance the CPAppearance.
*/
- (void)setAppearance:(CPAppearance)anAppearance
{
if (![self _validAppearance:anAppearance])
[CPException raise:CPInvalidArgumentException reason:"Appearance can only be CPAppearanceNameVibrantDark or CPAppearanceNameVibrantLight in CPVisualEffectView, but is " + anAppearance];
[super setAppearance:anAppearance];
[self setNeedsLayout:YES];
}
/*! Sets the received effect state.
Possible values:
<pre>
CPVisualEffectStateFollowsWindowActiveState (default)
CPVisualEffectStateActive
CPVisualEffectStateInactive
</pre>
*/
- (void)setState:(CPVisualEffectState)aState
{
if (_state == aState)
return;
[self willChangeValueForKey:"state"];
_state = aState;
[self didChangeValueForKey:"state"];
[self setNeedsLayout:YES];
}
#pragma mark -
#pragma mark Utilities
- (void)_setEffectEnabled:(BOOL)shouldEnable
{
var dark = [[self appearance] isEqual:[CPAppearance appearanceNamed:CPAppearanceNameVibrantDark]],
prop = CPBrowserStyleProperty("backdrop-filter"),
color = (dark ? [CPColor colorWithHexString:@"1e1e1e"] : [CPColor whiteColor]),
finalColor = shouldEnable ? [color colorWithAlphaComponent:0.6] : color;
[self setBackgroundColor:finalColor];
#if PLATFORM(DOM)
self._DOMElement.style[prop] = shouldEnable ? "blur(30px)" : nil;
#endif
}
- (void)layoutSubviews
{
switch (_state)
{
case CPVisualEffectStateFollowsWindowActiveState:
[self _setEffectEnabled:[self hasThemeState:CPThemeStateKeyWindow]];
break;
case CPVisualEffectStateActive:
[self _setEffectEnabled:YES];
break;
case CPVisualEffectStateInactive:
[self _setEffectEnabled:NO];
break;
}
}
- (BOOL)_validAppearance:(CPAppearance)anAppearance
{
return [anAppearance isEqual:[CPAppearance appearanceNamed:CPAppearanceNameVibrantDark]] || [anAppearance isEqual:[CPAppearance appearanceNamed:CPAppearanceNameVibrantLight]];
}
#pragma mark -
#pragma mark CPCoding
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super initWithCoder:aCoder])
{
_blendingMode = [aCoder decodeIntForKey:@"_blendingMode"] || CPVisualEffectBlendingModeWithinWindow;
_maskImage = [aCoder decodeObjectForKey:@"_maskImage"];
_material = [aCoder decodeIntForKey:@"_material"] || CPVisualEffectMaterialAppearanceBased;
_state = [aCoder decodeIntForKey:@"_state"] || CPVisualEffectStateFollowsWindowActiveState;
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_maskImage forKey:@"_maskImage"];
[aCoder encodeInt:_blendingMode forKey:@"_blendingMode"];
[aCoder encodeInt:_material forKey:@"_material"];
[aCoder encodeInt:_state forKey:@"_state"];
}
@end
+1 -4
View File
@@ -23,9 +23,6 @@
@import "CPView.j"
@import "CPScrollView.j"
@class CPWebScriptObject
@typedef Window
// FIXME: implement these where possible:
/*
@@ -96,7 +93,7 @@ CPWebViewAppKitScrollMaxPollCount = 3;
CPScrollView _scrollView;
CPView _frameView;
DOMElement _iframe;
IFrame _iframe;
CPString _mainFrameURL;
CPArray _backwardStack;
CPArray _forwardStack;
+273 -978
View File
File diff suppressed because it is too large Load Diff
-4
View File
@@ -81,7 +81,6 @@ CPWindowMinYMargin = 8;
CPWindowHeightSizable = 16;
CPWindowMaxYMargin = 32;
@typedef CPWindowLevel
CPBackgroundWindowLevel = -1;
/*
Default level for windows
@@ -144,7 +143,6 @@ CPDraggingWindowLevel = 500;
*/
CPScreenSaverWindowLevel = 1000;
@typedef CPWindowOrderingMode
/*
The receiver is placed directly in front of the window specified.
@global
@@ -196,5 +194,3 @@ CPStandardWindowShadowStyle = 0;
CPMenuWindowShadowStyle = 1;
CPPanelWindowShadowStyle = 2;
CPCustomWindowShadowStyle = 3;
CPWindowConstrainToScreen = YES;
@@ -32,7 +32,7 @@
return @"bordeless-bridge-window-view";
}
+ (CPDictionary)themeAttributes
+ (id)themeAttributes
{
return @{
@"toolbar-background-color": [CPColor grayColor],
+17 -9
View File
@@ -26,6 +26,7 @@
@implementation _CPDocModalWindowView : _CPWindowView
{
CPView _bodyView;
CPView _shadowView;
}
+ (CPString)defaultThemeClass
@@ -33,11 +34,11 @@
return @"doc-modal-window-view";
}
+ (CPDictionary)themeAttributes
+ (id)themeAttributes
{
return @{
@"body-color": [CPColor whiteColor],
@"shadow-height": 8,
@"height-shadow": 8,
};
}
@@ -49,7 +50,7 @@
*/
var contentRect = [super contentRectForFrameRect:aFrameRect];
return CGRectInset(contentRect, 1.0, 1.0);
return _CGRectInset(contentRect, 1.0, 1.0);
}
- (id)initWithFrame:(CGRect)aFrame styleMask:(unsigned)aStyleMask
@@ -60,13 +61,17 @@
{
var bounds = [self bounds];
_bodyView = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(bounds), CGRectGetHeight(bounds))];
_bodyView = [[CPView alloc] initWithFrame:_CGRectMake(0.0, 0.0, _CGRectGetWidth(bounds), _CGRectGetHeight(bounds))];
[_bodyView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
[_bodyView setHitTests:NO];
[self addSubview:_bodyView];
}
_shadowView = [[CPView alloc] initWithFrame:CGRectMake(0, 0, _CGRectGetWidth(bounds), [self valueForThemeAttribute:@"height-shadow"])];
[_shadowView setAutoresizingMask:CPViewWidthSizable];
[self addSubview:_shadowView];
}
return self;
}
@@ -81,6 +86,11 @@
return [[self class] frameRectForContentRect:aContentRect];
}
- (void)_enableSheet:(BOOL)enable
{
// do nothing, already a sheet
}
- (void)layoutSubviews
{
[super layoutSubviews];
@@ -88,11 +98,9 @@
var bounds = [self bounds];
[_bodyView setBackgroundColor:[self valueForThemeAttribute:@"body-color"]];
}
- (int)bodyOffset
{
return [_bodyView frame].origin.y;
[_shadowView setFrame:CGRectMake(0,0, _CGRectGetWidth(bounds), [self valueForThemeAttribute:@"height-shadow"])];
[_shadowView setBackgroundColor:[self valueForThemeAttribute:@"attached-sheet-shadow-color"]];
}
@end

Some files were not shown because too many files have changed in this diff Show More