33 CPUInteger _selectedIndex;
34 CPRectEdge _preferredEdge;
39 return "popup-button";
44 return [CPSet setWithObject:@"objectValue"];
49 return [CPSet setWithObject:@"objectValue"];
54 return [CPSet setWithObject:@"objectValue"];
63 - (id)initWithFrame:(CGRect)aFrame pullsDown:(BOOL)shouldPullDown
82 [
self addObserver:self forKeyPath:@"menu.items" options:options context:nil];
83 [
self addObserver:self forKeyPath:@"_firstItem.changeCount" options:options context:nil];
84 [
self addObserver:self forKeyPath:@"selectedItem.changeCount" options:options context:nil];
90 - (id)initWithFrame:(CGRect)aFrame
105 - (void)setPullsDown:(BOOL)shouldPullDown
108 var changed = [
self setThemeState:CPPopUpButtonStatePullsDown];
115 var items = [[
self menu] itemArray];
117 if ([items count] <= 0)
130 return [
self hasThemeState:CPPopUpButtonStatePullsDown];
140 [[
self menu] addItem:anItem];
149 [[
self menu] addItemWithTitle:aTitle action:NULL keyEquivalent:nil];
156 - (void)addItemsWithTitles:(CPArray)titles
159 count = [titles count];
161 for (; index < count; ++index)
162 [
self addItemWithTitle:titles[index]];
170 - (void)insertItemWithTitle:(
CPString)aTitle atIndex:(
int)anIndex
173 count = [items count];
176 if ([items[count]
title] == aTitle)
179 [[
self menu] insertItemWithTitle:aTitle action:NULL keyEquivalent:nil atIndex:anIndex];
187 [[
self menu] removeAllItems];
205 - (void)removeItemAtIndex:(
int)anIndex
207 [[
self menu] removeItemAtIndex:anIndex];
219 if (indexOfSelectedItem < 0 || indexOfSelectedItem > [
self numberOfItems] - 1)
222 return [[
self menu] itemAtIndex:indexOfSelectedItem];
238 return _selectedIndex;
255 - (void)selectItemAtIndex:(CPUInteger)anIndex
260 - (void)setSelectedIndex:(CPUInteger)anIndex
274 - (void)setObjectValue:(
id)anIndex
278 anIndex = parseInt(+anIndex, 10);
286 _selectedIndex = anIndex;
296 return _selectedIndex;
303 - (void)selectItemWithTag:(
int)aTag
324 return [[
self menu] numberOfItems];
332 return [[
self menu] itemArray];
341 return [[
self menu] itemAtIndex:anIndex];
350 return [[[
self menu] itemAtIndex:anIndex] title];
358 return [[
self itemArray] arrayByApplyingBlock:function(item)
370 var
menu = [
self menu],
371 itemIndex = [menu indexOfItemWithTitle:aTitle];
376 return [menu itemAtIndex:itemIndex];
384 return [[[
self menu] itemArray] lastObject];
394 return [[
self menu] indexOfItem:aMenuItem];
401 - (int)indexOfItemWithTag:(
int)aTag
403 return [[
self menu] indexOfItemWithTag:aTag];
412 return [[
self menu] indexOfItemWithTitle:aTitle];
421 - (int)indexOfItemWithRepresentedObject:(
id)anObject
423 return [[
self menu] indexOfItemWithRepresentedObject:anObject];
433 - (int)indexOfItemWithTarget:(
id)aTarget action:(
SEL)anAction
435 return [[
self menu] indexOfItemWithTarget:aTarget action:anAction];
446 return _preferredEdge;
454 - (void)setPreferredEdge:(CPRectEdge)aRectEdge
456 _preferredEdge = aRectEdge;
466 if ([
self title] === aTitle)
471 var items = [[
self menu] itemArray];
473 if ([items count] <= 0)
478 [items[0] setTitle:aTitle];
519 var items = [[
self menu] itemArray];
521 if ([items count] > 0)
531 - (void)observeValueForKeyPath:(
CPString)aKeyPath ofObject:(
id)anObject change:(
CPDictionary)changes context:(
id)aContext
535 if (!
pullsDown && aKeyPath ===
@"selectedItem.changeCount" ||
536 pullsDown && (aKeyPath ===
@"_firstItem" || aKeyPath ===
@"_firstItem.changeCount"))
540 if (aKeyPath ===
@"menu")
542 aKeyPath =
@"menu.items";
544 [changes
setObject:CPKeyValueChangeSetting
forKey:CPKeyValueChangeKindKey];
545 [changes
setObject:[[
self menu] itemArray]
forKey:CPKeyValueChangeNewKey];
548 if (aKeyPath ===
@"menu.items")
550 var changeKind = [changes
objectForKey:CPKeyValueChangeKindKey],
556 indexes = [changes
objectForKey:CPKeyValueChangeIndexesKey];
558 if ([indexes containsIndex:0] && [
self pullsDown])
559 [
self _firstItemDidChange];
564 indexOfSelectedItem = 0;
569 while ((index = [indexes indexGreaterThanIndex:index]) !==
CPNotFound &&
570 index <= indexOfSelectedItem)
579 var indexes = [changes
objectForKey:CPKeyValueChangeIndexesKey];
581 if (
pullsDown && [indexes containsIndex:0] ||
589 var newItems = [changes
objectForKey:CPKeyValueChangeNewKey];
591 [newItems enumerateObjectsUsingBlock:function(aMenuItem)
593 var action = [aMenuItem
action];
598 if (action === @selector(_popUpItemAction:))
604 [
self _firstItemDidChange];
612 var indexes = [changes
objectForKey:CPKeyValueChangeIndexesKey];
614 if ([
self pullsDown] && [indexes containsIndex:0])
616 [
self _firstItemDidChange];
623 while ((index = [indexes indexGreaterThanIndex:index]) !==
CPNotFound &&
624 index <= originalIndex)
639 while ((index = [indexes indexGreaterThanIndex:index]) !==
CPNotFound &&
657 var
menu = [
self menu];
660 if (
menu._lastCloseEvent === anEvent)
666 minimumWidth = CGRectGetWidth(
bounds);
669 [menu setFont:[
self font]];
673 var positionedItem = nil,
674 location = CGPointMake(0.0, CGRectGetMaxY(
bounds) - 1);
680 standardLeftMargin = [_CPMenuWindow _standardLeftMargin] + [_CPMenuItemStandardView _standardLeftMargin],
681 location = CGPointMake(CGRectGetMinX(contentRect) - standardLeftMargin, 0.0);
683 minimumWidth += standardLeftMargin;
686 [menu _highlightItemAtIndex:CPNotFound];
689 [menu setMinimumWidth:minimumWidth];
692 _popUpMenuPositioningItem:positionedItem
694 topY:CGRectGetMinY(bounds)
695 bottomY:CGRectGetMaxY(bounds)
697 callback:function(aMenu)
701 var highlightedItem = [aMenu highlightedItem];
703 if ([highlightedItem _isSelectable])
729 - (void)_popUpItemAction:(
id)aSender
734 - (void)_firstItemDidChange
736 [
self willChangeValueForKey:@"_firstItem"];
737 [
self didChangeValueForKey:@"_firstItem"];
739 [[
self _firstItem] setHidden:YES];
747 return [[
self menu] itemAtIndex:0];
750 - (void)takeValueFromKeyPath:(
CPString)aKeyPath ofObjects:(CPArray)objects
752 var count = objects.
length,
753 value = [objects[0] valueForKeyPath:aKeyPath];
759 if (value !== [objects[count] valueForKeyPath:aKeyPath])
767 + (Class)_binderClassForBinding:(
CPString)aBinding
777 var capitalizedBinding = aBinding.charAt(0).toUpperCase() + aBinding.substr(1);
779 return [CPClassFromString(@"_CPPopUpButton" + capitalizedBinding + "Binder") class];
782 return [
super _binderClassForBinding:aBinding];
792 - (void)_reverseSetBinding
794 [_CPPopUpButtonSelectionBinder _reverseSetValueFromExclusiveBinderForObject:self];
796 [
super _reverseSetBinding];
800 @implementation _CPPopUpButtonContentBinder :
CPBinder 805 - (CPInteger)_getInsertNullOffset
807 var options = [_info objectForKey:CPOptionsKey];
809 return [options objectForKey:CPInsertsNullPlaceholderBindingOption] ? 1 : 0;
814 var options = [_info objectForKey:CPOptionsKey],
815 placeholder = [options objectForKey:CPNullPlaceholderBindingOption] ||
@"";
817 if (placeholder === [
CPNull null])
823 - (id)transformValue:(CPArray)contentArray withOptions:(
CPDictionary)options
829 - (void)setValue:(CPArray)contentArray forBinding:(
CPString)aBinding
831 [
self _setContent:contentArray];
832 [
self _setContentValuesIfNeeded:contentArray];
835 - (id)valueForBinding:(
CPString)aBinding
837 return [
self _content];
840 - (void)_setContent:(CPArray)aValue
842 var count = [aValue count],
843 options = [_info objectForKey:CPOptionsKey],
844 offset = [
self _getInsertNullOffset],
845 selectedBindingInfo = [_source infoForBinding:CPSelectedObjectBinding],
846 selectedObject = nil;
848 if (selectedBindingInfo)
850 var destination = [selectedBindingInfo objectForKey:CPObservedObjectKey],
851 keyPath = [selectedBindingInfo objectForKey:CPObservedKeyPathKey];
853 selectedObject = [destination valueForKeyPath:keyPath];
858 [_source removeAllItems];
861 [_source addItemWithTitle:[
self _getNullPlaceholder]];
863 for (var i = 0; i < count; i++)
866 itemValue = [aValue objectAtIndex:i];
868 [
self _setValue:itemValue forItem:item withOptions:options];
869 [_source addItem:item];
874 if (itemValue === selectedObject)
876 [_source setSelectedIndex:[_source numberOfItems] - 1];
882 for (var i = 0; i < count; i++)
884 [
self _setValue:[aValue objectAtIndex:i] forItem:[_source itemAtIndex:i + offset] withOptions:options];
889 - (void)_setContentValuesIfNeeded:(CPArray)values
891 var offset = [
self _getInsertNullOffset];
896 [[_source itemAtIndex:0] setTitle:[
self _getNullPlaceholder]];
898 var count = [values count];
900 for (var i = 0; i < count; i++)
901 [[_source itemAtIndex:i + offset] setTitle:[[values objectAtIndex:i]
description]];
907 var value = [
self _transformValue:aValue withOptions:options];
911 - (id)_transformValue:(
id)aValue withOptions:(
CPDictionary)options
913 return [
super transformValue:aValue withOptions:options];
918 return [_source valueForKeyPath:@"itemArray.representedObject"];
922 @implementation _CPPopUpButtonContentValuesBinder : _CPPopUpButtonContentBinder
927 - (void)setValue:(CPArray)aValue forBinding:(
CPString)aBinding
929 [
super _setContent:aValue];
934 if (aValue === [
CPNull null])
937 var value = [
self _transformValue:aValue withOptions:options];
943 return [_source valueForKeyPath:@"itemArray.title"];
947 @implementation _CPPopUpButtonSelectionBinder :
CPBinder 952 - (void)setPlaceholderValue:(
id)aValue withMarker:(
CPString)aMarker forBinding:(
CPString)aBinding
954 [
self setValue:aValue forBinding:aBinding];
957 - (CPInteger)_getInsertNullOffset
961 return [options objectForKey:CPInsertsNullPlaceholderBindingOption] ? 1 : 0;
965 @implementation _CPPopUpButtonSelectedIndexBinder : _CPPopUpButtonSelectionBinder
970 - (void)setValue:(
id)aValue forBinding:(
CPString)aBinding
972 [_source selectItemAtIndex:aValue + [
self _getInsertNullOffset]];
975 - (id)valueForBinding:(
CPString)aBinding
977 return [_source indexOfSelectedItem] - [
self _getInsertNullOffset];
981 @implementation _CPPopUpButtonSelectedObjectBinder : _CPPopUpButtonSelectionBinder
986 - (void)setValue:(
id)aValue forBinding:(
CPString)aBinding
988 var index = [_source indexOfItemWithRepresentedObject:aValue],
989 offset = [
self _getInsertNullOffset];
1008 [_source selectItemAtIndex:index];
1011 - (id)valueForBinding:(
CPString)aBinding
1013 return [[_source selectedItem] representedObject];
1017 @implementation _CPPopUpButtonSelectedTagBinder : _CPPopUpButtonSelectionBinder
1022 - (void)setValue:(
id)aValue forBinding:(
CPString)aBinding
1024 [_source selectItemWithTag:aValue];
1027 - (id)valueForBinding:(
CPString)aBinding
1029 return [[_source selectedItem] tag];
1033 @implementation _CPPopUpButtonSelectedValueBinder : _CPPopUpButtonSelectionBinder
1038 - (void)setValue:(
id)aValue forBinding:(
CPString)aBinding
1040 [_source selectItemWithTitle:aValue];
1043 - (id)valueForBinding:(
CPString)aBinding
1045 return [_source titleOfSelectedItem];
1074 CPLog.warn(
self +
" was encoded with an older version of Cappuccino. Please nib2cib the original nib again or open and re-save in Atlas.");
1076 [
self setMenu:[aCoder decodeObjectForKey:DEPRECATED_CPPopUpButtonMenuKey]];
1077 [
self setObjectValue:[aCoder decodeObjectForKey:DEPRECATED_CPPopUpButtonSelectedIndexKey]];
1082 [
self addObserver:self forKeyPath:@"menu.items" options:options context:nil];
1083 [
self addObserver:self forKeyPath:@"_firstItem.changeCount" options:options context:nil];
1084 [
self addObserver:self forKeyPath:@"selectedItem.changeCount" options:options context:nil];
BOOL setThemeState:(ThemeState aState)
CPDictionary infoForBinding:forObject:(CPString aBinding, [forObject] id anObject)
An object representation of nil.
CPKeyValueChangeReplacement
void setEnabled:(BOOL isEnabled)
void setValue:forThemeAttribute:(id aValue, [forThemeAttribute] CPString aName)
A mutable key-value pair collection.
An immutable string (collection of characters).
id objectForKey:(id aKey)
BOOL sendAction:to:(SEL anAction, [to] id anObject)
CPKeyValueObservingOptionNew
void highlight:(BOOL shouldHighlight)
Defines methods for use when archiving & restoring (enc/decoding).
BOOL unsetThemeState:(ThemeState aState)
void setObject:forKey:(id anObject, [forKey] id aKey)
CPKeyValueObservingOptionOld
FrameUpdater prototype description