Skip to content

Commit 4c1908d

Browse files
committed
improved thumbnail display
1 parent 5b5c854 commit 4c1908d

File tree

4 files changed

+828
-196
lines changed

4 files changed

+828
-196
lines changed

Views/PGThumbnailBrowser.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
4646

4747
- (void)redisplayItem:(id)item recursively:(BOOL)flag;
4848

49+
- (void)selectAll;
50+
4951
@end
5052

53+
#pragma mark -
54+
5155
@protocol PGThumbnailBrowserDataSource <NSObject>
5256

5357
@optional
@@ -56,6 +60,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
5660

5761
@end
5862

63+
#pragma mark -
64+
5965
@protocol PGThumbnailBrowserDelegate <NSObject>
6066

6167
@optional

Views/PGThumbnailBrowser.m

Lines changed: 78 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Views/PGThumbnailView.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
5252
- (void)deselectItem:(id)item;
5353
- (void)toggleSelectionOfItem:(id)item;
5454
- (void)moveUp:(BOOL)up byExtendingSelection:(BOOL)ext;
55+
//- (void)selectAll; // 2023/09/18
5556

5657
- (NSUInteger)indexOfItemAtPoint:(NSPoint)p;
5758
- (NSRect)frameOfItemAtIndex:(NSUInteger)index withMargin:(BOOL)flag;
@@ -71,6 +72,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
7172
- (NSArray *)itemsForThumbnailView:(PGThumbnailView *)sender;
7273
- (NSImage *)thumbnailView:(PGThumbnailView *)sender thumbnailForItem:(id)item;
7374
- (BOOL)thumbnailView:(PGThumbnailView *)sender canSelectItem:(id)item;
75+
- (BOOL)thumbnailView:(PGThumbnailView *)sender isContainerItem:(id)item;
76+
- (NSURL *)thumbnailView:(PGThumbnailView *)sender urlForItem:(id)item; // 2023/10/14
7477
- (NSString *)thumbnailView:(PGThumbnailView *)sender labelForItem:(id)item;
7578
- (NSColor *)thumbnailView:(PGThumbnailView *)sender labelColorForItem:(id)item;
7679
- (NSRect)thumbnailView:(PGThumbnailView *)sender highlightRectForItem:(id)item; // A rect within {{0, 0}, {1, 1}}.
@@ -82,11 +85,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
8285
// upper half is folder count; lower half is image count
8386
//- (NSUInteger)thumbnailView:(PGThumbnailView *)sender folderAndImageDirectChildrenCountForItem:(id)item;
8487
- (uint64_t)thumbnailView:(PGThumbnailView *)sender byteSizeAndFolderAndImageCountOfDirectChildrenForItem:(id)item;
88+
- (uint64_t)thumbnailView:(PGThumbnailView *)sender byteSizeOfAllChildrenForItem:(id)item;
89+
- (uint64_t)thumbnailView:(PGThumbnailView *)sender byteSizeOf:(id)item;
8590
@end
8691

8792
@protocol PGThumbnailViewDelegate <NSObject>
8893

8994
@optional
9095
- (void)thumbnailViewSelectionDidChange:(PGThumbnailView *)sender;
96+
- (void)thumbnailView:(PGThumbnailView *)sender selectAllDirectChildrenOf:(id)item; // 2023/09/18
9197

9298
@end

0 commit comments

Comments
 (0)