From c7a16deb6faf770b9113ac739cbdbe1a430f5d9e Mon Sep 17 00:00:00 2001 From: Aparajita Fishman Date: Sat, 20 Aug 2011 00:58:43 -0400 Subject: [PATCH] Fixed some edge case bugs, added full nib2cib support --- AppKit/AppKit.j | 1 + AppKit/CPComboBox.j | 405 ++++++++-- AppKit/CPTextField.j | 4 +- .../Resources/combobox-bezel-center.png | Bin 0 -> 146 bytes .../combobox-bezel-disabled-center.png | Bin 0 -> 141 bytes .../combobox-bezel-disabled-left.png | Bin 0 -> 219 bytes .../combobox-bezel-disabled-right.png | Bin 0 -> 487 bytes .../combobox-bezel-focused-center.png | Bin 0 -> 160 bytes .../Resources/combobox-bezel-focused-left.png | Bin 0 -> 353 bytes .../combobox-bezel-focused-right.png | Bin 0 -> 661 bytes .../Aristo/Resources/combobox-bezel-left.png | Bin 0 -> 218 bytes .../combobox-bezel-no-border-center.png | Bin 0 -> 146 bytes ...mbobox-bezel-no-border-disabled-center.png | Bin 0 -> 141 bytes ...combobox-bezel-no-border-disabled-left.png | Bin 0 -> 219 bytes ...ombobox-bezel-no-border-disabled-right.png | Bin 0 -> 410 bytes ...ombobox-bezel-no-border-focused-center.png | Bin 0 -> 160 bytes .../combobox-bezel-no-border-focused-left.png | Bin 0 -> 348 bytes ...combobox-bezel-no-border-focused-right.png | Bin 0 -> 622 bytes .../combobox-bezel-no-border-left.png | Bin 0 -> 221 bytes .../combobox-bezel-no-border-right.png | Bin 0 -> 441 bytes .../Aristo/Resources/combobox-bezel-right.png | Bin 0 -> 527 bytes AppKit/Themes/Aristo/ThemeDescriptors.j | 94 ++- AppKit/_CPPopUpList.j | 87 +- .../CPComboBoxTest.xcodeproj/project.pbxproj | 361 +++++++++ .../contents.xcworkspacedata | 7 + ...ests_Manual_CPComboBoxTest_AppController.h | 14 + ...sts_Manual_CPComboBoxTest__AppController.h | 14 + Tests/Manual/CPComboBoxTest/AppController.j | 225 ++++++ Tests/Manual/CPComboBoxTest/Info.plist | 10 + Tests/Manual/CPComboBoxTest/Jakefile | 94 +++ .../CPComboBoxTest/Resources/MainMenu.cib | 1 + .../CPComboBoxTest/Resources/MainMenu.xib | 756 ++++++++++++++++++ .../CPComboBoxTest/Resources/spinner.gif | Bin 0 -> 1849 bytes Tests/Manual/CPComboBoxTest/index-debug.html | 103 +++ Tests/Manual/CPComboBoxTest/index.html | 78 ++ Tests/Manual/CPComboBoxTest/main.j | 18 + Tools/nib2cib/NSAppKit.j | 1 + Tools/nib2cib/NSComboBox.j | 104 +++ 38 files changed, 2276 insertions(+), 101 deletions(-) create mode 100644 AppKit/Themes/Aristo/Resources/combobox-bezel-center.png create mode 100644 AppKit/Themes/Aristo/Resources/combobox-bezel-disabled-center.png create mode 100644 AppKit/Themes/Aristo/Resources/combobox-bezel-disabled-left.png create mode 100644 AppKit/Themes/Aristo/Resources/combobox-bezel-disabled-right.png create mode 100644 AppKit/Themes/Aristo/Resources/combobox-bezel-focused-center.png create mode 100644 AppKit/Themes/Aristo/Resources/combobox-bezel-focused-left.png create mode 100644 AppKit/Themes/Aristo/Resources/combobox-bezel-focused-right.png create mode 100644 AppKit/Themes/Aristo/Resources/combobox-bezel-left.png create mode 100644 AppKit/Themes/Aristo/Resources/combobox-bezel-no-border-center.png create mode 100644 AppKit/Themes/Aristo/Resources/combobox-bezel-no-border-disabled-center.png create mode 100644 AppKit/Themes/Aristo/Resources/combobox-bezel-no-border-disabled-left.png create mode 100644 AppKit/Themes/Aristo/Resources/combobox-bezel-no-border-disabled-right.png create mode 100644 AppKit/Themes/Aristo/Resources/combobox-bezel-no-border-focused-center.png create mode 100644 AppKit/Themes/Aristo/Resources/combobox-bezel-no-border-focused-left.png create mode 100644 AppKit/Themes/Aristo/Resources/combobox-bezel-no-border-focused-right.png create mode 100644 AppKit/Themes/Aristo/Resources/combobox-bezel-no-border-left.png create mode 100644 AppKit/Themes/Aristo/Resources/combobox-bezel-no-border-right.png create mode 100644 AppKit/Themes/Aristo/Resources/combobox-bezel-right.png create mode 100644 Tests/Manual/CPComboBoxTest/.xCodeSupport/CPComboBoxTest.xcodeproj/project.pbxproj create mode 100644 Tests/Manual/CPComboBoxTest/.xCodeSupport/CPComboBoxTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Tests/Manual/CPComboBoxTest/.xCodeSupport/Sources/_Users_aparajita_Development_Projects_Clients_Intalio_Carbon_iocappuccino_Tests_Manual_CPComboBoxTest_AppController.h create mode 100644 Tests/Manual/CPComboBoxTest/.xCodeSupport/Sources/_Users_aparajita_Development_Projects_Clients_Intalio_Carbon_iocappuccino_Tests_Manual_CPComboBoxTest__AppController.h create mode 100644 Tests/Manual/CPComboBoxTest/AppController.j create mode 100644 Tests/Manual/CPComboBoxTest/Info.plist create mode 100644 Tests/Manual/CPComboBoxTest/Jakefile create mode 100644 Tests/Manual/CPComboBoxTest/Resources/MainMenu.cib create mode 100644 Tests/Manual/CPComboBoxTest/Resources/MainMenu.xib create mode 100644 Tests/Manual/CPComboBoxTest/Resources/spinner.gif create mode 100644 Tests/Manual/CPComboBoxTest/index-debug.html create mode 100644 Tests/Manual/CPComboBoxTest/index.html create mode 100644 Tests/Manual/CPComboBoxTest/main.j create mode 100644 Tools/nib2cib/NSComboBox.j diff --git a/AppKit/AppKit.j b/AppKit/AppKit.j index aad960d62..9190574d0 100644 --- a/AppKit/AppKit.j +++ b/AppKit/AppKit.j @@ -44,6 +44,7 @@ @import "CPColor.j" @import "CPColorPanel.j" @import "CPColorWell.j" +@import "CPComboBox.j" @import "CPCompatibility.j" @import "CPControl.j" @import "CPCookie.j" diff --git a/AppKit/CPComboBox.j b/AppKit/CPComboBox.j index b1623e9fa..3620ca192 100644 --- a/AppKit/CPComboBox.j +++ b/AppKit/CPComboBox.j @@ -20,8 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -@import -@import +@import "CPTextField.j" +@import "_CPPopUpList.j" CPComboBoxSelectionDidChangeNotification = @"CPComboBoxSelectionDidChangeNotification"; @@ -29,9 +29,12 @@ CPComboBoxSelectionIsChangingNotification = @"CPComboBoxSelectionIsChangingNotif CPComboBoxWillDismissNotification = @"CPComboBoxWillDismissNotification"; CPComboBoxWillPopUpNotification = @"CPComboBoxWillPopUpNotification"; +CPComboBoxStateButtonBordered = CPThemeState("button-bordered"); + var CPComboBoxTextSubview = @"text", CPComboBoxButtonSubview = @"button", - CPComboBoxDefaultNumberOfVisibleItems = 5; + CPComboBoxDefaultNumberOfVisibleItems = 5, + CPComboBoxFocusWidth = 2; @implementation CPComboBox : CPTextField @@ -47,6 +50,25 @@ var CPComboBoxTextSubview = @"text", BOOL _forceSelection; BOOL _hasVerticalScroller; CPString _selectedStringValue; + BOOL _popUpButtonCausedResign; +} + ++ (CPString)defaultThemeClass +{ + return "combobox"; +} + ++ (id)themeAttributes +{ + return [CPDictionary dictionaryWithObjects:[CGSizeMake(21.0, 23.0)] forKeys:[@"popup-button-size"]]; +} + ++ (Class)_binderClassForBinding:(CPString)theBinding +{ + if (theBinding === CPContentBinding || theBinding === CPContentValuesBinding) + return [_CPComboBoxContentBinder class]; + + return [super _binderClassForBinding:theBinding]; } - (id)initWithFrame:(CGRect)aFrame @@ -54,14 +76,14 @@ var CPComboBoxTextSubview = @"text", self = [super initWithFrame:aFrame]; if (self) - [self _init]; + [self _initComboBox]; return self; } -- (void)_init +- (void)_initComboBox { - _items = [] + _items = [CPArray array]; _listClass = [_CPPopUpList class]; _usesDataSource = NO; _completes = NO; @@ -70,14 +92,19 @@ var CPComboBoxTextSubview = @"text", _forceSelection = NO; _hasVerticalScroller = YES; _selectedStringValue = @""; + _popUpButtonCausedResign = NO; [self setTarget:self]; [self setAction:@selector(textFieldAction:)]; - [[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(controlTextDidChange:) name:CPControlTextDidChangeNotification object:self]; + [self setTheme:[CPTheme defaultTheme]]; + [self setBordered:YES]; + [self setBezeled:YES]; + [self setEditable:YES]; + [self setThemeState:CPComboBoxStateButtonBordered]; } -//#pragma mark Setting Display Attributes +#pragma mark Setting Display Attributes - (BOOL)hasVerticalScroller { @@ -107,13 +134,15 @@ var CPComboBoxTextSubview = @"text", - (BOOL)isButtonBordered { - return YES; - //return [[self ephemeralSubviewNamed:CPComboBoxButtonSubview] isBordered]; + return [self hasThemeState:CPComboBoxStateButtonBordered]; } - (void)setButtonBordered:(BOOL)flag { - //[[self ephemeralSubviewNamed:CPComboBoxButtonSubview] setBordered:flag]; + if (!!flag) + [self setThemeState:CPComboBoxStateButtonBordered]; + else + [self unsetThemeState:CPComboBoxStateButtonBordered]; } - (float)itemHeight @@ -124,6 +153,9 @@ var CPComboBoxTextSubview = @"text", - (void)setItemHeight:(float)itemHeight { [[_list tableView] setRowHeight:itemHeight]; + + // FIXME: This shouldn't be necessary, but CPTableView does not tile after setRowHeight + [[_list tableView] reloadData]; } - (int)numberOfVisibleItems @@ -137,7 +169,7 @@ var CPComboBoxTextSubview = @"text", _numberOfVisibleItems = MAX(visibleItems, 1); } -//#pragma mark Setting a Delegate +#pragma mark Setting a Delegate - (id < CPComboBoxDelegate >)delegate { @@ -197,11 +229,11 @@ var CPComboBoxTextSubview = @"text", [super setDelegate:aDelegate]; } -//#pragma mark Setting a Data Source +#pragma mark Setting a Data Source - (id < CPComboBoxDataSource >)dataSource { - if (_usesDataSource === NO) + if (!_usesDataSource) [self dataSourceWarningForMethod:_cmd condition:NO]; return _dataSource; @@ -209,7 +241,7 @@ var CPComboBoxTextSubview = @"text", - (void)setDataSource:(id < CPComboBoxDataSource >)aSource { - if (_usesDataSource === NO) + if (!_usesDataSource) [self dataSourceWarningForMethod:_cmd condition:NO]; else if (_dataSource !== aSource) { @@ -244,7 +276,7 @@ var CPComboBoxTextSubview = @"text", [self reloadData]; } -//#pragma mark Working with an Internal List +#pragma mark Working with an Internal List - (void)addItemsWithObjectValues:(CPArray)objects { @@ -271,8 +303,9 @@ var CPComboBoxTextSubview = @"text", } /*! - Returns the internal array of items. Note that this does a deep copy of the array, - effectively returning an immutable array to be consistent with Cocoa. + Returns the internal array of items. NOTE: Unlike Cocoa the array is mutable, + since all arrays in Objective-J are mutable. But you should treat it as + an immutable array. Do NOT attempt to change the returned array in any way. If usesDataSource is YES, a warning is logged and an empty array is returned. */ @@ -281,7 +314,7 @@ var CPComboBoxTextSubview = @"text", if (_usesDataSource) [self dataSourceWarningForMethod:_cmd condition:YES]; - return [[CPArray alloc] initWithArray:_items copyItems:YES]; + return _items; } - (void)removeAllItems @@ -316,7 +349,7 @@ var CPComboBoxTextSubview = @"text", return _items.length; } -//#pragma mark Manipulating the Displayed List +#pragma mark Manipulating the Displayed List /*! Returns the helper class to be used when creating the pop up list. @@ -329,7 +362,8 @@ var CPComboBoxTextSubview = @"text", /*! Sets the helper class to be used when creating the pop up list. By default this is _CPPopUpList. If you are using a subclass - of _CPPopUpList, call this method with your subclass. + of _CPPopUpList, call this method with your subclass before + the list is popped up for the first time. */ - (void)setListClass:(Class)aClass { @@ -379,7 +413,7 @@ var CPComboBoxTextSubview = @"text", [self makeList]; [self selectMatchingItem]; - [_list popUpRelativeTo:[self borderFrame]]; + [_list popUpRelativeToRect:[self borderFrame] view:self offset:CPComboBoxFocusWidth]; } /*! @ignore */ @@ -430,6 +464,10 @@ var CPComboBoxTextSubview = @"text", selector:@selector(comboBoxSelectionDidChange:) name:CPTableViewSelectionDidChangeNotification object:tableView]; + + // Apply our text style to the list + [_list setFont:[self font]]; + [_list setAlignment:[self alignment]]; } /*! @ignore */ @@ -449,21 +487,30 @@ var CPComboBoxTextSubview = @"text", /*! If the list is non-empty, sets the value of the field from the currently selected value of the list - and returns YES. IF the list is empty, immediately returns NO. + and returns YES. If the list is empty or the list has no selected item, returns NO. + @ignore */ - (BOOL)takeStringValueFromList { - if ([_dataSource numberOfItemsInComboBox:self] === 0) + if (_usesDataSource && _dataSource && [_dataSource numberOfItemsInComboBox:self] === 0) return NO; - _selectedStringValue = [_list selectedStringValue] || @""; + var selectedStringValue = [_list selectedStringValue]; + + if (selectedStringValue === nil) + return NO; + else + _selectedStringValue = selectedStringValue; [self setStringValue:_selectedStringValue]; + [self _reverseSetBinding]; + return YES; } /*! - The field receives this notification when the list is about to be pop up. + The receiver receives this notification when the list is about to be pop up. + @ignore */ - (void)listWillPopUp:(CPNotification)aNotification { @@ -471,7 +518,8 @@ var CPComboBoxTextSubview = @"text", } /*! - The field receives this notification when the list is about to be dismissed. + The receiver receives this notification when the list is about to be dismissed. + @ignore */ - (void)listWillDismiss:(CPNotification)aNotification { @@ -479,7 +527,8 @@ var CPComboBoxTextSubview = @"text", } /*! - The field receives this notification when the list is closed. + The receiver receives this notification when the list is closed. + @ignore */ - (void)listDidDismiss:(CPNotification)aNotification { @@ -487,14 +536,15 @@ var CPComboBoxTextSubview = @"text", } /*! - The field receives this notification when an item in the list is clicked. + The receiver receives this notification when an item in the list is clicked. + @ignore */ - (void)itemWasClicked:(CPNotification)aNotification { [self takeStringValueFromList]; } -//#pragma mark Manipulating the Selection +#pragma mark Manipulating the Selection - (void)deselectItemAtIndex:(int)index { @@ -546,7 +596,7 @@ var CPComboBoxTextSubview = @"text", [self selectItemAtIndex:index]; } -//#pragma mark Completing the Text Field +#pragma mark Completing the Text Field - (BOOL)completes { @@ -584,14 +634,26 @@ var CPComboBoxTextSubview = @"text", an item that is in the item list. If \c flag is \c YES and the user enters a value that is not in the list, when the field loses focus it will revert to the previous value. If \c flag is \c NO, the user can enter any value they wish. + + Note that this flag is ignored if \ref setStringValue or \ref setObjectValue are + called directly. */ - (void)setForceSelection:(BOOL)flag { _forceSelection = !!flag; } -//#pragma mark CPTextField Delegate Methods and Overrides +#pragma mark CPTextField Delegate Methods and Overrides +/*! @ignore */ +- (void)setObjectValue:(id)object +{ + [super setObjectValue:object]; + + _selectedStringValue = [self stringValue]; +} + +/*! @ignore */ - (void)keyDown:(CPEvent)anEvent { // Only if characters are added at the end of the value can completion occur @@ -611,6 +673,7 @@ var CPComboBoxTextSubview = @"text", [super keyDown:anEvent]; } +/*! @ignore */ - (void)paste:(id)sender { if (_completes) @@ -627,7 +690,8 @@ var CPComboBoxTextSubview = @"text", [super paste:sender]; } -- (void)controlTextDidChange:(CPNotification)anNotification +/*! @ignore */ +- (void)textDidChange:(CPNotification)aNotification { /* Completion is attempted iff: @@ -650,8 +714,11 @@ var CPComboBoxTextSubview = @"text", [self selectMatchingItem]; _canComplete = NO; + + [super textDidChange:aNotification]; } +/*! @ignore */ - (BOOL)performKeyEquivalent:(CPEvent)anEvent { if ([[self window] firstResponder] === self) @@ -679,7 +746,9 @@ var CPComboBoxTextSubview = @"text", case CPEscapeFunctionKey: if ([self listIsVisible]) { - if (_forceSelection) + // If we are forcing a selection and the user has entered a value which is not + // in the list, revert to the most recent valid value. + if (_forceSelection && ([self _inputElement].value !== _selectedStringValue)) [self setStringValue:_selectedStringValue]; [_list close]; @@ -724,25 +793,30 @@ var CPComboBoxTextSubview = @"text", return [super performKeyEquivalent:anEvent]; } +/*! @ignore */ - (BOOL)resignFirstResponder { + var buttonCausedResign = _popUpButtonCausedResign; + + _popUpButtonCausedResign = NO; + /* - If the list is clicked, we lose focus. In that case the list will refuse first responder, + If the list or popup button is clicked, we lose focus. The list will refuse first responder, and we refuse to resign. But we still have to manually restore the focus to the input element. */ - if ([_list listWasClicked]) + if ([_list listWasClicked] || buttonCausedResign) { /* If an item was not clicked (probably the scrollbar), clear the click flag so that future clicks outside the list will allow it to close. It isn't so great doing that here, but the sequence of events is such that it has to be done here. */ - if (![_list itemWasClicked]) + if ([_list listWasClicked] && ![_list itemWasClicked]) [_list setListWasClicked:NO]; -//#if PLATFORM(DOM) +#if PLATFORM(DOM) [self _inputElement].focus(); -//#endif +#endif return NO; } @@ -765,32 +839,65 @@ var CPComboBoxTextSubview = @"text", return [super resignFirstResponder]; } -/*! - We override this so that we can know when the field is about to lose focus - because the user pressed tab. -*/ -- (CPView)nextValidKeyView +- (void)setFont:(CPFont)aFont { - if ([self listIsVisible]) - [self takeStringValueFromList]; - - return [super nextValidKeyView]; + [super setFont:aFont]; + [_list setFont:aFont]; } -/*! - We override this so that we can know when the field is about to lose focus - because the user pressed shift tab. -*/ -- (CPView)previousValidKeyView +- (void)setAlignment:(CPTextAlignment)alignment { - if ([self listIsVisible]) - [self takeStringValueFromList]; - - return [super previousValidKeyView]; + [super setAlignment:alignment]; + [_list setAlignment:alignment]; } -//#pragma mark Internal Helpers +#pragma mark Pop Up Button Layout +- (CGRect)popupButtonRectForBounds:(CGRect)bounds +{ + var inset = [self currentValueForThemeAttribute:@"border-inset"], + buttonSize = [self currentValueForThemeAttribute:@"popup-button-size"]; + + bounds.origin.x += _CGRectGetMaxX(bounds) - inset.right - buttonSize.width; + bounds.origin.y += inset.top; + bounds.size.width = buttonSize.width; + bounds.size.height = buttonSize.height; + + return bounds; +} + +- (CGRect)rectForEphemeralSubviewNamed:(CPString)aName +{ + if (aName === "popup-button-view") + return [self popupButtonRectForBounds:[self bounds]]; + + return [super rectForEphemeralSubviewNamed:aName]; +} + +- (CPView)createEphemeralSubviewNamed:(CPString)aName +{ + if (aName === "popup-button-view") + { + var view = [[_CPComboBoxPopUpButton alloc] initWithFrame:_CGRectMakeZero() comboBox:self]; + + return view; + } + + return [super createEphemeralSubviewNamed:aName]; +} + +- (void)layoutSubviews +{ + [super layoutSubviews]; + + var popupButtonView = [self layoutEphemeralSubviewNamed:@"popup-button-view" + positioned:CPWindowAbove + relativeToEphemeralSubviewNamed:@"content-view"]; +} + +#pragma mark Internal Helpers + +/*! @ignore */ - (void)dataSourceWarningForMethod:(SEL)cmd condition:(CPString)flag { CPLog.warn("-[%s %s] should not be called when usesDataSource is set to %s", [self className], cmd, flag ? "YES" : "NO"); @@ -798,11 +905,15 @@ var CPComboBoxTextSubview = @"text", - (id)objectValueForItemAtIndex:(int)index { - return [_dataSource comboBox:self objectValueForItemAtIndex:index]; + if (_usesDataSource) + return [_dataSource comboBox:self objectValueForItemAtIndex:index]; + else + return _items[index]; } /*! Select the item that matches the current value of the combobox. + @ignore */ - (void)selectMatchingItem { @@ -822,11 +933,12 @@ var CPComboBoxTextSubview = @"text", // selectRow scrolls the row to visible, if a row is selected scroll it to the top if (index !== CPNotFound) { - [_list scrollRowToTop:index]; + [_list scrollItemAtIndexToTop:index]; _selectedStringValue = stringValue; } } +/*! @ignore */ - (BOOL)textFieldAction:(id)sender { if ([self listIsVisible]) @@ -839,46 +951,68 @@ var CPComboBoxTextSubview = @"text", } /*! - @ignore - Calculate the frame in base coordinates that will nestle just below the visible border of the text field. + @ignore */ - (CGRect)borderFrame { - // Calculate the focus inset by subtracting the focused bezel inset - // from the unfocused bezel inset - var unfocusedInset = [self valueForThemeAttribute:@"bezel-inset" inState:CPThemeStateBezeled], - focusedInset = [self valueForThemeAttribute:@"bezel-inset" inState:CPThemeStateBezeled | CPThemeStateEditing], - focusInset = CGInsetDifference(unfocusedInset, focusedInset), - bounds = [self convertRectToBase:[self bounds]]; + var borderInset = [self valueForThemeAttribute:@"border-inset"], + frame = [self bounds]; - bounds.origin.x += focusInset.left; - bounds.origin.y += focusInset.top; - bounds.size.width -= focusInset.left + focusInset.right; - bounds.size.height -= focusInset.top + focusInset.bottom; + frame.origin.x += borderInset.left; + frame.origin.y += borderInset.top; + frame.size.width -= borderInset.left + borderInset.right; + frame.size.height -= borderInset.top + borderInset.bottom; - return bounds; + return frame; +} + +/* @ignore */ +- (void)popUpButtonWasClicked +{ + if (![self isEnabled]) + return; + + // If we are currently the first responder, we will be asked to resign when the list pops up. + // Set a flag to let resignResponder know that the button was clicked and we should not resign. + var firstResponder = [[self window] firstResponder]; + + _popUpButtonCausedResign = firstResponder === self; + + if ([self listIsVisible]) + [_list close]; + else + { + if (firstResponder !== self) + [[self window] makeFirstResponder:self]; + + [self popUpList]; + } } @end @implementation CPComboBox (CPComboBoxDelegate) +/*! @ignore */ - (void)comboBoxSelectionIsChanging:(CPNotification)aNotification { [[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxSelectionIsChangingNotification object:self]; } +/*! @ignore */ - (void)comboBoxSelectionDidChange:(CPNotification)aNotification { [[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxSelectionDidChangeNotification object:self]; } +/*! @ignore */ - (void)comboBoxWillPopUp { [[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxWillPopUpNotification object:self]; } +/*! @ignore */ - (void)comboBoxWillDismiss { [[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxWillDismissNotification object:self]; @@ -888,6 +1022,7 @@ var CPComboBoxTextSubview = @"text", @implementation CPComboBox (CPComboBoxDataSource) +/*! @ignore */ - (CPString)comboBoxCompletedString:(CPString)uncompletedString { if ([_dataSource respondsToSelector:@selector(comboBox:completedString:)]) @@ -898,6 +1033,36 @@ var CPComboBoxTextSubview = @"text", @end +@implementation CPComboBox (Bindings) + +/*! @ignore */ +- (void)setContentValues:(CPArray)anArray +{ + [self setUsesDataSource:NO]; + [self removeAllItems]; + [self addItemsWithObjectValues:anArray]; +} + +/*! @ignore */ +- (void)setContent:(CPArray)anArray +{ + [self setUsesDataSource:NO]; + + // Directly nuke _items, [_items removeAll] will trigger an extra call to setContent + _items = []; + + var values = []; + + [anArray enumerateObjectsUsingBlock:function(object) + { + values.push([object description]); + }]; + + [self addItemsWithObjectValues:values]; +} + +@end + var CPComboBoxItemsKey = @"CPComboBoxItemsKey", CPComboBoxListKey = @"CPComboBoxListKey", CPComboBoxDelegateKey = @"CPComboBoxDelegateKey", @@ -905,7 +1070,8 @@ var CPComboBoxItemsKey = @"CPComboBoxItemsKey", CPComboBoxUsesDataSourceKey = @"CPComboBoxUsesDataSourceKey", CPComboBoxCompletesKey = @"CPComboBoxCompletesKey", CPComboBoxNumberOfVisibleItemsKey = @"CPComboBoxNumberOfVisibleItemsKey", - CPComboBoxHasVerticalScrollerKey = @"CPComboBoxHasVerticalScrollerKey"; + CPComboBoxHasVerticalScrollerKey = @"CPComboBoxHasVerticalScrollerKey", + CPComboBoxButtonBorderedKey = @"CPComboBoxButtonBorderedKey"; @implementation CPComboBox (CPCoding) @@ -915,7 +1081,7 @@ var CPComboBoxItemsKey = @"CPComboBoxItemsKey", if (self) { - [self _init]; + [self _initComboBox]; _items = [aCoder decodeObjectForKey:CPComboBoxItemsKey]; _list = [aCoder decodeObjectForKey:CPComboBoxListKey]; @@ -925,6 +1091,7 @@ var CPComboBoxItemsKey = @"CPComboBoxItemsKey", _completes = [aCoder decodeBoolForKey:CPComboBoxCompletesKey]; _numberOfVisibleItems = [aCoder decodeIntForKey:CPComboBoxNumberOfVisibleItemsKey]; _hasVerticalScroller = [aCoder decodeBoolForKey:CPComboBoxHasVerticalScrollerKey]; + [self setButtonBordered:[aCoder decodeBoolForKey:CPComboBoxButtonBorderedKey]]; } return self; @@ -942,6 +1109,7 @@ var CPComboBoxItemsKey = @"CPComboBoxItemsKey", [aCoder encodeBool:_completes forKey:CPComboBoxCompletesKey]; [aCoder encodeInt:_numberOfVisibleItems forKey:CPComboBoxNumberOfVisibleItemsKey]; [aCoder encodeBool:_hasVerticalScroller forKey:CPComboBoxHasVerticalScrollerKey]; + [aCoder encodeBool:[self isButtonBordered] forKey:CPComboBoxButtonBorderedKey]; } @end @@ -951,3 +1119,90 @@ var CPComboBoxCompletionTest = function(object, index, context) { return object.toString().indexOf(context) === 0; }; + + +/* + This class is only used for CPContentBinding and CPContentValuesBinding. +*/ +@implementation _CPComboBoxContentBinder : CPBinder + +- (void)setValueFor:(CPString)theBinding +{ + var destination = [_info objectForKey:CPObservedObjectKey], + keyPath = [_info objectForKey:CPObservedKeyPathKey], + options = [_info objectForKey:CPOptionsKey], + newValue = [destination valueForKeyPath:keyPath], + isPlaceholder = CPIsControllerMarker(newValue); + + [_source removeAllItems]; + + if (isPlaceholder) + { + // By default the placeholders will all result in an empty list + switch (newValue) + { + case CPMultipleValuesMarker: + newValue = [options objectForKey:CPMultipleValuesPlaceholderBindingOption] || []; + break; + + case CPNoSelectionMarker: + newValue = [options objectForKey:CPNoSelectionPlaceholderBindingOption] || []; + break; + + case CPNotApplicableMarker: + if ([options objectForKey:CPRaisesForNotApplicableKeysBindingOption]) + [CPException raise:CPGenericException + reason:@"can't transform non applicable key on: "+ _source + " value: " + newValue]; + + newValue = [options objectForKey:CPNotApplicablePlaceholderBindingOption] || []; + break; + + case CPNullMarker: + newValue = [options objectForKey:CPNullPlaceholderBindingOption] || []; + break; + } + + if (![newValue isKindOfClass:[CPArray class]]) + newValue = []; + } + else + newValue = [self transformValue:newValue withOptions:options]; + + switch (theBinding) + { + case CPContentBinding: [_source setContent:newValue]; + break; + + case CPContentValuesBinding: [_source setContentValues:newValue]; + break; + } +} + +@end + +@implementation _CPComboBoxPopUpButton : CPView +{ + CPComboBox _comboBox; +} + +- (id)initWithFrame:(CGRect)aFrame comboBox:(CPComboBox)aComboBox +{ + self = [super initWithFrame:aFrame]; + + if (self) + _comboBox = aComboBox; + + return self; +} + +- (void)mouseDown:(CPEvent)theEvent +{ + [_comboBox popUpButtonWasClicked]; +} + +- (BOOL)acceptsFirstResponder +{ + return NO; +} + +@end diff --git a/AppKit/CPTextField.j b/AppKit/CPTextField.j index afcab8aaf..b11c3db05 100644 --- a/AppKit/CPTextField.j +++ b/AppKit/CPTextField.j @@ -169,8 +169,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); + (id)themeAttributes { - return [CPDictionary dictionaryWithObjects:[_CGInsetMakeZero(), _CGInsetMake(2.0, 2.0, 2.0, 2.0), [CPNull null]] - forKeys:[@"bezel-inset", @"content-inset", @"bezel-color"]]; + return [CPDictionary dictionaryWithObjects:[_CGInsetMakeZero(), _CGInsetMake(2.0, 2.0, 2.0, 2.0), _CGInsetMake(3.0, 3.0, 3.0, 3.0), [CPNull null]] + forKeys:[@"bezel-inset", @"content-inset", @"border-inset", @"bezel-color"]]; } /* @ignore */ diff --git a/AppKit/Themes/Aristo/Resources/combobox-bezel-center.png b/AppKit/Themes/Aristo/Resources/combobox-bezel-center.png new file mode 100644 index 0000000000000000000000000000000000000000..3968077ff1230ffc44efb696805188894090b300 GIT binary patch literal 146 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{Q!3HF=8QC&{lw^r(L`iUdT1k0gQ7VIDN`6wR zf@f}GdTLN=VoGJ<$y6JlA`?#+$B>F!Nk9Jow`Ue+7I5g$jo$Vrz2ei8ll5)&|Ns3> sPfAH~nYPrd@WBB_HntFP1{MhhEhl09eQVFk0`)U^y85}Sb4q9e08EuF!TF!Nk9Jow`Ue+7I5hBp04*d{l}-Lr|a1k9I02~ moF!2H?oMKYLn)&}10zF;rwDJIxz!t>Rt8U3KbLh*2~7YsNh=rt literal 0 HcmV?d00001 diff --git a/AppKit/Themes/Aristo/Resources/combobox-bezel-disabled-left.png b/AppKit/Themes/Aristo/Resources/combobox-bezel-disabled-left.png new file mode 100644 index 0000000000000000000000000000000000000000..c08de096be381d98dee2e5d5f8264e7bd84aa3b7 GIT binary patch literal 219 zcmeAS@N?(olHy`uVBq!ia0vp^Y(Ol_0U|r^$_fA}$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1GwVp1HAr-fh{`~)M&un(!NCWeODG83xVs@2u@_JllEM)3p zQC3b?wzjTrU9m!gnfXMK1ly~MuU}tZ|NsBr-{1Xt?HcOp>K^LLo+>y#n#&#R%PJdU z(j_--vYz9#;`qapgm?Arl((x%U~toAu1Z=_|NEP+w1B%|kiIGtiv+{eBL*@BYqy#J P9m3%0>gTe~DWM4fU7Ade literal 0 HcmV?d00001 diff --git a/AppKit/Themes/Aristo/Resources/combobox-bezel-disabled-right.png b/AppKit/Themes/Aristo/Resources/combobox-bezel-disabled-right.png new file mode 100644 index 0000000000000000000000000000000000000000..cad4200ec7704bd531ecf521876537f47bc9ddb1 GIT binary patch literal 487 zcmV^SB#xYT9iD&_F9CPP1q}(bmI-M;ZI*;I(tx#{HntQAQn?4a_Gf>tlOWDH zR0|9!`FuFF1`lVYl!Uq_AV#sCo^wb#CXF^*)+^H1QrZjYO` zy)i&c0_F_-;4L_H>icsQsOSR~A*djVF>Zd>>s$h;YicrCJyyhzGJr%ZWfXl?02vkJ zN|E9USP}qa1w7{_X8=qlAv|=uKq*bxG);rH=Ye6Ami7S8C`wADT!N10WM{)<{F!Nh_kNZ_nv$Y+TsT+23y7^zwN3YaX6zecONM zKge@92=Q!D%-i#WOJyE&=j`?WjSXsleX3OTNMdqmU}W$vl-wWjlj9N4GzL#sKbLh* G2~7Y?v^66D literal 0 HcmV?d00001 diff --git a/AppKit/Themes/Aristo/Resources/combobox-bezel-focused-left.png b/AppKit/Themes/Aristo/Resources/combobox-bezel-focused-left.png new file mode 100644 index 0000000000000000000000000000000000000000..054084c3d3b11714371b237bff8190588455776b GIT binary patch literal 353 zcmV-n0iOPeP)8MNVz>px^#A&(dn>H5@7)L02yN_jtqrLdch_9A%ur(BYxFR{G(|8 z5;Z6`K~+1luJK>H0t@Fj5On`mY&&vrTU+~*TSG-@y;SEHQwOm|eK=C%Wv!z3mGGm! z!2`H1tMUo(CZ@W#AFr{dJnoL)0yn(7KLQK@SW{DjK}hrY00000NkvXXu0mjfehrNS literal 0 HcmV?d00001 diff --git a/AppKit/Themes/Aristo/Resources/combobox-bezel-focused-right.png b/AppKit/Themes/Aristo/Resources/combobox-bezel-focused-right.png new file mode 100644 index 0000000000000000000000000000000000000000..8aa890bb6f3407390d3542a2f4f8559cbf314ad6 GIT binary patch literal 661 zcmV;G0&4w-|uFZ~k)QRq?hPY@3Z=3s3E?ICU>CTY@cn*A{| zzS(B|k!)M&P6ob#d9yR$e($}RdB)S#>H^|7N$?3ap-t!zdIZj>d!m6r5OxU`;R~Tc z_^yc9iHYO)ps5KV;Q5~Axb6xK-w@Ur>?#byh`l*Wm`EB)?8uWjjHMnsu2Um(ok=Ni z_iFqw*trkDp+Uo60mzNHZZMgp{!f zTrT0lgyZ>Ojo8=p@Knl z9T(Z@(?m94whSD@pAP&iGf%V$2 zBc6l4@ARF6C;~p>yGZMG{ny=6yNkH*YxF z;7$Jg;azNkiF6t>=gz{MoQ3WBbuz7~B8(Ll?r8JBuj(S#+w9jxm4KkLv;9g_=@?da vYyHhPRQaeP@=TKePx+j%^>1zZTYv!o=;o=D3riG?00000NkvXXu0mjf`W!J> literal 0 HcmV?d00001 diff --git a/AppKit/Themes/Aristo/Resources/combobox-bezel-left.png b/AppKit/Themes/Aristo/Resources/combobox-bezel-left.png new file mode 100644 index 0000000000000000000000000000000000000000..91f0bd995f48409d6aab88a0d18cd2ef2f038ed7 GIT binary patch literal 218 zcmeAS@N?(olHy`uVBq!ia0vp^Y(Ol_0U|r^$_fA}$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1GHJ&bxAr-fh{`~)M&un(!NCWeODG4rSS*NGz<~Xe4>ky6z z2r)D=D=I1qJ8|NK!G;AhC#+ey@}z>6R##%XhR1}~R@P9a43UTl70;VWCOmVTW3?jV zioj->`F+>-*Z)7ZD*4^t-`^$c{{Cv6<;5ps!QiF()bP0l+XkK+00QW literal 0 HcmV?d00001 diff --git a/AppKit/Themes/Aristo/Resources/combobox-bezel-no-border-center.png b/AppKit/Themes/Aristo/Resources/combobox-bezel-no-border-center.png new file mode 100644 index 0000000000000000000000000000000000000000..3968077ff1230ffc44efb696805188894090b300 GIT binary patch literal 146 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{Q!3HF=8QC&{lw^r(L`iUdT1k0gQ7VIDN`6wR zf@f}GdTLN=VoGJ<$y6JlA`?#+$B>F!Nk9Jow`Ue+7I5g$jo$Vrz2ei8ll5)&|Ns3> sPfAH~nYPrd@WBB_HntFP1{MhhEhl09eQVFk0`)U^y85}Sb4q9e08EuF!TF!Nk9Jow`Ue+7I5hBp04*d{l}-Lr|a1k9I02~ moF!2H?oMKYLn)&}10zF;rwDJIxz!t>Rt8U3KbLh*2~7YsNh=rt literal 0 HcmV?d00001 diff --git a/AppKit/Themes/Aristo/Resources/combobox-bezel-no-border-disabled-left.png b/AppKit/Themes/Aristo/Resources/combobox-bezel-no-border-disabled-left.png new file mode 100644 index 0000000000000000000000000000000000000000..c08de096be381d98dee2e5d5f8264e7bd84aa3b7 GIT binary patch literal 219 zcmeAS@N?(olHy`uVBq!ia0vp^Y(Ol_0U|r^$_fA}$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1GwVp1HAr-fh{`~)M&un(!NCWeODG83xVs@2u@_JllEM)3p zQC3b?wzjTrU9m!gnfXMK1ly~MuU}tZ|NsBr-{1Xt?HcOp>K^LLo+>y#n#&#R%PJdU z(j_--vYz9#;`qapgm?Arl((x%U~toAu1Z=_|NEP+w1B%|kiIGtiv+{eBL*@BYqy#J P9m3%0>gTe~DWM4fU7Ade literal 0 HcmV?d00001 diff --git a/AppKit/Themes/Aristo/Resources/combobox-bezel-no-border-disabled-right.png b/AppKit/Themes/Aristo/Resources/combobox-bezel-no-border-disabled-right.png new file mode 100644 index 0000000000000000000000000000000000000000..7cb591fc6e989b9152e8149db9c25e31cd9ef05d GIT binary patch literal 410 zcmV;L0cHM)P)e<=9(@85rrWtT2p zdIhqOT9^s$6-Gt|PEJk`Q6gbFf5?9FNVGkSctLU-p4;g8K%U~ zLf8Ua;L`prT0rU;5c6Y^{s_cYN&x}a$POYsN1xBqYPwgj$;qheT?WZh8p)4^rR7V7 zq~vZR3kpjs+yaV~faIwW$;YKtby~Uj1Yd(V+ycTcq}6olfy|RsOGS)KOpE2T4CjLk zm)AC$2^3mEQYs<>{A1(fYEd?{1VwBg$;p&R0E*Byvho43>3f8hMW7l8=!4fZDT{zr zCd0>%po9Ug_^D^XojZ46>=!`14CsTJ(S{dYEdU5G0El&|T(0kBCIA2c07*qoM6N<$ Ef^NaGcK`qY literal 0 HcmV?d00001 diff --git a/AppKit/Themes/Aristo/Resources/combobox-bezel-no-border-focused-center.png b/AppKit/Themes/Aristo/Resources/combobox-bezel-no-border-focused-center.png new file mode 100644 index 0000000000000000000000000000000000000000..4af36b6a4187d4688890cb87df82fe3924c33bcf GIT binary patch literal 160 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{Q!3HF=8QC&{lw^r(L`iUdT1k0gQ7VIDN`6wR zf@f}GdTLN=VoGJ<$y6JlA}3E5$B>F!Nh_kNZ_nv$Y+TsT+23y7^zwN3YaX6zecONM zKge@92=Q!D%-i#WOJyE&=j`?WjSXsleX3OTNMdqmU}W$vl-wWjlj9N4GzL#sKbLh* G2~7Y?v^66D literal 0 HcmV?d00001 diff --git a/AppKit/Themes/Aristo/Resources/combobox-bezel-no-border-focused-left.png b/AppKit/Themes/Aristo/Resources/combobox-bezel-no-border-focused-left.png new file mode 100644 index 0000000000000000000000000000000000000000..634334cc5c342b3c9f4659d1abfa2d663e8c927a GIT binary patch literal 348 zcmV-i0i*tjP)X3s|Fa{%#sQM;{S2_r;edV7>DM{7Ua~Qwx+<7PVfkK2;tyq#IHGse-zbU zq6AqJ6s09&EB9-+U}Y@_f*#(oeIo_;r74ONuS9 zHH3ue_n&_m9=`g-@ZrlV239^tDxAjZ0lZ7#P(4onPLH;2yLTUKA5}r z0oir(fEE@1psfw+Sn%iXe}-Sb{~^o$00~oE7TtL96=K@2e+-Y`|6us@kBQ;mf3U+} zP+H+bEO`DE-m3TptoT3uH+4KT_qxcM3p%>Vu|GW`DY=LxVyF%`(YN)-z} zefhi!8lm5jT6UL#_z|@ENO6784^1t9(AuUyC~Y=^06>5N0PtkTg7ED%5dZ)H07*qo IM6N<$f`f1yq5uE@ literal 0 HcmV?d00001 diff --git a/AppKit/Themes/Aristo/Resources/combobox-bezel-no-border-left.png b/AppKit/Themes/Aristo/Resources/combobox-bezel-no-border-left.png new file mode 100644 index 0000000000000000000000000000000000000000..1c91406ecfeca8fe5a68c938121c613f6889a4c4 GIT binary patch literal 221 zcmeAS@N?(olHy`uVBq!ia0vp^Y(Ol_0U|r^$_fA}$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1G^`0({Ar-fhe*OP%&un()NCWeODG83xa&B&F<@LDASjg1H zqO6>(tgfEk+S9|cici7g+LbFQ0-~ZvH#m!^oH%r-NsG~hOQ+*{sDu^AuVxF`5R}f9Rp&1EYcr=*b12LuaO-@cR&38+|)be3O2dc3DYlw z4;5ALkqF=v$F+6zifB{+{5tQ~9200000NkvXXu0mjf9(=<* literal 0 HcmV?d00001 diff --git a/AppKit/Themes/Aristo/Resources/combobox-bezel-right.png b/AppKit/Themes/Aristo/Resources/combobox-bezel-right.png new file mode 100644 index 0000000000000000000000000000000000000000..e796d2f7e7f3c4dd42a470e90ef108dd6363bfc4 GIT binary patch literal 527 zcmV+q0`UEbP)vnC`1J=fkQQ&w{^y|Dsv&_aBBJReb;oe{2@KefySS$?}y9KY#wj zkYi_OXNZXmXAl+^Cg=kukPrS~!D1pJ49VdESY4SK83dNcrVrf*OfVmy<8MEIF^EV= zGx#{$p=j`Tb7T+{lLX6S(}&dufB#{}@4o(EFgG`2&{0l;6WH2!?VR#P|$E627 zPvMLM7ADcl-Fo~ ze*b28`|>%1w5Z@76bnFg^7V5kD7Ju$gZ;a-sL%l^VW9|QamLY>9U%Y^U;t&MX5J(I RXi5M8002ovPDHLkV1k-Q<(>cl literal 0 HcmV?d00001 diff --git a/AppKit/Themes/Aristo/ThemeDescriptors.j b/AppKit/Themes/Aristo/ThemeDescriptors.j index 506fd9655..43a428e36 100755 --- a/AppKit/Themes/Aristo/ThemeDescriptors.j +++ b/AppKit/Themes/Aristo/ThemeDescriptors.j @@ -801,7 +801,7 @@ var themedButtonValues = nil, placeholderColor = [CPColor colorWithCalibratedRed:189.0 / 255.0 green:199.0 / 255.0 blue:211.0 / 255.0 alpha:1.0]; - // Global for reuse by CPTokenField. + // Global for reuse by subclasses themedTextFieldValues = [ [@"vertical-alignment", CPTopVerticalTextAlignment, CPThemeStateBezeled], @@ -815,6 +815,9 @@ var themedButtonValues = nil, [@"bezel-inset", CGInsetMake(0.0, 0.0, 0.0, 0.0), CPThemeStateBezeled], [@"bezel-inset", CGInsetMake(0.0, 0.0, 0.0, 0.0), CPThemeStateBezeled | CPThemeStateEditing], + // Because the bezel artwork does not use insets, provide an inset to the border + [@"border-inset", CGInsetMake(3.0, 3.0, 3.0, 3.0), CPThemeStateBezeled], + [@"text-color", placeholderColor, CPTextFieldStatePlaceholder], [@"line-break-mode", CPLineBreakByTruncatingTail, CPThemeStateTableDataView], @@ -998,6 +1001,95 @@ var themedButtonValues = nil, return button; } ++ (CPComboBox)themedComboBox +{ + var combo = [[CPComboBox alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 29.0)], + + bezelColor = PatternColor( + [ + ["combobox-bezel-left.png", 6.0, 29.0], + ["combobox-bezel-center.png", 1.0, 29.0], + ["combobox-bezel-right.png", 24.0, 29.0] + ], + PatternIsHorizontal), + + bezelFocusedColor = PatternColor( + [ + ["combobox-bezel-focused-left.png", 6.0, 29.0], + ["combobox-bezel-focused-center.png", 1.0, 29.0], + ["combobox-bezel-focused-right.png", 24.0, 29.0] + ], + PatternIsHorizontal), + + bezelDisabledColor = PatternColor( + [ + ["combobox-bezel-disabled-left.png", 6.0, 29.0], + ["combobox-bezel-disabled-center.png", 1.0, 29.0], + ["combobox-bezel-disabled-right.png", 24.0, 29.0] + ], + PatternIsHorizontal), + + bezelNoBorderColor = PatternColor( + [ + ["combobox-bezel-no-border-left.png", 6.0, 29.0], + ["combobox-bezel-no-border-center.png", 1.0, 29.0], + ["combobox-bezel-no-border-right.png", 24.0, 29.0] + ], + PatternIsHorizontal), + + bezelNoBorderFocusedColor = PatternColor( + [ + ["combobox-bezel-no-border-focused-left.png", 6.0, 29.0], + ["combobox-bezel-no-border-focused-center.png", 1.0, 29.0], + ["combobox-bezel-no-border-focused-right.png", 24.0, 29.0] + ], + PatternIsHorizontal), + + bezelNoBorderDisabledColor = PatternColor( + [ + ["combobox-bezel-no-border-disabled-left.png", 6.0, 29.0], + ["combobox-bezel-no-border-disabled-center.png", 1.0, 29.0], + ["combobox-bezel-no-border-disabled-right.png", 24.0, 29.0] + ], + PatternIsHorizontal), + + overrides = + [ + [@"bezel-color", bezelColor, CPThemeStateBezeled | CPComboBoxStateButtonBordered], + [@"bezel-color", bezelFocusedColor, CPThemeStateBezeled | CPComboBoxStateButtonBordered | CPThemeStateEditing], + [@"bezel-color", bezelDisabledColor, CPThemeStateBezeled | CPComboBoxStateButtonBordered | CPThemeStateDisabled], + + [@"bezel-color", bezelNoBorderColor, CPThemeStateBezeled], + [@"bezel-color", bezelNoBorderFocusedColor, CPThemeStateBezeled | CPThemeStateEditing], + [@"bezel-color", bezelNoBorderDisabledColor, CPThemeStateBezeled | CPThemeStateDisabled], + + // The right inset has to make room for the popup button + [@"content-inset", CGInsetMake(8.0, 28.0, 5.0, 8.0), CPThemeStateBezeled | CPComboBoxStateButtonBordered], + [@"content-inset", CGInsetMake(7.0, 26.0, 6.0, 8.0), CPThemeStateBezeled | CPComboBoxStateButtonBordered | CPThemeStateEditing], + + [@"content-inset", CGInsetMake(8.0, 25.0, 5.0, 8.0), CPThemeStateBezeled], + [@"content-inset", CGInsetMake(7.0, 23.0, 6.0, 8.0), CPThemeStateBezeled | CPThemeStateEditing], + + [@"content-inset", CGInsetMake(0.0, 15.0, 0.0, 5.0), CPThemeStateTableDataView], + [@"content-inset", CGInsetMake(6.0, 20.0, 6.0, 5.0), CPThemeStateTableDataView | CPThemeStateEditing], + + [@"content-inset", CGInsetMake(0.0, 20.0, 0.0, 5.0), CPThemeStateTableDataView | CPComboBoxStateButtonBordered], + [@"content-inset", CGInsetMake(6.0, 25.0, 6.0, 5.0), CPThemeStateTableDataView | CPComboBoxStateButtonBordered | CPThemeStateEditing], + + [@"content-inset", CGInsetMake(0.0, 20.0, 0.0, 5.0), CPThemeStateTableDataView], + + // Because combo box uses a thre-part bezel, the height is fixed + [@"min-size", CGSizeMake(-1, 29.0)], + [@"max-size", CGSizeMake(-1, 29.0)], + + [@"popup-button-size", CGSizeMake(21.0, 23.0)] + ]; + + [self registerThemeValues:overrides forView:combo inherit:themedTextFieldValues]; + + return combo; +} + + (CPRadioButton)themedRadioButton { var button = [CPRadio radioWithTitle:@"Hello Friend!"], diff --git a/AppKit/_CPPopUpList.j b/AppKit/_CPPopUpList.j index eb7d1cbee..ae227bb06 100644 --- a/AppKit/_CPPopUpList.j +++ b/AppKit/_CPPopUpList.j @@ -20,7 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -@import +@import "CPTableView.j" /*! @@ -55,6 +55,8 @@ _CPPopUpListDidDismissNotification = @"_CPPopUpListDidDismissNotification"; _CPPopUpListItemWasClickedNotification = @"_CPPopUpListItemWasClickedNotification"; /*! + @ignore + The minimum number of items that must be visible below the related field. If less than this number would be completely visible, and there is room for this many complete items above the field, the list is displayed above. @@ -98,7 +100,6 @@ var ListColumnIdentifier = @"1"; Creates a pop up list of choices which will display relative to the given rect in base coordinates. @param aDelegate The object that usually is controlling this list. - @param baseRect A rect in base coordinates relative to which the list should be displayed */ - (id)initWithDelegate:(_CPPopUpListDelegate)aDelegate { @@ -107,6 +108,10 @@ var ListColumnIdentifier = @"1"; if (self) { _delegate = aDelegate; + _itemWasClicked = NO; + _listWasClicked = NO; + _listWidth = 0; + _tableView = [self makeTableView]; // Start with a default size, we will resize it later @@ -152,7 +157,8 @@ var ListColumnIdentifier = @"1"; [panel setTitle:@""]; [panel setFloatingPanel:YES]; [panel setBecomesKeyOnlyIfNeeded:YES]; - [panel setHasShadow:NO]; + [panel setHasShadow:YES]; + [panel setShadowStyle:CPMenuWindowShadowStyle]; [panel setDelegate:self]; return panel; @@ -220,6 +226,7 @@ var ListColumnIdentifier = @"1"; return scroll; } + /*! Returns the desired width of the list. */ @@ -238,22 +245,53 @@ var ListColumnIdentifier = @"1"; _listWidth = width; } -/!* +- (void)setFont:(CPFont)aFont +{ + var oldDataView = [_tableColumn dataView], + newDataView = [CPTextField new]; + + [newDataView setFont:aFont]; + [newDataView setAlignment:[oldDataView alignment]]; + [_tableColumn setDataView:newDataView]; + + // Force the data view cache to flush + [_tableView reloadData]; +} + +- (void)setAlignment:(CPTextAlignment)alignment +{ + var oldDataView = [_tableColumn dataView], + newDataView = [CPTextField new]; + + [newDataView setAlignment:alignment]; + [newDataView setFont:[oldDataView font]]; + [_tableColumn setDataView:newDataView]; + + // Force the data view cache to flush + [_tableView reloadData]; +} + +/*! Pop up the list if it is not already visible. If it is not visible, a _CPPopUpListWillPopUpNotification will be sent. + + @param aRect A rect (in \c aView coordinates) to display relative to + @param aView The view whose coordinate system \c aRect is in + @param offset How far to offset the list from \c aRect */ -- (void)popUpRelativeTo:(CGRect)baseRect +- (void)popUpRelativeToRect:(CGRect)aRect view:(CPView)aView offset:(int)offset { if ([_panel isVisible]) return; - var frame = CGRectMake(0, 0, MAX(_listWidth, CGRectGetWidth(baseRect)), [self rowHeightForTableView:_tableView] * [self numberOfRowsInTableView:_tableView]); + var frame = CGRectMake(0, 0, MAX(_listWidth, CGRectGetWidth(aRect)), [self rowHeightForTableView:_tableView] * [self numberOfRowsInTableView:_tableView]); - // Place the frame relative to the baseRect and constrain it to the screen bounds - frame = [self constrain:frame relativeTo:baseRect]; + // Place the frame relative to aRect and constrain it to the screen bounds + frame = [self constrain:frame relativeToRect:aRect view:aView offset:offset]; [_panel setFrame:frame]; [_scrollView setFrameSize:CGSizeMakeCopy(frame.size)]; + [self scrollItemAtIndexToTop:[_tableView selectedRow]]; [self listWillPopUp]; @@ -261,20 +299,26 @@ var ListColumnIdentifier = @"1"; } /*! - Return a frame in base coordinates such that the list, when displayed, will show at least ListMinimumItems - items completely on screen. Normally the list should be displayed below \c baseRect, but if there is not room + Return a frame in platform window base coordinates such that the list, when displayed, will show at least ListMinimumItems + items completely on screen. Normally the list should be displayed below \c aRect, but if there is not room for at least ListMinimumItems items, an attempt should be made to display that many - items above \c baseRect. If the minimum cannot be displayed on top, whichever direction can display more items + items above \c aRect. If the minimum cannot be displayed on top, whichever direction can display more items is chosen. */ -- (CGRect)constrain:(CGRect)aFrame relativeTo:(CGRect)baseRect +- (CGRect)constrain:(CGRect)aFrame relativeToRect:(CGRect)aRect view:(CPView)aView offset:(int)offset { - var baseOrigin = CGPointMake(CGRectGetMinX(baseRect), CGRectGetMaxY(baseRect)), + // Convert from the view's coordinate system to the coordinate system of the primary platform window + var baseOrigin = [aView convertPointToBase:aRect.origin], + windowOrigin = [[aView window] convertBaseToPlatformWindow:baseOrigin], rowHeight = [self rowHeightForTableView:_tableView], + // Be sure to clip the number of displayed rows to what the field wants numberOfRows = MIN([self numberOfRowsInTableView:_tableView], [_delegate numberOfVisibleItems]), + // Add 2 to height for border - frame = CGRectMake(baseOrigin.x, baseOrigin.y, MAX(_listWidth, CGRectGetWidth(aFrame)), (rowHeight * numberOfRows) + 2), + frame = CGRectMake(windowOrigin.x, windowOrigin.y + CGRectGetHeight(aRect) + offset, MAX(_listWidth, CGRectGetWidth(aFrame)), (rowHeight * numberOfRows) + 2), + + // Get the bottom coordinate of the frame and the platform window bottomFrame = CGRectMakeCopy(frame), bottom = CGRectGetMaxY(bottomFrame), viewRect = [[CPPlatformWindow primaryPlatformWindow] visibleFrame], @@ -294,7 +338,7 @@ var ListColumnIdentifier = @"1"; // The minimum number of items will not fit, try above var topFrame = CGRectMakeCopy(frame); - topFrame.origin.y = CGRectGetMinY(baseRect) - CGRectGetHeight(topFrame); + topFrame.origin.y = windowOrigin.y - offset - CGRectGetHeight(topFrame); var visibleTop = CGRectGetMinY(viewRect), topVisibleRows = numberOfRows; @@ -418,7 +462,7 @@ var ListColumnIdentifier = @"1"; return NO; } -- (void)scrollRowToTop:(int)row +- (void)scrollItemAtIndexToTop:(int)row { var rect = [_tableView rectOfRow:row]; @@ -584,6 +628,9 @@ var _CPPopUpListFieldKey = @"_CPPopUpListDelegateKey", if (self) { + _listWasClicked = NO; + _itemWasClicked = NO; + _delegate = [aCoder decodeObjectForKey:_CPPopUpListDelegateKey]; _listWidth = [aCoder decodeIntForKey:_CPPopUpListListWidthKey]; _panel = [aCoder decodeObjectForKey:_CPPopUpListListPanelKey]; @@ -607,12 +654,6 @@ var _CPPopUpListFieldKey = @"_CPPopUpListDelegateKey", [aCoder encodeObject:_tableView forKey:_CPPopUpListTableViewKey]; } -@end - -@implementation _CPPopUpList (CPTableViewDelegate) - - - @end @implementation _CPPopUpList (CPTableViewDataSource) @@ -653,7 +694,7 @@ var _CPPopUpListFieldKey = @"_CPPopUpListDelegateKey", */ - (CPTableColumn)listColumn { - return [self tableColumnWithIdentifier:ListColumnIdentifier]; + return _tableColumn; } @end diff --git a/Tests/Manual/CPComboBoxTest/.xCodeSupport/CPComboBoxTest.xcodeproj/project.pbxproj b/Tests/Manual/CPComboBoxTest/.xCodeSupport/CPComboBoxTest.xcodeproj/project.pbxproj new file mode 100644 index 000000000..e7bd2ca25 --- /dev/null +++ b/Tests/Manual/CPComboBoxTest/.xCodeSupport/CPComboBoxTest.xcodeproj/project.pbxproj @@ -0,0 +1,361 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 9EEC4498135749D200615446 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EEC4497135749D200615446 /* Cocoa.framework */; }; + 9EEC44B5135749D300615446 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EEC4497135749D200615446 /* Cocoa.framework */; }; + 9EEC44CC13574A0B00615446 /* CPComboBoxTest in Resources */ = {isa = PBXBuildFile; fileRef = 9EEC44CB13574A0B00615446 /* CPComboBoxTest */; }; + E172BA5013FF420400B03445 /* MainMenu.xib in Sources */ = {isa = PBXBuildFile; fileRef = E172BA4F13FF420400B03445 /* MainMenu.xib */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 9EEC44B6135749D300615446 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 9EEC448A135749D200615446 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9EEC4492135749D200615446; + remoteInfo = Another; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 9EEC4493135749D200615446 /* Another.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Another.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 9EEC4497135749D200615446 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + 9EEC449A135749D300615446 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; + 9EEC449B135749D300615446 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; + 9EEC449C135749D300615446 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 9EEC44B4135749D300615446 /* AnotherTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AnotherTests.octest; sourceTree = BUILT_PRODUCTS_DIR; }; + 9EEC44CB13574A0B00615446 /* CPComboBoxTest */ = {isa = PBXFileReference; lastKnownFileType = folder; name = CPComboBoxTest; path = ..; sourceTree = ""; }; + E172BA4F13FF420400B03445 /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainMenu.xib; path = ../Resources/MainMenu.xib; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 9EEC4490135749D200615446 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9EEC4498135749D200615446 /* Cocoa.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9EEC44B0135749D300615446 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9EEC44B5135749D300615446 /* Cocoa.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9EEC4488135749D200615446 = { + isa = PBXGroup; + children = ( + E172BA4F13FF420400B03445 /* MainMenu.xib */, + 9EEC44CB13574A0B00615446 /* CPComboBoxTest */, + 9EEC4496135749D200615446 /* Frameworks */, + 9EEC4494135749D200615446 /* Products */, + ); + sourceTree = ""; + }; + 9EEC4494135749D200615446 /* Products */ = { + isa = PBXGroup; + children = ( + 9EEC4493135749D200615446 /* Another.app */, + 9EEC44B4135749D300615446 /* AnotherTests.octest */, + ); + name = Products; + sourceTree = ""; + }; + 9EEC4496135749D200615446 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 9EEC4497135749D200615446 /* Cocoa.framework */, + 9EEC4499135749D300615446 /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9EEC4499135749D300615446 /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 9EEC449A135749D300615446 /* AppKit.framework */, + 9EEC449B135749D300615446 /* CoreData.framework */, + 9EEC449C135749D300615446 /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 9EEC4492135749D200615446 /* Another */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9EEC44C5135749D300615446 /* Build configuration list for PBXNativeTarget "Another" */; + buildPhases = ( + 9EEC448F135749D200615446 /* Sources */, + 9EEC4490135749D200615446 /* Frameworks */, + 9EEC4491135749D200615446 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Another; + productName = Another; + productReference = 9EEC4493135749D200615446 /* Another.app */; + productType = "com.apple.product-type.application"; + }; + 9EEC44B3135749D300615446 /* AnotherTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9EEC44C8135749D300615446 /* Build configuration list for PBXNativeTarget "AnotherTests" */; + buildPhases = ( + 9EEC44AF135749D300615446 /* Sources */, + 9EEC44B0135749D300615446 /* Frameworks */, + 9EEC44B1135749D300615446 /* Resources */, + 9EEC44B2135749D300615446 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 9EEC44B7135749D300615446 /* PBXTargetDependency */, + ); + name = AnotherTests; + productName = AnotherTests; + productReference = 9EEC44B4135749D300615446 /* AnotherTests.octest */; + productType = "com.apple.product-type.bundle"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 9EEC448A135749D200615446 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + ORGANIZATIONNAME = "280 North, Inc."; + }; + buildConfigurationList = 9EEC448D135749D200615446 /* Build configuration list for PBXProject "CPComboBoxTest" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 9EEC4488135749D200615446; + productRefGroup = 9EEC4494135749D200615446 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 9EEC4492135749D200615446 /* Another */, + 9EEC44B3135749D300615446 /* AnotherTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 9EEC4491135749D200615446 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9EEC44CC13574A0B00615446 /* CPComboBoxTest in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9EEC44B1135749D300615446 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 9EEC44B2135749D300615446 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 9EEC448F135749D200615446 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E172BA5013FF420400B03445 /* MainMenu.xib in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9EEC44AF135749D300615446 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 9EEC44B7135749D300615446 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 9EEC4492135749D200615446 /* Another */; + targetProxy = 9EEC44B6135749D300615446 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 9EEC44C3135749D300615446 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = DEBUG; + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.6; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 9EEC44C4135749D300615446 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.6; + SDKROOT = macosx; + }; + name = Release; + }; + 9EEC44C6135749D300615446 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Another/Another-Prefix.pch"; + INFOPLIST_FILE = "Another/Another-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 9EEC44C7135749D300615446 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Another/Another-Prefix.pch"; + INFOPLIST_FILE = "Another/Another-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; + 9EEC44C9135749D300615446 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Another.app/Contents/MacOS/Another"; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks"; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "AnotherTests/AnotherTests-Prefix.pch"; + INFOPLIST_FILE = "AnotherTests/AnotherTests-Info.plist"; + OTHER_LDFLAGS = ( + "-framework", + SenTestingKit, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUNDLE_LOADER)"; + WRAPPER_EXTENSION = octest; + }; + name = Debug; + }; + 9EEC44CA135749D300615446 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Another.app/Contents/MacOS/Another"; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks"; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "AnotherTests/AnotherTests-Prefix.pch"; + INFOPLIST_FILE = "AnotherTests/AnotherTests-Info.plist"; + OTHER_LDFLAGS = ( + "-framework", + SenTestingKit, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUNDLE_LOADER)"; + WRAPPER_EXTENSION = octest; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 9EEC448D135749D200615446 /* Build configuration list for PBXProject "CPComboBoxTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9EEC44C3135749D300615446 /* Debug */, + 9EEC44C4135749D300615446 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 9EEC44C5135749D300615446 /* Build configuration list for PBXNativeTarget "Another" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9EEC44C6135749D300615446 /* Debug */, + 9EEC44C7135749D300615446 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 9EEC44C8135749D300615446 /* Build configuration list for PBXNativeTarget "AnotherTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9EEC44C9135749D300615446 /* Debug */, + 9EEC44CA135749D300615446 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 9EEC448A135749D200615446 /* Project object */; +} diff --git a/Tests/Manual/CPComboBoxTest/.xCodeSupport/CPComboBoxTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Tests/Manual/CPComboBoxTest/.xCodeSupport/CPComboBoxTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..2d8d577c2 --- /dev/null +++ b/Tests/Manual/CPComboBoxTest/.xCodeSupport/CPComboBoxTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Tests/Manual/CPComboBoxTest/.xCodeSupport/Sources/_Users_aparajita_Development_Projects_Clients_Intalio_Carbon_iocappuccino_Tests_Manual_CPComboBoxTest_AppController.h b/Tests/Manual/CPComboBoxTest/.xCodeSupport/Sources/_Users_aparajita_Development_Projects_Clients_Intalio_Carbon_iocappuccino_Tests_Manual_CPComboBoxTest_AppController.h new file mode 100644 index 000000000..1543222d9 --- /dev/null +++ b/Tests/Manual/CPComboBoxTest/.xCodeSupport/Sources/_Users_aparajita_Development_Projects_Clients_Intalio_Carbon_iocappuccino_Tests_Manual_CPComboBoxTest_AppController.h @@ -0,0 +1,14 @@ + +@interface Companies : NSObject +{ + +} + +@end +@interface AppController : NSObject +{ + IBOutlet NSWindow* theWindow; + IBOutlet NSComboBox* cibCombo; +} + +@end \ No newline at end of file diff --git a/Tests/Manual/CPComboBoxTest/.xCodeSupport/Sources/_Users_aparajita_Development_Projects_Clients_Intalio_Carbon_iocappuccino_Tests_Manual_CPComboBoxTest__AppController.h b/Tests/Manual/CPComboBoxTest/.xCodeSupport/Sources/_Users_aparajita_Development_Projects_Clients_Intalio_Carbon_iocappuccino_Tests_Manual_CPComboBoxTest__AppController.h new file mode 100644 index 000000000..1543222d9 --- /dev/null +++ b/Tests/Manual/CPComboBoxTest/.xCodeSupport/Sources/_Users_aparajita_Development_Projects_Clients_Intalio_Carbon_iocappuccino_Tests_Manual_CPComboBoxTest__AppController.h @@ -0,0 +1,14 @@ + +@interface Companies : NSObject +{ + +} + +@end +@interface AppController : NSObject +{ + IBOutlet NSWindow* theWindow; + IBOutlet NSComboBox* cibCombo; +} + +@end \ No newline at end of file diff --git a/Tests/Manual/CPComboBoxTest/AppController.j b/Tests/Manual/CPComboBoxTest/AppController.j new file mode 100644 index 000000000..463aeda99 --- /dev/null +++ b/Tests/Manual/CPComboBoxTest/AppController.j @@ -0,0 +1,225 @@ +/* + * AppController.j + * CPComboBoxTest + * + * Created by Aparajita Fishman. + * Copyright (c) 2011, Intalio, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +@import + + +@implementation Companies : CPObject +{ + CPMutableArray items @accessors; +} + +- (id)init +{ + self = [super init]; + + if (self) + { + items = [CPMutableArray array]; + + var employees = "Tom,Dick,Harry,Ted,Sam,Fred,Ralph,Ed,Tim,John,Bill,Irving,Stan,Rodney".split(","); + + employees = [CPArray arrayWithObjects:employees count:employees.length]; + [items addObject:[CPDictionary dictionaryWithObjectsAndKeys:@"Spacely Sprockets", @"name", employees, @"employees"]]; + + employees = "Jane,Sally,Joan,Sara,Melissa,Beverly,Gillian,Sandra,Samantha,Mary,Kate".split(","); + employees = [CPArray arrayWithObjects:employees count:employees.length]; + [items addObject:[CPDictionary dictionaryWithObjectsAndKeys:@"Cogswell Cogs", @"name", employees, @"employees"]]; + } + + return self; +} + +@end + +@implementation AppController : CPObject +{ + @outlet CPWindow theWindow; + CPString employee @accessors; + Companies companies @accessors; + CPArrayController companiesController; + CPArrayController employeesController; + CPComboBox combo; + @outlet CPComboBox cibCombo; + CPString fontName; + int nextCheckboxY; +} + +- (id)init +{ + if (self = [super init]) + { + fontName = [CPFont systemFontFace]; + companies = [Companies new]; + } + + return self; +} + +- (void)awakeFromCib +{ +} + +- (void)applicationDidFinishLaunching:(CPNotification)aNotification +{ + theWindow = [[CPWindow alloc] initWithContentRect:CGRectMake(30, 50, 500, 400) styleMask:CPTitledWindowMask | CPResizableWindowMask]; + + var contentView = [theWindow contentView], + companiesScrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(30, 30, 200, 100)], + companiesTable = [[CPTableView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)], + employeesScrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(250, 30, 200, 200)], + employeesTable = [[CPTableView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)]; + + [theWindow setTitle:@"CPComboBox (from code)"]; + + var column = [[CPTableColumn alloc] initWithIdentifier:@"name"]; + + [column setResizingMask:CPTableColumnAutoresizingMask]; + [companiesTable addTableColumn:column]; + [companiesTable setAllowsMultipleSelection:YES]; + [companiesTable setColumnAutoresizingStyle:CPTableViewLastColumnOnlyAutoresizingStyle]; + [companiesScrollView setHasHorizontalScroller:NO]; + [companiesScrollView setHasVerticalScroller:YES]; + [companiesScrollView setDocumentView:companiesTable]; + [companiesScrollView setBorderType:CPBezelBorder]; + [companiesTable setHeaderView:nil]; + [companiesTable setAllowsEmptySelection:NO]; + + [contentView addSubview:companiesScrollView]; + + column = [[CPTableColumn alloc] initWithIdentifier:@"name"]; + + [column setResizingMask:CPTableColumnAutoresizingMask]; + [employeesTable addTableColumn:column]; + [employeesTable setAllowsMultipleSelection:YES]; + [employeesTable setColumnAutoresizingStyle:CPTableViewLastColumnOnlyAutoresizingStyle]; + [employeesScrollView setHasHorizontalScroller:NO]; + [employeesScrollView setHasVerticalScroller:YES]; + [employeesScrollView setDocumentView:employeesTable]; + [employeesScrollView setBorderType:CPBezelBorder]; + [employeesTable setHeaderView:nil]; + [employeesTable setAllowsEmptySelection:YES]; + + [contentView addSubview:employeesScrollView]; + + combo = [[CPComboBox alloc] initWithFrame:CGRectMake(250, 240, 200, 29)]; + [combo setCompletes:YES]; + [contentView addSubview:combo]; + + var center = [CPNotificationCenter defaultCenter]; + + [center addObserver:self selector:@selector(comboNote:) name:CPComboBoxSelectionDidChangeNotification object:combo]; + [center addObserver:self selector:@selector(comboNote:) name:CPComboBoxSelectionIsChangingNotification object:combo]; + [center addObserver:self selector:@selector(comboNote:) name:CPComboBoxWillDismissNotification object:combo]; + [center addObserver:self selector:@selector(comboNote:) name:CPComboBoxWillPopUpNotification object:combo]; + + nextCheckboxY = 166; + [self makeCheckBoxWithTitle:@"Enabled" defaultState:CPOnState]; + [self makeCheckBoxWithTitle:@"Button bordered" defaultState:CPOnState]; + [self makeCheckBoxWithTitle:@"Bold" defaultState:CPOffState]; + [self makeCheckBoxWithTitle:@"Completes" defaultState:CPOnState]; + [self makeCheckBoxWithTitle:@"Force selection" defaultState:CPOffState]; + [self makeCheckBoxWithTitle:@"Vertical scroller" defaultState:CPOnState]; + [self makeCheckBoxWithTitle:@"Big item height" defaultState:CPOffState]; + [self makeCheckBoxWithTitle:@"More visible items" defaultState:CPOffState]; + + companiesController = [CPArrayController new]; + [companiesController bind:@"contentArray" toObject:companies withKeyPath:@"items" options:nil]; + + employeesController = [CPArrayController new]; + [employeesController bind:@"contentArray" toObject:companiesController withKeyPath:@"selection.employees" options:nil]; + + var employeeController = [CPObjectController new]; + + [employeeController bind:@"content" toObject:employeesController withKeyPath:@"selection.self" options:nil]; + + [[companiesTable tableColumnWithIdentifier:@"name"] bind:@"value" toObject:companiesController withKeyPath:@"arrangedObjects.name" options:nil]; + [[employeesTable tableColumnWithIdentifier:@"name"] bind:@"value" toObject:employeesController withKeyPath:@"arrangedObjects" options:nil]; + [combo bind:@"contentValues" toObject:employeesController withKeyPath:@"arrangedObjects" options:nil]; + [combo bind:@"value" toObject:employeeController withKeyPath:@"content" options:nil]; + + [companiesController addObserver:self forKeyPath:@"selection" options:0 context:@"companies.selection"]; + [companiesController addObserver:self forKeyPath:@"selectionIndexes" options:0 context:@"companies.selectionIndexes"]; + [companiesController addObserver:self forKeyPath:@"arrangedObjects" options:0 context:@"companies.arrangedObjects"]; + [employeesController addObserver:self forKeyPath:@"selectionIndexes" options:0 context:@"employees.selectionIndexes"]; + [employeesController addObserver:self forKeyPath:@"selection" options:0 context:@"employees.selection"]; + [employeesController addObserver:self forKeyPath:@"arrangedObjects" options:0 context:@"employees.arrangedObjects"]; + [combo addObserver:self forKeyPath:@"value" options:0 context:@"combo.value"]; + + [theWindow setInitialFirstResponder:companiesTable]; + [theWindow orderFront:self]; +} + +- (void)makeCheckBoxWithTitle:(CPString)aTitle defaultState:(BOOL)aState +{ + var checkbox = [CPCheckBox checkBoxWithTitle:aTitle]; + [checkbox setFrameOrigin:CGPointMake(55, nextCheckboxY)]; + [checkbox setState:aState]; + [checkbox setTarget:self]; + [checkbox setAction:@selector(setComboState:)]; + [[theWindow contentView] addSubview:checkbox]; + + nextCheckboxY += 25; +} + +- (void)observeValueForKeyPath:(CPString)keyPath ofObject:(id)object change:(CPDictionary)change context:(id)context +{ + console.log("\nkeyPath: %s\ncontext: %s\nnew: %s\nold: %s", keyPath, context, [[change valueForKey:CPKeyValueChangeNewKey] description], [[change valueForKey:CPKeyValueChangeOldKey] description]); +} + +- (void)setComboState:(id)sender +{ + var title = [sender title], + state = [sender state] === CPOnState; + + if (title === @"Enabled") + [combo setEnabled:state]; + else if (title === @"Button bordered") + [combo setButtonBordered:state]; + else if (title === @"Bold") + { + var font = [sender state] === CPOnState ? [CPFont boldFontWithName:fontName size:12] : [CPFont fontWithName:fontName size:12]; + [combo setFont:font]; + } + else if (title === @"Completes") + [combo setCompletes:state]; + else if (title === @"Force selection") + [combo setForceSelection:state]; + else if (title === @"Vertical scroller") + [combo setHasVerticalScroller:state]; + else if (title === @"Big item height") + [combo setItemHeight:state ? 47 : 23]; + else if (title === @"More visible items") + [combo setNumberOfVisibleItems:state ? 10 : 5]; +} + +- (void)comboNote:(CPNotification)aNote +{ + console.log([aNote name]); + + var object = [aNote object]; + + if ([aNote name] === CPComboBoxWillDismissNotification) + console.log("Selected: %d - %s", [object indexOfSelectedItem], [object objectValueOfSelectedItem]); +} + +@end diff --git a/Tests/Manual/CPComboBoxTest/Info.plist b/Tests/Manual/CPComboBoxTest/Info.plist new file mode 100644 index 000000000..eee5519b4 --- /dev/null +++ b/Tests/Manual/CPComboBoxTest/Info.plist @@ -0,0 +1,10 @@ + + + + + Main cib file base name + MainMenu.cib + CPBundleName + CPComboBoxTest + + diff --git a/Tests/Manual/CPComboBoxTest/Jakefile b/Tests/Manual/CPComboBoxTest/Jakefile new file mode 100644 index 000000000..a83c45d07 --- /dev/null +++ b/Tests/Manual/CPComboBoxTest/Jakefile @@ -0,0 +1,94 @@ +/* + * Jakefile + * test + * + * Created by aparajita on August 19, 2011. + * Copyright 2011, Victory-Heart Productions All rights reserved. + */ + +var ENV = require("system").env, + FILE = require("file"), + JAKE = require("jake"), + task = JAKE.task, + FileList = JAKE.FileList, + app = require("cappuccino/jake").app, + configuration = ENV["CONFIG"] || ENV["CONFIGURATION"] || ENV["c"] || "Debug", + OS = require("os"); + +app ("test", function(task) +{ + task.setBuildIntermediatesPath(FILE.join("Build", "test.build", configuration)); + task.setBuildPath(FILE.join("Build", configuration)); + + task.setProductName("test"); + task.setIdentifier("com.aparajita.test"); + task.setVersion("1.0"); + task.setAuthor("Victory-Heart Productions"); + task.setEmail("feedback @nospam@ yourcompany.com"); + task.setSummary("test"); + task.setSources((new FileList("**/*.j")).exclude(FILE.join("Build", "**"))); + task.setResources(new FileList("Resources/**")); + task.setIndexFilePath("index.html"); + task.setInfoPlistPath("Info.plist"); + task.setNib2CibFlags("-R Resources/"); + + if (configuration === "Debug") + task.setCompilerFlags("-DDEBUG -g"); + else + task.setCompilerFlags("-O"); +}); + +task ("default", ["test"], function() +{ + printResults(configuration); +}); + +task ("build", ["default"]); + +task ("debug", function() +{ + ENV["CONFIGURATION"] = "Debug"; + JAKE.subjake(["."], "build", ENV); +}); + +task ("release", function() +{ + ENV["CONFIGURATION"] = "Release"; + JAKE.subjake(["."], "build", ENV); +}); + +task ("run", ["debug"], function() +{ + OS.system(["open", FILE.join("Build", "Debug", "test", "index.html")]); +}); + +task ("run-release", ["release"], function() +{ + OS.system(["open", FILE.join("Build", "Release", "test", "index.html")]); +}); + +task ("deploy", ["release"], function() +{ + FILE.mkdirs(FILE.join("Build", "Deployment", "test")); + OS.system(["press", "-f", FILE.join("Build", "Release", "test"), FILE.join("Build", "Deployment", "test")]); + printResults("Deployment") +}); + +task ("desktop", ["release"], function() +{ + FILE.mkdirs(FILE.join("Build", "Desktop", "test")); + require("cappuccino/nativehost").buildNativeHost(FILE.join("Build", "Release", "test"), FILE.join("Build", "Desktop", "test", "test.app")); + printResults("Desktop") +}); + +task ("run-desktop", ["desktop"], function() +{ + OS.system([FILE.join("Build", "Desktop", "test", "test.app", "Contents", "MacOS", "NativeHost"), "-i"]); +}); + +function printResults(configuration) +{ + print("----------------------------"); + print(configuration+" app built at path: "+FILE.join("Build", configuration, "test")); + print("----------------------------"); +} diff --git a/Tests/Manual/CPComboBoxTest/Resources/MainMenu.cib b/Tests/Manual/CPComboBoxTest/Resources/MainMenu.cib new file mode 100644 index 000000000..1db4a0421 --- /dev/null +++ b/Tests/Manual/CPComboBoxTest/Resources/MainMenu.cib @@ -0,0 +1 @@ +280NPLIST;1.0;D;K;4;$topD;K;18;CPCibObjectDataKeyD;K;6;CP$UIDd;1;2E;E;K;8;$objectsA;S;5;$nullD;K;10;$classnameS;16;_CPCibObjectDataK;8;$classesA;S;16;_CPCibObjectDataS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;1;1E;K;28;_CPCibObjectDataNamesKeysKeyD;K;6;CP$UIDd;1;4E;K;30;_CPCibObjectDataNamesValuesKeyD;K;6;CP$UIDd;1;5E;K;30;_CPCibObjectDataClassesKeysKeyD;K;6;CP$UIDd;1;6E;K;32;_CPCibObjectDataClassesValuesKeyD;K;6;CP$UIDd;1;7E;K;30;_CPCibObjectDataConnectionsKeyD;K;6;CP$UIDd;1;8E;K;28;_CPCibObjectDataFrameworkKeyD;K;6;CP$UIDd;1;9E;K;26;_CPCibObjectDataNextOidKeyD;K;6;CP$UIDd;2;10E;K;30;_CPCibObjectDataObjectsKeysKeyD;K;6;CP$UIDd;2;11E;K;32;_CPCibObjectDataObjectsValuesKeyD;K;6;CP$UIDd;2;12E;K;26;_CPCibObjectDataOidKeysKeyD;K;6;CP$UIDd;2;13E;K;28;_CPCibObjectDataOidValuesKeyD;K;6;CP$UIDd;2;14E;K;28;_CPCibObjectDataFileOwnerKeyD;K;6;CP$UIDd;2;16E;K;33;_CPCibObjectDataVisibleWindowsKeyD;K;6;CP$UIDd;2;18E;E;D;K;10;$classnameS;7;CPArrayK;8;$classesA;S;7;CPArrayS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;2;20E;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;2;22E;D;K;6;CP$UIDd;2;16E;D;K;6;CP$UIDd;2;23E;D;K;6;CP$UIDd;2;25E;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;2;26E;D;K;6;CP$UIDd;2;27E;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;2;28E;D;K;6;CP$UIDd;2;30E;D;K;6;CP$UIDd;2;31E;D;K;6;CP$UIDd;2;32E;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;2;34E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;35E;D;K;6;CP$UIDd;2;36E;D;K;6;CP$UIDd;2;37E;D;K;6;CP$UIDd;2;38E;D;K;6;CP$UIDd;2;39E;D;K;6;CP$UIDd;2;40E;D;K;6;CP$UIDd;2;41E;D;K;6;CP$UIDd;2;42E;D;K;6;CP$UIDd;2;43E;D;K;6;CP$UIDd;2;44E;D;K;6;CP$UIDd;2;45E;D;K;6;CP$UIDd;2;46E;D;K;6;CP$UIDd;2;47E;D;K;6;CP$UIDd;2;48E;D;K;6;CP$UIDd;2;49E;D;K;6;CP$UIDd;2;50E;D;K;6;CP$UIDd;2;51E;D;K;6;CP$UIDd;2;52E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;54E;D;K;6;CP$UIDd;2;55E;D;K;6;CP$UIDd;2;56E;D;K;6;CP$UIDd;2;58E;D;K;6;CP$UIDd;2;59E;D;K;6;CP$UIDd;2;60E;D;K;6;CP$UIDd;2;61E;D;K;6;CP$UIDd;2;62E;D;K;6;CP$UIDd;2;63E;D;K;6;CP$UIDd;2;64E;E;E;S;16;IBCocoaFrameworkD;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;34E;D;K;6;CP$UIDd;2;20E;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;2;25E;D;K;6;CP$UIDd;2;22E;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;2;23E;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;2;26E;D;K;6;CP$UIDd;2;27E;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;2;28E;D;K;6;CP$UIDd;2;30E;D;K;6;CP$UIDd;2;31E;D;K;6;CP$UIDd;2;32E;D;K;6;CP$UIDd;1;0E;D;K;6;CP$UIDd;1;0E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;20E;D;K;6;CP$UIDd;2;16E;D;K;6;CP$UIDd;2;28E;D;K;6;CP$UIDd;2;16E;D;K;6;CP$UIDd;2;34E;D;K;6;CP$UIDd;2;26E;D;K;6;CP$UIDd;2;16E;D;K;6;CP$UIDd;2;30E;D;K;6;CP$UIDd;2;34E;D;K;6;CP$UIDd;2;34E;D;K;6;CP$UIDd;2;27E;D;K;6;CP$UIDd;2;34E;D;K;6;CP$UIDd;2;34E;D;K;6;CP$UIDd;2;34E;D;K;6;CP$UIDd;2;16E;D;K;6;CP$UIDd;2;22E;D;K;6;CP$UIDd;2;31E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;10;$classnameS;18;_CPCibCustomObjectK;8;$classesA;S;18;_CPCibCustomObjectS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;15E;K;27;_CPCibCustomObjectClassNameD;K;6;CP$UIDd;2;65E;E;D;K;10;$classnameS;5;CPSetK;8;$classesA;S;5;CPSetS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;17E;K;15;CPSetObjectsKeyD;K;6;CP$UIDd;2;66E;E;D;K;10;$classnameS;20;_CPCibWindowTemplateK;8;$classesA;S;20;_CPCibWindowTemplateS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;19E;K;30;_CPCibWindowTemplateMaxSizeKeyD;K;6;CP$UIDd;2;67E;K;32;_CPCibWindowTemplateViewClassKeyD;K;6;CP$UIDd;1;0E;K;34;_CPCibWindowTemplateWindowClassKeyD;K;6;CP$UIDd;2;68E;K;33;_CPCibWindowTemplateWindowRectKeyD;K;6;CP$UIDd;2;69E;K;30;_CPCibWindowTempatStyleMaskKeyD;K;6;CP$UIDd;2;70E;K;34;_CPCibWindowTemplateWindowTitleKeyD;K;6;CP$UIDd;2;71E;K;33;_CPCibWindowTemplateWindowViewKeyD;K;6;CP$UIDd;2;34E;E;D;K;10;$classnameS;10;CPCheckBoxK;8;$classesA;S;10;CPCheckBoxS;8;CPButtonS;9;CPControlS;6;CPViewS;11;CPResponderS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;21E;K;27;CPResponderNextResponderKeyD;K;6;CP$UIDd;2;34E;K;18;CPResponderMenuKeyD;K;6;CP$UIDd;1;0E;K;12;CPViewTagKeyD;K;6;CP$UIDd;2;72E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;2;73E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;2;74E;K;18;CPViewSuperviewKeyD;K;6;CP$UIDd;2;34E;K;22;CPViewAutoresizingMaskD;K;6;CP$UIDd;2;75E;K;19;CPViewThemeClassKeyD;K;6;CP$UIDd;2;76E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;2;77E;K;16;$aimage-positionD;K;6;CP$UIDd;2;78E;K;6;$afontD;K;6;CP$UIDd;2;80E;K;17;$aline-break-modeD;K;6;CP$UIDd;2;72E;K;11;$aalignmentD;K;6;CP$UIDd;2;72E;K;17;CPControlValueKeyD;K;6;CP$UIDd;2;81E;K;24;CPControlSendActionOnKeyD;K;6;CP$UIDd;2;82E;K;16;CPButtonTitleKeyD;K;6;CP$UIDd;2;83E;K;25;CPButtonAlternateTitleKeyD;K;6;CP$UIDd;1;0E;K;27;CPButtonAllowsMixedStateKeyD;K;6;CP$UIDd;2;84E;K;32;CPButtonImageDimsWhenDisabledKeyD;K;6;CP$UIDd;1;0E;K;24;CPButtonImagePositionKeyD;K;6;CP$UIDd;2;78E;K;28;CPButtonKeyEquivalentMaskKeyD;K;6;CP$UIDd;2;72E;K;24;CPButtonPeriodicDelayKeyD;K;6;CP$UIDd;1;0E;K;27;CPButtonPeriodicIntervalKeyD;K;6;CP$UIDd;1;0E;E;D;K;6;$classD;K;6;CP$UIDd;2;15E;K;27;_CPCibCustomObjectClassNameD;K;6;CP$UIDd;2;85E;E;D;K;10;$classnameS;18;CPObjectControllerK;8;$classesA;S;18;CPObjectControllerS;12;CPControllerS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;24E;K;28;CPObjectControllerContentKeyD;K;6;CP$UIDd;1;0E;K;36;CPObjectControllerObjectClassNameKeyD;K;6;CP$UIDd;2;86E;K;31;CPObjectControllerIsEditableKeyD;K;6;CP$UIDd;2;87E;K;49;CPObjectControllerAutomaticallyPreparesContentKeyD;K;6;CP$UIDd;2;84E;E;D;K;6;$classD;K;6;CP$UIDd;2;21E;K;27;CPResponderNextResponderKeyD;K;6;CP$UIDd;2;34E;K;18;CPResponderMenuKeyD;K;6;CP$UIDd;1;0E;K;12;CPViewTagKeyD;K;6;CP$UIDd;2;72E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;2;88E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;2;89E;K;18;CPViewSuperviewKeyD;K;6;CP$UIDd;2;34E;K;22;CPViewAutoresizingMaskD;K;6;CP$UIDd;2;75E;K;19;CPViewThemeClassKeyD;K;6;CP$UIDd;2;76E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;2;77E;K;16;$aimage-positionD;K;6;CP$UIDd;2;78E;K;6;$afontD;K;6;CP$UIDd;2;80E;K;17;$aline-break-modeD;K;6;CP$UIDd;2;72E;K;11;$aalignmentD;K;6;CP$UIDd;2;72E;K;17;CPControlValueKeyD;K;6;CP$UIDd;2;81E;K;24;CPControlSendActionOnKeyD;K;6;CP$UIDd;2;82E;K;16;CPButtonTitleKeyD;K;6;CP$UIDd;2;90E;K;25;CPButtonAlternateTitleKeyD;K;6;CP$UIDd;1;0E;K;27;CPButtonAllowsMixedStateKeyD;K;6;CP$UIDd;2;84E;K;32;CPButtonImageDimsWhenDisabledKeyD;K;6;CP$UIDd;1;0E;K;24;CPButtonImagePositionKeyD;K;6;CP$UIDd;2;78E;K;28;CPButtonKeyEquivalentMaskKeyD;K;6;CP$UIDd;2;72E;K;24;CPButtonPeriodicDelayKeyD;K;6;CP$UIDd;1;0E;K;27;CPButtonPeriodicIntervalKeyD;K;6;CP$UIDd;1;0E;E;D;K;6;$classD;K;6;CP$UIDd;2;21E;K;27;CPResponderNextResponderKeyD;K;6;CP$UIDd;2;34E;K;18;CPResponderMenuKeyD;K;6;CP$UIDd;1;0E;K;12;CPViewTagKeyD;K;6;CP$UIDd;2;72E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;2;91E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;2;92E;K;18;CPViewSuperviewKeyD;K;6;CP$UIDd;2;34E;K;22;CPViewAutoresizingMaskD;K;6;CP$UIDd;2;75E;K;19;CPViewThemeClassKeyD;K;6;CP$UIDd;2;76E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;2;77E;K;16;$aimage-positionD;K;6;CP$UIDd;2;78E;K;6;$afontD;K;6;CP$UIDd;2;80E;K;17;$aline-break-modeD;K;6;CP$UIDd;2;72E;K;11;$aalignmentD;K;6;CP$UIDd;2;72E;K;17;CPControlValueKeyD;K;6;CP$UIDd;2;81E;K;24;CPControlSendActionOnKeyD;K;6;CP$UIDd;2;82E;K;16;CPButtonTitleKeyD;K;6;CP$UIDd;2;93E;K;25;CPButtonAlternateTitleKeyD;K;6;CP$UIDd;1;0E;K;27;CPButtonAllowsMixedStateKeyD;K;6;CP$UIDd;2;84E;K;32;CPButtonImageDimsWhenDisabledKeyD;K;6;CP$UIDd;1;0E;K;24;CPButtonImagePositionKeyD;K;6;CP$UIDd;2;78E;K;28;CPButtonKeyEquivalentMaskKeyD;K;6;CP$UIDd;2;72E;K;24;CPButtonPeriodicDelayKeyD;K;6;CP$UIDd;1;0E;K;27;CPButtonPeriodicIntervalKeyD;K;6;CP$UIDd;1;0E;E;D;K;6;$classD;K;6;CP$UIDd;2;21E;K;27;CPResponderNextResponderKeyD;K;6;CP$UIDd;2;34E;K;18;CPResponderMenuKeyD;K;6;CP$UIDd;1;0E;K;12;CPViewTagKeyD;K;6;CP$UIDd;2;72E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;2;94E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;2;95E;K;18;CPViewSuperviewKeyD;K;6;CP$UIDd;2;34E;K;22;CPViewAutoresizingMaskD;K;6;CP$UIDd;2;75E;K;19;CPViewThemeClassKeyD;K;6;CP$UIDd;2;76E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;2;96E;K;16;$aimage-positionD;K;6;CP$UIDd;2;78E;K;6;$afontD;K;6;CP$UIDd;2;80E;K;17;$aline-break-modeD;K;6;CP$UIDd;2;72E;K;11;$aalignmentD;K;6;CP$UIDd;2;72E;K;17;CPControlValueKeyD;K;6;CP$UIDd;2;72E;K;24;CPControlSendActionOnKeyD;K;6;CP$UIDd;2;82E;K;16;CPButtonTitleKeyD;K;6;CP$UIDd;2;97E;K;25;CPButtonAlternateTitleKeyD;K;6;CP$UIDd;1;0E;K;27;CPButtonAllowsMixedStateKeyD;K;6;CP$UIDd;2;84E;K;32;CPButtonImageDimsWhenDisabledKeyD;K;6;CP$UIDd;1;0E;K;24;CPButtonImagePositionKeyD;K;6;CP$UIDd;2;78E;K;28;CPButtonKeyEquivalentMaskKeyD;K;6;CP$UIDd;2;72E;K;24;CPButtonPeriodicDelayKeyD;K;6;CP$UIDd;1;0E;K;27;CPButtonPeriodicIntervalKeyD;K;6;CP$UIDd;1;0E;E;D;K;10;$classnameS;10;CPComboBoxK;8;$classesA;S;10;CPComboBoxS;11;CPTextFieldS;9;CPControlS;6;CPViewS;11;CPResponderS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;29E;K;27;CPResponderNextResponderKeyD;K;6;CP$UIDd;2;34E;K;18;CPResponderMenuKeyD;K;6;CP$UIDd;1;0E;K;12;CPViewTagKeyD;K;6;CP$UIDd;2;72E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;2;98E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;2;99E;K;18;CPViewSuperviewKeyD;K;6;CP$UIDd;2;34E;K;22;CPViewAutoresizingMaskD;K;6;CP$UIDd;2;75E;K;19;CPViewThemeClassKeyD;K;6;CP$UIDd;3;100E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;3;101E;K;6;$afontD;K;6;CP$UIDd;2;80E;K;17;$aline-break-modeD;K;6;CP$UIDd;2;78E;K;11;$aalignmentD;K;6;CP$UIDd;2;82E;K;35;CPControlSendsActionOnEndEditingKeyD;K;6;CP$UIDd;2;87E;K;17;CPControlValueKeyD;K;6;CP$UIDd;3;102E;K;24;CPControlSendActionOnKeyD;K;6;CP$UIDd;3;103E;K;24;CPTextFieldIsEditableKeyD;K;6;CP$UIDd;2;87E;K;26;CPTextFieldIsSelectableKeyD;K;6;CP$UIDd;2;87E;K;29;CPTextFieldDrawsBackgroundKeyD;K;6;CP$UIDd;2;87E;K;29;CPTextFieldBackgroundColorKeyD;K;6;CP$UIDd;3;105E;K;27;CPTextFieldLineBreakModeKeyD;K;6;CP$UIDd;2;78E;K;23;CPTextFieldAlignmentKeyD;K;6;CP$UIDd;2;82E;K;31;CPTextFieldPlaceholderStringKeyD;K;6;CP$UIDd;1;0E;K;18;CPComboBoxItemsKeyD;K;6;CP$UIDd;3;106E;K;17;CPComboBoxListKeyD;K;6;CP$UIDd;1;0E;K;21;CPComboBoxDelegateKeyD;K;6;CP$UIDd;1;0E;K;23;CPComboBoxDataSourceKeyD;K;6;CP$UIDd;1;0E;K;27;CPComboBoxUsesDataSourceKeyD;K;6;CP$UIDd;2;84E;K;22;CPComboBoxCompletesKeyD;K;6;CP$UIDd;2;87E;K;33;CPComboBoxNumberOfVisibleItemsKeyD;K;6;CP$UIDd;3;107E;K;32;CPComboBoxHasVerticalScrollerKeyD;K;6;CP$UIDd;2;87E;K;27;CPComboBoxButtonBorderedKeyD;K;6;CP$UIDd;2;87E;E;D;K;6;$classD;K;6;CP$UIDd;2;21E;K;27;CPResponderNextResponderKeyD;K;6;CP$UIDd;2;34E;K;18;CPResponderMenuKeyD;K;6;CP$UIDd;1;0E;K;12;CPViewTagKeyD;K;6;CP$UIDd;2;72E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;3;108E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;3;109E;K;18;CPViewSuperviewKeyD;K;6;CP$UIDd;2;34E;K;22;CPViewAutoresizingMaskD;K;6;CP$UIDd;2;75E;K;19;CPViewThemeClassKeyD;K;6;CP$UIDd;2;76E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;2;77E;K;16;$aimage-positionD;K;6;CP$UIDd;2;78E;K;6;$afontD;K;6;CP$UIDd;2;80E;K;17;$aline-break-modeD;K;6;CP$UIDd;2;72E;K;11;$aalignmentD;K;6;CP$UIDd;2;72E;K;17;CPControlValueKeyD;K;6;CP$UIDd;2;81E;K;24;CPControlSendActionOnKeyD;K;6;CP$UIDd;2;82E;K;16;CPButtonTitleKeyD;K;6;CP$UIDd;3;110E;K;25;CPButtonAlternateTitleKeyD;K;6;CP$UIDd;1;0E;K;27;CPButtonAllowsMixedStateKeyD;K;6;CP$UIDd;2;84E;K;32;CPButtonImageDimsWhenDisabledKeyD;K;6;CP$UIDd;1;0E;K;24;CPButtonImagePositionKeyD;K;6;CP$UIDd;2;78E;K;28;CPButtonKeyEquivalentMaskKeyD;K;6;CP$UIDd;2;72E;K;24;CPButtonPeriodicDelayKeyD;K;6;CP$UIDd;1;0E;K;27;CPButtonPeriodicIntervalKeyD;K;6;CP$UIDd;1;0E;E;D;K;6;$classD;K;6;CP$UIDd;2;15E;K;27;_CPCibCustomObjectClassNameD;K;6;CP$UIDd;2;65E;E;D;K;10;$classnameS;6;CPViewK;8;$classesA;S;6;CPViewS;11;CPResponderS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;33E;K;18;CPResponderMenuKeyD;K;6;CP$UIDd;1;0E;K;12;CPViewTagKeyD;K;6;CP$UIDd;2;72E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;3;111E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;3;111E;K;17;CPViewSubviewsKeyD;K;6;CP$UIDd;3;112E;K;19;CPViewThemeClassKeyD;K;6;CP$UIDd;1;0E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;2;96E;E;S;2;16S;1;1S;1;2S;1;5S;1;4S;12;File's OwnerS;1;6S;1;3S;1;7S;1;8S;1;9S;2;10S;2;11S;2;12S;2;13S;2;14S;2;15S;1;0D;K;10;$classnameS;20;CPCibOutletConnectorK;8;$classesA;S;20;CPCibOutletConnectorS;14;CPCibConnectorS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;53E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;16E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;23E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;3;113E;E;D;K;6;$classD;K;6;CP$UIDd;2;53E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;23E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;30E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;3;114E;E;D;K;6;$classD;K;6;CP$UIDd;2;53E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;23E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;20E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;3;115E;E;D;K;10;$classnameS;21;CPCibBindingConnectorK;8;$classesA;S;21;CPCibBindingConnectorS;14;CPCibConnectorS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;57E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;27E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;23E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;3;116E;K;31;CPCibBindingConnectorBindingKeyD;K;6;CP$UIDd;3;117E;K;31;CPCibBindingConnectorKeyPathKeyD;K;6;CP$UIDd;3;118E;K;31;CPCibBindingConnectorOptionsKeyD;K;6;CP$UIDd;3;120E;E;D;K;6;$classD;K;6;CP$UIDd;2;57E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;26E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;23E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;3;121E;K;31;CPCibBindingConnectorBindingKeyD;K;6;CP$UIDd;3;117E;K;31;CPCibBindingConnectorKeyPathKeyD;K;6;CP$UIDd;3;122E;K;31;CPCibBindingConnectorOptionsKeyD;K;6;CP$UIDd;3;123E;E;D;K;6;$classD;K;6;CP$UIDd;2;57E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;28E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;23E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;3;124E;K;31;CPCibBindingConnectorBindingKeyD;K;6;CP$UIDd;3;117E;K;31;CPCibBindingConnectorKeyPathKeyD;K;6;CP$UIDd;3;125E;K;31;CPCibBindingConnectorOptionsKeyD;K;6;CP$UIDd;3;126E;E;D;K;6;$classD;K;6;CP$UIDd;2;57E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;31E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;23E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;3;127E;K;31;CPCibBindingConnectorBindingKeyD;K;6;CP$UIDd;3;117E;K;31;CPCibBindingConnectorKeyPathKeyD;K;6;CP$UIDd;3;128E;K;31;CPCibBindingConnectorOptionsKeyD;K;6;CP$UIDd;3;129E;E;D;K;6;$classD;K;6;CP$UIDd;2;57E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;25E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;23E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;3;130E;K;31;CPCibBindingConnectorBindingKeyD;K;6;CP$UIDd;3;131E;K;31;CPCibBindingConnectorKeyPathKeyD;K;6;CP$UIDd;3;132E;K;31;CPCibBindingConnectorOptionsKeyD;K;6;CP$UIDd;3;133E;E;D;K;6;$classD;K;6;CP$UIDd;2;57E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;22E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;23E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;3;134E;K;31;CPCibBindingConnectorBindingKeyD;K;6;CP$UIDd;3;117E;K;31;CPCibBindingConnectorKeyPathKeyD;K;6;CP$UIDd;3;135E;K;31;CPCibBindingConnectorOptionsKeyD;K;6;CP$UIDd;3;136E;E;D;K;6;$classD;K;6;CP$UIDd;2;57E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;30E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;25E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;3;137E;K;31;CPCibBindingConnectorBindingKeyD;K;6;CP$UIDd;3;138E;K;31;CPCibBindingConnectorKeyPathKeyD;K;6;CP$UIDd;3;139E;K;31;CPCibBindingConnectorOptionsKeyD;K;6;CP$UIDd;3;140E;E;S;13;CPApplicationD;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;20E;E;E;S;32;{10000000000000, 10000000000000}S;8;CPWindowS;24;{{583, 126}, {394, 166}}d;2;15S;21;CPComboBox (from cib)d;1;0S;21;{{247, 30}, {72, 18}}S;18;{{0, 0}, {72, 18}}d;2;36S;9;check-boxS;8;selectedd;1;2D;K;10;$classnameS;6;CPFontK;8;$classesA;S;6;CPFontS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;79E;K;13;CPFontNameKeyD;K;6;CP$UIDd;3;141E;K;13;CPFontSizeKeyD;K;6;CP$UIDd;3;142E;K;15;CPFontIsBoldKeyD;K;6;CP$UIDd;2;84E;K;17;CPFontIsItalicKeyD;K;6;CP$UIDd;2;84E;E;d;1;1d;1;4S;7;EnabledF;S;13;AppControllerS;10;CPComboBoxT;S;23;{{247, 130}, {129, 18}}S;19;{{0, 0}, {129, 18}}S;18;Vertical scrollbarS;22;{{247, 55}, {125, 18}}S;19;{{0, 0}, {125, 18}}S;15;Button borderedS;23;{{247, 105}, {117, 18}}S;19;{{0, 0}, {117, 18}}S;6;normalS;15;Force selectionS;21;{{14, 25}, {199, 29}}S;19;{{0, 0}, {199, 29}}S;8;comboboxS;35;bezeled+placeholder+button-borderedS;0;d;4;3072D;K;10;$classnameS;7;CPColorK;8;$classesA;S;7;CPColorS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;3;104E;K;20;CPColorComponentsKeyD;K;6;CP$UIDd;3;143E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;3;144E;D;K;6;CP$UIDd;3;145E;D;K;6;CP$UIDd;3;146E;D;K;6;CP$UIDd;3;147E;D;K;6;CP$UIDd;3;148E;D;K;6;CP$UIDd;3;149E;D;K;6;CP$UIDd;3;150E;D;K;6;CP$UIDd;3;151E;D;K;6;CP$UIDd;3;152E;E;E;d;1;7S;21;{{247, 80}, {89, 18}}S;18;{{0, 0}, {89, 18}}S;9;CompletesS;20;{{0, 0}, {394, 166}}D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;30E;D;K;6;CP$UIDd;2;22E;D;K;6;CP$UIDd;2;27E;D;K;6;CP$UIDd;2;31E;D;K;6;CP$UIDd;2;28E;D;K;6;CP$UIDd;2;26E;E;E;S;8;delegateS;8;cibComboS;9;theWindowS;30;value: cibCombo.buttonBorderedS;5;valueS;23;cibCombo.buttonBorderedD;K;10;$classnameS;12;CPDictionaryK;8;$classesA;S;12;CPDictionaryS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;3;119E;K;10;CP.objectsD;E;E;S;35;value: cibCombo.hasVerticalScrollerS;28;cibCombo.hasVerticalScrollerD;K;6;$classD;K;6;CP$UIDd;3;119E;K;10;CP.objectsD;E;E;S;30;value: cibCombo.forceSelectionS;23;cibCombo.forceSelectionD;K;6;$classD;K;6;CP$UIDd;3;119E;K;10;CP.objectsD;E;E;S;25;value: cibCombo.completesS;18;cibCombo.completesD;K;6;$classD;K;6;CP$UIDd;3;119E;K;10;CP.objectsD;E;E;S;20;contentObject: comboS;13;contentObjectS;5;comboD;K;6;$classD;K;6;CP$UIDd;3;119E;K;10;CP.objectsD;E;E;S;23;value: cibCombo.enabledS;16;cibCombo.enabledD;K;6;$classD;K;6;CP$UIDd;3;119E;K;10;CP.objectsD;E;E;S;18;enabled: selectionS;7;enabledS;9;selectionD;K;6;$classD;K;6;CP$UIDd;3;119E;K;10;CP.objectsD;E;E;S;17;Arial, sans-serifd;2;12D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;81E;D;K;6;CP$UIDd;2;81E;D;K;6;CP$UIDd;2;81E;D;K;6;CP$UIDd;2;81E;E;E;S;3;MoeS;5;LarryS;6;CheeseS;5;CurlyS;5;ShempS;7;GrouchoS;5;HarpoS;5;ChicoS;5;ZeppoE;K;9;$archiverS;15;CPKeyedArchiverK;8;$versionS;6;100000E; \ No newline at end of file diff --git a/Tests/Manual/CPComboBoxTest/Resources/MainMenu.xib b/Tests/Manual/CPComboBoxTest/Resources/MainMenu.xib new file mode 100644 index 000000000..5f2dc4983 --- /dev/null +++ b/Tests/Manual/CPComboBoxTest/Resources/MainMenu.xib @@ -0,0 +1,756 @@ + + + + 1050 + 10K549 + 1923 + 1038.36 + 461.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 1923 + + + YES + NSView + NSComboBox + NSWindowTemplate + NSObjectController + NSButtonCell + NSComboBoxCell + NSButton + NSCustomObject + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + YES + + NSApplication + + + FirstResponder + + + NSApplication + + + AppController + + + NSComboBox + YES + + + + 15 + 2 + {{583, 886}, {394, 166}} + 544735232 + CPComboBox (from cib) + NSWindow + + + + 256 + + YES + + + 268 + {{20, 115}, {191, 26}} + + + + YES + + 343014976 + 272630784 + + + LucidaGrande + 13 + 1044 + + + YES + + 6 + System + textBackgroundColor + + 3 + MQA + + + + 6 + System + controlTextColor + + 3 + MAA + + + 7 + YES + YES + + YES + Moe + Larry + Cheese + Curly + Shemp + Groucho + Harpo + Chico + Zeppo + + + + + 274 + {13, 189} + + + YES + + YES + + 10 + 10 + 1000 + + 75628032 + 0 + + + LucidaGrande + 12 + 16 + + + 3 + MC4zMzMzMzI5ODU2AA + + + + + 338820672 + 1024 + + + YES + + 6 + System + controlBackgroundColor + + 3 + MC42NjY2NjY2NjY3AA + + + + + 3 + YES + + + + 3 + 2 + + + 6 + System + gridColor + + 3 + MC41AA + + + 19 + tableViewAction: + -765427712 + + + + 1 + 15 + 0 + YES + 0 + + + + + + 268 + {{247, 118}, {72, 18}} + + + + YES + + -2080244224 + 0 + Enabled + + + 1211912703 + 2 + + NSImage + NSSwitch + + + NSSwitch + + + + 200 + 25 + + + + + 268 + {{247, 93}, {125, 18}} + + + + YES + + -2080244224 + 0 + Button bordered + + + 1211912703 + 2 + + + + + 200 + 25 + + + + + 268 + {{247, 68}, {89, 18}} + + + + YES + + -2080244224 + 0 + Completes + + + 1211912703 + 2 + + + + + 200 + 25 + + + + + 268 + {{247, 43}, {117, 18}} + + + + YES + + 67239424 + 0 + Force selection + + + 1211912703 + 2 + + + + + 200 + 25 + + + + + 268 + {{247, 18}, {129, 18}} + + + + YES + + -2080244224 + 0 + Vertical scrollbar + + + 1211912703 + 2 + + + + + 200 + 25 + + + + {394, 166} + + + + + {{0, 0}, {1920, 1178}} + {1e+13, 1e+13} + + + + + YES + + + delegate + + + + 451 + + + + theWindow + + + + 464 + + + + cibCombo + + + + 529 + + + + enabled: selection + + + + + + enabled: selection + enabled + selection + 2 + + + 522 + + + + value: cibCombo.enabled + + + + + + value: cibCombo.enabled + value + cibCombo.enabled + 2 + + + 531 + + + + contentObject: combo + + + + + + contentObject: combo + contentObject + combo + 2 + + + 521 + + + + value: cibCombo.completes + + + + + + value: cibCombo.completes + value + cibCombo.completes + 2 + + + 535 + + + + value: cibCombo.forceSelection + + + + + + value: cibCombo.forceSelection + value + cibCombo.forceSelection + 2 + + + 548 + + + + value: cibCombo.hasVerticalScroller + + + + + + value: cibCombo.hasVerticalScroller + value + cibCombo.hasVerticalScroller + 2 + + + 546 + + + + value: cibCombo.buttonBordered + + + + + + value: cibCombo.buttonBordered + value + cibCombo.buttonBordered + 2 + + + 552 + + + + + YES + + 0 + + YES + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 450 + + + + + 460 + + + YES + + + + + + 461 + + + YES + + + + + + + + + + + 462 + + + YES + + + + + + 463 + + + + + 515 + + + YES + + + + + + 516 + + + + + 517 + + + + + 532 + + + YES + + + + + + 533 + + + + + 536 + + + YES + + + + + + 537 + + + + + 539 + + + YES + + + + + + 540 + + + + + 549 + + + YES + + + + + + 550 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency + 450.IBPluginDependency + 460.IBPluginDependency + 460.IBWindowTemplateEditedContentRect + 460.NSWindowTemplate.visibleAtLaunch + 461.IBPluginDependency + 462.IBPluginDependency + 463.IBComboBoxObjectValuesKey.objectValues + 463.IBPluginDependency + 515.IBPluginDependency + 516.IBPluginDependency + 517.IBPluginDependency + 532.IBPluginDependency + 533.IBPluginDependency + 536.IBPluginDependency + 537.IBPluginDependency + 539.IBPluginDependency + 540.IBPluginDependency + 549.IBPluginDependency + 550.IBPluginDependency + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{357, 418}, {480, 270}} + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + YES + Moe + Larry + Cheese + Curly + Shemp + Groucho + Harpo + Chico + Zeppo + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + YES + + + + + + YES + + + + + 552 + + + + YES + + AppController + NSObject + + YES + + YES + cibCombo + theWindow + + + YES + NSComboBox + NSWindow + + + + YES + + YES + cibCombo + theWindow + + + YES + + cibCombo + NSComboBox + + + theWindow + NSWindow + + + + + IBProjectSource + ./Classes/AppController.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + 3 + + NSSwitch + {15, 15} + + + diff --git a/Tests/Manual/CPComboBoxTest/Resources/spinner.gif b/Tests/Manual/CPComboBoxTest/Resources/spinner.gif new file mode 100644 index 0000000000000000000000000000000000000000..06dbc2bc21dddcf0e09b566d5b211aee89570f52 GIT binary patch literal 1849 zcma*odr(tX9tZHtz31lM+(&Y`A`Ou`NeG&R#DrIfV%?hng21vs6v>ooRQQFbk7E_K!V( z{?5!fpZWgIZ%*d6t%i*j24bL}AZUJm9)h6R*;%L4IWse3G#VWaN1#$zSSXcBhlYlH zJ|D}n{r&w2f+Qp)SS*&n?*G4}{}!h?td_mjU6Kad-rW*QwWYCUk7d^e+sjpZAn6kT z5rM;`{~_}-wm+L@%+E;JphLm}C3WzQAQD0wBoY|rOTQX{(@pp-WAA8Iw0HKl|15j) zhGh(SFWu#5zUCw^T!}C~eC}~?{xG-r7ugQC>taC+|L^xr&a%{#cgUOZXIM&v?)k^2 z1i5%0!U00wq)r4vlAwXBA_m5J5WNeuBm-XJQ5pG4GD%vc|K){+TJ{AkHqN@SJKczX zU}QRd9n*_bf^h94)6Ctv{CUfz_;qs#RDuQ$DR%y1&5G-a6rhf*4Y zl+UOD1*GE{GQ7vv;c-tTIMkz0ovO>9j%b5hpa@a*CBJ#W!0@ndSwF|%hMkdFtXiU) z`BEp+yhkt8ZY>tg&uyH@%^%K4jDrbA;et&vnnzZ3z22@e6<27z2Vk13kb7OtISyxv z(XoO-LNQCZe3lfzc%*pNqU<9T+p~teThOEB+~e&U0mC|zS{Q)dJZ)!^1f7L(zg*L> z*vSW%?dR~@@0(}x6-V^A`~ImD;)NaBUnP8;RH=bS2@pk`wp>>8r&jGjmGPy%1BW}v zoPo}ca$~bze@efc3kapuEVW1!%teOZT3j2Tw5=hjiAf02d}7dL0oFC%@=RXp5Ow#% z@a>+AM|YWt$n&e`>sB-32gBcuTi>R>*|8@lp`y6thc7ydyqDsuUn~YzZf|{-R@-3y zL#wx{Ii}xxL_csiW*LBn0-A$>zp4WOmkf6=ilrjlW?-l9+bCd7|i?*b5NTmy<<6NZ0T8$SN@mwdC2f z6jqK=N@bS@!=YSj%>h0}*4p+%0HbTIrE$w7UMT6+AZZ&DAo*qZAAi(OtNbIfl#Dw^ zJWeiCp~zi#&t6x}m9)O^eR4HiLV3QA<<0>HZ8%$^lrSE94Wb}=+MM^!b>n#5&-JQR zkr-CEu9C;_F*7DqDisulV6Pmg$nFL0TPn%~*m^-`Z3^BgU(sNpnx%nW(!eV9A&FvI zHL3X3lw8Wji^6=8KbQDE-e%b?svdFxxdh$8r97@7$ojeI`6AL8Ob6QC$qh&>ZWVDX1F{0vJnT%%mE;GveKWR%C} zM&4d;Jf3s9|HAA)yVUPo`Aq;0do#)uHSXi5*QF*)x@MVVHr+cN)uMZ__F|&Ta#p8d z53TOKtce!PJUuie8UWol-S(`c2nH?UGqJP{!4RR4u$LCfn)q-hj0^f=h(VYy)T6eN zhRO!ja-aDBTcgeyP(8Ua4IdiOog^*CQa?R(cP#9AgL9`j>EX-6Yf1lzX(!~``M1XC zNmM<4<6d~wWZ$Xrk0K}UteTrq@LBBk#MsjkK;pbuVhe)NI7(7Pf(l?lxC7=1Z7Pzl zMbS;nV4NI5_N{1$P)&XC)huOGQ+h^zpYUZfb*1n6>!`#*b3y52LGmi+<4sY5jyD#- zw&$d}DTguLAfnRtjrM*JfqtHqUu6rQoU=g%1E9xk%;)TDm^2<8n-0IhTsQFaek)MY}>PK4;nBk=ow4pF>vzkO& gna%Org-kgQCf=+BeMi^RbuY;YE~rTjend;_cdi8t>i_@% literal 0 HcmV?d00001 diff --git a/Tests/Manual/CPComboBoxTest/index-debug.html b/Tests/Manual/CPComboBoxTest/index-debug.html new file mode 100644 index 000000000..052bcacac --- /dev/null +++ b/Tests/Manual/CPComboBoxTest/index-debug.html @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + CPComboBoxTest + + + + + + + + + + + + + + +
+
+ + + +
+
+ + + diff --git a/Tests/Manual/CPComboBoxTest/index.html b/Tests/Manual/CPComboBoxTest/index.html new file mode 100644 index 000000000..bf35f355e --- /dev/null +++ b/Tests/Manual/CPComboBoxTest/index.html @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + CPComboBoxTest + + + + + + + + + + + + +
+
+ + + +
+
+ + + + diff --git a/Tests/Manual/CPComboBoxTest/main.j b/Tests/Manual/CPComboBoxTest/main.j new file mode 100644 index 000000000..e2cfd7a56 --- /dev/null +++ b/Tests/Manual/CPComboBoxTest/main.j @@ -0,0 +1,18 @@ +/* + * AppController.j + * test + * + * Created by aparajita on August 19, 2011. + * Copyright 2011, Victory-Heart Productions All rights reserved. + */ + +@import +@import + +@import "AppController.j" + + +function main(args, namedArgs) +{ + CPApplicationMain(args, namedArgs); +} diff --git a/Tools/nib2cib/NSAppKit.j b/Tools/nib2cib/NSAppKit.j index 93a671da5..27a4e25e7 100644 --- a/Tools/nib2cib/NSAppKit.j +++ b/Tools/nib2cib/NSAppKit.j @@ -31,6 +31,7 @@ @import "NSColorWell.j" @import "NSCollectionView.j" @import "NSCollectionViewItem.j" +@import "NSComboBox.j" @import "NSControl.j" @import "NSCustomObject.j" @import "NSCustomResource.j" diff --git a/Tools/nib2cib/NSComboBox.j b/Tools/nib2cib/NSComboBox.j new file mode 100644 index 000000000..f41a6cc0e --- /dev/null +++ b/Tools/nib2cib/NSComboBox.j @@ -0,0 +1,104 @@ +/* + * NSComboBox.j + * nib2cib + * + * Created by Aparajita Fishman. + * Copyright (c) 2011, Intalio, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +@import + +@import "NSTextField.j" + + +@implementation CPComboBox (NSCoding) + +- (id)NS_initWithCoder:(CPCoder)aCoder +{ + self = [super NS_initWithCoder:aCoder]; + + if (self) + { + var cell = [aCoder decodeObjectForKey:@"NSCell"]; + + _items = [cell itemList]; + _usesDataSource = [cell usesDataSource]; + _completes = [cell completes]; + _numberOfVisibleItems = [cell visibleItemCount]; + _hasVerticalScroller = [cell hasVerticalScroller]; + [self setButtonBordered:[cell borderedButton]]; + + // Make sure the height is clipped to the max given by the theme + var maxSize = [[[Converter sharedConverter] themes][0] valueForAttributeWithName:@"max-size" forClass:[CPComboBox class]], + size = [self frameSize]; + + [self setFrameSize:CGSizeMake(size.width, MIN(size.height, maxSize.height))]; + } + + return self; +} + +@end + +@implementation NSComboBox : CPComboBox + +- (id)initWithCoder:(CPCoder)aCoder +{ + return [self NS_initWithCoder:aCoder]; +} + +- (Class)classForKeyedArchiver +{ + return [CPComboBox class]; +} + +@end + +@implementation NSComboBoxCell : NSTextFieldCell +{ + int _visibleItemCount @accessors(readonly, getter=visibleItemCount); + BOOL _hasVerticalScroller @accessors(readonly, getter=hasVerticalScroller); + BOOL _usesDataSource @accessors(readonly, getter=usesDataSource); + BOOL _completes @accessors(readonly, getter=completes); + CPArray _itemList @accessors(readonly, getter=itemList); + BOOL _borderedButton @accessors(readonly, getter=borderedButton); +} + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super initWithCoder:aCoder]; + + if (self) + { + _visibleItemCount = [aCoder decodeIntForKey:@"NSVisibleItemCount"]; + _hasVerticalScroller = [aCoder decodeBoolForKey:@"NSHasVerticalScroller"]; + _usesDataSource = [aCoder decodeBoolForKey:@"NSUsesDataSource"]; + _completes = [aCoder decodeBoolForKey:@"NSCompletes"]; + + if (!_usesDataSource) + _itemList = [aCoder decodeObjectForKey:@"NSPopUpListData"]; + else + _itemList = []; + + // NSButtonBordered key is present only if the value is NO, go figure + _borderedButton = [aCoder containsValueForKey:@"NSButtonBordered"] ? [aCoder decodeBoolForKey:@"NSButtonBordered"] : YES; + } + + return self; +} + +@end