From 8fdb149eb38952b13c4a78d7a6940c43d90870f1 Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Mon, 31 May 2021 16:13:43 -0400 Subject: [PATCH] start of bookmarking support. Untested. --- Ample/Ample.h | 6 ++ Ample/MachineViewController.h | 5 ++ Ample/MachineViewController.m | 43 ++++++++++++++ Ample/MediaViewController.h | 4 +- Ample/MediaViewController.m | 103 ++++++++++++++++++++++++++++++++++ Ample/Slot.h | 3 +- Ample/Slot.m | 63 ++++++++++++++++++--- Ample/SlotViewController.h | 4 ++ Ample/SlotViewController.m | 42 ++++++++++++++ 9 files changed, 263 insertions(+), 10 deletions(-) diff --git a/Ample/Ample.h b/Ample/Ample.h index 44968f5..883f382 100644 --- a/Ample/Ample.h +++ b/Ample/Ample.h @@ -40,4 +40,10 @@ extern NSString *kDownloadExtension; extern NSString *kDefaultDownloadURL; extern NSString *kDefaultDownloadExtension; + +@protocol Bookmark +-(BOOL)loadBookmark: (NSDictionary *)bookmark; +-(BOOL)saveBookmark: (NSMutableDictionary *)bookmark; +@end + #endif /* Ample_h */ diff --git a/Ample/MachineViewController.h b/Ample/MachineViewController.h index 5f00a42..74aade3 100644 --- a/Ample/MachineViewController.h +++ b/Ample/MachineViewController.h @@ -8,6 +8,7 @@ #import #import +#import "Ample.h" NS_ASSUME_NONNULL_BEGIN @@ -17,4 +18,8 @@ NS_ASSUME_NONNULL_BEGIN @end +@interface MachineViewController (Bookmark) + +@end + NS_ASSUME_NONNULL_END diff --git a/Ample/MachineViewController.m b/Ample/MachineViewController.m index a961f4b..1b96638 100644 --- a/Ample/MachineViewController.m +++ b/Ample/MachineViewController.m @@ -110,5 +110,48 @@ return [data count]; } +@end + +@implementation MachineViewController (Bookmark) + +-(BOOL)loadBookmark: (NSDictionary *)bookmark { + + NSBrowser *browser = (NSBrowser *)[self view]; + NSString *machine = [bookmark objectForKey: @"machine"]; + + NSIndexPath *path = nil; + NSUInteger ix[2] = {0, 0 }; + for (NSDictionary *d in _data) { + + NSString *value = [d objectForKey: @"value"]; + NSArray *children = [d objectForKey: @"children"]; + if ([machine isEqualToString: value]) { + path = [NSIndexPath indexPathWithIndexes: ix length: 1]; + [browser setSelectionIndexPath: path]; + return YES; + } + + for (NSDictionary *dd in children) { + NSString *value = [dd objectForKey: @"value"]; + + if ([machine isEqualToString: value]) { + path = [NSIndexPath indexPathWithIndexes: ix length: 2]; + [browser setSelectionIndexPath: path]; + return YES; + } + ++ix[1]; + } + ix[1] = 0; + ++ix[0]; + + } + NSLog(@"MachineViewController: Unable to find %@", machine); + return NO; +} + +-(BOOL)saveBookmark: (NSMutableDictionary *)bookmark { + // machine saved in parent. + return YES; +} @end diff --git a/Ample/MediaViewController.h b/Ample/MediaViewController.h index e8e9ac4..b6907bb 100644 --- a/Ample/MediaViewController.h +++ b/Ample/MediaViewController.h @@ -8,6 +8,7 @@ #import #import "Media.h" +#import "Ample.h" NS_ASSUME_NONNULL_BEGIN @@ -20,8 +21,9 @@ NS_ASSUME_NONNULL_BEGIN - (IBAction)ejectAction:(id)sender; - (IBAction)pathAction:(id)sender; +@end -//-(void)setMedia: (NSDictionary *)media; +@interface MediaViewController (Bookmark) @end diff --git a/Ample/MediaViewController.m b/Ample/MediaViewController.m index 1827451..60e309e 100644 --- a/Ample/MediaViewController.m +++ b/Ample/MediaViewController.m @@ -376,6 +376,28 @@ x = media.name; cat = _data[index]; delta |= [cat setItemCount: x] } } +-(void)resetDiskImages { + + BOOL delta = NO; + for (unsigned j = 0; j < CATEGORY_COUNT; ++j) { + + MediaCategory *cat = _data[j]; + NSInteger count = [cat count]; + for (NSInteger i = 0; i < count; ++i) { + + MediaItem *item = [cat objectAtIndex: i]; + NSURL *url = [item url]; + if (!url) continue; + [item setUrl: nil]; + delta = YES; + } + } + if (delta) { + [self rebuildRoot]; + [self rebuildArgs]; + } +} + static NSString *kDragType = @"private.ample.media"; - (void)viewDidLoad { @@ -641,4 +663,85 @@ static NSString *kDragType = @"private.ample.media"; [self rebuildArgs]; } + +@end + +@implementation MediaViewController (Bookmark) + +-(BOOL)loadBookmark: (NSDictionary *)bookmark { + +#if 0 + // hmmm... should rely on machine/slots to set media + // so it doesn't go out of sync after an update. + NSDictionary *d = [bookmark objectForKey: @"media"]; + Media m = EmptyMedia; + + if (d) m = MediaFromDictionary(d); + [self setMedia: m]; +#endif + + // reset all media + [self resetDiskImages]; + + // if order of indexes change, would need to do a version check. + + NSArray *media = [bookmark objectForKey: @"media"]; + unsigned ix = 0; + for (NSArray *a in media) { + if (ix >= CATEGORY_COUNT) { + NSLog(@"MediaViewController: too many categories."); + break; + } + MediaCategory *cat = _data[ix++]; + NSInteger count = [cat count]; + unsigned i = 0; + for (NSString *path in a) { + if (i >= count) { + NSLog(@"MediaViewController: too many files."); + break; // + } + MediaItem *item = [cat objectAtIndex: i++]; + NSURL *url = nil; + if ([path length]) + url = [NSURL fileURLWithPath: path]; + + [item setUrl: url]; + } + } + + // add will load bookmark / did load bookmark to block all the rebuilding ? + [self rebuildRoot]; + [self rebuildArgs]; + return YES; + +} + +-(BOOL)saveBookmark: (NSMutableDictionary *)bookmark { + + NSMutableArray *media = [NSMutableArray arrayWithCapacity: CATEGORY_COUNT]; + + for (unsigned ix = 0; ix < CATEGORY_COUNT; ++ix) { + + MediaCategory *cat = _data[ix]; + NSInteger count = [cat validCount]; + + NSMutableArray *array = [NSMutableArray new]; + for (NSInteger i = 0; i < count; ++i) { + + MediaItem *item = [cat objectAtIndex: i]; + NSURL *url = [item url]; + NSString *s = @""; + if (url) + s = [NSString stringWithCString: [url fileSystemRepresentation] encoding: NSUTF8StringEncoding]; + + [array addObject: s]; + } + [media addObject: array]; + } + + [bookmark setObject: media forKey: @"media"]; + + return YES; +} + @end diff --git a/Ample/Slot.h b/Ample/Slot.h index 687727b..952b6c7 100644 --- a/Ample/Slot.h +++ b/Ample/Slot.h @@ -27,7 +27,8 @@ @property (readonly) SlotOption *selectedItem; -(NSArray *)args; --(NSArray *)serialize; +-(NSDictionary *)serialize; +-(void)reserialize: (NSDictionary *)dict; -(void)reset; -(void)prepareView: (SlotTableCellView *)view; diff --git a/Ample/Slot.m b/Ample/Slot.m index d3b65d3..1d012b0 100644 --- a/Ample/Slot.m +++ b/Ample/Slot.m @@ -60,7 +60,10 @@ static NSArray *DeepCopyArray(NSArray *src) { -(void)setKeyPath: (NSString *)path; -(void)buildArgs: (NSMutableArray *)args; -(void)buildMedia: (Media *)media; --(void)buildSerial: (NSMutableArray *)array; +-(void)buildSerial: (NSMutableDictionary *)array; + + +-(void)reserialize: (NSDictionary *)dict; //-(BOOL)loadDeviceSlots: (NSDictionary *)devices; @@ -138,15 +141,47 @@ static NSDictionary *IndexMap = nil; return rv; } --(NSArray *)serialize { +-(NSDictionary *)serialize { if (_selectedIndex < 0) return nil; - NSMutableArray *array = [NSMutableArray new]; + NSMutableDictionary *d = [NSMutableDictionary new]; SlotOption *option = [_options objectAtIndex: _selectedIndex]; - [option buildSerial: array]; - return array; + [option buildSerial: d]; + //if (![d count]) return nil; //? + return d; } +-(void)reserialize: (NSDictionary *)dict { + // { 'sl3' : 'uthernet' } + + // special case for smartport since the name isn't used. + if (_index == kSMARTPORT) { + SlotOption *option = [_options objectAtIndex: _selectedIndex]; + [option reserialize: dict]; + return; + } + NSString *value = [dict objectForKey: _name]; + if (!value) { + //[self reset]; + return; + } + // find it... + BOOL found = NO; + unsigned ix = 0; + for (SlotOption *option in _options) { + if ([value isEqualToString: [option value]]) { + + [self setSelectedIndex: ix]; + [option reserialize: dict]; + found = YES; + break; + } + ++ix; + } + +} + + -(Media)selectedMedia { if (_selectedIndex < 0) return EmptyMedia; @@ -457,14 +492,26 @@ https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/KeyVa } } +-(void)reserialize: (NSDictionary *)dict { + +#if 0 + NSString *value = [dict objectForKey: _keyPath]; + if (value) { + // don't need to do anything since set by slot. + } +#endif + for (Slot *s in _children) { + [s reserialize: dict]; + } +} --(void)buildSerial: (NSMutableArray *)array { +-(void)buildSerial: (NSMutableDictionary *)dict { if (!_default) - [array addObject: _keyPath]; + [dict setObject: _value forKey: _keyPath]; for (Slot *s in _children) - [[s selectedItem] buildSerial: array]; + [[s selectedItem] buildSerial: dict]; } diff --git a/Ample/SlotViewController.h b/Ample/SlotViewController.h index 141274d..3f861be 100644 --- a/Ample/SlotViewController.h +++ b/Ample/SlotViewController.h @@ -8,6 +8,7 @@ #import #import "Media.h" +#import "Ample.h" NS_ASSUME_NONNULL_BEGIN @@ -17,13 +18,16 @@ NS_ASSUME_NONNULL_BEGIN @property Media media; @property NSSize resolution; @property (nonatomic) NSString *machine; + @end @interface SlotViewController (OutlineView) @end +@interface SlotViewController (Bookmark) +@end NS_ASSUME_NONNULL_END diff --git a/Ample/SlotViewController.m b/Ample/SlotViewController.m index ae27b4b..92b4948 100644 --- a/Ample/SlotViewController.m +++ b/Ample/SlotViewController.m @@ -338,5 +338,47 @@ static unsigned RootKey = 0; } +@end + + +@implementation SlotViewController (Bookmark) + +-(BOOL)loadBookmark: (NSDictionary *)bookmark { + + NSDictionary *dict = [bookmark objectForKey: @"slots"]; + + [self resetSlots: nil]; + for (Slot *item in _root) { + [item reserialize: dict]; + + NSInteger index = [item index]; + if (index >= 0 && index < SLOT_COUNT) { + unsigned mask = 1 << index; + + if ([item defaultIndex] != [item selectedIndex]) + _slots_explicit |= mask; // grrr. + + _slot_media[index] = [item selectedMedia]; + _slot_value[index] = [[item selectedItem] value]; + } + + ++index; + } + + [self rebuildMedia]; + [self rebuildArgs]; + return YES; +} +-(BOOL)saveBookmark: (NSMutableDictionary *)bookmark { + + NSMutableDictionary *slots = [NSMutableDictionary new]; + for (Slot *item in _root) { + NSDictionary *d = [item serialize]; + [slots addEntriesFromDictionary: d]; + } + + [bookmark setObject: slots forKey: @"slots"]; + return YES; +} @end