Squashed commit of the following:

commit c41312ac604526fbfa8eb9c70c26afb5711531ed
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Mon Jun 7 22:55:43 2021 -0400

    replace custom table delegate/datasource with array controller

    required a few tweaks to get the binding correct and equivalent to the hand-rolled version.

    The only advantage is the filtering capability (currently All/Missing)

    Also, refreshing didn't update the status and url if the local file had been deleted.

commit 3aedf237344fa9fbb8225cf3513a27da9647ea07
Author: Kelvin Sherlock <ksherlock@gmail.com>
Date:   Mon Jun 7 21:13:39 2021 -0400

    add toolbar and array controller to filter missing roms, etc.
This commit is contained in:
Kelvin Sherlock 2021-06-07 22:56:55 -04:00
parent 3d5a2951bb
commit ef2bbeb9c3
3 changed files with 181 additions and 112 deletions

View File

@ -8,8 +8,11 @@
<objects> <objects>
<customObject id="-2" userLabel="File's Owner" customClass="DownloadWindowController"> <customObject id="-2" userLabel="File's Owner" customClass="DownloadWindowController">
<connections> <connections>
<outlet property="allFilterButton" destination="Kgj-LP-FsF" id="yub-s9-RVW"/>
<outlet property="arrayController" destination="jhO-4z-Qwt" id="GHu-xb-4zU"/>
<outlet property="downloadField" destination="sJz-So-jbA" id="WjK-48-FcE"/> <outlet property="downloadField" destination="sJz-So-jbA" id="WjK-48-FcE"/>
<outlet property="formatButton" destination="2Rg-eX-DUq" id="oYo-MG-Sc6"/> <outlet property="formatButton" destination="2Rg-eX-DUq" id="oYo-MG-Sc6"/>
<outlet property="missingFilterButton" destination="6c7-tU-3F3" id="89Y-wQ-9pB"/>
<outlet property="tableView" destination="FLX-Wt-y53" id="a4O-pk-EAt"/> <outlet property="tableView" destination="FLX-Wt-y53" id="a4O-pk-EAt"/>
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/> <outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
</connections> </connections>
@ -26,7 +29,7 @@
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="rg5-Qf-4Mw"> <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="rg5-Qf-4Mw">
<rect key="frame" x="324" y="19" width="56" height="23"/> <rect key="frame" x="324.5" y="19" width="56" height="23"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
<buttonCell key="cell" type="roundTextured" title="Cancel" bezelStyle="texturedRounded" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="i6Z-OM-lqE"> <buttonCell key="cell" type="roundTextured" title="Cancel" bezelStyle="texturedRounded" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="i6Z-OM-lqE">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
@ -69,26 +72,8 @@
</textFieldCell> </textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES"/> <tableColumnResizingMask key="resizingMask" resizeWithTable="YES"/>
<prototypeCellViews> <prototypeCellViews>
<tableCellView identifier="Cell" focusRingType="none" id="aBv-F5-XWo"> <tableCellView focusRingType="none" id="onK-6l-2iV">
<rect key="frame" x="1" y="1" width="397" height="17"/> <rect key="frame" x="1" y="1" width="397" height="49"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="pWm-hb-BXB">
<rect key="frame" x="0.0" y="0.0" width="397" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="p71-gJ-vFV">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<connections>
<outlet property="textField" destination="pWm-hb-BXB" id="NNG-rj-AAQ"/>
</connections>
</tableCellView>
<tableCellView identifier="DownloadCell" focusRingType="none" id="onK-6l-2iV" customClass="DownloadTableCellView">
<rect key="frame" x="1" y="20" width="397" height="49"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="A44-us-TEl"> <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="A44-us-TEl">
@ -99,10 +84,28 @@
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell> </textFieldCell>
<connections>
<binding destination="onK-6l-2iV" name="textColor" keyPath="objectValue.titleColor" id="0Qx-rz-DEZ"/>
<binding destination="onK-6l-2iV" name="value" keyPath="objectValue.name" id="t1L-kM-AW6">
<dictionary key="options">
<string key="NSMultipleValuesPlaceholder">multiple</string>
<string key="NSNoSelectionPlaceholder">no selection</string>
<string key="NSNotApplicablePlaceholder">n/a</string>
<string key="NSNullPlaceholder">null</string>
</dictionary>
</binding>
</connections>
</textField> </textField>
<progressIndicator wantsLayer="YES" fixedFrame="YES" maxValue="100" displayedWhenStopped="NO" indeterminate="YES" controlSize="small" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="jBN-UJ-tWi"> <progressIndicator wantsLayer="YES" fixedFrame="YES" maxValue="100" displayedWhenStopped="NO" indeterminate="YES" controlSize="small" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="jBN-UJ-tWi">
<rect key="frame" x="3" y="29" width="16" height="16"/> <rect key="frame" x="3" y="29" width="16" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<connections>
<binding destination="onK-6l-2iV" name="animate" keyPath="objectValue.task" id="d22-JL-3Z7">
<dictionary key="options">
<string key="NSValueTransformerName">NSIsNotNil</string>
</dictionary>
</binding>
</connections>
</progressIndicator> </progressIndicator>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hfu-hP-QAH"> <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hfu-hP-QAH">
<rect key="frame" x="25" y="3" width="371" height="17"/> <rect key="frame" x="25" y="3" width="371" height="17"/>
@ -112,20 +115,21 @@
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell> </textFieldCell>
<connections>
<binding destination="onK-6l-2iV" name="textColor" keyPath="objectValue.descriptionColor" id="KVi-3N-Swm"/>
<binding destination="onK-6l-2iV" name="value" keyPath="objectValue.statusDescription" id="yV1-5r-YDh"/>
</connections>
</textField> </textField>
</subviews> </subviews>
<connections> <connections>
<outlet property="activity" destination="jBN-UJ-tWi" id="ZwD-yU-Vne"/> <outlet property="textField" destination="A44-us-TEl" id="ude-er-Gm4"/>
<outlet property="statusTextField" destination="hfu-hP-QAH" id="8Hv-BB-kYA"/>
<outlet property="textField" destination="A44-us-TEl" id="Ta5-nd-ed1"/>
</connections> </connections>
</tableCellView> </tableCellView>
</prototypeCellViews> </prototypeCellViews>
</tableColumn> </tableColumn>
</tableColumns> </tableColumns>
<connections> <connections>
<outlet property="dataSource" destination="-2" id="Ghf-k9-bRK"/> <binding destination="jhO-4z-Qwt" name="content" keyPath="arrangedObjects" id="2av-gV-V4K"/>
<outlet property="delegate" destination="-2" id="rpR-0W-4Nu"/>
<outlet property="menu" destination="RJM-21-hjO" id="xpL-0n-1jm"/> <outlet property="menu" destination="RJM-21-hjO" id="xpL-0n-1jm"/>
</connections> </connections>
</tableView> </tableView>
@ -239,6 +243,44 @@
</popUpButton> </popUpButton>
</subviews> </subviews>
</view> </view>
<toolbar key="toolbar" implicitIdentifier="B60021E6-BFBC-44E6-97DC-120AA9FD3269" autosavesConfiguration="NO" allowsUserCustomization="NO" displayMode="iconOnly" sizeMode="regular" id="kpz-W4-xgh">
<allowedToolbarItems>
<toolbarItem implicitItemIdentifier="NSToolbarSpaceItem" id="tbY-ts-Irb"/>
<toolbarItem implicitItemIdentifier="NSToolbarFlexibleSpaceItem" id="3Kc-zG-IdN"/>
<toolbarItem implicitItemIdentifier="BD743A15-0B61-48FF-9EED-FD8D57EF8459" label="All" paletteLabel="All" tag="1" sizingBehavior="auto" id="Jj0-n8-I5a">
<nil key="toolTip"/>
<button key="view" verticalHuggingPriority="750" tag="1" id="Kgj-LP-FsF">
<rect key="frame" x="0.0" y="14" width="74" height="20"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="recessed" title="All" bezelStyle="recessed" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="9s7-S1-hW1">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES" changeBackground="YES" changeGray="YES"/>
<font key="font" metaFont="systemBold" size="12"/>
</buttonCell>
<connections>
<action selector="filterButton:" target="-2" id="gTc-Ul-FYR"/>
</connections>
</button>
</toolbarItem>
<toolbarItem implicitItemIdentifier="5B013840-E582-4568-8448-DDD7EE1E5AE2" label="Missing" paletteLabel="Missing" tag="2" sizingBehavior="auto" id="GV4-aX-5Ox">
<nil key="toolTip"/>
<button key="view" verticalHuggingPriority="750" tag="2" id="6c7-tU-3F3">
<rect key="frame" x="0.0" y="14" width="74" height="20"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="recessed" title="Missing" bezelStyle="recessed" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="ui2-dz-IZj">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES" changeBackground="YES" changeGray="YES"/>
<font key="font" metaFont="systemBold" size="12"/>
</buttonCell>
<connections>
<action selector="filterButton:" target="-2" id="R6W-hU-oqL"/>
</connections>
</button>
</toolbarItem>
</allowedToolbarItems>
<defaultToolbarItems>
<toolbarItem reference="Jj0-n8-I5a"/>
<toolbarItem reference="GV4-aX-5Ox"/>
</defaultToolbarItems>
</toolbar>
<connections> <connections>
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/> <outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
</connections> </connections>
@ -270,6 +312,7 @@
</connections> </connections>
<point key="canvasLocation" x="-348" y="164"/> <point key="canvasLocation" x="-348" y="164"/>
</menu> </menu>
<arrayController objectClassName="DownloadItem" editable="NO" preservesSelection="NO" selectsInsertedObjects="NO" avoidsEmptySelection="NO" clearsFilterPredicateOnInsertion="NO" automaticallyRearrangesObjects="YES" id="jhO-4z-Qwt" customClass="DownloadItemArrayController"/>
<userDefaultsController representsSharedInstance="YES" id="721-9N-Bma"/> <userDefaultsController representsSharedInstance="YES" id="721-9N-Bma"/>
</objects> </objects>
<resources> <resources>

View File

@ -26,17 +26,9 @@ NS_ASSUME_NONNULL_BEGIN
@interface DownloadWindowController (URL) <NSURLSessionTaskDelegate, NSURLSessionDownloadDelegate> @interface DownloadWindowController (URL) <NSURLSessionTaskDelegate, NSURLSessionDownloadDelegate>
@end @end
@interface DownloadWindowController (Table) <NSTableViewDelegate, NSTableViewDataSource>
@end
@interface DownloadWindowController (Menu) <NSMenuDelegate, NSMenuItemValidation> @interface DownloadWindowController (Menu) <NSMenuDelegate, NSMenuItemValidation>
@end @end
@interface DownloadTableCellView : NSTableCellView
@property (weak) IBOutlet NSTextField *statusTextField;
@property (weak) IBOutlet NSProgressIndicator *activity;
@end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

View File

@ -90,6 +90,9 @@ enum {
@property NSUInteger status; @property NSUInteger status;
@property NSUInteger index; @property NSUInteger index;
@property (readonly) NSColor *titleColor;
@property (readonly) NSColor *descriptionColor;
-(void)cancelDownload; -(void)cancelDownload;
-(void)beginDownloadWithTask:(NSURLSessionDownloadTask *)task; -(void)beginDownloadWithTask:(NSURLSessionDownloadTask *)task;
@ -98,6 +101,21 @@ enum {
@end @end
@interface DownloadItemArrayController : NSArrayController
@property(readonly, copy) NSArray<NSString *> *automaticRearrangementKeyPaths;
@end
@implementation DownloadItemArrayController
-(NSArray<NSString *> *)automaticRearrangementKeyPaths {
return @[@"localURL"]; // , @"error", @"task", @"statusDescription"];
}
@end
@interface DownloadWindowController () @interface DownloadWindowController ()
@property (weak) IBOutlet NSTableView *tableView; @property (weak) IBOutlet NSTableView *tableView;
@ -105,6 +123,14 @@ enum {
@property (weak) IBOutlet NSTextField *downloadField; @property (weak) IBOutlet NSTextField *downloadField;
@property NSString *downloadExtension; @property NSString *downloadExtension;
/* filter buttons */
@property (weak) IBOutlet NSButton *allFilterButton;
@property (weak) IBOutlet NSButton *missingFilterButton;
@property (strong) IBOutlet NSArrayController *arrayController;
@end @end
@implementation DownloadWindowController { @implementation DownloadWindowController {
@ -117,6 +143,8 @@ enum {
NSURLSession *_session; NSURLSession *_session;
NSMutableDictionary *_taskIndex; NSMutableDictionary *_taskIndex;
NSUserDefaults *_defaults; NSUserDefaults *_defaults;
NSArray<NSButton *> *_filterButtons;
} }
+(instancetype)sharedInstance { +(instancetype)sharedInstance {
@ -166,6 +194,12 @@ enum {
[window setRestorationClass: [self class]]; [window setRestorationClass: [self class]];
#endif #endif
_filterButtons = @[
_allFilterButton,
_missingFilterButton
];
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
NSError *error = nil; NSError *error = nil;
@ -217,6 +251,7 @@ enum {
} }
_items = tmp; _items = tmp;
[self refreshROMs: nil]; [self refreshROMs: nil];
[_arrayController setContent: _items];
//[_tableView reloadData]; //[_tableView reloadData];
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
@ -299,8 +334,10 @@ enum {
-(DownloadItem *)clickedItem { -(DownloadItem *)clickedItem {
NSInteger row = [_tableView clickedRow]; NSInteger row = [_tableView clickedRow];
if (row < 0 || row >= [_items count]) return nil; if (row < 0 || row >= [_items count]) return nil;
return [_items objectAtIndex: row]; return [[_arrayController arrangedObjects] objectAtIndex: row];
//return [_items objectAtIndex: row];
} }
#if 0
-(void)redrawRow: (NSUInteger)row { -(void)redrawRow: (NSUInteger)row {
//NSRect r = [_tableView rectOfRow: row]; //NSRect r = [_tableView rectOfRow: row];
@ -311,7 +348,7 @@ enum {
[_tableView reloadDataForRowIndexes: rIx columnIndexes: cIx]; [_tableView reloadDataForRowIndexes: rIx columnIndexes: cIx];
} }
#endif
-(void)initializeExtensionMenu { -(void)initializeExtensionMenu {
@ -350,7 +387,7 @@ enum {
[self setCurrentCount: 0]; [self setCurrentCount: 0];
[self setActive: NO]; [self setActive: NO];
[_tableView reloadData]; //[_tableView reloadData];
//[_tableView setNeedsDisplay: YES]; // doesn't work... //[_tableView setNeedsDisplay: YES]; // doesn't work...
} }
@ -368,7 +405,7 @@ enum {
if (delta) { if (delta) {
[self setActive: YES]; [self setActive: YES];
[_tableView reloadData]; //[_tableView reloadData];
} }
} }
- (IBAction)showRomFolder:(id)sender { - (IBAction)showRomFolder:(id)sender {
@ -399,11 +436,10 @@ enum {
[item setLocalURL: [NSURL fileURLWithPath: path]]; [item setLocalURL: [NSURL fileURLWithPath: path]];
continue; continue;
} }
[item setStatus: ItemMissing];
[item setLocalURL: nil];
} }
// only needed if items aren't bound.
[_tableView reloadData];
} }
- (IBAction)showInFinder:(id)sender { - (IBAction)showInFinder:(id)sender {
@ -422,14 +458,14 @@ enum {
[self downloadItem: item]; [self downloadItem: item];
[self setActive: YES]; [self setActive: YES];
[self redrawRow: [item index]]; //[self redrawRow: [item index]];
} }
- (IBAction)cancel:(id)sender { - (IBAction)cancel:(id)sender {
DownloadItem *item = [self clickedItem]; DownloadItem *item = [self clickedItem];
if (!item) return; if (!item) return;
[item cancelDownload]; [item cancelDownload];
[self redrawRow: [item index]]; //[self redrawRow: [item index]];
} }
// binding screws up with placeholder. // binding screws up with placeholder.
@ -449,6 +485,36 @@ enum {
[_defaults setValue: _downloadExtension forKey: kDownloadExtension]; [_defaults setValue: _downloadExtension forKey: kDownloadExtension];
} }
- (IBAction)filterButton:(id)sender {
NSPredicate *p = nil;
NSUInteger tag = [sender tag];
[sender setState: NSControlStateValueOn];
for (NSButton *b in _filterButtons) {
if (b != sender) [b setState: NSControlStateValueOff];
}
switch (tag) {
case 1: // all
default:
[_arrayController setFilterPredicate: nil];
break;
case 2: // missing.
p = [NSPredicate predicateWithBlock: ^BOOL(DownloadItem *item, NSDictionary *bindings){
NSURL *localURL = [item localURL];
return localURL == nil;
}];
[_arrayController setFilterPredicate: p];
break;
}
}
#pragma mark - NSURLSessionDelegate #pragma mark - NSURLSessionDelegate
static NSInteger TaskStatusCode(NSURLSessionTask *task) { static NSInteger TaskStatusCode(NSURLSessionTask *task) {
@ -495,9 +561,9 @@ static NSInteger TaskStatusCode(NSURLSessionTask *task) {
if (item) { if (item) {
[item completeWithError: error]; [item completeWithError: error];
NSUInteger row = [item index]; //NSUInteger row = [item index];
[self redrawRow: row]; //[self redrawRow: row];
} }
}); });
@ -536,91 +602,46 @@ static NSInteger TaskStatusCode(NSURLSessionTask *task) {
@end @end
@implementation DownloadWindowController (Table)
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return [_items count];
}
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
return [_items objectAtIndex: row];
}
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
DownloadItem *item = [_items objectAtIndex: row];
DownloadTableCellView *v = [tableView makeViewWithIdentifier: @"DownloadCell" owner: self];
NSTextField *tf;
NSColor *redColor = [NSColor systemRedColor];
tf = [v textField];
[[v textField] setObjectValue: [item name]];
if ([item localURL]) {
[tf setTextColor: nil];
} else {
[tf setTextColor: redColor];
}
tf = [v statusTextField];
[tf setObjectValue: [item statusDescription]];
if ([item error]) {
[tf setTextColor: redColor];
} else {
[tf setTextColor: nil];
//if ([tableView isRowSelected: row]){
//[tf setTextColor: [NSColor whiteColor]];
//}
}
if ([item task]) {
[[v activity] startAnimation: nil];
} else {
[[v activity] stopAnimation: nil];
}
return v;
}
@end
@implementation DownloadTableCellView
@end
@implementation DownloadItem @implementation DownloadItem
-(void)beginDownloadWithTask:(NSURLSessionDownloadTask *)task { -(void)beginDownloadWithTask:(NSURLSessionDownloadTask *)task {
_task = task; [self setTask: task];
_error = nil; [self setError: nil];
if (task) _status = ItemDownloading; if (task) [self setStatus: ItemDownloading];
} }
-(void)cancelDownload { -(void)cancelDownload {
if (!_task) return; if (!_task) return;
[_task cancel]; [_task cancel];
_task = nil; [self setTask: nil];
_status = ItemCanceled; [self setStatus: ItemCanceled];
} }
-(void)completeWithError: (NSError *)error { -(void)completeWithError: (NSError *)error {
_task = nil; [self setTask: nil];
if (error) { if (error) {
_error = error; [self setError: error];
_status = ItemError; [self setStatus: ItemError];
} else { } else {
// what if there was an error moving it? // what if there was an error moving it?
_error = nil; [self setError: nil];
_status = ItemDownloaded; [self setStatus: ItemDownloaded];
} }
} }
#if 0
// in practice, error and status set concurrently.
+(NSSet *)keyPathsForValuesAffectingStatus {
static NSSet *set = nil;
if (!set) set = [NSSet setWithObjects: @"error", nil];
return set;
}
#endif
-(NSString *)statusDescription { -(NSString *)statusDescription {
static NSString *Names[] = { static NSString *Names[] = {
@ -637,6 +658,19 @@ static NSInteger TaskStatusCode(NSURLSessionTask *task) {
return Names[_status]; return Names[_status];
} }
+(NSSet *)keyPathsForValuesAffectingTitleColor {
return [NSSet setWithObject: @"localURL"];
}
-(NSColor *)titleColor {
return _localURL ? nil : [NSColor systemRedColor];
}
+(NSSet *)keyPathsForValuesAffectingDescriptionColor {
return [NSSet setWithObject: @"error"];
}
-(NSColor *)descriptionColor {
return _error ? [NSColor systemRedColor] : nil;
}
@end @end
@ -655,7 +689,7 @@ enum {
NSInteger row = [_tableView clickedRow]; NSInteger row = [_tableView clickedRow];
if (row < 0) return NO; if (row < 0) return NO;
DownloadItem *item = [_items objectAtIndex: row]; DownloadItem *item = [[_arrayController arrangedObjects] objectAtIndex: row]; //[_items objectAtIndex: row];
NSUInteger status = [item status]; NSUInteger status = [item status];
switch([menuItem tag]) { switch([menuItem tag]) {