From 35fb894ecc4ec85d1358648fcb908f4cbf3779fe Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Wed, 28 Aug 2024 17:42:30 -0400 Subject: [PATCH] Update bindings handlng in NSBrowser, NSTextFieldCell --- Source/NSBrowser.m | 214 +++++++++++++++++++++++++++++---------- Source/NSTextFieldCell.m | 4 + 2 files changed, 162 insertions(+), 56 deletions(-) diff --git a/Source/NSBrowser.m b/Source/NSBrowser.m index ccdbd5113d..e79f3911be 100644 --- a/Source/NSBrowser.m +++ b/Source/NSBrowser.m @@ -56,10 +56,13 @@ #import "AppKit/NSColor.h" #import "AppKit/NSFont.h" #import "AppKit/NSGraphics.h" +#import "AppKit/NSKeyValueBinding.h" #import "AppKit/NSMatrix.h" #import "AppKit/NSScroller.h" #import "AppKit/NSScrollView.h" #import "AppKit/NSTableHeaderCell.h" +#import "AppKit/NSTreeController.h" +#import "AppKit/NSTreeNode.h" #import "AppKit/NSEvent.h" #import "AppKit/NSViewController.h" #import "AppKit/NSWindow.h" @@ -2262,62 +2265,73 @@ - (id) delegate - (void) setDelegate: (id)anObject { BOOL flag = NO; + GSKeyValueBinding *theBinding; - /* Default to YES for nil delegate. */ - _passiveDelegate = YES; - _itemBasedDelegate = NO; - - if ([anObject respondsToSelector: - @selector(browser:numberOfChildrenOfItem:)] - && [anObject respondsToSelector: - @selector(browser:child:ofItem:)] - && [anObject respondsToSelector: - @selector(browser:isLeafItem:)]) + theBinding = [GSKeyValueBinding getBinding: NSContentBinding + forObject: self]; + if (theBinding != nil) { _passiveDelegate = NO; _itemBasedDelegate = YES; } else { - if ([anObject respondsToSelector: - @selector(browser:numberOfRowsInColumn:)]) - { - flag = YES; - if (![anObject respondsToSelector: - @selector(browser:willDisplayCell:atRow:column:)]) - [NSException raise: NSBrowserIllegalDelegateException - format: @"(Passive) Delegate does not respond to %s\n", - GSNameFromSelector - (@selector(browser:willDisplayCell:atRow:column:))]; - } + /* Default to YES for nil delegate. */ + _passiveDelegate = YES; + _itemBasedDelegate = NO; if ([anObject respondsToSelector: - @selector(browser:createRowsForColumn:inMatrix:)]) + @selector(browser:numberOfChildrenOfItem:)] + && [anObject respondsToSelector: + @selector(browser:child:ofItem:)] + && [anObject respondsToSelector: + @selector(browser:isLeafItem:)]) { _passiveDelegate = NO; + _itemBasedDelegate = YES; + } + else + { + if ([anObject respondsToSelector: + @selector(browser:numberOfRowsInColumn:)]) + { + flag = YES; + if (![anObject respondsToSelector: + @selector(browser:willDisplayCell:atRow:column:)]) + [NSException raise: NSBrowserIllegalDelegateException + format: @"(Passive) Delegate does not respond to %s\n", + GSNameFromSelector + (@selector(browser:willDisplayCell:atRow:column:))]; + } - /* If flag is already set - then the delegate must respond to both methods. */ - if (flag) + if ([anObject respondsToSelector: + @selector(browser:createRowsForColumn:inMatrix:)]) { - [NSException raise: NSBrowserIllegalDelegateException - format: @"Delegate responds to both %s and %s\n", - GSNameFromSelector - (@selector(browser:numberOfRowsInColumn:)), - GSNameFromSelector - (@selector(browser:createRowsForColumn:inMatrix:))]; + _passiveDelegate = NO; + + /* If flag is already set + then the delegate must respond to both methods. */ + if (flag) + { + [NSException raise: NSBrowserIllegalDelegateException + format: @"Delegate responds to both %s and %s\n", + GSNameFromSelector + (@selector(browser:numberOfRowsInColumn:)), + GSNameFromSelector + (@selector(browser:createRowsForColumn:inMatrix:))]; + } + + flag = YES; } - flag = YES; + if (!flag && anObject) + [NSException raise: NSBrowserIllegalDelegateException + format: @"Delegate does not respond to %s or %s\n", + GSNameFromSelector + (@selector(browser:numberOfRowsInColumn:)), + GSNameFromSelector + (@selector(browser:createRowsForColumn:inMatrix:))]; } - - if (!flag && anObject) - [NSException raise: NSBrowserIllegalDelegateException - format: @"Delegate does not respond to %s or %s\n", - GSNameFromSelector - (@selector(browser:numberOfRowsInColumn:)), - GSNameFromSelector - (@selector(browser:createRowsForColumn:inMatrix:))]; } _browserDelegate = anObject; @@ -2486,6 +2500,10 @@ + (void) initialize } [self _themeDidActivate: nil]; + + // Bindings... + [self exposeBinding: NSContentBinding]; + [self exposeBinding: NSContentValuesBinding]; } } @@ -3299,7 +3317,18 @@ - (id) _itemForColumn: (NSInteger)column if (column == 0) { - item = [_browserDelegate rootItemForBrowser: self]; + GSKeyValueBinding *theBinding; + theBinding = [GSKeyValueBinding getBinding: NSContentBinding + forObject: self]; + + if (theBinding != nil) + { + item = [_browserDelegate rootItemForBrowser: self]; + } + else + { + item = nil; // [NSNull null]; + } } else { @@ -3340,10 +3369,46 @@ - (void) _performLoadOfColumn: (NSInteger)column if (_itemBasedDelegate) { + GSKeyValueBinding *theBinding; + theBinding = [GSKeyValueBinding getBinding: NSContentBinding + forObject: self]; + item = [self _itemForColumn: column]; - // Ask the delegate for the number of rows for a given item... - rows = [_browserDelegate browser: self numberOfChildrenOfItem: item]; + if (theBinding != nil) + { + rows = 0; + if (item == nil) + { + rows = [[item mutableChildNodes] count]; + } + else + { + NSTreeController *tc = [theBinding observedObject]; + NSString *childrenKeyPath = [tc childrenKeyPathForNode: item]; + + if (childrenKeyPath != nil) + { + NSString *countKeyPath = [tc countKeyPathForNode: item]; + NSArray *children = [item valueForKeyPath: childrenKeyPath]; + + if (countKeyPath == nil) + { + rows = [children count]; // get the count directly... + } + else + { + NSNumber *countValue = [item valueForKeyPath: countKeyPath]; + rows = [countValue integerValue]; + } + } + } + } + else + { + // Ask the delegate for the number of rows for a given item... + rows = [_browserDelegate browser: self numberOfChildrenOfItem: item]; + } cols = 1; } else if (_passiveDelegate) @@ -3412,21 +3477,58 @@ - (void) _performLoadOfColumn: (NSInteger)column // Loading is different based upon item/passive/active delegate if (_itemBasedDelegate) { - // Iterate over the children for the item.... - for (i = 0; i < rows; i++) + GSKeyValueBinding *valueBinding; + + valueBinding = [GSKeyValueBinding getBinding: NSContentValuesBinding + forObject: self]; + if (valueBinding != nil) { - id aCell = [matrix cellAtRow: i column: 0]; - if (![aCell isLoaded]) + NSTreeController *tc = [valueBinding observedObject]; + NSString *childrenKeyPath = [tc childrenKeyPathForNode: item]; + + if (childrenKeyPath != nil) { - BOOL leaf = YES; - id val = nil; - - child = [_browserDelegate browser: self child: i ofItem: item]; - leaf = [_browserDelegate browser: self isLeafItem: child]; - val = [_browserDelegate browser: self objectValueForItem: child]; - [aCell setLeaf: leaf]; - [aCell setObjectValue: val]; - [aCell setLoaded: YES]; + NSString *leafKeyPath = [tc leafKeyPathForNode: item]; + NSArray *children = [item valueForKeyPath: childrenKeyPath]; + + // Iterate over the children for the item.... + for (i = 0; i < rows; i++) + { + id aCell = [matrix cellAtRow: i column: 0]; + if (![aCell isLoaded]) + { + BOOL leaf = YES; + id val = nil; + NSNumber *leafBool = [child valueForKeyPath: leafKeyPath]; + + child = [children objectAtIndex: i]; + leaf = [leafBool boolValue]; + val = [child valueForKeyPath: @"value"]; // temporary + [aCell setLeaf: leaf]; + [aCell setObjectValue: val]; + [aCell setLoaded: YES]; + } + } + } + } + else + { + // Iterate over the children for the item.... + for (i = 0; i < rows; i++) + { + id aCell = [matrix cellAtRow: i column: 0]; + if (![aCell isLoaded]) + { + BOOL leaf = YES; + id val = nil; + + child = [_browserDelegate browser: self child: i ofItem: item]; + leaf = [_browserDelegate browser: self isLeafItem: child]; + val = [_browserDelegate browser: self objectValueForItem: child]; + [aCell setLeaf: leaf]; + [aCell setObjectValue: val]; + [aCell setLoaded: YES]; + } } } } diff --git a/Source/NSTextFieldCell.m b/Source/NSTextFieldCell.m index f60b2447e0..63717817e3 100644 --- a/Source/NSTextFieldCell.m +++ b/Source/NSTextFieldCell.m @@ -36,17 +36,21 @@ #import "AppKit/NSEvent.h" #import "AppKit/NSFont.h" #import "AppKit/NSGraphics.h" +#import "AppKit/NSKeyValueBinding.h" #import "AppKit/NSStringDrawing.h" #import "AppKit/NSTextField.h" #import "AppKit/NSTextFieldCell.h" #import "AppKit/NSText.h" +#import "GSBindingHelpers.h" + @implementation NSTextFieldCell + (void) initialize { if (self == [NSTextFieldCell class]) { + [self exposeBinding: NSValueBinding]; [self setVersion: 2]; } }