diff --git a/AppKit/CPKeyValueBinding.j b/AppKit/CPKeyValueBinding.j index f7ac25126..7b75920ad 100644 --- a/AppKit/CPKeyValueBinding.j +++ b/AppKit/CPKeyValueBinding.j @@ -551,18 +551,32 @@ CPNotApplicableMarker = @"CPNotApplicableMarker"; CPNullMarker = @"CPNullMarker"; // Binding name constants -CPAlignmentBinding = @"alignment"; -CPEditableBinding = @"editable"; -CPEnabledBinding = @"enabled"; -CPFontBinding = @"font"; -CPHiddenBinding = @"hidden"; -CPSelectedIndexBinding = @"selectedIndex"; -CPTextColorBinding = @"textColor"; -CPToolTipBinding = @"toolTip"; -CPValueBinding = @"value"; -CPValueURLBinding = @"valueURL"; -CPValuePathBinding = @"valuePath"; -CPDataBinding = @"data"; +CPAlignmentBinding = @"alignment"; +CPContentArrayBinding = @"contentArray"; +CPContentBinding = @"content"; +CPContentObjectBinding = @"contentObject"; +CPContentObjectsBinding = @"contentObjects"; +CPContentValuesBinding = @"contentValues"; +CPEnabledBinding = @"enabled"; +CPFontBinding = @"font"; +CPFontNameBinding = @"fontName"; +CPFontBoldBinding = @"fontBold"; +CPHiddenBinding = @"hidden"; +CPFilterPredicateBinding = @"filterPredicate"; +CPPredicateBinding = @"predicate"; +CPSelectedIndexBinding = @"selectedIndex"; +CPSelectedLabelBinding = @"selectedLabel"; +CPSelectedObjectBinding = @"selectedObject"; +CPSelectedObjectsBinding = @"selectedObjects"; +CPSelectedTagBinding = @"selectedTag"; +CPSelectedValueBinding = @"selectedValue"; +CPSelectedValuesBinding = @"selectedValues"; +CPSelectionIndexesBinding = @"selectionIndexes"; +CPTitleBinding = @"title"; +CPValueBinding = @"value"; +CPValueURLBinding = @"valueURL"; +CPValuePathBinding = @"valuePath"; +CPDataBinding = @"data"; //Binding options constants CPAllowsEditingMultipleValuesSelectionBindingOption = @"CPAllowsEditingMultipleValuesSelection"; diff --git a/AppKit/CPPopUpButton.j b/AppKit/CPPopUpButton.j index cbc011db0..859231f0e 100644 --- a/AppKit/CPPopUpButton.j +++ b/AppKit/CPPopUpButton.j @@ -22,10 +22,10 @@ @import "CPButton.j" @import "CPGeometry.j" +@import "CPKeyValueBinding.j" @import "CPMenu.j" @import "CPMenuItem.j" - var VISIBLE_MARGIN = 7.0; CPPopUpButtonStatePullsDown = CPThemeState("pulls-down"); @@ -246,22 +246,6 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down"); return _selectedIndex; } -/*! - @ignore -*/ -- (int)_selectedTag -{ - return [[self selectedItem] tag]; -} - -/*! - @ignore -*/ -- (void)_setSelectedTag:(int)aTag -{ - [self selectItemWithTag:aTag]; -} - // Setting the Current Selection /*! Selects the specified menu item. @@ -778,16 +762,146 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down"); - (void)_reverseSetBinding { - var binderClass = [[self class] _binderClassForBinding:CPSelectedIndexBinding], - theBinding = [binderClass getBinding:CPSelectedIndexBinding forObject:self]; - - [theBinding reverseSetValueFor:@"objectValue"]; + [_CPPopUpButtonSelectionBinder reverseSetValueForObject:self]; [super _reverseSetBinding]; } @end +@implementation CPPopUpButton (BindingSupport) + ++ (Class)_binderClassForBinding:(CPString)aBinding +{ + if (aBinding == CPSelectedIndexBinding || + aBinding == CPSelectedObjectBinding || + aBinding == CPSelectedTagBinding || + aBinding == CPSelectedValueBinding) + return [_CPPopUpButtonSelectionBinder class]; + + return [super _binderClassForBinding:aBinding]; +} + +- (CPArray)_contentValues +{ + return [self valueForKeyPath:@"itemArray.title"]; +} + +- (void)_setContentValues:(CPArray)aValue +{ + var count = [aValue count]; + + if (count != [self numberOfItems]) + { + [self removeAllItems]; + for (var i = 0; i < count; i++) + [self addItemWithTitle:[aValue objectAtIndex:i]]; + } + else + { + for (var i = 0; i < count; i++) + [[self itemAtIndex:i] setTitle:[aValue objectAtIndex:i]]; + } + [self synchronizeTitleAndSelectedItem]; +} + +- (CPArray)_content +{ + return [self valueForKeyPath:@"itemArray.representedObject"]; +} + +- (void)_setContent:(CPArray)aValue +{ + var count = [aValue count]; + + if (count != [self numberOfItems]) + { + [self removeAllItems]; + for (var i = 0; i < count; i++) + { + var item = [[CPMenuItem alloc] initWithTitle:@"" action:NULL keyEquivalent:nil]; + [item setRepresentedObject:[aValue objectAtIndex:i]]; + [self addItem:item]; + } + } + else + { + for (var i = 0; i < count; i++) + [[self itemAtIndex:i] setRepresentedObject:[aValue objectAtIndex:i]]; + } + + if (![self infoForBinding:CPContentValuesBinding]) + { + for (var i = 0; i < count; i++) + [[self itemAtIndex:i] setTitle:[[aValue objectAtIndex:i] description]]; + } +} + +@end + +var binderForObject = {}, + selectionBindings = [CPSelectedIndexBinding, CPSelectedObjectBinding, CPSelectedTagBinding, CPSelectedValueBinding]; + +@implementation _CPPopUpButtonSelectionBinder : CPBinder +{ + CPString _selectionBinding @accessors(property=binding); +} + ++ (void)reverseSetValueForObject:(id)aSource +{ + var uid = [aSource UID], + binder = binderForObject[uid]; + + if (binder == nil) + { + var count = selectionBindings.length; + while (count--) + { + var binding = selectionBindings[count]; + binder = [self getBinding:binding forObject:aSource]; + if (binder != nil) + { + binderForObject[uid] = binder; + [binder setBinding:binding]; + break; + } + } + } + + [binder reverseSetValueFor:[binder binding]]; +} + +- (void)setValue:(id)aValue forBinding:(CPString)aBinding +{ + if (aBinding == CPSelectedIndexBinding) + [_source selectItemAtIndex:aValue]; + else if (aBinding == CPSelectedObjectBinding) + [_source selectItemAtIndex:[_source indexOfItemWithRepresentedObject:aValue]]; + else if (aBinding == CPSelectedTagBinding) + [_source selectItemWithTag:aValue]; + else if (aBinding == CPSelectedValueBinding) + [_source selectItemWithTitle:aValue]; +} + +- (void)setPlaceholderValue:(id)aValue withMarker:(CPString)aMarker forBinding:(CPString)aBinding +{ + [self setValue:aValue forBinding:aBinding]; +} + +- (id)valueForBinding:(CPString)aBinding +{ + if (aBinding == CPSelectedIndexBinding) + return [_source indexOfSelectedItem]; + else if (aBinding == CPSelectedObjectBinding) + return [[_source selectedItem] representedObject]; + else if (aBinding == CPSelectedTagBinding) + return [[_source selectedItem] tag]; + else if (aBinding == CPSelectedValueBinding) + return [_source titleOfSelectedItem]; +} + +@end + var DEPRECATED_CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey", DEPRECATED_CPPopUpButtonSelectedIndexKey = @"CPPopUpButtonSelectedIndexKey"; diff --git a/Tests/Manual/CPPopUpButtonBindings/AppController.j b/Tests/Manual/CPPopUpButtonBindings/AppController.j new file mode 100644 index 000000000..74b2e940f --- /dev/null +++ b/Tests/Manual/CPPopUpButtonBindings/AppController.j @@ -0,0 +1,41 @@ +/* + * AppController.j + * CPPopUpButtonBindings + * + * Created by You on December 2, 2010. + * Copyright 2010, Your Company All rights reserved. + */ + +@import + +@implementation AppController : CPObject +{ + @outlet CPWindow mainWindow; + @outlet CPPopUpButton tagPopUp; + + CPArray people @accessors; +} + +- (void)awakeFromCib +{ + var array = []; + [array addObject:[CPDictionary dictionaryWithObjectsAndKeys:@"John",@"name",@"Butcher",@"job",@"john@meat.com",@"email", 2, @"tag"]]; + [array addObject:[CPDictionary dictionaryWithObjectsAndKeys:@"Alberto",@"name",@"Seller",@"job",@"alberto@gmail.com",@"email", 0, @"tag"]]; + [array addObject:[CPDictionary dictionaryWithObjectsAndKeys:@"Barack",@"name",@"President",@"job",@"barack@whitehouse.gov",@"email", 1, @"tag"]]; + + [self setPeople:array]; + +// Setup tags for the second popup + var items = [tagPopUp itemArray]; + [items enumerateObjectsUsingBlock:function(item, idx) + { + [item setTag:idx]; + [item setTitle:([item title] + " Tag:" + idx)]; + }]; + + [mainWindow setFullBridge:YES]; + +} + +@end +