From c2bf47eca2aaad43cb35d4570c3d722c056956ce Mon Sep 17 00:00:00 2001 From: Alexander Ljungberg Date: Tue, 11 Dec 2012 17:15:24 +0000 Subject: [PATCH 1/4] Support CPThemeStateEditable for text fields. --- AppKit/CPTextField.j | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/AppKit/CPTextField.j b/AppKit/CPTextField.j index 76d50f339..5e27a56b7 100644 --- a/AppKit/CPTextField.j +++ b/AppKit/CPTextField.j @@ -308,6 +308,11 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); if (shouldBeEditable) _isSelectable = YES; + if (_isEditable) + [self setThemeState:CPThemeStateEditable]; + else + [self unsetThemeState:CPThemeStateEditable]; + // We only allow first responder status if the field is editable and enabled. if (!shouldBeEditable && [[self window] firstResponder] === self) [[self window] makeFirstResponder:nil]; From d27e33394139dbcd6f5a7c1ce43d6f41b7834301 Mon Sep 17 00:00:00 2001 From: Alexander Ljungberg Date: Tue, 11 Dec 2012 17:19:02 +0000 Subject: [PATCH 2/4] Fixed: tokens could be deleted in an non editable token field. Prior to this fix, clicking the (X) button on a token would delete the token even if the field was not actually editable. --- AppKit/CPTokenField.j | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/AppKit/CPTokenField.j b/AppKit/CPTokenField.j index b15aec542..396cbf6ce 100755 --- a/AppKit/CPTokenField.j +++ b/AppKit/CPTokenField.j @@ -570,6 +570,7 @@ var CPScrollDestinationNone = 0, [newToken setTokenField:self]; [newToken setRepresentedObject:tokenObject]; [newToken setStringValue:tokenValue]; + [newToken setEditable:[self isEditable]]; [contentView addSubview:newToken]; } @@ -615,6 +616,13 @@ var CPScrollDestinationNone = 0, } } +- (void)setEditable:(BOOL)shouldBeEditable +{ + [super setEditable:shouldBeEditable]; + + [[self _tokens] makeObjectsPerformSelector:@selector(setEditable:) withObject:shouldBeEditable]; +} + - (void)sendAction:(SEL)anAction to:(id)anObject { _shouldNotifyTarget = NO; @@ -1324,6 +1332,12 @@ var CPScrollDestinationNone = 0, _representedObject = representedObject; } +- (void)setEditable:(BOOL)shouldBeEditable +{ + [super setEditable:shouldBeEditable]; + [self setNeedsLayout]; +} + - (CGSize)_minimumFrameSize { var size = _CGSizeMakeZero(), @@ -1349,6 +1363,7 @@ var CPScrollDestinationNone = 0, { [_deleteButton setTarget:self]; [_deleteButton setAction:@selector(_delete:)]; + [_deleteButton setEnabled:[self isEditable]]; var frame = [bezelView frame], buttonOffset = [_deleteButton currentValueForThemeAttribute:@"offset"], @@ -1370,7 +1385,8 @@ var CPScrollDestinationNone = 0, - (void)_delete:(id)sender { - [_tokenField _deleteToken:self]; + if ([self isEditable]) + [_tokenField _deleteToken:self]; } @end From bd1f64bfdeff42d9406c593e0941e98cbf783403 Mon Sep 17 00:00:00 2001 From: Alexander Ljungberg Date: Tue, 11 Dec 2012 17:27:13 +0000 Subject: [PATCH 3/4] Only show token delete button on hover, and only when token field is editable. Before this change the close button showed at all times, even for token fields which weren't even editable. This change brings us closer to Cocoa in that there's no token delete button most of the time, and just like in Cocoa there are more controls available on hover. (Although in Cocoa there's a disclosure arrow and we have a close button instead.) --- AppKit/CPTokenField.j | 22 ++++++++++++++++++++++ AppKit/Themes/Aristo/ThemeDescriptors.j | 13 +++++++------ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/AppKit/CPTokenField.j b/AppKit/CPTokenField.j index 396cbf6ce..5bc5828f2 100755 --- a/AppKit/CPTokenField.j +++ b/AppKit/CPTokenField.j @@ -1338,6 +1338,28 @@ var CPScrollDestinationNone = 0, [self setNeedsLayout]; } +- (BOOL)setThemeState:(CPThemeState)aState +{ + var r = [super setThemeState:aState]; + + // Share hover state with the delete button. + if (r && aState === CPThemeStateHovered) + [_deleteButton setThemeState:aState]; + + return r; +} + +- (BOOL)unsetThemeState:(CPThemeState)aState +{ + var r = [super unsetThemeState:aState]; + + // Share hover state with the delete button. + if (r && aState === CPThemeStateHovered) + [_deleteButton unsetThemeState:aState]; + + return r; +} + - (CGSize)_minimumFrameSize { var size = _CGSizeMakeZero(), diff --git a/AppKit/Themes/Aristo/ThemeDescriptors.j b/AppKit/Themes/Aristo/ThemeDescriptors.j index 5c77deb67..4eaa51738 100755 --- a/AppKit/Themes/Aristo/ThemeDescriptors.j +++ b/AppKit/Themes/Aristo/ThemeDescriptors.j @@ -1089,7 +1089,7 @@ var themedButtonValues = nil, [@"text-color", textHighlightedColor, CPThemeStateHighlighted], [@"bezel-inset", CGInsetMakeZero(), CPThemeStateBezeled], - [@"content-inset", CGInsetMake(2.0, 22.0, 2.0, 15.0), CPThemeStateBezeled], + [@"content-inset", CGInsetMake(2.0, 20.0, 2.0, 20.0), CPThemeStateBezeled], // Minimum height == maximum height since tokens are fixed height. [@"min-size", CGSizeMake(0.0, 19.0)], @@ -1112,16 +1112,17 @@ var themedButtonValues = nil, themeValues = [ - [@"bezel-color", bezelColor, CPThemeStateBordered], - [@"bezel-color", bezelHighlightedColor, CPThemeStateBordered | CPThemeStateHighlighted], + [@"bezel-color", bezelColor, CPThemeStateBordered | CPThemeStateHovered], + [@"bezel-color", [bezelColor colorWithAlphaComponent:0], CPThemeStateBordered | CPThemeStateDisabled], + [@"bezel-color", bezelHighlightedColor, CPThemeStateBordered | CPThemeStateHighlighted], [@"min-size", CGSizeMake(8.0, 8.0)], [@"max-size", CGSizeMake(8.0, 8.0)], - [@"bezel-inset", CGInsetMake(0.0, 0.0, 0.0, 0.0), CPThemeStateBordered], - [@"bezel-inset", CGInsetMake(0.0, 0.0, 0.0, 0.0), CPThemeStateBordered | CPThemeStateHighlighted], + [@"bezel-inset", CGInsetMake(0.0, 0.0, 0.0, 0.0), CPThemeStateBordered], + [@"bezel-inset", CGInsetMake(0.0, 0.0, 0.0, 0.0), CPThemeStateBordered | CPThemeStateHighlighted], - [@"offset", CGPointMake(17, 6), CPThemeStateBordered] + [@"offset", CGPointMake(17, 6), CPThemeStateBordered] ]; [self registerThemeValues:themeValues forView:button]; From 947b116c06b34b8bc43990ae3895d8638a73347a Mon Sep 17 00:00:00 2001 From: Alexander Ljungberg Date: Wed, 12 Dec 2012 17:50:05 +0000 Subject: [PATCH 4/4] Manual test for non-editable token fields. --- Tests/Manual/CPTokenFieldTest/AppController.j | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Tests/Manual/CPTokenFieldTest/AppController.j b/Tests/Manual/CPTokenFieldTest/AppController.j index ea8fc7038..a50e8d46d 100644 --- a/Tests/Manual/CPTokenFieldTest/AppController.j +++ b/Tests/Manual/CPTokenFieldTest/AppController.j @@ -87,6 +87,11 @@ var STATES = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorad // Delegate must be set before objectValue [tokenFieldD setDelegate:self]; + var tokenFieldDEditable = [CPCheckBox checkBoxWithTitle:"Editable"]; + [tokenFieldDEditable setFrame:CGRectMake(525, CGRectGetMinY([tokenFieldD frame]), 200, 30)]; + [tokenFieldDEditable bind:CPValueBinding toObject:tokenFieldD withKeyPath:@"editable" options:nil]; + [contentView addSubview:tokenFieldDEditable]; + allPersons = [ [Person personWithFirstName:@"Luc" lastName:@"Vauvillier"], [Person personWithFirstName:@"John" lastName:@"Doe"],