Rewrote KVB to use separate binding class.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@25728 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Fred Kiefer 2007-12-13 01:10:09 +00:00
parent 311bead94e
commit 295b663a75
5 changed files with 488 additions and 428 deletions

View file

@ -1,3 +1,10 @@
2007-12-13 Fred Kiefer <FredKiefer@gmx.de>
* Source/GSBindingHelpers.h,
* Source/NSKeyValueBinding.m: Rewrote KVB to use separate binding class.
* Source/NSTextField.m,
* Source/NSView.m: Use it here.
2007-12-12 Fred Kiefer <FredKiefer@gmx.de>
* Source/NSNibBindingConnector.m (-establishConnection): Swap

View file

@ -27,51 +27,44 @@
#ifndef _GS_BINDING_HELPER_H
#define _GS_BINDING_HELPER_H
#include <Foundation/NSObject.h>
@class NSString;
@class NSDictionary;
@class NSMutableDictionary;
@class NSArray;
typedef enum {
GSBindingOperationAnd = 0,
GSBindingOperationOr
} GSBindingOperationKind;
@interface GSKeyValueBinding : NSObject
{
@public
NSDictionary *info;
id src;
}
//Obtain a lock
void GSBindingLock();
//Releases the lock
void GSBindingReleaseLock();
//Get the mutable list of bindings for an object. You must obtain a lock
//with GSBindingLock() before calling this function and release the lock with
//GSBindingReleaseLock() when done with the dictionary.
NSMutableDictionary *GSBindingListForObject(id object);
//TODO: document
BOOL GSBindingResolveMultipleValueBool(NSString *key, NSDictionary *bindings,
GSBindingOperationKind operationKind);
//TODO: document
void GSBindingInvokeAction(NSString *targetKey, NSString *argumentKey,
NSDictionary *bindings);
NSArray *GSBindingExposeMultipleValueBindings(
NSArray *bindingNames,
NSMutableDictionary *bindingList);
NSArray *GSBindingExposePatternBindings(
NSArray *bindingNames,
NSMutableDictionary *bindingList);
void GSBindingUnbindAll(id object);
+ (void) exposeBinding: (NSString *)binding forClass: (Class)clazz;
+ (NSArray *) exposedBindingsForClass: (Class)clazz;
+ (NSDictionary *) infoForBinding: (NSString *)binding forObject: (id)anObject;
+ (void) unbind: (NSString *)binding forObject: (id)anObject;
+ (void) unbindAllForObject: (id)anObject;
- (id) initWithBinding: (NSString *)binding
withName: (NSString *)name
toObject: (id)dest
withKeyPath: (NSString *)keyPath
options: (NSDictionary *)options
fromObject: (id)source;
- (void) setValueFor: (NSString *)binding;
/* Transforms the value with a value transformer, if specified and available,
* and takes care of any placeholders
*/
id GSBindingTransformedValue(id value, NSDictionary *options);
id GSBindingReverseTransformedValue(id value, NSDictionary *options);
- (id) transformValue: (id)value withOptions: (NSDictionary *)options;
@end
@interface GSKeyValueOrBinding : GSKeyValueBinding
@end
@interface GSKeyValueAndBinding : GSKeyValueBinding
@end
#endif //_GS_BINDING_HELPER_H

View file

@ -29,50 +29,24 @@
#include <Foundation/NSArray.h>
#include <Foundation/NSDictionary.h>
#include <Foundation/NSEnumerator.h>
#include <Foundation/NSMapTable.h>
#include <Foundation/NSLock.h>
#include <Foundation/NSException.h>
#include <Foundation/NSInvocation.h>
#include <Foundation/NSKeyValueObserving.h>
#include <Foundation/NSKeyValueCoding.h>
#include <Foundation/NSLock.h>
#include <Foundation/NSMapTable.h>
#include <Foundation/NSValue.h>
#include <Foundation/NSValueTransformer.h>
#include <Foundation/NSInvocation.h>
#include <Foundation/NSException.h>
#include <GNUstepBase/GSLock.h>
#include "AppKit/NSKeyValueBinding.h"
#include "GSBindingHelpers.h"
static NSRecursiveLock *bindingLock = nil;
static NSMapTable *classTable = NULL; //available bindings
static NSMapTable *objectTable = NULL; //bound bindings
static inline void setup()
{
if (bindingLock == nil)
{
bindingLock = [GSLazyRecursiveLock new];
classTable = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks,
NSOwnedPointerMapValueCallBacks, 128);
objectTable = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks,
NSOwnedPointerMapValueCallBacks, 128);
}
}
@implementation NSObject (NSKeyValueBindingCreation)
+ (void) exposeBinding: (NSString *)binding
{
NSMutableArray *bindings;
setup();
[bindingLock lock];
bindings = (NSMutableArray *)NSMapGet(classTable, (void*)self);
if (bindings == nil)
{
bindings = [NSMutableArray arrayWithCapacity: 15];
NSMapInsert(classTable, (void*)self, (void*)bindings);
}
[bindings addObject: binding];
[bindingLock unlock];
[GSKeyValueBinding exposeBinding: binding forClass: [self class]];
}
- (NSArray *) exposedBindings
@ -81,18 +55,16 @@ static inline void setup()
NSArray *tmp;
Class class = [self class];
setup();
[bindingLock lock];
while (class && class != [NSObject class])
{
tmp = NSMapGet(classTable, (void*)class);
tmp = [GSKeyValueBinding exposedBindingsForClass: class];
if (tmp != nil)
{
[exposedBindings addObjectsFromArray: tmp];
}
class = [class superclass];
}
[bindingLock unlock];
return exposedBindings;
}
@ -107,36 +79,22 @@ static inline void setup()
withKeyPath: (NSString *)keyPath
options: (NSDictionary *)options
{
NSMutableDictionary *bindings;
NSDictionary *info;
id newValue;
if ((anObject == nil)
|| (keyPath == nil))
{
NSLog(@"No object or path for binding on %@ for %@", self, binding);
return;
}
if ([[self exposedBindings] containsObject: binding])
{
[self unbind: binding];
info = [NSDictionary dictionaryWithObjectsAndKeys:
anObject, NSObservedObjectKey,
keyPath, NSObservedKeyPathKey,
options, NSOptionsKey,
nil];
[anObject addObserver: self
forKeyPath: keyPath
options: NSKeyValueObservingOptionNew
context: binding];
[bindingLock lock];
bindings = (NSMutableDictionary *)NSMapGet(objectTable, (void *)self);
if (bindings == nil)
{
bindings = [NSMutableDictionary dictionary];
NSMapInsert(objectTable, (void*)self, (void*)bindings);
}
[bindings setValue: info forKey: binding];
[bindingLock unlock];
newValue = [anObject valueForKeyPath: keyPath];
newValue = GSBindingTransformedValue(newValue, options);
[self setValue: newValue forKey: binding];
[[GSKeyValueBinding alloc] initWithBinding: binding
withName: binding
toObject: anObject
withKeyPath: keyPath
options: options
fromObject: self];
}
else
{
@ -146,181 +104,133 @@ static inline void setup()
- (NSDictionary *) infoForBinding: (NSString *)binding
{
NSMutableDictionary *bindings;
NSDictionary *info;
setup();
[bindingLock lock];
bindings = (NSMutableDictionary *)NSMapGet(objectTable, (void *)self);
if (bindings != nil)
{
info = [bindings objectForKey: binding];
}
[bindingLock unlock];
return [[info copy] autorelease];
return [GSKeyValueBinding infoForBinding: binding forObject: self];
}
- (void) unbind: (NSString *)binding
{
[GSKeyValueBinding unbind: binding forObject: self];
}
@end
static NSRecursiveLock *bindingLock = nil;
static NSMapTable *classTable = NULL; //available bindings
static NSMapTable *objectTable = NULL; //bound bindings
typedef enum {
GSBindingOperationAnd = 0,
GSBindingOperationOr
} GSBindingOperationKind;
//TODO: document
BOOL GSBindingResolveMultipleValueBool(NSString *key, NSDictionary *bindings,
GSBindingOperationKind operationKind);
//TODO: document
void GSBindingInvokeAction(NSString *targetKey, NSString *argumentKey,
NSDictionary *bindings);
NSArray *GSBindingExposeMultipleValueBindings(
NSArray *bindingNames,
NSMutableDictionary *bindingList);
NSArray *GSBindingExposePatternBindings(
NSArray *bindingNames,
NSMutableDictionary *bindingList);
id GSBindingReverseTransformedValue(id value, NSDictionary *options);
@implementation GSKeyValueBinding
+ (void) initialize
{
if (self == [GSKeyValueBinding class])
{
bindingLock = [GSLazyRecursiveLock new];
classTable = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks,
NSOwnedPointerMapValueCallBacks, 128);
objectTable = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks,
NSOwnedPointerMapValueCallBacks, 128);
}
}
+ (void) exposeBinding: (NSString *)binding forClass: (Class)clazz
{
NSMutableArray *bindings;
[bindingLock lock];
bindings = (NSMutableArray *)NSMapGet(classTable, (void*)clazz);
if (bindings == nil)
{
// Need to retain it ourselves
bindings = [[NSMutableArray alloc] initWithCapacity: 5];
NSMapInsert(classTable, (void*)clazz, (void*)bindings);
}
[bindings addObject: binding];
[bindingLock unlock];
}
+ (NSArray *) exposedBindingsForClass: (Class)clazz
{
NSArray *tmp;
if (!classTable)
return nil;
[bindingLock lock];
tmp = NSMapGet(classTable, (void*)clazz);
[bindingLock unlock];
return tmp;
}
+ (NSDictionary *) infoForBinding: (NSString *)binding forObject: (id)anObject
{
NSMutableDictionary *bindings;
GSKeyValueBinding *theBinding;
if (!objectTable)
return nil;
[bindingLock lock];
bindings = (NSMutableDictionary *)NSMapGet(objectTable, (void *)anObject);
if (bindings != nil)
{
theBinding = (GSKeyValueBinding*)[bindings objectForKey: binding];
}
[bindingLock unlock];
return theBinding->info;
}
+ (void) unbind: (NSString *)binding forObject: (id)anObject
{
NSMutableDictionary *bindings;
NSDictionary *info;
id observedObject;
NSString *keyPath;
GSKeyValueBinding *theBinding;
if (!objectTable)
return;
[bindingLock lock];
bindings = (NSMutableDictionary *)NSMapGet(objectTable, (void *)self);
bindings = (NSMutableDictionary *)NSMapGet(objectTable, (void *)anObject);
if (bindings != nil)
{
info = [bindings objectForKey: binding];
if (info != nil)
theBinding = (GSKeyValueBinding*)[bindings objectForKey: binding];
if (theBinding != nil)
{
observedObject = [info objectForKey: NSObservedObjectKey];
keyPath = [info objectForKey: NSObservedKeyPathKey];
[observedObject removeObserver: self forKeyPath: keyPath];
observedObject = [theBinding->info objectForKey: NSObservedObjectKey];
keyPath = [theBinding->info objectForKey: NSObservedKeyPathKey];
[observedObject removeObserver: theBinding forKeyPath: keyPath];
[bindings setValue: nil forKey: binding];
}
}
[bindingLock unlock];
}
// FIXME: This method should not be defined on this class, as it make all
// other value observation impossible. Better add a new GSBinding class
// to handle this. Perhaps with plenty of specific subclasses for the
// different special cases?
- (void) observeValueForKeyPath: (NSString *)keyPath
ofObject: (id)object
change: (NSDictionary *)change
context: (void *)context
{
NSMutableDictionary *bindings;
NSString *binding = (NSString *)context;
setup();
[bindingLock lock];
bindings = (NSMutableDictionary *)NSMapGet(objectTable, (void *)self);
if (bindings != nil)
{
NSDictionary *info;
info = [bindings objectForKey: binding];
if (info != nil)
{
NSDictionary *options;
id newValue;
options = [info objectForKey: NSOptionsKey];
newValue = [change objectForKey: NSKeyValueChangeNewKey];
newValue = GSBindingTransformedValue(newValue, options);
[self setValue: newValue forKey: binding];
}
}
[bindingLock unlock];
}
@end
//Helper functions
BOOL GSBindingResolveMultipleValueBool(NSString *key, NSDictionary *bindings,
GSBindingOperationKind operationKind)
{
NSString *bindingName;
NSDictionary *info;
int count = 1;
id object;
NSString *keyPath;
id value;
NSDictionary *options;
bindingName = key;
while ((info = [bindings objectForKey: bindingName]))
{
object = [info objectForKey: NSObservedObjectKey];
keyPath = [info objectForKey: NSObservedKeyPathKey];
options = [info objectForKey: NSOptionsKey];
value = [object valueForKeyPath: keyPath];
value = GSBindingTransformedValue(value, options);
if ([value boolValue] == operationKind)
{
return operationKind;
}
bindingName = [NSString stringWithFormat: @"%@%i", key, ++count];
}
return !operationKind;
}
void GSBindingInvokeAction(NSString *targetKey, NSString *argumentKey,
NSDictionary *bindings)
{
NSString *bindingName;
NSDictionary *info;
NSDictionary *options;
int count = 1;
id object;
id target;
SEL selector;
NSString *keyPath;
NSInvocation *invocation;
info = [bindings objectForKey: targetKey];
object = [info objectForKey: NSObservedObjectKey];
keyPath = [info objectForKey: NSObservedKeyPathKey];
options = [info objectForKey: NSOptionsKey];
target = [object valueForKeyPath: keyPath];
selector = NSSelectorFromString([options objectForKey:
NSSelectorNameBindingOption]);
if (target == nil || selector == NULL) return;
invocation = [NSInvocation invocationWithMethodSignature:
[target methodSignatureForSelector: selector]];
[invocation setSelector: selector];
bindingName = argumentKey;
while ((info = [bindings objectForKey: bindingName]))
{
object = [info objectForKey: NSObservedObjectKey];
keyPath = [info objectForKey: NSObservedKeyPathKey];
if ((object = [object valueForKeyPath: keyPath]))
{
[invocation setArgument: object atIndex: ++count];
}
bindingName = [NSString stringWithFormat: @"%@%i", argumentKey, count];
}
[invocation invoke];
}
void GSBindingLock()
{
[bindingLock lock];
}
void GSBindingReleaseLock()
{
[bindingLock unlock];
}
NSMutableDictionary *GSBindingListForObject(id object)
{
NSMutableDictionary *list;
if (!objectTable)
return nil;
list = (NSMutableDictionary *)NSMapGet(objectTable, (void *)object);
if (list == nil)
{
list = [NSMutableDictionary dictionary];
NSMapInsert(objectTable, (void *)object, (void *)list);
}
return list;
}
void GSBindingUnbindAll(id object)
+ (void) unbindAllForObject: (id)anObject
{
NSEnumerator *enumerator;
NSString *binding;
@ -330,71 +240,105 @@ void GSBindingUnbindAll(id object)
return;
[bindingLock lock];
list = (NSDictionary *)NSMapGet(objectTable, (void *)object);
list = (NSDictionary *)NSMapGet(objectTable, (void *)anObject);
if (list != nil)
{
enumerator = [list keyEnumerator];
while ((binding = [enumerator nextObject]))
{
[object unbind: binding];
[anObject unbind: binding];
}
NSMapRemove(objectTable, (void *)object);
NSMapRemove(objectTable, (void *)anObject);
RELEASE(list);
}
[bindingLock unlock];
}
- (id) initWithBinding: (NSString *)binding
withName: (NSString *)name
toObject: (id)dest
withKeyPath: (NSString *)keyPath
options: (NSDictionary *)options
fromObject: (id)source
{
NSMutableDictionary *bindings;
NSArray *GSBindingExposeMultipleValueBindings(
NSArray *bindingNames,
NSMutableDictionary *bindingList)
{
NSEnumerator *nameEnum;
NSString *name;
NSString *numberedName;
NSMutableArray *additionalBindings;
int count;
additionalBindings = [NSMutableArray array];
nameEnum = [bindingNames objectEnumerator];
while ((name = [nameEnum nextObject]))
src = source;
if (options == nil)
{
count = 1;
numberedName = name;
while ([bindingList objectForKey: numberedName] != nil)
{
numberedName = [NSString stringWithFormat: @"%@%i", name, ++count];
[additionalBindings addObject: numberedName];
}
info = [[NSDictionary alloc] initWithObjectsAndKeys:
dest, NSObservedObjectKey,
keyPath, NSObservedKeyPathKey,
nil];
}
return additionalBindings;
else
{
info = [[NSDictionary alloc] initWithObjectsAndKeys:
dest, NSObservedObjectKey,
keyPath, NSObservedKeyPathKey,
options, NSOptionsKey,
nil];
}
[dest addObserver: self
forKeyPath: keyPath
options: NSKeyValueObservingOptionNew
context: binding];
[bindingLock lock];
bindings = (NSMutableDictionary *)NSMapGet(objectTable, (void *)source);
if (bindings == nil)
{
bindings = [NSMutableDictionary new];
NSMapInsert(objectTable, (void*)source, (void*)bindings);
}
[bindings setObject: self forKey: name];
[bindingLock unlock];
[self setValueFor: binding];
return self;
}
NSArray *GSBindingExposePatternBindings(
NSArray *bindingNames,
NSMutableDictionary *bindingList)
- (void)dealloc
{
NSEnumerator *nameEnum;
NSString *name;
NSString *numberedName;
NSMutableArray *additionalBindings;
int count;
additionalBindings = [NSMutableArray array];
nameEnum = [bindingNames objectEnumerator];
while ((name = [nameEnum nextObject]))
{
count = 1;
numberedName = [NSString stringWithFormat:@"%@1", name];
while ([bindingList objectForKey: numberedName] != nil)
{
numberedName = [NSString stringWithFormat:@"%@%i", name, ++count];
[additionalBindings addObject: numberedName];
}
}
return additionalBindings;
DESTROY(info);
src = nil;
[super dealloc];
}
id GSBindingTransformedValue(id value, NSDictionary *options)
- (void) setValueFor: (NSString *)binding
{
id newValue;
id dest;
NSString *keyPath;
NSDictionary *options;
dest = [info objectForKey: NSObservedObjectKey];
keyPath = [info objectForKey: NSObservedKeyPathKey];
options = [info objectForKey: NSOptionsKey];
newValue = [dest valueForKeyPath: keyPath];
newValue = [self transformValue: newValue withOptions: options];
[src setValue: newValue forKey: binding];
}
- (void) observeValueForKeyPath: (NSString *)keyPath
ofObject: (id)object
change: (NSDictionary *)change
context: (void *)context
{
NSString *binding = (NSString *)context;
NSDictionary *options;
id newValue;
options = [info objectForKey: NSOptionsKey];
newValue = [change objectForKey: NSKeyValueChangeNewKey];
newValue = [self transformValue: newValue withOptions: options];
[src setValue: newValue forKey: binding];
}
- (id) transformValue: (id)value withOptions: (NSDictionary *)options
{
NSString *valueTransformerName;
NSValueTransformer *valueTransformer;
@ -466,7 +410,225 @@ id GSBindingTransformedValue(id value, NSDictionary *options)
return value;
}
@end
@implementation GSKeyValueOrBinding : GSKeyValueBinding
- (void) setValueFor: (NSString *)binding
{
NSDictionary *bindings;
BOOL res;
if (!objectTable)
return;
[bindingLock lock];
bindings = (NSDictionary *)NSMapGet(objectTable, (void *)src);
if (!bindings)
return;
res = GSBindingResolveMultipleValueBool(binding, bindings,
GSBindingOperationOr);
[bindingLock unlock];
[src setValue: [NSNumber numberWithBool: res] forKey: binding];
}
- (void) observeValueForKeyPath: (NSString *)keyPath
ofObject: (id)object
change: (NSDictionary *)change
context: (void *)context
{
[self setValueFor: (NSString*)context];
}
@end
@implementation GSKeyValueAndBinding : GSKeyValueBinding
- (void) setValueFor: (NSString *)binding
{
NSDictionary *bindings;
BOOL res;
if (!objectTable)
return;
[bindingLock lock];
bindings = (NSDictionary *)NSMapGet(objectTable, (void *)src);
if (!bindings)
return;
res = GSBindingResolveMultipleValueBool(binding, bindings,
GSBindingOperationAnd);
[bindingLock unlock];
[src setValue: [NSNumber numberWithBool: res] forKey: binding];
}
- (void) observeValueForKeyPath: (NSString *)keyPath
ofObject: (id)object
change: (NSDictionary *)change
context: (void *)context
{
[self setValueFor: (NSString*)context];
}
@end
//Helper functions
BOOL GSBindingResolveMultipleValueBool(NSString *key, NSDictionary *bindings,
GSBindingOperationKind operationKind)
{
NSString *bindingName;
NSDictionary *info;
int count = 1;
id object;
NSString *keyPath;
id value;
NSDictionary *options;
GSKeyValueBinding *theBinding;
bindingName = key;
while ((theBinding = [bindings objectForKey: bindingName]))
{
info = theBinding->info;
object = [info objectForKey: NSObservedObjectKey];
keyPath = [info objectForKey: NSObservedKeyPathKey];
options = [info objectForKey: NSOptionsKey];
value = [object valueForKeyPath: keyPath];
value = [theBinding transformValue: value withOptions: options];
if ([value boolValue] == operationKind)
{
return operationKind;
}
bindingName = [NSString stringWithFormat: @"%@%i", key, ++count];
}
return !operationKind;
}
void GSBindingInvokeAction(NSString *targetKey, NSString *argumentKey,
NSDictionary *bindings)
{
NSString *bindingName;
NSDictionary *info;
NSDictionary *options;
int count = 1;
id object;
id target;
SEL selector;
NSString *keyPath;
NSInvocation *invocation;
GSKeyValueBinding *theBinding;
theBinding = [bindings objectForKey: targetKey];
info = theBinding->info;
object = [info objectForKey: NSObservedObjectKey];
keyPath = [info objectForKey: NSObservedKeyPathKey];
options = [info objectForKey: NSOptionsKey];
target = [object valueForKeyPath: keyPath];
selector = NSSelectorFromString([options objectForKey:
NSSelectorNameBindingOption]);
if (target == nil || selector == NULL) return;
invocation = [NSInvocation invocationWithMethodSignature:
[target methodSignatureForSelector: selector]];
[invocation setSelector: selector];
bindingName = argumentKey;
while ((theBinding = [bindings objectForKey: bindingName]))
{
info = theBinding->info;
object = [info objectForKey: NSObservedObjectKey];
keyPath = [info objectForKey: NSObservedKeyPathKey];
if ((object = [object valueForKeyPath: keyPath]))
{
[invocation setArgument: object atIndex: ++count];
}
bindingName = [NSString stringWithFormat: @"%@%i", argumentKey, count];
}
[invocation invoke];
}
void GSBindingLock()
{
[bindingLock lock];
}
void GSBindingReleaseLock()
{
[bindingLock unlock];
}
NSMutableDictionary *GSBindingListForObject(id object)
{
NSMutableDictionary *list;
if (!objectTable)
return nil;
list = (NSMutableDictionary *)NSMapGet(objectTable, (void *)object);
if (list == nil)
{
list = [NSMutableDictionary new];
NSMapInsert(objectTable, (void *)object, (void *)list);
}
return list;
}
NSArray *GSBindingExposeMultipleValueBindings(
NSArray *bindingNames,
NSMutableDictionary *bindingList)
{
NSEnumerator *nameEnum;
NSString *name;
NSString *numberedName;
NSMutableArray *additionalBindings;
int count;
additionalBindings = [NSMutableArray array];
nameEnum = [bindingNames objectEnumerator];
while ((name = [nameEnum nextObject]))
{
count = 1;
numberedName = name;
while ([bindingList objectForKey: numberedName] != nil)
{
numberedName = [NSString stringWithFormat: @"%@%i", name, ++count];
[additionalBindings addObject: numberedName];
}
}
return additionalBindings;
}
NSArray *GSBindingExposePatternBindings(
NSArray *bindingNames,
NSMutableDictionary *bindingList)
{
NSEnumerator *nameEnum;
NSString *name;
NSString *numberedName;
NSMutableArray *additionalBindings;
int count;
additionalBindings = [NSMutableArray array];
nameEnum = [bindingNames objectEnumerator];
while ((name = [nameEnum nextObject]))
{
count = 1;
numberedName = [NSString stringWithFormat:@"%@1", name];
while ([bindingList objectForKey: numberedName] != nil)
{
numberedName = [NSString stringWithFormat:@"%@%i", name, ++count];
[additionalBindings addObject: numberedName];
}
}
return additionalBindings;
}
id GSBindingReverseTransformedValue(id value, NSDictionary *options)
{
NSValueTransformer *valueTransformer;

View file

@ -36,7 +36,6 @@
#include <Foundation/NSNotification.h>
#include <Foundation/NSString.h>
#include <Foundation/NSValue.h>
#include <Foundation/NSKeyValueObserving.h>
#include "AppKit/NSApplication.h"
#include "AppKit/NSCursor.h"
@ -753,98 +752,38 @@ static Class textFieldCellClass;
*/
- (void) bind: (NSString *)binding
toObject: (id)object
toObject: (id)anObject
withKeyPath: (NSString *)keyPath
options: (NSDictionary *)options
{
NSMutableDictionary *bindings;
NSDictionary *info;
BOOL bVal;
if ([binding hasPrefix: NSEditableBinding])
{
[self unbind: binding];
[object addObserver: self
forKeyPath: keyPath
options: 0
context: NSEditableBinding];
info = [NSDictionary dictionaryWithObjectsAndKeys:
object, NSObservedObjectKey,
keyPath, NSObservedKeyPathKey,
options, NSOptionsKey,
nil];
GSBindingLock();
bindings = GSBindingListForObject(self);
[bindings setValue: info forKey: binding];
bVal = GSBindingResolveMultipleValueBool(NSHiddenBinding, bindings,
GSBindingOperationAnd);
GSBindingReleaseLock();
[self setEditable: bVal];
[[GSKeyValueAndBinding alloc] initWithBinding: NSEditableBinding
withName: binding
toObject: anObject
withKeyPath: keyPath
options: options
fromObject: self];
}
else if ([binding hasPrefix: NSEnabledBinding])
{
[object addObserver: self
forKeyPath: keyPath
options: 0
context: NSEnabledBinding];
info = [NSMutableDictionary dictionaryWithObjectsAndKeys:
object, NSObservedObjectKey,
keyPath, NSObservedKeyPathKey,
options, NSOptionsKey,
nil];
[self unbind: binding];
GSBindingLock();
bindings = GSBindingListForObject(self);
[bindings setValue: info forKey: binding];
bVal = GSBindingResolveMultipleValueBool(NSHiddenBinding, bindings,
GSBindingOperationAnd);
GSBindingReleaseLock();
[self setEnabled: bVal];
[[GSKeyValueAndBinding alloc] initWithBinding: NSEnabledBinding
withName: binding
toObject: anObject
withKeyPath: keyPath
options: options
fromObject: self];
}
else
{
[super bind: binding
toObject: object
toObject: anObject
withKeyPath: keyPath
options: options];
}
}
- (void) observeValueForKeyPath: (NSString *)keyPath
ofObject: (id)object
change: (NSDictionary *)change
context: (void *)context
{
BOOL bVal;
NSDictionary *bindings;
if (context == NSEditableBinding)
{
GSBindingLock();
bindings = GSBindingListForObject(self);
bVal = GSBindingResolveMultipleValueBool(NSEditableBinding, bindings,
GSBindingOperationAnd);
GSBindingReleaseLock();
[self setEditable: bVal];
}
else if (context == NSEnabledBinding)
{
GSBindingLock();
bindings = GSBindingListForObject(self);
bVal = GSBindingResolveMultipleValueBool(NSEnabledBinding, bindings,
GSBindingOperationAnd);
GSBindingReleaseLock();
[self setEnabled: bVal];
}
else
{
[super observeValueForKeyPath: keyPath
ofObject: object
change: change
context: context];
}
}
@end

View file

@ -41,7 +41,6 @@
#include <Foundation/NSCalendarDate.h>
#include <Foundation/NSCoder.h>
#include <Foundation/NSKeyedArchiver.h>
#include <Foundation/NSKeyValueObserving.h>
#include <Foundation/NSDictionary.h>
#include <Foundation/NSThread.h>
#include <Foundation/NSLock.h>
@ -511,7 +510,8 @@ GSSetDragTypes(NSView* obj, NSArray *types)
NSView *tmp;
unsigned count;
GSBindingUnbindAll(self);
// Remove all key value bindings for this view.
[GSKeyValueBinding unbindAllForObject: self];
while ([_sub_views count] > 0)
{
@ -4728,69 +4728,28 @@ static NSView* findByTag(NSView *view, int aTag, unsigned *level)
}
- (void) bind: (NSString *)binding
toObject: (id)object
toObject: (id)anObject
withKeyPath: (NSString *)keyPath
options: (NSDictionary *)options
{
NSMutableDictionary *bindings;
NSDictionary *info;
BOOL hidden;
if ([binding hasPrefix: NSHiddenBinding])
{
[self unbind: binding];
[object addObserver: self
forKeyPath: keyPath
options: 0
context: NSHiddenBinding];
info = [NSDictionary dictionaryWithObjectsAndKeys:
object, NSObservedObjectKey,
keyPath, NSObservedKeyPathKey,
options, NSOptionsKey,
nil];
GSBindingLock();
bindings = GSBindingListForObject(self);
[bindings setValue: info forKey: binding];
hidden = GSBindingResolveMultipleValueBool(NSHiddenBinding, bindings,
GSBindingOperationOr);
GSBindingReleaseLock();
[self setHidden: hidden];
[[GSKeyValueOrBinding alloc] initWithBinding: NSHiddenBinding
withName: binding
toObject: anObject
withKeyPath: keyPath
options: options
fromObject: self];
}
else
{
[super bind: binding
toObject: object
toObject: anObject
withKeyPath: keyPath
options: options];
}
}
- (void) observeValueForKeyPath: (NSString *)keyPath
ofObject: (id)object
change: (NSDictionary *)change
context: (void *)context
{
BOOL hidden;
NSDictionary * bindings;
if (context == NSHiddenBinding)
{
GSBindingLock();
bindings = GSBindingListForObject(self);
hidden = GSBindingResolveMultipleValueBool(NSHiddenBinding, bindings,
GSBindingOperationOr);
GSBindingReleaseLock();
[self setHidden: hidden];
}
else
{
[super observeValueForKeyPath: keyPath
ofObject: object
change: change
context: context];
}
}
@end