37 CPUInteger _selectedIndex;
38 CPRectEdge _preferredEdge;
43 return "popup-button";
46 + (
CPSet)keyPathsForValuesAffectingSelectedIndex
51 + (
CPSet)keyPathsForValuesAffectingSelectedTag
56 + (
CPSet)keyPathsForValuesAffectingSelectedItem
67 - (id)initWithFrame:(CGRect)aFrame pullsDown:(BOOL)shouldPullDown
94 - (id)initWithFrame:(CGRect)aFrame
109 - (void)setPullsDown:(BOOL)shouldPullDown
112 var changed = [
self setThemeState:CPPopUpButtonStatePullsDown];
121 if ([items count] <= 0)
163 count = [titles
count];
165 for (; index < count; ++index)
166 [
self addItemWithTitle:titles[index]];
174 - (void)insertItemWithTitle:(
CPString)aTitle atIndex:(
int)anIndex
177 count = [items count];
180 if ([items[count] title] == aTitle)
189 - (void)removeAllItems
209 - (void)removeItemAtIndex:(
int)anIndex
223 if (indexOfSelectedItem < 0 || indexOfSelectedItem > [
self numberOfItems] - 1)
240 - (int)indexOfSelectedItem
242 return _selectedIndex;
259 - (void)selectItemAtIndex:(CPUInteger)anIndex
264 - (void)setSelectedIndex:(CPUInteger)anIndex
269 - (CPUInteger)selectedIndex
278 - (void)setObjectValue:(
int)anIndex
282 anIndex = parseInt(+anIndex, 10);
284 if (indexOfSelectedItem === anIndex)
287 if (indexOfSelectedItem >= 0 && ![
self pullsDown])
290 _selectedIndex = anIndex;
292 if (indexOfSelectedItem >= 0 && ![
self pullsDown])
300 return _selectedIndex;
307 - (void)selectItemWithTag:(
int)aTag
365 count = [items count];
367 for (; index < count; ++index)
368 titles.push([items[index] title]);
410 - (int)indexOfItemWithTag:(
int)aTag
430 - (int)indexOfItemWithRepresentedObject:(
id)anObject
442 - (int)indexOfItemWithTarget:(
id)aTarget action:(
SEL)anAction
444 return [[
self menu] indexOfItemWithTarget:aTarget action:anAction];
453 - (CPRectEdge)preferredEdge
455 return _preferredEdge;
463 - (void)setPreferredEdge:(CPRectEdge)aRectEdge
465 _preferredEdge = aRectEdge;
475 if ([
self title] === aTitle)
478 if ([
self pullsDown])
482 if ([items count] <= 0)
487 [items[0] setTitle:aTitle];
522 - (void)synchronizeTitleAndSelectedItem
526 if ([
self pullsDown])
530 if ([items count] > 0)
540 - (void)observeValueForKeyPath:(
CPString)aKeyPath ofObject:(
id)anObject change:(
CPDictionary)changes context:(
id)aContext
544 if (!pullsDown && aKeyPath ===
@"selectedItem.changeCount" ||
545 pullsDown && (aKeyPath ===
@"_firstItem" || aKeyPath ===
@"_firstItem.changeCount"))
549 if (aKeyPath ===
@"menu")
551 aKeyPath =
@"menu.items";
553 [changes
setObject:CPKeyValueChangeSetting
forKey:CPKeyValueChangeKindKey];
557 if (aKeyPath ===
@"menu.items")
559 var changeKind = [changes
objectForKey:CPKeyValueChangeKindKey],
565 indexes = [changes
objectForKey:CPKeyValueChangeIndexesKey];
567 if ([indexes containsIndex:0] && [
self pullsDown])
568 [
self _firstItemDidChange];
570 if (![
self pullsDown] && [indexes containsIndex:indexOfSelectedItem])
573 indexOfSelectedItem = 0;
578 while ((index = [indexes indexGreaterThanIndex:index]) !==
CPNotFound &&
579 index <= indexOfSelectedItem)
580 --indexOfSelectedItem;
588 var indexes = [changes
objectForKey:CPKeyValueChangeIndexesKey];
590 if (pullsDown && [indexes containsIndex:0] ||
591 !pullsDown && [indexes containsIndex:indexOfSelectedItem])
598 var newItems = [changes
objectForKey:CPKeyValueChangeNewKey];
600 [newItems enumerateObjectsUsingBlock:function(aMenuItem)
602 var action = [aMenuItem
action];
607 if (action === @selector(_popUpItemAction:))
613 [
self _firstItemDidChange];
621 var indexes = [changes
objectForKey:CPKeyValueChangeIndexesKey];
623 if ([
self pullsDown] && [indexes containsIndex:0])
625 [
self _firstItemDidChange];
627 if ([
self numberOfItems] > 1)
632 while ((index = [indexes indexGreaterThanIndex:index]) !==
CPNotFound &&
633 index <= originalIndex)
640 if (indexOfSelectedItem < 0)
648 while ((index = [indexes indexGreaterThanIndex:index]) !==
CPNotFound &&
649 index <= indexOfSelectedItem)
650 ++indexOfSelectedItem;
663 if (![
self isEnabled] || ![
self numberOfItems])
670 minimumWidth = CGRectGetWidth(bounds);
675 if ([
self pullsDown])
677 var positionedItem = nil,
678 location = CGPointMake(0.0, CGRectGetMaxY(bounds));
684 standardLeftMargin = [_CPMenuWindow _standardLeftMargin] + [_CPMenuItemStandardView _standardLeftMargin],
685 location = CGPointMake(CGRectGetMinX(contentRect) - standardLeftMargin, 0.0);
687 minimumWidth += standardLeftMargin;
690 [
menu _highlightItemAtIndex:CPNotFound];
696 _popUpMenuPositioningItem:positionedItem
698 topY:CGRectGetMinY(bounds)
699 bottomY:CGRectGetMaxY(bounds)
701 callback:function(aMenu)
705 var highlightedItem = [aMenu highlightedItem];
707 if ([highlightedItem _isSelectable])
733 - (void)_popUpItemAction:(
id)aSender
735 [
self sendAction:[
self action] to:[
self target]];
738 - (void)_firstItemDidChange
740 [
self willChangeValueForKey:@"_firstItem"];
741 [
self didChangeValueForKey:@"_firstItem"];
743 [[
self _firstItem] setHidden:YES];
748 if ([
self numberOfItems] <= 0)
751 return [[
self menu] itemAtIndex:0];
756 var count = objects.length,
763 if (value !== [objects[count] valueForKeyPath:aKeyPath])
767 - (void)_reverseSetBinding
769 [_CPPopUpButtonSelectionBinder reverseSetValueForObject:self];
771 [
super _reverseSetBinding];
778 + (Class)_binderClassForBinding:(
CPString)aBinding
788 var capitalizedBinding = aBinding.charAt(0).toUpperCase() + aBinding.substr(1);
790 return [CPClassFromString(@"_CPPopUpButton" + capitalizedBinding + "Binder") class];
793 return [
super _binderClassForBinding:aBinding];
797 @implementation _CPPopUpButtonContentBinder :
CPBinder
802 - (CPInteger)_getInsertNullOffset
804 var options = [_info objectForKey:CPOptionsKey];
806 return [options objectForKey:CPInsertsNullPlaceholderBindingOption] ? 1 : 0;
811 var options = [_info objectForKey:CPOptionsKey],
812 placeholder = [options objectForKey:CPNullPlaceholderBindingOption] ||
@"";
814 if (placeholder === [
CPNull null])
828 [
self _setContent:contentArray];
829 [
self _setContentValuesIfNeeded:contentArray];
832 - (void)valueForBinding:(
CPString)aBinding
834 return [
self _content];
837 - (void)_setContent:(
CPArray)aValue
839 var count = [aValue
count],
840 options = [_info objectForKey:CPOptionsKey],
841 offset = [
self _getInsertNullOffset];
843 if (count + offset != [_source numberOfItems])
845 [_source removeAllItems];
848 [_source addItemWithTitle:[
self _getNullPlaceholder]];
850 for (var i = 0; i < count; i++)
853 [
self _setValue:[aValue
objectAtIndex:i] forItem:item withOptions:options];
854 [_source addItem:item];
859 for (var i = 0; i < count; i++)
861 [
self _setValue:[aValue
objectAtIndex:i] forItem:[_source itemAtIndex:i + offset] withOptions:options];
866 - (void)_setContentValuesIfNeeded:(
CPArray)values
868 var offset = [
self _getInsertNullOffset];
873 [[_source itemAtIndex:0] setTitle:[
self _getNullPlaceholder]];
875 var count = [values
count];
877 for (var i = 0; i < count; i++)
878 [[_source itemAtIndex:i + offset] setTitle:[[values objectAtIndex:i] description]];
884 var value = [
self _transformValue:aValue withOptions:options];
888 - (id)_transformValue:(
id)aValue withOptions:(
CPDictionary)options
890 return [
super transformValue:aValue withOptions:options];
895 return [_source valueForKeyPath:@"itemArray.representedObject"];
899 @implementation _CPPopUpButtonContentValuesBinder : _CPPopUpButtonContentBinder
904 - (void)setValue:(
id)aValue forBinding:(
CPString)aBinding
906 [
super _setContent:aValue];
911 if (aValue === [
CPNull null])
914 var value = [
self _transformValue:aValue withOptions:options];
920 return [_source valueForKeyPath:@"itemArray.title"];
927 @implementation _CPPopUpButtonSelectionBinder :
CPBinder
934 self = [
super initWithBinding:aBinding name:aName to:aDestination keyPath:aKeyPath options:options from:aSource];
939 _selectionBinding = aName;
945 + (void)reverseSetValueForObject:(
id)aSource
948 [binder reverseSetValueFor:[binder _selectionBinding]];
951 - (void)setPlaceholderValue:(
id)aValue withMarker:(
CPString)aMarker forBinding:(
CPString)aBinding
953 [
self setValue:aValue forBinding:aBinding];
956 - (CPInteger)_getInsertNullOffset
960 return [options
objectForKey:CPInsertsNullPlaceholderBindingOption] ? 1 : 0;
964 @implementation _CPPopUpButtonSelectedIndexBinder : _CPPopUpButtonSelectionBinder
969 - (void)setValue:(
id)aValue forBinding:(
CPString)aBinding
971 [_source selectItemAtIndex:aValue + [
self _getInsertNullOffset]];
974 - (id)valueForBinding:(
CPString)aBinding
976 return [_source indexOfSelectedItem] - [self _getInsertNullOffset];
980 @implementation _CPPopUpButtonSelectedObjectBinder : _CPPopUpButtonSelectionBinder
985 - (void)setValue:(
id)aValue forBinding:(
CPString)aBinding
987 var index = [_source indexOfItemWithRepresentedObject:aValue],
988 offset = [
self _getInsertNullOffset];
1007 [_source selectItemAtIndex:index];
1010 - (id)valueForBinding:(
CPString)aBinding
1012 return [[_source selectedItem] representedObject];
1016 @implementation _CPPopUpButtonSelectedTagBinder : _CPPopUpButtonSelectionBinder
1021 - (void)setValue:(
id)aValue forBinding:(
CPString)aBinding
1023 [_source selectItemWithTag:aValue];
1026 - (id)valueForBinding:(
CPString)aBinding
1028 return [[_source selectedItem] tag];
1032 @implementation _CPPopUpButtonSelectedValueBinder : _CPPopUpButtonSelectionBinder
1037 - (void)setValue:(
id)aValue forBinding:(
CPString)aBinding
1039 [_source selectItemWithTitle:aValue];
1042 - (id)valueForBinding:(
CPString)aBinding
1044 return [_source titleOfSelectedItem];
1073 CPLog.warn(
self +
" was encoded with an older version of Cappuccino. Please nib2cib the original nib again or open and re-save in Atlas.");
1075 [
self setMenu:[aCoder decodeObjectForKey:DEPRECATED_CPPopUpButtonMenuKey]];
1076 [
self setObjectValue:[aCoder decodeObjectForKey:DEPRECATED_CPPopUpButtonSelectedIndexKey]];