mirror of
https://github.com/ksherlock/ample.git
synced 2025-01-23 00:33:32 +00:00
enable/disable media based on slots.
This commit is contained in:
parent
9cce33ffe9
commit
259b5f31a7
@ -91,6 +91,9 @@ static NSString *kMyContext = @"kMyContext";
|
||||
[self addObserver: self forKeyPath: @"mameNoThrottle" options:0 context: (__bridge void * _Nullable)(kMyContext)];
|
||||
|
||||
[_slotController addObserver: self forKeyPath: @"args" options: 0 context: (__bridge void * _Nullable)(kMyContext)];
|
||||
|
||||
[_mediaController bind: @"media" toObject: _slotController withKeyPath: @"media" options: 0];
|
||||
|
||||
[self buildCommandLine];
|
||||
}
|
||||
|
||||
|
@ -736,7 +736,7 @@
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ug9-kz-ZSS">
|
||||
<rect key="frame" x="621" y="53" width="85" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Launch" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="evD-kp-H2u">
|
||||
<buttonCell key="cell" type="push" title="Launch" bezelStyle="rounded" image="NSAppleMenuImage" imagePosition="leading" alignment="center" borderStyle="border" inset="2" id="evD-kp-H2u">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
@ -778,4 +778,7 @@
|
||||
<viewController title="Slot View" nibName="SlotView" id="CYF-Xd-EdF" customClass="SlotViewController"/>
|
||||
<viewController title="Media View" nibName="MediaView" id="kiU-IX-LTW" customClass="MediaViewController"/>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="NSAppleMenuImage" width="128" height="128"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
@ -14,7 +14,7 @@
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="20" horizontalPageScroll="10" verticalLineScroll="20" verticalPageScroll="10" usesPredominantAxisScrolling="NO" id="nVT-kT-bWl">
|
||||
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="20" horizontalPageScroll="10" verticalLineScroll="20" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" id="nVT-kT-bWl">
|
||||
<rect key="frame" x="0.0" y="0.0" width="306" height="500"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="IBD-wb-pch">
|
||||
@ -81,17 +81,17 @@
|
||||
<rect key="frame" x="1" y="41" width="304" height="27"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<pathControl verticalHuggingPriority="750" fixedFrame="YES" allowsExpansionToolTips="YES" translatesAutoresizingMaskIntoConstraints="NO" id="f7R-TO-fmF">
|
||||
<pathControl focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" allowsExpansionToolTips="YES" translatesAutoresizingMaskIntoConstraints="NO" id="f7R-TO-fmF">
|
||||
<rect key="frame" x="0.0" y="1" width="251" height="22"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<pathCell key="cell" controlSize="small" selectable="YES" editable="YES" alignment="left" pathStyle="popUp" id="dcz-8y-tKb">
|
||||
<pathCell key="cell" controlSize="small" selectable="YES" editable="YES" focusRingType="none" alignment="left" pathStyle="popUp" id="dcz-8y-tKb">
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
</pathCell>
|
||||
</pathControl>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zNo-ij-mUl">
|
||||
<rect key="frame" x="278" y="4" width="23" height="18"/>
|
||||
<rect key="frame" x="256" y="5" width="23" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<buttonCell key="cell" type="bevel" bezelStyle="rounded" image="NSStopProgressFreestandingTemplate" imagePosition="overlaps" alignment="center" controlSize="small" imageScaling="proportionallyDown" inset="2" id="IZA-Tu-olu">
|
||||
<buttonCell key="cell" type="bevel" bezelStyle="rounded" image="NSNavEjectButton.normalSelected" imagePosition="overlaps" alignment="center" controlSize="small" imageScaling="proportionallyDown" inset="2" id="IZA-Tu-olu">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
</buttonCell>
|
||||
@ -99,14 +99,9 @@
|
||||
<action selector="buttonDelete:" target="-2" id="f30-YS-1UK"/>
|
||||
</connections>
|
||||
</button>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" id="jeU-0Q-Eps">
|
||||
<rect key="frame" x="256" y="6" width="14" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<imageCell key="cell" enabled="NO" refusesFirstResponder="YES" alignment="left" image="NSStatusUnavailable" id="dtr-VF-lvn"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<connections>
|
||||
<outlet property="imageView" destination="jeU-0Q-Eps" id="Cjz-C6-w1l"/>
|
||||
<outlet property="deleteButton" destination="zNo-ij-mUl" id="9br-3c-ddI"/>
|
||||
<outlet property="pathControl" destination="f7R-TO-fmF" id="oH7-N3-JC7"/>
|
||||
</connections>
|
||||
</tableCellView>
|
||||
@ -122,7 +117,7 @@
|
||||
<nil key="backgroundColor"/>
|
||||
</clipView>
|
||||
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="9Vz-lW-4GG">
|
||||
<rect key="frame" x="0.0" y="485" width="306" height="15"/>
|
||||
<rect key="frame" x="-100" y="-100" width="306" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="f8l-nC-KhG">
|
||||
@ -133,7 +128,6 @@
|
||||
</scrollView>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="NSStatusUnavailable" width="16" height="16"/>
|
||||
<image name="NSStopProgressFreestandingTemplate" width="14" height="14"/>
|
||||
<image name="NSNavEjectButton.normalSelected" width="128" height="128"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
@ -13,11 +13,11 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@interface MediaViewController : NSViewController <NSOutlineViewDelegate, NSOutlineViewDataSource>
|
||||
|
||||
@property (weak) IBOutlet NSOutlineView *outlineView;
|
||||
|
||||
@property (nonatomic) NSDictionary *media;
|
||||
- (IBAction)buttonDelete:(id)sender;
|
||||
|
||||
|
||||
-(void)setMedia: (NSDictionary *)media;
|
||||
//-(void)setMedia: (NSDictionary *)media;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -86,25 +86,26 @@
|
||||
|
||||
|
||||
-(BOOL)setItemCount: (unsigned)newCount {
|
||||
unsigned count = (unsigned)[_children count];
|
||||
if (count == newCount) return NO;
|
||||
|
||||
if (newCount == _validCount) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
unsigned count = (unsigned)[_children count];
|
||||
NSMutableArray *tmp = [NSMutableArray arrayWithArray: _children];
|
||||
|
||||
_validCount = newCount;
|
||||
|
||||
while (newCount > count) {
|
||||
for (unsigned i = count; i < newCount; ++i) {
|
||||
[tmp addObject: [MediaItem new]];
|
||||
++count;
|
||||
}
|
||||
// delete excess items, if blank. otherwise, mark invalid.
|
||||
unsigned ix = 0;
|
||||
for(MediaItem *item in tmp) {
|
||||
[item setValid: ix < newCount];
|
||||
[item setValid: ix++ < newCount];
|
||||
}
|
||||
|
||||
while (newCount > count) {
|
||||
--newCount;
|
||||
for (unsigned i = newCount; i < count; ++i) {
|
||||
MediaItem *item = [tmp lastObject];
|
||||
if ([item url]) break;
|
||||
|
||||
@ -115,6 +116,25 @@
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(BOOL)pruneChildren {
|
||||
NSUInteger count = [_children count];
|
||||
BOOL delta = NO;
|
||||
if (_validCount == count) return NO;
|
||||
|
||||
NSMutableArray *tmp = [NSMutableArray arrayWithArray: _children];
|
||||
for (NSInteger i = _validCount; i < count; ++i) {
|
||||
MediaItem *item = [tmp lastObject];
|
||||
if ([item url]) break;
|
||||
|
||||
[tmp removeLastObject];
|
||||
delta = YES;
|
||||
}
|
||||
if (delta) {
|
||||
[self setChildren: tmp];
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
@ -152,6 +172,10 @@
|
||||
[pc setURL: _url]; //??? will binding take care of it?
|
||||
[pc unbind: @"value"];
|
||||
[pc bind: @"value" toObject: self withKeyPath: @"url" options: nil];
|
||||
|
||||
NSColor *tintColor = nil;
|
||||
if (!_valid) tintColor = [NSColor redColor];
|
||||
[[view deleteButton] setContentTintColor: tintColor];
|
||||
}
|
||||
|
||||
-(CGFloat)height {
|
||||
@ -167,8 +191,8 @@
|
||||
|
||||
MediaCategory *_data[5];
|
||||
NSArray *_root;
|
||||
NSDictionary *_media;
|
||||
}
|
||||
@property (weak) IBOutlet NSPathControl *_hacky_hack;
|
||||
|
||||
@end
|
||||
|
||||
@ -196,28 +220,8 @@
|
||||
_data[3] = d;
|
||||
_data[4] = e;
|
||||
|
||||
_root = @[a,b,c,d,e];
|
||||
|
||||
|
||||
[a setChildren: @[
|
||||
[MediaItem new],
|
||||
[MediaItem new],
|
||||
]];
|
||||
_root = @[];
|
||||
|
||||
[b setChildren: @[
|
||||
[MediaItem new],
|
||||
[MediaItem new],
|
||||
]];
|
||||
|
||||
[c setChildren: @[
|
||||
[MediaItem new],
|
||||
[MediaItem new],
|
||||
]];
|
||||
|
||||
[d setChildren: @[
|
||||
[MediaItem new],
|
||||
[MediaItem new],
|
||||
]];
|
||||
}
|
||||
|
||||
|
||||
@ -228,6 +232,20 @@ enum {
|
||||
kIndexCDROM,
|
||||
kIndexCassette
|
||||
};
|
||||
|
||||
-(void)rebuildRoot {
|
||||
NSMutableArray *tmp = [NSMutableArray new];
|
||||
for (unsigned j = 0 ; j < 5; ++j) {
|
||||
MediaCategory *cat = _data[j];
|
||||
if ([cat count]) [tmp addObject: cat];
|
||||
}
|
||||
_root = tmp;
|
||||
//[_outlineView reloadItem: nil reloadChildren: YES];
|
||||
|
||||
[_outlineView reloadData];
|
||||
[_outlineView expandItem: nil expandChildren: YES];
|
||||
}
|
||||
|
||||
-(void)setMedia: (NSDictionary *)media {
|
||||
|
||||
static NSString *Keys[] = {
|
||||
@ -237,11 +255,16 @@ enum {
|
||||
@"cdrm",
|
||||
@"cass"
|
||||
};
|
||||
|
||||
NSNumber *o;
|
||||
MediaCategory *cat;
|
||||
unsigned i;
|
||||
BOOL delta = NO;
|
||||
|
||||
|
||||
if (_media == media) return;
|
||||
_media = media;
|
||||
|
||||
for (unsigned j = 0; j < 5; ++j) {
|
||||
|
||||
o = [media objectForKey: Keys[j]];
|
||||
@ -251,15 +274,7 @@ enum {
|
||||
}
|
||||
|
||||
|
||||
if (delta) {
|
||||
NSMutableArray *tmp = [NSMutableArray new];
|
||||
for (unsigned j = 0 ; j < 5; ++j) {
|
||||
MediaCategory *cat = _data[j];
|
||||
if ([cat count]) [tmp addObject: cat];
|
||||
}
|
||||
_root = tmp;
|
||||
[_outlineView reloadData];
|
||||
}
|
||||
if (delta) [self rebuildRoot];
|
||||
}
|
||||
|
||||
- (void)viewDidLoad {
|
||||
@ -269,6 +284,7 @@ enum {
|
||||
//NSOutlineView *view = [self view];
|
||||
//[view expandItem: nil expandChildren: YES];
|
||||
// Do view setup here.
|
||||
[_outlineView reloadData];
|
||||
[_outlineView expandItem: nil expandChildren: YES];
|
||||
}
|
||||
|
||||
@ -364,5 +380,11 @@ enum {
|
||||
MediaItem *item = [_outlineView itemAtRow: row];
|
||||
[item setUrl: nil];
|
||||
//[[pv pathControl] setURL: nil];
|
||||
|
||||
// if item is invalid, should attempt to remove...
|
||||
if (![item valid]) {
|
||||
MediaCategory *cat = [_outlineView parentForItem: item];
|
||||
if ([cat pruneChildren]) [self rebuildRoot];
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
@ -37,6 +37,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@property NSSize resolution;
|
||||
|
||||
@property NSArray *args;
|
||||
@property NSDictionary *media;
|
||||
|
||||
//-(void)setMachine: (NSDictionary *)machine;
|
||||
|
||||
|
@ -15,6 +15,10 @@ const unsigned kMemoryMask = 1 << 16;
|
||||
unsigned _slots_explicit;
|
||||
unsigned _slots_valid;
|
||||
unsigned _slots_default;
|
||||
|
||||
NSDictionary *_slot_object[14];
|
||||
NSDictionary *_slot_media[14];
|
||||
NSDictionary *_machine_media;
|
||||
}
|
||||
|
||||
@property (weak) IBOutlet NSPopUpButton *ram_menu;
|
||||
@ -89,7 +93,19 @@ const unsigned kMemoryMask = 1 << 16;
|
||||
_slots_explicit = 0;
|
||||
_slots_valid = 0;
|
||||
|
||||
_machine_media = nil;
|
||||
|
||||
[self setArgs: @[]];
|
||||
[self setMedia: @{}];
|
||||
|
||||
|
||||
#if 0
|
||||
// retain for later?
|
||||
for (unsigned i = 0; i < 14; ++i) {
|
||||
_slot_media[i] = nil;
|
||||
_slot_object[i] = nil;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static NSFont *ItalicMenuFont(void) {
|
||||
@ -212,20 +228,26 @@ static void DeactivateMenus(NSArray *items, NSPopUpButton *button) {
|
||||
if ([value isEqualToString: [d objectForKey: @"value"]]) {
|
||||
|
||||
[button selectItemAtIndex: ix];
|
||||
_slot_object[index] = d;
|
||||
_slot_media[index] = [d objectForKey: @"media"];
|
||||
return;
|
||||
}
|
||||
++ix;
|
||||
}
|
||||
}
|
||||
_slots_explicit &= ~mask;
|
||||
|
||||
if (default_index) {
|
||||
NSDictionary *d = [items objectAtIndex: default_index];
|
||||
[button selectItemAtIndex: default_index];
|
||||
[self setValue: [d objectForKey: @"value"] forKey: slot];
|
||||
_slot_object[index] = d;
|
||||
_slot_media[index] = [d objectForKey: @"media"];
|
||||
} else {
|
||||
|
||||
[self setValue: @"" forKey: slot];
|
||||
[button selectItemAtIndex: 0];
|
||||
[self setValue: @"" forKey: slot];
|
||||
_slot_object[index] = nil;
|
||||
_slot_media[index] = nil;
|
||||
}
|
||||
}
|
||||
|
||||
@ -267,11 +289,14 @@ static void DeactivateMenus(NSArray *items, NSPopUpButton *button) {
|
||||
res.height = [(NSNumber *)[r objectAtIndex: 1 /*@"height"*/] doubleValue];
|
||||
}
|
||||
[self setResolution: res];
|
||||
|
||||
_machine_media = [d objectForKey: @"media"];
|
||||
|
||||
// n.b. - does content binding propogate immediately?
|
||||
[self setMachine: d];
|
||||
[self syncSlots];
|
||||
[self rebuildArgs];
|
||||
[self rebuildMedia];
|
||||
}
|
||||
|
||||
|
||||
@ -297,6 +322,16 @@ static void DeactivateMenus(NSArray *items, NSPopUpButton *button) {
|
||||
|
||||
[self setValue: [o objectForKey: @"value"] forKey: key];
|
||||
|
||||
_slot_object[tag] = o;
|
||||
NSDictionary *newMedia = [o objectForKey: @"media"];
|
||||
NSDictionary *oldMedia = _slot_media[tag];
|
||||
|
||||
if (newMedia != oldMedia) {
|
||||
_slot_media[tag] = newMedia;
|
||||
[self rebuildMedia];
|
||||
}
|
||||
|
||||
|
||||
[self rebuildArgs];
|
||||
}
|
||||
|
||||
@ -359,8 +394,53 @@ static BOOL should_add_arg(unsigned slot, unsigned valid_slots, unsigned explici
|
||||
_(11, _gameio, @"-gameio")
|
||||
_(12, _printer, @"-printer")
|
||||
_(13, _modem, @"-modem")
|
||||
|
||||
#undef _
|
||||
[self setArgs: args];
|
||||
}
|
||||
|
||||
|
||||
-(void)rebuildMedia {
|
||||
|
||||
|
||||
#define _(var, o) var += [[o objectForKey: @ # var ] unsignedIntValue]
|
||||
|
||||
unsigned cass = 0;
|
||||
unsigned cdrm = 0;
|
||||
unsigned hard = 0;
|
||||
unsigned flop_5_25 = 0;
|
||||
unsigned flop_3_5 = 0;
|
||||
|
||||
unsigned mask = 1;
|
||||
for (unsigned i = 0; i < 14; ++i, mask <<= 1) {
|
||||
|
||||
if (_slots_valid & mask) {
|
||||
NSDictionary *tmp = _slot_media[i];
|
||||
if (tmp) {
|
||||
_(cass, tmp);
|
||||
_(cdrm, tmp);
|
||||
_(hard, tmp);
|
||||
_(flop_5_25, tmp);
|
||||
_(flop_3_5, tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
NSDictionary *tmp = _machine_media;
|
||||
if (tmp) {
|
||||
_(cass, tmp);
|
||||
_(cdrm, tmp);
|
||||
_(hard, tmp);
|
||||
_(flop_5_25, tmp);
|
||||
_(flop_3_5, tmp);
|
||||
}
|
||||
|
||||
[self setMedia: @{
|
||||
@"cass": @(cass),
|
||||
@"cdrm": @(cdrm),
|
||||
@"hard": @(hard),
|
||||
@"flop_5_25": @(flop_5_25),
|
||||
@"flop_3_5": @(flop_3_5),
|
||||
}];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
Loading…
x
Reference in New Issue
Block a user