mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-23 07:00:46 +00:00
Key binding patch by Chris Farber <chris@chrisfarber.net>.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@25724 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
f70a4455e6
commit
5966ffcd3f
8 changed files with 881 additions and 10 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
|||
2007-12-11 Fred Kiefer <FredKiefer@gmx.de>
|
||||
|
||||
* Headers/AppKit/NSKeyValueBinding.h,
|
||||
* Source/GSBindingHelpers.h,
|
||||
* Source/NSKeyValueBinding.m: Basic key value binding implementation.
|
||||
* Source/GNUmakefile: Add new source file.
|
||||
* Source/externs.m: Variables for key binding.
|
||||
* Source/NSTextField.m,
|
||||
* Source/NSView.m: Class specific key bindings.
|
||||
Patch by Chris Farber <chris@chrisfarber.net>.
|
||||
|
||||
2007-12-10 Fred Kiefer <FredKiefer@gmx.de>
|
||||
|
||||
* Source/NSColor.m (-numberOfComponents, -getComponents:): Raise
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/** <title>NSKeyValueBinding</title>
|
||||
|
||||
<abstract>Interfae declaration for key value binding</abstract>
|
||||
<abstract>Interface declaration for key value binding</abstract>
|
||||
|
||||
Copyright <copy>(C) 2006 Free Software Foundation, Inc.</copy>
|
||||
|
||||
|
@ -29,9 +29,11 @@
|
|||
#ifndef _GNUstep_H_NSKeyValueBinding
|
||||
#define _GNUstep_H_NSKeyValueBinding
|
||||
|
||||
#import <GNUstepBase/GSVersionMacros.h>
|
||||
#include <Foundation/NSObject.h>
|
||||
#include <AppKit/AppKitDefines.h>
|
||||
|
||||
#if OS_API_VERSION(100300,GS_API_LATEST)
|
||||
#if OS_API_VERSION(MAC_OS_X_VERSION_10_3, GS_API_LATEST)
|
||||
|
||||
@class NSString;
|
||||
@class NSArray;
|
||||
|
@ -49,11 +51,9 @@
|
|||
withKeyPath: (NSString *)keyPath
|
||||
options: (NSDictionary *)options;
|
||||
- (void) unbind: (NSString *)binding;
|
||||
- (void) commitEditingWithDelegate: (id)delegate
|
||||
didCommitSelector: (SEL)didCommitSelector
|
||||
contextInfo: (void *)contextInfo;
|
||||
#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
|
||||
- (NSDictionary *) infoForBinding: (NSString *)binding;
|
||||
|
||||
#endif
|
||||
@end
|
||||
|
||||
@interface NSObject (NSPlaceholder)
|
||||
|
@ -71,6 +71,11 @@
|
|||
|
||||
- (BOOL) commitEditing;
|
||||
- (void) discardEditing;
|
||||
#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
|
||||
- (void) commitEditingWithDelegate: (id)delegate
|
||||
didCommitSelector: (SEL)didCommitSelector
|
||||
contextInfo: (void *)contextInfo;
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
|
@ -85,9 +90,10 @@
|
|||
|
||||
// binding values
|
||||
|
||||
#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
|
||||
// Keys in dictionary returned by infoForBinding
|
||||
APPKIT_EXPORT NSString *NSObservedObjectKey;
|
||||
APPKIT_EXPORT NSString *NSObservedKeyPath;
|
||||
APPKIT_EXPORT NSString *NSObservedKeyPathKey;
|
||||
APPKIT_EXPORT NSString *NSOptionsKey;
|
||||
|
||||
// special markers
|
||||
|
@ -95,6 +101,44 @@ APPKIT_EXPORT id NSMultipleValuesMarker;
|
|||
APPKIT_EXPORT id NSNoSelectionMarker;
|
||||
APPKIT_EXPORT id NSNotApplicableMarker;
|
||||
|
||||
// Binding name constants
|
||||
APPKIT_EXPORT NSString *NSAlignmentBinding;
|
||||
APPKIT_EXPORT NSString *NSEditableBinding;
|
||||
APPKIT_EXPORT NSString *NSEnabledBinding;
|
||||
APPKIT_EXPORT NSString *NSFontBinding;
|
||||
APPKIT_EXPORT NSString *NSHiddenBinding;
|
||||
APPKIT_EXPORT NSString *NSSelectedIndexBinding;
|
||||
APPKIT_EXPORT NSString *NSTextColorBinding;
|
||||
APPKIT_EXPORT NSString *NSToolTipBinding;
|
||||
APPKIT_EXPORT NSString *NSValueBinding;
|
||||
|
||||
//Binding options constants
|
||||
APPKIT_EXPORT NSString *NSAllowsEditingMultipleValuesSelectionBindingOption;
|
||||
APPKIT_EXPORT NSString *NSAllowsNullArgumentBindingOption;
|
||||
APPKIT_EXPORT NSString *NSConditionallySetsEditableBindingOption;
|
||||
APPKIT_EXPORT NSString *NSConditionallySetsEnabledBindingOption;
|
||||
APPKIT_EXPORT NSString *NSConditionallySetsHiddenBindingOption;
|
||||
APPKIT_EXPORT NSString *NSContinuouslyUpdatesValueBindingOption;
|
||||
APPKIT_EXPORT NSString *NSCreatesSortDescriptorBindingOption;
|
||||
APPKIT_EXPORT NSString *NSDeletesObjectsOnRemoveBindingsOption;
|
||||
APPKIT_EXPORT NSString *NSDisplayNameBindingOption;
|
||||
APPKIT_EXPORT NSString *NSDisplayPatternBindingOption;
|
||||
APPKIT_EXPORT NSString *NSHandlesContentAsCompoundValueBindingOption;
|
||||
APPKIT_EXPORT NSString *NSInsertsNullPlaceholderBindingOption;
|
||||
APPKIT_EXPORT NSString *NSInvokesSeparatelyWithArrayObjectsBindingOption;
|
||||
APPKIT_EXPORT NSString *NSMultipleValuesPlaceholderBindingOption;
|
||||
APPKIT_EXPORT NSString *NSNoSelectionPlaceholderBindingOption;
|
||||
APPKIT_EXPORT NSString *NSNotApplicablePlaceholderBindingOption;
|
||||
APPKIT_EXPORT NSString *NSNullPlaceholderBindingOption;
|
||||
APPKIT_EXPORT NSString *NSPredicateFormatBindingOption;
|
||||
APPKIT_EXPORT NSString *NSRaisesForNotApplicableKeysBindingOption;
|
||||
APPKIT_EXPORT NSString *NSSelectorNameBindingOption;
|
||||
APPKIT_EXPORT NSString *NSSelectsAllWhenSettingContentBindingOption;
|
||||
APPKIT_EXPORT NSString *NSValidatesImmediatelyBindingOption;
|
||||
APPKIT_EXPORT NSString *NSValueTransformerNameBindingOption;
|
||||
APPKIT_EXPORT NSString *NSValueTransformerBindingOption;
|
||||
#endif
|
||||
|
||||
#endif // OS_API_VERSION
|
||||
|
||||
#endif // _GNUstep_H_NSKeyValueBinding
|
||||
|
|
|
@ -104,6 +104,7 @@ NSImageView.m \
|
|||
NSInputManager.m \
|
||||
NSInputServer.m \
|
||||
NSInterfaceStyle.m \
|
||||
NSKeyValueBinding.m \
|
||||
NSLayoutManager.m \
|
||||
NSLevelIndicator.m \
|
||||
NSLevelIndicatorCell.m \
|
||||
|
|
77
Source/GSBindingHelpers.h
Normal file
77
Source/GSBindingHelpers.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
/** Private Bindings helper functions for GNUstep
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Chris Farber <chris@chrisfarber.net>
|
||||
Date: 2007
|
||||
|
||||
This file is part of the GNUstep GUI 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 3 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; see the file COPYING.LIB.
|
||||
If not, see <http://www.gnu.org/licenses/> or write to the
|
||||
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef _GS_BINDING_HELPER_H
|
||||
#define _GS_BINDING_HELPER_H
|
||||
|
||||
@class NSString;
|
||||
@class NSDictionary;
|
||||
@class NSMutableDictionary;
|
||||
@class NSArray;
|
||||
|
||||
typedef enum {
|
||||
GSBindingOperationAnd = 0,
|
||||
GSBindingOperationOr
|
||||
} GSBindingOperationKind;
|
||||
|
||||
//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);
|
||||
|
||||
/* 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);
|
||||
|
||||
#endif //_GS_BINDING_HELPER_H
|
513
Source/NSKeyValueBinding.m
Normal file
513
Source/NSKeyValueBinding.m
Normal file
|
@ -0,0 +1,513 @@
|
|||
/** <title>NSKeyValueBinding informal protocol reference</title>
|
||||
|
||||
Implementation of KeyValueBinding for GNUStep
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Chris Farber <chris@chrisfarber.net>
|
||||
Date: 2007
|
||||
|
||||
This file is part of the GNUstep GUI 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 3 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; see the file COPYING.LIB.
|
||||
If not, see <http://www.gnu.org/licenses/> or write to the
|
||||
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <Foundation/NSArray.h>
|
||||
#include <Foundation/NSDictionary.h>
|
||||
#include <Foundation/NSEnumerator.h>
|
||||
#include <Foundation/NSMapTable.h>
|
||||
#include <Foundation/NSLock.h>
|
||||
#include <Foundation/NSKeyValueObserving.h>
|
||||
#include <Foundation/NSKeyValueCoding.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];
|
||||
}
|
||||
|
||||
- (NSArray *) exposedBindings
|
||||
{
|
||||
NSMutableArray *exposedBindings = [NSMutableArray array];
|
||||
NSArray *tmp;
|
||||
Class class = [self class];
|
||||
|
||||
setup();
|
||||
[bindingLock lock];
|
||||
while (class && class != [NSObject class])
|
||||
{
|
||||
tmp = NSMapGet(classTable, (void*)class);
|
||||
if (tmp != nil)
|
||||
{
|
||||
[exposedBindings addObjectsFromArray: tmp];
|
||||
}
|
||||
class = [class superclass];
|
||||
}
|
||||
[bindingLock unlock];
|
||||
|
||||
return exposedBindings;
|
||||
}
|
||||
|
||||
- (Class) valueClassForBinding: (NSString *)binding
|
||||
{
|
||||
return [NSString class];
|
||||
}
|
||||
|
||||
- (void)bind: (NSString *)binding
|
||||
toObject: (id)anObject
|
||||
withKeyPath: (NSString *)keyPath
|
||||
options: (NSDictionary *)options
|
||||
{
|
||||
NSMutableDictionary *bindings;
|
||||
NSDictionary *info;
|
||||
id newValue;
|
||||
|
||||
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];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"No binding exposed on %@ for %@", self, binding);
|
||||
}
|
||||
}
|
||||
|
||||
- (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];
|
||||
}
|
||||
|
||||
- (void) unbind: (NSString *)binding
|
||||
{
|
||||
NSMutableDictionary *bindings;
|
||||
NSDictionary *info;
|
||||
id observedObject;
|
||||
NSString *keyPath;
|
||||
|
||||
setup();
|
||||
[bindingLock lock];
|
||||
bindings = (NSMutableDictionary *)NSMapGet(objectTable, (void *)self);
|
||||
if (bindings != nil)
|
||||
{
|
||||
info = [bindings objectForKey: binding];
|
||||
if (info != nil)
|
||||
{
|
||||
observedObject = [info objectForKey: NSObservedObjectKey];
|
||||
keyPath = [info objectForKey: NSObservedKeyPathKey];
|
||||
[observedObject removeObserver: self forKeyPath: keyPath];
|
||||
[bindings setValue: nil forKey: binding];
|
||||
}
|
||||
}
|
||||
[bindingLock unlock];
|
||||
}
|
||||
|
||||
- (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;
|
||||
|
||||
list = (NSMutableDictionary *) NSMapGet(objectTable, (void *)object);
|
||||
if (list == nil)
|
||||
{
|
||||
list = [NSMutableDictionary dictionary];
|
||||
NSMapInsert(objectTable, (void *)object, (void *)list);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
void GSBindingUnbindAll(id object)
|
||||
{
|
||||
NSEnumerator *enumerator;
|
||||
NSString *binding;
|
||||
NSArray *bindings;
|
||||
|
||||
[bindingLock lock];
|
||||
bindings = [(GSBindingListForObject(object)) allKeys];
|
||||
enumerator = [bindings objectEnumerator];
|
||||
while ((binding = [enumerator nextObject]))
|
||||
{
|
||||
[object unbind: binding];
|
||||
}
|
||||
NSMapRemove(objectTable, (void *)object);
|
||||
[bindingLock unlock];
|
||||
}
|
||||
|
||||
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 GSBindingTransformedValue(id value, NSDictionary *options)
|
||||
{
|
||||
NSString *valueTransformerName;
|
||||
NSValueTransformer *valueTransformer;
|
||||
NSString *placeholder;
|
||||
|
||||
if (value == NSMultipleValuesMarker)
|
||||
{
|
||||
placeholder = [options objectForKey: NSMultipleValuesPlaceholderBindingOption];
|
||||
if (placeholder == nil)
|
||||
{
|
||||
placeholder = @"Multiple Values";
|
||||
}
|
||||
return placeholder;
|
||||
}
|
||||
if (value == NSNoSelectionMarker)
|
||||
{
|
||||
placeholder = [options objectForKey: NSNoSelectionPlaceholderBindingOption];
|
||||
if (placeholder == nil)
|
||||
{
|
||||
placeholder = @"No Selection";
|
||||
}
|
||||
return placeholder;
|
||||
}
|
||||
if (value == NSNotApplicableMarker)
|
||||
{
|
||||
if ([[options objectForKey: NSRaisesForNotApplicableKeysBindingOption]
|
||||
boolValue])
|
||||
{
|
||||
[NSException raise: NSGenericException
|
||||
format: @"This binding does not accept not applicable keys"];
|
||||
}
|
||||
|
||||
placeholder = [options objectForKey:
|
||||
NSNotApplicablePlaceholderBindingOption];
|
||||
if (placeholder == nil)
|
||||
{
|
||||
placeholder = @"Not Applicable";
|
||||
}
|
||||
return placeholder;
|
||||
}
|
||||
if (value == nil)
|
||||
{
|
||||
placeholder = [options objectForKey:
|
||||
NSNullPlaceholderBindingOption];
|
||||
if (placeholder == nil)
|
||||
{
|
||||
placeholder = @"";
|
||||
}
|
||||
return placeholder;
|
||||
}
|
||||
|
||||
valueTransformerName = [options objectForKey:
|
||||
NSValueTransformerNameBindingOption];
|
||||
if (valueTransformerName != nil)
|
||||
{
|
||||
valueTransformer = [NSValueTransformer valueTransformerForName:
|
||||
valueTransformerName];
|
||||
}
|
||||
else
|
||||
{
|
||||
valueTransformer = [options objectForKey:
|
||||
NSValueTransformerBindingOption];
|
||||
}
|
||||
|
||||
if (valueTransformer != nil)
|
||||
{
|
||||
value = [valueTransformer transformedValue: value];
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
id GSBindingReverseTransformedValue(id value, NSDictionary *options)
|
||||
{
|
||||
NSValueTransformer *valueTransformer;
|
||||
NSString *valueTransformerName;
|
||||
|
||||
valueTransformerName = [options objectForKey:
|
||||
NSValueTransformerNameBindingOption];
|
||||
valueTransformer = [NSValueTransformer valueTransformerForName:
|
||||
valueTransformerName];
|
||||
if (valueTransformer && [[valueTransformer class]
|
||||
allowsReverseTransformation])
|
||||
{
|
||||
value = [valueTransformer reverseTransformedValue: value];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
@interface _GSStateMarker : NSObject
|
||||
{
|
||||
NSString * description;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation _GSStateMarker
|
||||
|
||||
- (id) initWithType: (int)type
|
||||
{
|
||||
if (type == 0)
|
||||
{
|
||||
description = @"<MULTIPLE VALUES MARKER>";
|
||||
}
|
||||
else if (type == 1)
|
||||
{
|
||||
description = @"<NO SELECTION MARKER>";
|
||||
}
|
||||
else
|
||||
{
|
||||
description = @"<NOT APPLICABLE MARKER>";
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) valueForKey: (NSString *)key
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) retain { return self; }
|
||||
- (oneway void) release {}
|
||||
|
||||
- (NSString *) description
|
||||
{
|
||||
return description;
|
||||
}
|
||||
|
||||
@end
|
||||
*/
|
|
@ -36,6 +36,7 @@
|
|||
#include <Foundation/NSNotification.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <Foundation/NSValue.h>
|
||||
#include <Foundation/NSKeyValueObserving.h>
|
||||
|
||||
#include "AppKit/NSApplication.h"
|
||||
#include "AppKit/NSCursor.h"
|
||||
|
@ -43,6 +44,9 @@
|
|||
#include "AppKit/NSTextField.h"
|
||||
#include "AppKit/NSTextFieldCell.h"
|
||||
#include "AppKit/NSWindow.h"
|
||||
#include "AppKit/NSKeyValueBinding.h"
|
||||
#include "GSBindingHelpers.h"
|
||||
|
||||
static NSNotificationCenter *nc;
|
||||
|
||||
/*
|
||||
|
@ -63,6 +67,11 @@ static Class textFieldCellClass;
|
|||
textFieldCellClass = [NSTextFieldCell class];
|
||||
usedCellClass = textFieldCellClass;
|
||||
nc = [NSNotificationCenter defaultCenter];
|
||||
|
||||
[self exposeBinding: NSEditableBinding];
|
||||
[self exposeBinding: NSEnabledBinding];
|
||||
[self exposeBinding: NSAlignmentBinding];
|
||||
[self exposeBinding: NSFontBinding];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -731,5 +740,111 @@ static Class textFieldCellClass;
|
|||
return self;
|
||||
}
|
||||
|
||||
//
|
||||
// Bindings
|
||||
//
|
||||
|
||||
/*
|
||||
* Bindings implemented:
|
||||
* alignment, hidden, editable, enabled, font, toolTip
|
||||
*
|
||||
* Bindings left to implement:
|
||||
* other font bindings, value, displayPatternValue1
|
||||
*/
|
||||
|
||||
- (void) bind: (NSString *)binding
|
||||
toObject: (id)object
|
||||
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];
|
||||
}
|
||||
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];
|
||||
}
|
||||
else
|
||||
{
|
||||
[super bind: binding
|
||||
toObject: object
|
||||
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
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#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>
|
||||
|
@ -62,6 +63,7 @@
|
|||
#include "AppKit/NSClipView.h"
|
||||
#include "AppKit/NSFont.h"
|
||||
#include "AppKit/NSGraphics.h"
|
||||
#include "AppKit/NSKeyValueBinding.h"
|
||||
#include "AppKit/NSMenu.h"
|
||||
#include "AppKit/NSPasteboard.h"
|
||||
#include "AppKit/NSPrintInfo.h"
|
||||
|
@ -74,6 +76,7 @@
|
|||
#include "GNUstepGUI/GSDisplayServer.h"
|
||||
#include "GNUstepGUI/GSTrackingRect.h"
|
||||
#include "GSToolTips.h"
|
||||
#include "GSBindingHelpers.h"
|
||||
|
||||
/*
|
||||
* We need a fast array that can store objects without retain/release ...
|
||||
|
@ -431,6 +434,10 @@ GSSetDragTypes(NSView* obj, NSArray *types)
|
|||
rectClass = [GSTrackingRect class];
|
||||
NSDebugLLog(@"NSView", @"Initialize NSView class\n");
|
||||
[self setVersion: 1];
|
||||
|
||||
// expose bindings
|
||||
[self exposeBinding: NSToolTipBinding];
|
||||
[self exposeBinding: NSHiddenBinding];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -504,6 +511,8 @@ GSSetDragTypes(NSView* obj, NSArray *types)
|
|||
NSView *tmp;
|
||||
unsigned count;
|
||||
|
||||
GSBindingUnbindAll(self);
|
||||
|
||||
while ([_sub_views count] > 0)
|
||||
{
|
||||
[[_sub_views lastObject] removeFromSuperviewWithoutNeedingDisplay];
|
||||
|
@ -4718,5 +4727,70 @@ static NSView* findByTag(NSView *view, int aTag, unsigned *level)
|
|||
return YES;
|
||||
}
|
||||
|
||||
- (void) bind: (NSString *)binding
|
||||
toObject: (id)object
|
||||
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];
|
||||
}
|
||||
else
|
||||
{
|
||||
[super bind: binding
|
||||
toObject: object
|
||||
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
|
||||
|
||||
|
|
|
@ -592,9 +592,45 @@ const NSWindowDepth _GSWindowDepths[7] = { 258, 264, 514, 516, 517, 520, 0 };
|
|||
/* End of color functions externs */
|
||||
|
||||
// NSKeyValueBinding
|
||||
NSString *NSObservedObjectKey = @"NSObservedObjectKey";
|
||||
NSString *NSObservedKeyPath = @"NSObservedKeyPath";
|
||||
NSString *NSOptionsKey = @"NSOptionsKey";
|
||||
NSString *NSObservedObjectKey = @"NSObservedObject";
|
||||
NSString *NSObservedKeyPathKey = @"NSObservedKeyPath";
|
||||
NSString *NSOptionsKey = @"NSOptions";
|
||||
|
||||
NSString *NSAllowsEditingMultipleValuesSelectionBindingOption = @"NSAllowsEditingMultipleValuesSelection";
|
||||
NSString *NSAllowsNullArgumentBindingOption = @"NSAllowsNullArgument";
|
||||
NSString *NSConditionallySetsEditableBindingOption = @"NSConditionallySetsEditable";
|
||||
NSString *NSConditionallySetsEnabledBindingOption = @"NSConditionallySetsEnabled";
|
||||
NSString *NSConditionallySetsHiddenBindingOption = @"NSConditionallySetsHidden";
|
||||
NSString *NSContinuouslyUpdatesValueBindingOption = @"NSContinuouslyUpdatesValue";
|
||||
NSString *NSCreatesSortDescriptorBindingOption = @"NSCreatesSortDescriptor";
|
||||
NSString *NSDeletesObjectsOnRemoveBindingsOption = @"NSDeletesObjectsOnRemove";
|
||||
NSString *NSDisplayNameBindingOption = @"NSDisplayName";
|
||||
NSString *NSDisplayPatternBindingOption = @"NSDisplayPattern";
|
||||
NSString *NSHandlesContentAsCompoundValueBindingOption = @"NSHandlesContentAsCompoundValue";
|
||||
NSString *NSInsertsNullPlaceholderBindingOption = @"NSInsertsNullPlaceholder";
|
||||
NSString *NSInvokesSeparatelyWithArrayObjectsBindingOption = @"NSInvokesSeparatelyWithArrayObjects";
|
||||
NSString *NSMultipleValuesPlaceholderBindingOption = @"NSMultipleValuesPlaceholder";
|
||||
NSString *NSNoSelectionPlaceholderBindingOption = @"NSNoSelectionPlaceholder";
|
||||
NSString *NSNotApplicablePlaceholderBindingOption = @"NSNotApplicablePlaceholder";
|
||||
NSString *NSNullPlaceholderBindingOption = @"NSNullPlaceholder";
|
||||
NSString *NSPredicateFormatBindingOption = @"NSPredicateFormat";
|
||||
NSString *NSRaisesForNotApplicableKeysBindingOption = @"NSRaisesForNotApplicableKeys";
|
||||
NSString *NSSelectorNameBindingOption = @"NSSelectorName";
|
||||
NSString *NSSelectsAllWhenSettingContentBindingOption = @"NSSelectsAllWhenSettingContent";
|
||||
NSString *NSValidatesImmediatelyBindingOption = @"NSValidatesImmediately";
|
||||
NSString *NSValueTransformerNameBindingOption = @"NSValueTransformerName";
|
||||
NSString *NSValueTransformerBindingOption = @"NSValueTransformer";
|
||||
|
||||
NSString *NSAlignmentBinding = @"alignment";
|
||||
NSString *NSEditableBinding = @"editable";
|
||||
NSString *NSEnabledBinding = @"enabled";
|
||||
NSString *NSFontBinding = @"font";
|
||||
NSString *NSHiddenBinding = @"hidden";
|
||||
NSString *NSSelectedIndexBinding = @"selectedIndex";
|
||||
NSString *NSTextColorBinding = @"textColor";
|
||||
NSString *NSToolTipBinding = @"toolTip";
|
||||
NSString *NSValueBinding = @"value";
|
||||
|
||||
// FIXME: Need to defined!
|
||||
id NSMultipleValuesMarker = nil;
|
||||
id NSNoSelectionMarker = nil;
|
||||
|
|
Loading…
Reference in a new issue