@@ -72,7 +72,25 @@ - (void)setSelection:(NSSet *)aSet
7272
7373 NSMutableArray *const path = [NSMutableArray array ];
7474 id obj = [aSet anyObject ];
75- while ((obj = [[self dataSource ] thumbnailBrowser: self parentOfItem: obj])) [path insertObject: obj atIndex: 0 ];
75+ while ((obj = [[self dataSource ] thumbnailBrowser: self parentOfItem: obj]))
76+ [path insertObject: obj atIndex: 0 ];
77+
78+ // 2023/09/25 special case: if the selection is a single container
79+ // then the thumbnail view showing the container's contents is removed
80+ // from the array of views displayed, which does not match the
81+ // behavior of clicking on a single container (which displays the
82+ // container's contents in a thumbnail view), so handle this special
83+ // case by appending the container to the path, which will trigger
84+ // the correct display in the following code; the code to restore
85+ // the selection below also needs to handle this special case.
86+ BOOL singleContainerIsSelected = NO ;
87+ if (1 == aSet.count ) {
88+ obj = [aSet anyObject ];
89+ if ([[self dataSource ] thumbnailBrowser: self itemCanHaveChildren: obj]) {
90+ [path insertObject: obj atIndex: 0 ];
91+ singleContainerIsSelected = YES ;
92+ }
93+ }
7694
7795 NSUInteger i = 0 ;
7896 for (; i < [path count ]; i++) {
@@ -89,14 +107,48 @@ - (void)setSelection:(NSSet *)aSet
89107
90108 PGThumbnailView *const lastView = [self viewAtIndex: i];
91109 [self removeColumnsAfterView: lastView];
92- if ([lastView representedObject ] == [path lastObject ]) [lastView setSelection: aSet];
110+ if (singleContainerIsSelected) {
111+ // 2023/09/25 special case: need to set selection in 2nd-last
112+ // thumbnail view instead of the last thumbnail view
113+ NSAssert (i > 0 , @" i" );
114+ [[self viewAtIndex: i-1 ] setSelection: aSet];
115+ } else if ([lastView representedObject ] == [path lastObject ])
116+ [lastView setSelection: aSet];
93117
94118 --_updateCount;
95119 if (!_updateCount) {
96120 [[self window ] makeFirstResponder: [[self views ] lastObject ]];
97121 [[self delegate ] thumbnailBrowser: self numberOfColumnsDidChangeFrom: initialNumberOfColumns];
98122 }
99- if ([self numberOfColumns ] > initialNumberOfColumns) [self scrollToLastColumnAnimate: YES ];
123+ if ([self numberOfColumns ] > initialNumberOfColumns)
124+ [self scrollToLastColumnAnimate: YES ];
125+
126+ // 2023/10/02 bugfix: delegate was not being invoked
127+ [[self delegate ] thumbnailBrowserSelectionDidChange: self ];
128+ }
129+
130+ // 2023/09/24 select all siblings of the currently selected node(s)
131+ // or all children if the selected node is a container
132+ - (void )selectAll {
133+ // if the last thumbnail view has selected nodes
134+ // then select all viewable siblings in that thumbnail view
135+ PGThumbnailView *const lastView = [[self views ] lastObject ];
136+ NSSet *const selection = [lastView selection ];
137+ if ([selection count ]) {
138+ [lastView selectAll: self ];
139+ return ;
140+ }
141+
142+ // if the last thumbnail view has no selection then get its rep-obj
143+ // and select of its direct children (which are viewable)
144+ id const item = [lastView representedObject ];
145+ if (item) {
146+ // if views.count is N then last thumbnail view is at index N-1
147+ // and its rep-obj is displayed in the thumbnail view at index N-2
148+ NSParameterAssert ([[self views ] indexOfObject: lastView] == [[self views ] count ] - 1 );
149+ PGThumbnailView *thumbnailView = [[self views ] objectAtIndex: [[self views ] count ] - 2 ];
150+ [self thumbnailView: thumbnailView selectAllDirectChildrenOf: item];
151+ }
100152}
101153
102154#pragma mark -
@@ -114,7 +166,7 @@ - (void)redisplayItem:(id)item recursively:(BOOL)flag
114166 }
115167}
116168
117- #pragma mark -PGThumbnailBrowser(Private)
169+ #pragma mark - PGThumbnailBrowser(Private)
118170
119171- (void )_addColumnWithItem : (id )item
120172{
@@ -130,7 +182,7 @@ - (void)_addColumnWithItem:(id)item
130182 [self addColumnWithView: thumbnailView];
131183}
132184
133- #pragma mark -PGColumnView
185+ #pragma mark - PGColumnView
134186
135187- (void )insertColumnWithView : (NSView *)aView atIndex : (NSUInteger )index
136188{
@@ -145,7 +197,7 @@ - (void)removeColumnsAfterView:(NSView *)aView
145197 if (!_updateCount) [[self delegate ] thumbnailBrowser: self numberOfColumnsDidChangeFrom: columns];
146198}
147199
148- #pragma mark -NSResponder
200+ #pragma mark - NSResponder
149201
150202- (IBAction )moveLeft : (id )sender
151203{
@@ -164,14 +216,15 @@ - (IBAction)moveRight:(id)sender
164216 if ([items count ] && ![[view selection ] count ]) [view selectItem: [items objectAtIndex: 0 ] byExtendingSelection: NO ];
165217}
166218
167- #pragma mark -<PGThumbnailViewDelegate>
219+ #pragma mark - <PGThumbnailViewDelegate>
168220
169221- (void )thumbnailViewSelectionDidChange : (PGThumbnailView *)sender
170222{
171223 if (_updateCount) return ;
172224 NSSet *const newSelection = [sender selection ];
173225 id const selectedItem = [newSelection anyObject ];
174- if ([newSelection count ] != 1 || (dataSource && ![dataSource thumbnailBrowser: self itemCanHaveChildren: selectedItem])) {
226+ if ([newSelection count ] != 1 ||
227+ (dataSource && ![dataSource thumbnailBrowser: self itemCanHaveChildren: selectedItem])) {
175228 [self removeColumnsAfterView: sender];
176229 [[self delegate ] thumbnailBrowserSelectionDidChange: self ];
177230 return ;
@@ -186,13 +239,29 @@ - (void)thumbnailViewSelectionDidChange:(PGThumbnailView *)sender
186239 [nextView setRepresentedObject: selectedItem];
187240 [nextView reloadData ];
188241 [self scrollToTopOfColumnWithView: nextView];
189- } else [self _addColumnWithItem: selectedItem];
242+ } else
243+ [self _addColumnWithItem: selectedItem];
190244 [self scrollToLastColumnAnimate: YES ];
191245 [[self delegate ] thumbnailBrowserSelectionDidChange: self ];
192246}
193247
248+ - (void )thumbnailView : (PGThumbnailView *)sender selectAllDirectChildrenOf : (id )item {
249+ // 2023/09/18 implements selecting all of a container's children when option-clicked
250+ NSParameterAssert (dataSource && [dataSource thumbnailBrowser: self itemCanHaveChildren: item]);
251+
252+ NSArray *const views = [self views ];
253+ NSUInteger const col = [views indexOfObjectIdenticalTo: sender];
254+ NSParameterAssert (NSNotFound != col);
255+ NSParameterAssert (col + 1 < [views count ]);
256+ PGThumbnailView *const nextView = [views objectAtIndex: col + 1 ];
257+ NSParameterAssert (nextView);
258+ NSParameterAssert ([nextView representedObject ] == item);
259+ [nextView selectAll: nil ];
260+ }
261+
194262@end
195263
264+ #pragma mark -
196265@implementation NSObject (PGThumbnailBrowserDataSource)
197266
198267- (id )thumbnailBrowser : (PGThumbnailBrowser *)sender parentOfItem : (id )item
0 commit comments