From 031e5e7ca3fcbdbf4c48c23dc60d1db1d91c3689 Mon Sep 17 00:00:00 2001 From: daboe01 Date: Sun, 8 Mar 2026 19:52:58 +0100 Subject: [PATCH] fixed: selection issues --- AppKit/CPOutlineView.j | 29 +++++++++++++++-------------- AppKit/CPTreeController.j | 1 - AppKit/CPTreeNode.j | 32 ++++++++++++++++++-------------- Tests/AppKit/CPTreeNodeTest.j | 2 +- 4 files changed, 34 insertions(+), 30 deletions(-) diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index 593da156f..3e8cb34d8 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -1110,7 +1110,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0, var parent = itemInfo.parent; // Check if the parent is the root item because we never return the actual root item - if (parent && itemInfo[[parent UID]] === _rootItemInfo) + if (parent && _itemInfosForItems[[parent UID]] === _rootItemInfo) parent = nil; return parent; @@ -2531,25 +2531,26 @@ var colorForDisclosureTriangle = function(isSelected, isHighlighted) BOOL _isSyncingFromModel; } -- (void)bind +- (id)initWithBinding:(CPString)aBinding name:(CPString)aName to:(id)aDestination keyPath:(CPString)aKeyPath options:(CPDictionary)options from:(id)aSource { - [super bind]; - - [[CPNotificationCenter defaultCenter] + self = [super initWithBinding:aBinding name:aName to:aDestination keyPath:aKeyPath options:options from:aSource]; + + [[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(outlineViewSelectionDidChange:) name:CPOutlineViewSelectionDidChangeNotification - object:_source]; + object:aSource]; } -- (void)unbind ++ (void)unbind:(CPString)aBinding forObject:(id)anObject { - [[CPNotificationCenter defaultCenter] - removeObserver:self - name:CPOutlineViewSelectionDidChangeNotification - object:_source]; - - [super unbind]; + if (aBinding === "selectionIndexPaths") + [[CPNotificationCenter defaultCenter] + removeObserver:self + name:CPOutlineViewSelectionDidChangeNotification + object:anObject]; + + [super unbind:aBinding forObject:anObject]; } - (void)setValueFor:(CPString)aBinding @@ -2606,7 +2607,7 @@ var colorForDisclosureTriangle = function(isSelected, isHighlighted) if (_isSyncingFromModel) return; - // In CPBinder, reverseSetValueFor: takes the name of the property on _source + // In CPBinder, reverseSetValueFor: takes the name of the property on _source // it should fetch the updated value from. Since CPOutlineView has the selectionIndexPaths method: [self reverseSetValueFor:@"selectionIndexPaths"]; } diff --git a/AppKit/CPTreeController.j b/AppKit/CPTreeController.j index 8bee3ef95..2d0e46802 100644 --- a/AppKit/CPTreeController.j +++ b/AppKit/CPTreeController.j @@ -300,7 +300,6 @@ [self willChangeValueForKey:@"selectionIndexPaths"]; _selectionIndexPaths = [newPaths copy]; - var binderClass = [[self class] _binderClassForBinding:@"selectionIndexPaths"]; diff --git a/AppKit/CPTreeNode.j b/AppKit/CPTreeNode.j index a095ca13c..f25c83649 100644 --- a/AppKit/CPTreeNode.j +++ b/AppKit/CPTreeNode.j @@ -54,7 +54,8 @@ // If we have a parent, calculate path based on parent's path + our index if (_parentNode) { - var index = [_childNodes indexOfObjectIdenticalTo:self]; + // Search the parent's child nodes, not our own! + var index = [[_parentNode childNodes] indexOfObjectIdenticalTo:self]; // If the parent is the root (and technically has no path itself in some implementations), // we might get nil. Handle that gracefully. @@ -68,7 +69,7 @@ // If we are the root, we don't have an index path in the context of a tree controller usually, // or we are [] (empty path). Returning nil is acceptable for the absolute root. - return nil; + return nil; } - (BOOL)isLeaf @@ -167,18 +168,21 @@ if (!indexPath || [indexPath length] == 0) return self; - var index = [indexPath indexAtPosition:0], - count = [_childNodes count]; - - if (index >= count) - return nil; - - var child = [_childNodes objectAtIndex:index]; - - if ([indexPath length] == 1) - return child; - - return [child descendantNodeAtIndexPath:[indexPath indexPathByRemovingFirstIndex]]; + var node = self, + length = [indexPath length]; + + for (var i = 0; i < length; i++) + { + var index = [indexPath indexAtPosition:i], + count = [node count]; + + if (index >= count || index < 0) + return nil; + + node = [node objectAtIndex:index]; + } + + return node; } @end diff --git a/Tests/AppKit/CPTreeNodeTest.j b/Tests/AppKit/CPTreeNodeTest.j index 4e40b5f98..a9c8c9c19 100644 --- a/Tests/AppKit/CPTreeNodeTest.j +++ b/Tests/AppKit/CPTreeNodeTest.j @@ -25,7 +25,7 @@ indexPath = [CPIndexPath indexPathWithIndex:1]; - [self assert:undefined equals:[treeNode descendantNodeAtIndexPath:indexPath]]; + [self assert:nil equals:[treeNode descendantNodeAtIndexPath:indexPath]]; } @end