diff --git a/Headers/AppKit/AppKit.h b/Headers/AppKit/AppKit.h index 5bc651ed0..47fb690f4 100644 --- a/Headers/AppKit/AppKit.h +++ b/Headers/AppKit/AppKit.h @@ -167,6 +167,7 @@ #import #import #import +#import #import #import #import diff --git a/Headers/AppKit/NSDictionaryController.h b/Headers/AppKit/NSDictionaryController.h new file mode 100644 index 000000000..cb1b39eac --- /dev/null +++ b/Headers/AppKit/NSDictionaryController.h @@ -0,0 +1,151 @@ +/* Definition of class NSDictionaryController + Copyright (C) 2021 Free Software Foundation, Inc. + + By: Gregory John Casamento + Date: 16-10-2021 + + This file is part of the GNUstep Library. + + 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 USA. +*/ + +#ifndef _NSDictionaryController_h_GNUSTEP_GUI_INCLUDE +#define _NSDictionaryController_h_GNUSTEP_GUI_INCLUDE + +#import + +#if OS_API_VERSION(MAC_OS_X_VERSION_10_11, GS_API_LATEST) + +APPKIT_EXPORT_CLASS +@interface NSDictionaryControllerKeyValuePair : NSObject +{ + NSString *_key; + id _value; + NSString *_localizedKey; + BOOL _explicitlyIncluded; +} + +- (instancetype) init; + +/** + * Returns a copy of the key + */ +- (NSString *) key; +- (void) setKey: (NSString *)key; + +/** + * Returns a strong reference to the value + */ +- (id) value; +- (void) setValue: (id)value; + +/** + * Localized key copy + */ +- (NSString *) localizedKey; +- (void) setLocalizedKey: (NSString *)localizedKey; + +/** + * Is this key value pair included in the underlying dictionary. + */ +- (BOOL) isExplicitlyIncluded; +- (void) setExplicitlyIncluded: (BOOL)flag; + +@end + +#endif + + +#if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST) + +#if defined(__cplusplus) +extern "C" { +#endif + +APPKIT_EXPORT_CLASS +@interface NSDictionaryController : NSArrayController +{ + NSMutableDictionary *_contentDictionary; + NSString *_initialKey; + id _initialValue; + NSArray *_includedKeys; + NSArray *_excludedKeys; + NSDictionary *_localizedKeyDictionary; + NSString *_localizedKeyTable; + NSUInteger _count; +} + +/** + * Returns a new object conforming to the NSDictionaryControllerKeyValuePair + * informal protocol. Overriden from superclass. + */ +- (NSDictionaryControllerKeyValuePair *) newObject; + +/** + * Returns a copy of the initialKey. + */ +- (NSString *) initialKey; +- (void) setInitialKey: (NSString *)initialKey; + +/** + * Returns a strong reference to the initialValue. + */ +- (id) initialValue; +- (void) setInitialValue: (id)value; + +/** + * Returns a copy of the included keys. Included keys are always represented by a + * key value pair whether or not they are included in the underlying dictionary. + */ +- (NSArray *) includedKeys; +- (void) setIncludedKeys: (NSArray *)includedKeys; + +/** + * Returns a copy of the included keys. Included keys are always represented by a + * key value pair whether or not they are included in the underlying dictionary. + */ +- (NSArray *) excludedKeys; +- (void) setExcludedKeys: (NSArray *)excludedKeys; + +/** + * Returns a copy of the localized key dictionary. + */ +- (NSDictionary *) localizedKeyDictionary; + +/** + * Sets the localized key dictionary. + */ +- (void) setLocalizedKeyDictionary: (NSDictionary *)dict; + +/** + * Returns the keyTable which is the dictionary in strings format. + */ +- (NSString *) localizedKeyTable; + +/** + * Sets the localized keyTable in strings format. + */ +- (void) setLocalizedKeyTable: (NSString *)keyTable; + +@end + +#if defined(__cplusplus) +} +#endif + +#endif /* GS_API_MACOSX */ + +#endif /* _NSDictionaryController_h_GNUSTEP_GUI_INCLUDE */ diff --git a/Headers/AppKit/NSKeyValueBinding.h b/Headers/AppKit/NSKeyValueBinding.h index c85852fec..456335724 100644 --- a/Headers/AppKit/NSKeyValueBinding.h +++ b/Headers/AppKit/NSKeyValueBinding.h @@ -107,14 +107,20 @@ APPKIT_EXPORT id NSNotApplicableMarker; APPKIT_EXPORT NSString *NSAlignmentBinding; APPKIT_EXPORT NSString *NSContentArrayBinding; APPKIT_EXPORT NSString *NSContentBinding; +APPKIT_EXPORT NSString *NSContentDictionaryBinding; APPKIT_EXPORT NSString *NSContentObjectBinding; APPKIT_EXPORT NSString *NSContentValuesBinding; APPKIT_EXPORT NSString *NSEditableBinding; APPKIT_EXPORT NSString *NSEnabledBinding; +APPKIT_EXPORT NSString *NSExcludedKeysBinding; APPKIT_EXPORT NSString *NSFontBinding; APPKIT_EXPORT NSString *NSFontNameBinding; APPKIT_EXPORT NSString *NSFontSizeBinding; APPKIT_EXPORT NSString *NSHiddenBinding; +APPKIT_EXPORT NSString *NSIncludedKeysBinding; +APPKIT_EXPORT NSString *NSInitialKeyBinding; +APPKIT_EXPORT NSString *NSInitialValueBinding; +APPKIT_EXPORT NSString *NSLocalizedKeyDictionaryBinding; APPKIT_EXPORT NSString *NSSelectedIndexBinding; APPKIT_EXPORT NSString *NSSelectedObjectBinding; APPKIT_EXPORT NSString *NSSelectedTagBinding; diff --git a/MISSING b/MISSING index d7af49855..7b40e66d5 100644 --- a/MISSING +++ b/MISSING @@ -1,7 +1,6 @@ MISSING HEADERS ( * = difficult, - = quick, + = placeholder, x = won't do ) --- > NSATSTypesetter.h + -> NSDictionaryController.h - > NSDiffableDataSource.h * > NSDraggingItem.h - > NSDraggingSession.h - diff --git a/Source/GNUmakefile b/Source/GNUmakefile index 756de5bc7..ce41a088b 100644 --- a/Source/GNUmakefile +++ b/Source/GNUmakefile @@ -103,6 +103,7 @@ NSDataLinkManager.m \ NSDataLinkPanel.m \ NSDatePicker.m \ NSDatePickerCell.m \ +NSDictionaryController.m \ NSDockTile.m \ NSDocument.m \ NSDocumentController.m \ @@ -435,6 +436,7 @@ NSDataLinkManager.h \ NSDataLinkPanel.h \ NSDatePicker.h \ NSDatePickerCell.h \ +NSDictionaryController.h \ NSDockTile.h \ NSDocument.h \ NSDocumentController.h \ diff --git a/Source/NSArrayController.m b/Source/NSArrayController.m index feec51aca..80e3aaaf4 100644 --- a/Source/NSArrayController.m +++ b/Source/NSArrayController.m @@ -21,8 +21,8 @@ You should have received a copy of the GNU Lesser General Public License along with this library; see the file COPYING.LIB. - If not, see or write to the - Free Software Foundation, 51 Franklin Street, Fifth Floor, + If not, see or write to the + Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @@ -79,7 +79,7 @@ NSArray *result = [_array objectsAtIndexes: indexes]; return AUTORELEASE([[GSObservableArray alloc] - initWithArray: result]); + initWithArray: result]); } - (id) valueForKey: (NSString*)key @@ -93,7 +93,7 @@ // object until this gets fixed. //return AUTORELEASE([[GSObservableArray alloc] return ([[GSObservableArray alloc] - initWithArray: result]); + initWithArray: result]); } return result; @@ -104,7 +104,7 @@ NSArray * result = [_array arrayByAddingObject: anObject]; return AUTORELEASE([[GSObservableArray alloc] - initWithArray: result]); + initWithArray: result]); } - (NSArray*) arrayByAddingObjectsFromArray: (NSArray*)anotherArray @@ -112,7 +112,7 @@ NSArray * result = [_array arrayByAddingObjectsFromArray: anotherArray]; return AUTORELEASE([[GSObservableArray alloc] - initWithArray: result]); + initWithArray: result]); } - (void) addObserver: (NSObject*)anObserver @@ -124,9 +124,9 @@ [self addObserver: anObserver toObjectsAtIndexes: indexes - forKeyPath: aPath - options: options - context: aContext]; + forKeyPath: aPath + options: options + context: aContext]; } - (void) removeObserver: (NSObject*)anObserver forKeyPath: (NSString*)aPath @@ -135,7 +135,7 @@ [self removeObserver: anObserver fromObjectsAtIndexes: indexes - forKeyPath: aPath]; + forKeyPath: aPath]; } @end @@ -147,8 +147,8 @@ if (self == [NSArrayController class]) { [self exposeBinding: NSContentArrayBinding]; - [self setKeys: [NSArray arrayWithObjects: NSContentBinding, NSContentObjectBinding, nil] - triggerChangeNotificationsForDependentKey: @"arrangedObjects"]; + [self setKeys: [NSArray arrayWithObjects: NSContentBinding, NSContentObjectBinding, nil] + triggerChangeNotificationsForDependentKey: @"arrangedObjects"]; } } @@ -188,7 +188,7 @@ { [self rearrangeObjects]; } - else + else { DESTROY(_arranged_objects); } @@ -207,7 +207,7 @@ { [self rearrangeObjects]; } - else + else { DESTROY(_arranged_objects); } @@ -227,7 +227,7 @@ { [self rearrangeObjects]; } - else + else { DESTROY(_arranged_objects); } @@ -243,7 +243,7 @@ { [self rearrangeObjects]; } - else + else { DESTROY(_arranged_objects); } @@ -279,7 +279,7 @@ NSUInteger index = [_arranged_objects indexOfObject: obj]; if (NSNotFound != index) { - [tmp addIndex: index]; + [tmp addIndex: index]; } } END_FOR_IN(enumerator) @@ -307,8 +307,8 @@ - (BOOL) setSelectionIndex: (NSUInteger)idx { - return [self setSelectionIndexes: - [NSIndexSet indexSetWithIndex: idx]]; + return [self setSelectionIndexes: + [NSIndexSet indexSetWithIndex: idx]]; } - (BOOL) setSelectionIndexes: (NSIndexSet*)idx @@ -369,16 +369,16 @@ { NSUInteger cur = [self selectionIndex]; - [self setSelectionIndexes: - [NSIndexSet indexSetWithIndex: cur + 1]]; + [self setSelectionIndexes: + [NSIndexSet indexSetWithIndex: cur + 1]]; } - (void) selectPrevious: (id)sender { NSUInteger cur = [self selectionIndex]; - [self setSelectionIndexes: - [NSIndexSet indexSetWithIndex: cur - 1]]; + [self setSelectionIndexes: + [NSIndexSet indexSetWithIndex: cur - 1]]; } - (NSArray*) selectedObjects @@ -483,7 +483,7 @@ [self willChangeValueForKey: @"arrangedObjects"]; DESTROY(_arranged_objects); _arranged_objects = [[GSObservableArray alloc] - initWithArray: [self arrangeObjects: _content]]; + initWithArray: [self arrangeObjects: _content]]; [self didChangeValueForKey: @"arrangedObjects"]; } @@ -507,14 +507,14 @@ return _filter_predicate; } -- (void) insertObject: (id)obj +- (void) insertObject: (id)obj atArrangedObjectIndex: (NSUInteger)idx { // FIXME [self addObject: obj]; } -- (void) insertObjects: (NSArray*)obj +- (void) insertObjects: (NSArray*)obj atArrangedObjectIndexes: (NSIndexSet*)idx { // FIXME @@ -531,7 +531,7 @@ atArrangedObjectIndexes: (NSIndexSet*)idx [self removeObjects: [_arranged_objects objectsAtIndexes: idx]]; } -- (void) bind: (NSString *)binding +- (void) bind: (NSString *)binding toObject: (id)anObject withKeyPath: (NSString *)keyPath options: (NSDictionary *)options @@ -541,21 +541,21 @@ atArrangedObjectIndexes: (NSIndexSet*)idx GSKeyValueBinding *kvb; [self unbind: binding]; - kvb = [[GSKeyValueBinding alloc] initWithBinding: @"content" - withName: binding - toObject: anObject - withKeyPath: keyPath - options: options - fromObject: self]; + kvb = [[GSKeyValueBinding alloc] initWithBinding: @"content" + withName: binding + toObject: anObject + withKeyPath: keyPath + options: options + fromObject: self]; // The binding will be retained in the binding table RELEASE(kvb); } else { - [super bind: binding - toObject: anObject - withKeyPath: keyPath - options: options]; + [super bind: binding + toObject: anObject + withKeyPath: keyPath + options: options]; } } @@ -572,24 +572,44 @@ atArrangedObjectIndexes: (NSIndexSet*)idx } - (void) encodeWithCoder: (NSCoder *)coder -{ +{ [super encodeWithCoder: coder]; if ([coder allowsKeyedCoding]) { - [coder encodeBool: [self avoidsEmptySelection] forKey: @"NSAvoidsEmptySelection"]; - [coder encodeBool: [self preservesSelection] forKey: @"NSPreservesSelection"]; - [coder encodeBool: [self selectsInsertedObjects] forKey: @"NSSelectsInsertedObjects"]; - [coder encodeBool: [self clearsFilterPredicateOnInsertion] forKey: - @"NSClearsFilterPredicateOnInsertion"]; - [coder encodeBool: [self automaticallyRearrangesObjects] forKey: @"NSAutomaticallyRearrangesObjects"]; + [coder encodeBool: [self avoidsEmptySelection] + forKey: @"NSAvoidsEmptySelection"]; + [coder encodeBool: [self preservesSelection] + forKey: @"NSPreservesSelection"]; + [coder encodeBool: [self selectsInsertedObjects] + forKey: @"NSSelectsInsertedObjects"]; + [coder encodeBool: [self clearsFilterPredicateOnInsertion] + forKey: @"NSClearsFilterPredicateOnInsertion"]; + [coder encodeBool: [self automaticallyRearrangesObjects] + forKey: @"NSAutomaticallyRearrangesObjects"]; } else { + BOOL f; + f = _acflags.avoids_empty_selection; + [coder encodeValueOfObjCType: @encode(BOOL) + at: &f]; + f = _acflags.preserves_selection; + [coder encodeValueOfObjCType: @encode(BOOL) + at: &f]; + f = _acflags.selects_inserted_objects; + [coder encodeValueOfObjCType: @encode(BOOL) + at: &f]; + f = _acflags.clears_filter_predicate_on_insertion; + [coder encodeValueOfObjCType: @encode(BOOL) + at: &f]; + f = _acflags.automatically_rearranges_objects; + [coder encodeValueOfObjCType: @encode(BOOL) + at: &f]; } } - (id) initWithCoder: (NSCoder *)coder -{ +{ if ((self = [super initWithCoder: coder]) == nil) { return nil; @@ -598,36 +618,52 @@ atArrangedObjectIndexes: (NSIndexSet*)idx if ([coder allowsKeyedCoding]) { if ([coder containsValueForKey: @"NSAvoidsEmptySelection"]) - { - [self setAvoidsEmptySelection: - [coder decodeBoolForKey: @"NSAvoidsEmptySelection"]]; - } + { + [self setAvoidsEmptySelection: + [coder decodeBoolForKey: @"NSAvoidsEmptySelection"]]; + } if ([coder containsValueForKey: @"NSPreservesSelection"]) - { - [self setPreservesSelection: - [coder decodeBoolForKey: @"NSPreservesSelection"]]; - } + { + [self setPreservesSelection: + [coder decodeBoolForKey: @"NSPreservesSelection"]]; + } if ([coder containsValueForKey: @"NSSelectsInsertedObjects"]) - { - [self setSelectsInsertedObjects: - [coder decodeBoolForKey: @"NSSelectsInsertedObjects"]]; - } + { + [self setSelectsInsertedObjects: + [coder decodeBoolForKey: @"NSSelectsInsertedObjects"]]; + } if ([coder containsValueForKey: @"NSClearsFilterPredicateOnInsertion"]) - { - [self setClearsFilterPredicateOnInsertion: - [coder decodeBoolForKey: @"NSClearsFilterPredicateOnInsertion"]]; - } + { + [self setClearsFilterPredicateOnInsertion: + [coder decodeBoolForKey: @"NSClearsFilterPredicateOnInsertion"]]; + } if ([coder containsValueForKey: @"NSAutomaticallyRearrangesObjects"]) - { - [self setAutomaticallyRearrangesObjects: - [coder decodeBoolForKey: @"NSAutomaticallyRearrangesObjects"]]; - } + { + [self setAutomaticallyRearrangesObjects: + [coder decodeBoolForKey: @"NSAutomaticallyRearrangesObjects"]]; + } } else { + BOOL f; + [coder decodeValueOfObjCType: @encode(BOOL) + at: &f]; + _acflags.avoids_empty_selection = f; + [coder decodeValueOfObjCType: @encode(BOOL) + at: &f]; + _acflags.preserves_selection = f; + [coder decodeValueOfObjCType: @encode(BOOL) + at: &f]; + _acflags.selects_inserted_objects = f; + [coder decodeValueOfObjCType: @encode(BOOL) + at: &f]; + _acflags.clears_filter_predicate_on_insertion = f; + [coder decodeValueOfObjCType: @encode(BOOL) + at: &f]; + _acflags.automatically_rearranges_objects = f; } - return self; + return self; } @end diff --git a/Source/NSDictionaryController.m b/Source/NSDictionaryController.m new file mode 100644 index 000000000..382922098 --- /dev/null +++ b/Source/NSDictionaryController.m @@ -0,0 +1,477 @@ +/* Implementation of class NSDictionaryController + Copyright (C) 2021 Free Software Foundation, Inc. + + By: Gregory John Casamento + Date: 16-10-2021 + + This file is part of the GNUstep Library. + + 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 USA. +*/ + +#import +#import +#import +#import +#import +#import +#import + +#import "AppKit/NSDictionaryController.h" +#import "AppKit/NSKeyValueBinding.h" + +#import "GSBindingHelpers.h" +#import "GSFastEnumeration.h" + +// Private methods for NSString and NSDictionary... +@interface NSDictionary (GSPrivate_DictionaryToStrings) + +- (NSString *) _stringsFromDictionary; + +@end + +@implementation NSDictionary (GSPrivate_DictionaryToStrings) + +- (NSString *) _stringsFromDictionary +{ + NSEnumerator *en = [self keyEnumerator]; + NSString *k = nil; + NSString *result = @""; + + while ((k = [en nextObject]) != nil) + { + NSString *v = [self objectForKey: k]; + result = [result stringByAppendingString: + [NSString stringWithFormat: @"\"%@\" = \"%@\";\n", k, v]]; + } + + return result; +} + +@end + +@interface NSString (GSPrivate_StringsToDictionary) + +- (NSDictionary *) _dictionaryFromStrings; + +@end + +@implementation NSString (GSPrivate_StringsToDictionary) + +- (NSDictionary *) _dictionaryFromStrings +{ + NSError *error = nil; + NSDictionary *dictionary = + [NSPropertyListSerialization + propertyListWithData: [self dataUsingEncoding: NSUTF8StringEncoding] + options: NSPropertyListImmutable + format: NULL + error: &error]; + if (error != nil) + { + NSLog(@"Error reading strings file: %@", error); + } + + return dictionary; +} + +@end + +@interface NSDictionaryController (GSPrivate_BuildArray) + +- (NSArray *) _buildArray: (NSDictionary *)content; + +@end + +@implementation NSDictionaryController (GSPrivate_BuildArray) + +- (NSArray *) _buildArray: (NSDictionary *)content +{ + NSArray *allKeys = [content keysSortedByValueUsingSelector: @selector(compare:)]; + NSMutableArray *result = [NSMutableArray arrayWithCapacity: [allKeys count]]; + + FOR_IN(id, k, allKeys) + { + if (![_excludedKeys containsObject: k]) + { + NSDictionaryControllerKeyValuePair *kvp = + AUTORELEASE([[NSDictionaryControllerKeyValuePair alloc] init]); + id v = [content objectForKey: k]; + NSString *localizedKey = [_localizedKeyDictionary objectForKey: k]; + + [kvp setLocalizedKey: localizedKey]; + [kvp setKey: k]; + [kvp setValue: v]; + [kvp setExplicitlyIncluded: NO]; + + if ([_includedKeys containsObject: k]) + { + [kvp setExplicitlyIncluded: YES]; + } + + [result addObject: kvp]; + } + } + END_FOR_IN(allKeys); + + return result; +} + +@end + +// NSDictionary class implementation... +@implementation NSDictionaryController + ++ (void) initialize +{ + if (self == [NSDictionaryController class]) + { + [self exposeBinding: NSContentDictionaryBinding]; + [self exposeBinding: NSIncludedKeysBinding]; + [self exposeBinding: NSExcludedKeysBinding]; + [self exposeBinding: NSInitialKeyBinding]; + [self exposeBinding: NSInitialValueBinding]; + [self setKeys: [NSArray arrayWithObjects: NSContentBinding, NSContentObjectBinding, + NSExcludedKeysBinding, NSIncludedKeysBinding, nil] + triggerChangeNotificationsForDependentKey: @"arrangedObjects"]; + } +} + +- (void) _setup +{ + _contentDictionary = [[NSMutableDictionary alloc] init]; + _includedKeys = [[NSArray alloc] init]; + _excludedKeys = [[NSArray alloc] init]; + _initialKey = [[NSString alloc] initWithString: @"key"]; + _initialValue = [[NSString alloc] initWithString: @"value"]; + _count = 0; +} + +- (instancetype) initWithContent: (id)content +{ + self = [super initWithContent: content]; + + if (self != nil) + { + [self _setup]; + } + + return self; +} + +- (void) dealloc +{ + RELEASE(_contentDictionary); + RELEASE(_includedKeys); + RELEASE(_excludedKeys); + RELEASE(_initialKey); + RELEASE(_initialValue); + [super dealloc]; +} + +- (void) addObject: (id)obj +{ + NSString *k = [obj key]; + NSString *v = [obj value]; + + [super addObject: obj]; + [_contentDictionary setObject: v + forKey: k]; + [self rearrangeObjects]; +} + +- (void) addObjects: (NSArray *)array +{ + [super addObjects: array]; + + FOR_IN(NSDictionaryControllerKeyValuePair*, kvp, array) + { + NSString *k = [kvp key]; + id v = [kvp value]; + + [_contentDictionary setObject: v + forKey: k]; + } + END_FOR_IN(array); + [self rearrangeObjects]; +} + +- (void) removeObject: (id)obj +{ + NSString *k = [obj key]; + + [super removeObject: obj]; + [_contentDictionary removeObjectForKey: k]; + [self rearrangeObjects]; +} + +- (void) removeObjects: (NSArray *)array +{ + [super removeObjects: array]; + + FOR_IN(NSDictionaryControllerKeyValuePair*, kvp, array) + { + NSString *k = [kvp key]; + + [_contentDictionary removeObjectForKey: k]; + } + END_FOR_IN(array); + [self rearrangeObjects]; +} + +- (NSDictionaryControllerKeyValuePair *) newObject +{ + NSDictionaryControllerKeyValuePair *kvp = [[NSDictionaryControllerKeyValuePair alloc] init]; + NSString *k = nil; + + if (_count > 0) + { + k = [NSString stringWithFormat: @"%@%lu", _initialKey, _count]; + } + else + { + k = [_initialKey copy]; + } + + [kvp setKey: k]; + [kvp setValue: _initialValue]; + + _count++; + AUTORELEASE(kvp); + + return kvp; +} + +- (void) rearrangeObjects +{ + [self willChangeValueForKey: NSContentBinding]; + DESTROY(_arranged_objects); + _arranged_objects = [[GSObservableArray alloc] + initWithArray: [self arrangeObjects: + [self _buildArray: _contentDictionary]]]; + [self didChangeValueForKey: NSContentBinding]; +} + +- (NSString *) initialKey +{ + return _initialKey; +} + +- (void) setInitialKey: (NSString *)key +{ + ASSIGNCOPY(_initialKey, key); +} + +- (id) initialValue +{ + return _initialValue; +} + +- (void) setInitialValue: (id)value +{ + ASSIGNCOPY(_initialValue, value); +} + +- (NSArray *) includedKeys +{ + return _includedKeys; +} + +- (void) setIncludedKeys: (NSArray *)includedKeys +{ + ASSIGNCOPY(_includedKeys, includedKeys); + [self rearrangeObjects]; +} + +- (NSArray *) excludedKeys +{ + return _excludedKeys; +} + +- (void) setExcludedKeys: (NSArray *)excludedKeys +{ + ASSIGNCOPY(_excludedKeys, excludedKeys); + [self rearrangeObjects]; +} + +- (NSDictionary *) localizedKeyDictionary +{ + return _localizedKeyDictionary; +} + +- (void) setLocalizedKeyDictionary: (NSDictionary *)dict +{ + NSString *strings = [dict _stringsFromDictionary]; + ASSIGN(_localizedKeyTable, strings); + ASSIGNCOPY(_localizedKeyDictionary, dict); + [self rearrangeObjects]; +} + +- (NSString *) localizedKeyTable +{ + return _localizedKeyTable; +} + +- (void) setLocalizedKeyTable: (NSString *)keyTable +{ + NSDictionary *dictionary = [keyTable _dictionaryFromStrings]; + ASSIGN(_localizedKeyDictionary, dictionary); + ASSIGNCOPY(_localizedKeyTable, keyTable); + [self rearrangeObjects]; +} + +- (void) setContent: (id)content +{ + ASSIGN(_contentDictionary, content); + [super setContent: [self _buildArray: content]]; +} + +- (void) observeValueForKeyPath: (NSString*)aPath + ofObject: (id)anObject + change: (NSDictionary*)aChange + context: (void*)aContext +{ + [NSException raise: NSInvalidArgumentException + format: @"-%@ cannot be sent to %@ ..." + @" create an instance overriding this", + NSStringFromSelector(_cmd), NSStringFromClass([self class])]; +} + +- (void) bind: (NSString *)binding + toObject: (id)anObject + withKeyPath: (NSString *)keyPath + options: (NSDictionary *)options +{ + if ([binding isEqual: NSContentDictionaryBinding]) + { + GSKeyValueBinding *kvb; + + [self unbind: binding]; + kvb = [[GSKeyValueBinding alloc] initWithBinding: @"content" + withName: binding + toObject: anObject + withKeyPath: keyPath + options: options + fromObject: self]; + // The binding will be retained in the binding table + RELEASE(kvb); + } + else + { + [super bind: binding + toObject: anObject + withKeyPath: keyPath + options: options]; + } +} + +- (Class) valueClassForBinding: (NSString *)binding +{ + if ([binding isEqual: NSContentDictionaryBinding]) + { + return [NSObject class]; + } + else + { + return nil; + } +} + +- (instancetype) initWithCoder: (NSCoder *)coder +{ + self = [super initWithCoder: coder]; + + if (self != nil) + { + [self _setup]; + } + + return self; +} + +@end + +@implementation NSDictionaryControllerKeyValuePair + +- (instancetype) init +{ + self = [super init]; + if (self != nil) + { + _key = nil; + _value = nil; + _localizedKey = nil; + _explicitlyIncluded = YES; + } + return self; +} + +- (void) dealloc +{ + RELEASE(_key); + RELEASE(_value); + RELEASE(_localizedKey); + + [super dealloc]; +} + +/** + * Returns a copy of the key + */ +- (NSString *) key +{ + return _key; +} + +- (void) setKey: (NSString *)key +{ + ASSIGNCOPY(_key, key); +} + +/** + * Returns a strong reference to the value + */ +- (id) value +{ + return _value; +} + +- (void) setValue: (id)value +{ + ASSIGNCOPY(_value, value); +} + +- (NSString *) localizedKey +{ + return _localizedKey; +} + +- (void) setLocalizedKey: (NSString *)localizedKey +{ + ASSIGNCOPY(_localizedKey, localizedKey); +} + +- (BOOL) isExplicitlyIncluded +{ + return _explicitlyIncluded; +} + +- (void) setExplicitlyIncluded: (BOOL)flag +{ + _explicitlyIncluded = flag; +} + +@end diff --git a/Source/externs.m b/Source/externs.m index b85859774..c4464829f 100644 --- a/Source/externs.m +++ b/Source/externs.m @@ -692,14 +692,20 @@ APPKIT_DECLARE NSString *NSValueTransformerBindingOption = @"NSValueTransformer" APPKIT_DECLARE NSString *NSAlignmentBinding = @"alignment"; APPKIT_DECLARE NSString *NSContentArrayBinding = @"contentArray"; APPKIT_DECLARE NSString *NSContentBinding = @"content"; +APPKIT_DECLARE NSString *NSContentDictionaryBinding = @"contentDictionary"; APPKIT_DECLARE NSString *NSContentObjectBinding = @"contentObject"; APPKIT_DECLARE NSString *NSContentValuesBinding = @"contentValues"; APPKIT_DECLARE NSString *NSEditableBinding = @"editable"; APPKIT_DECLARE NSString *NSEnabledBinding = @"enabled"; +APPKIT_DECLARE NSString *NSExcludedKeysBinding = @"excludedKeys"; APPKIT_DECLARE NSString *NSFontBinding = @"font"; APPKIT_DECLARE NSString *NSFontNameBinding = @"fontName"; APPKIT_DECLARE NSString *NSFontSizeBinding = @"fontSize"; APPKIT_DECLARE NSString *NSHiddenBinding = @"hidden"; +APPKIT_DECLARE NSString *NSIncludedKeysBinding = @"includedKeys"; +APPKIT_DECLARE NSString *NSInitialKeyBinding = @"initialKey"; +APPKIT_DECLARE NSString *NSInitialValueBinding = @"initialValue"; +APPKIT_DECLARE NSString *NSLocalizedKeyDictionaryBinding = @"localizedKeyDictionary"; APPKIT_DECLARE NSString *NSSelectedIndexBinding = @"selectedIndex"; APPKIT_DECLARE NSString *NSSelectedObjectBinding = @"selectedObject"; APPKIT_DECLARE NSString *NSSelectedTagBinding = @"selectedTag";