libs-gui/Source/NSDictionaryController.m

438 lines
9.1 KiB
Mathematica
Raw Normal View History

/* 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 <Foundation/NSArray.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSException.h>
#import <Foundation/NSIndexSet.h>
#import <Foundation/NSKeyValueObserving.h>
#import <Foundation/NSPropertyList.h>
#import <Foundation/NSString.h>
#import "AppKit/NSDictionaryController.h"
#import "AppKit/NSKeyValueBinding.h"
2021-10-19 17:07:22 +00:00
#import "GSBindingHelpers.h"
#import "GSFastEnumeration.h"
2023-02-28 05:40:40 +00:00
// Private methods for NSString and NSDictionary...
@interface NSDictionary (GSPrivate_DictionaryToStrings)
- (NSString *) _stringsFromDictionary;
@end
2023-02-28 05:40:40 +00:00
@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
2023-02-28 05:40:40 +00:00
@interface NSString (GSPrivate_StringsToDictionary)
- (NSDictionary *) _dictionaryFromStrings;
@end
2023-02-28 05:40:40 +00:00
@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
2023-02-28 05:40:40 +00:00
@interface NSDictionaryController (GSPrivate_BuildArray)
- (NSArray *) _buildArray: (NSDictionary *)content;
- (NSDictionary *) _rebuildDictionary;
@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)
{
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];
if (![_excludedKeys containsObject: k])
{
[kvp setExplicitlyIncluded: NO];
}
if ([_includedKeys containsObject: k])
{
[kvp setExplicitlyIncluded: YES];
}
else
{
[kvp setExplicitlyIncluded: NO];
}
[result addObject: kvp];
}
END_FOR_IN(allKeys);
return result;
}
- (NSDictionary *) _rebuildDictionary
{
NSMutableDictionary *result = [NSMutableDictionary dictionary];
FOR_IN(NSDictionaryControllerKeyValuePair*, kvp, _content)
{
NSString *k = [kvp key];
NSString *v = [kvp value];
[result setObject: v forKey: k];
}
END_FOR_IN(_content);
return [result copy];
}
@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];
2023-02-28 05:40:40 +00:00
[self setKeys: [NSArray arrayWithObjects: NSContentBinding, NSContentObjectBinding,
NSExcludedKeysBinding, NSIncludedKeysBinding, nil]
triggerChangeNotificationsForDependentKey: @"arrangedObjects"];
}
}
- (void) _setup
{
2023-02-28 05:40:40 +00:00
_contentDictionary = [[NSDictionary alloc] init];
_includedKeys = [[NSArray alloc] init];
_excludedKeys = [[NSArray alloc] init];
_initialKey = @"key";
_initialValue = @"value";
_count = 0;
}
- (instancetype) initWithContent: (id)content
{
self = [super initWithContent: content];
if (self != nil)
{
[self _setup];
}
return self;
}
2023-02-28 05:40:40 +00:00
- (void) dealloc
{
RELEASE(_contentDicrionary);
RELEASE(_includedKeys);
RELEASE(_excludedKeys);
RELEASE(_initialKey);
RELEASE(_initialValue);
[super dealloc];
}
2021-10-16 17:14:14 +00:00
- (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;
2021-10-16 17:14:14 +00:00
}
- (NSString *) initialKey
{
return _initialKey;
2021-10-16 17:14:14 +00:00
}
- (void) setInitialKey: (NSString *)key
{
ASSIGNCOPY(_initialKey, key);
2021-10-16 17:14:14 +00:00
}
- (id) initialValue
{
return _initialValue;
2021-10-16 17:14:14 +00:00
}
- (void) setInitialValue: (id)value
{
ASSIGNCOPY(_initialValue, value);
2021-10-16 17:14:14 +00:00
}
- (NSArray *) includedKeys
{
return _includedKeys;
2021-10-16 17:14:14 +00:00
}
- (void) setIncludedKeys: (NSArray *)includedKeys
{
ASSIGNCOPY(_includedKeys, includedKeys);
2023-02-28 05:40:40 +00:00
[self rearrangeObjects];
2021-10-16 17:14:14 +00:00
}
- (NSArray *) excludedKeys
{
return _excludedKeys;
2021-10-16 17:14:14 +00:00
}
- (void) setExcludedKeys: (NSArray *)excludedKeys
{
ASSIGNCOPY(_excludedKeys, excludedKeys);
2023-02-28 05:40:40 +00:00
[self rearrangeObjects];
2021-10-16 17:14:14 +00:00
}
- (NSDictionary *) localizedKeyDictionary
{
return _localizedKeyDictionary;
2021-10-16 17:14:14 +00:00
}
- (void) setLocalizedKeyDictionary: (NSDictionary *)dict
{
NSString *strings = [dict _stringsFromDictionary];
ASSIGN(_localizedKeyTable, strings);
ASSIGNCOPY(_localizedKeyDictionary, dict);
2023-02-28 05:40:40 +00:00
[self rearrangeObjects];
2021-10-16 17:14:14 +00:00
}
- (NSString *) localizedKeyTable
{
return _localizedKeyTable;
2021-10-16 17:14:14 +00:00
}
- (void) setLocalizedKeyTable: (NSString *)keyTable
{
NSDictionary *dictionary = [keyTable _dictionaryFromStrings];
ASSIGN(_localizedKeyDictionary, dictionary);
ASSIGNCOPY(_localizedKeyTable, keyTable);
2023-02-28 05:40:40 +00:00
[self rearrangeObjects];
2021-10-16 17:14:14 +00:00
}
2023-02-28 05:40:40 +00:00
- (void) setContent: (id)content
{
2023-02-28 05:40:40 +00:00
[super setContent: [self _buildArray: content]];
}
2023-02-28 05:40:40 +00:00
- (NSArray *) arrangeObjects: (NSArray *)obj
2021-10-19 17:07:22 +00:00
{
2023-02-28 05:40:40 +00:00
NSArray *array = [self _buildArray: obj];
NSArray *result = [super arrangeObjects: obj];
return result;
}
- (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])];
return;
}
- (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;
}
/**
* Returns a copy of the key
*/
- (NSString *) key
{
return [_key copy];
}
- (void) setKey: (NSString *)key
{
ASSIGN(_key, key);
}
/**
* Returns a strong reference to the value
*/
- (id) value
{
return [_value copy];
}
- (void) setValue: (id)value
{
ASSIGN(_value, value);
}
- (NSString *) localizedKey
{
return [_localizedKey copy];
}
- (void) setLocalizedKey: (NSString *)localizedKey
{
ASSIGN(_localizedKey, localizedKey);
}
- (BOOL) isExplicitlyIncluded
{
return _explicitlyIncluded;
}
- (void) setExplicitlyIncluded: (BOOL)flag
{
_explicitlyIncluded = flag;
}
@end