From d2cbbe01fad30e39908186c268254c408bcd3523 Mon Sep 17 00:00:00 2001 From: Mitchell Livingston Date: Wed, 8 Aug 2007 01:03:34 +0000 Subject: [PATCH] begins of individual action menus --- Transmission.xcodeproj/project.pbxproj | 8 ++ macosx/Images/ActionOff.png | Bin 0 -> 454 bytes macosx/Images/ActionOn.png | Bin 0 -> 457 bytes macosx/Torrent.h | 4 + macosx/Torrent.m | 13 ++ macosx/TorrentCell.m | 5 +- macosx/TorrentTableView.h | 18 ++- macosx/TorrentTableView.m | 169 +++++++++++++++++++++++-- 8 files changed, 198 insertions(+), 19 deletions(-) create mode 100644 macosx/Images/ActionOff.png create mode 100644 macosx/Images/ActionOn.png diff --git a/Transmission.xcodeproj/project.pbxproj b/Transmission.xcodeproj/project.pbxproj index 748f05eef..6cbf55de1 100644 --- a/Transmission.xcodeproj/project.pbxproj +++ b/Transmission.xcodeproj/project.pbxproj @@ -99,6 +99,8 @@ A261F1DC0A69A1610002815A /* Growl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A261F1DB0A69A1610002815A /* Growl.framework */; }; A261F1E40A69A1B10002815A /* Growl.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = A261F1DB0A69A1610002815A /* Growl.framework */; }; A2710E770A86796000CE4F7D /* PrefsWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = A2710E750A86796000CE4F7D /* PrefsWindow.m */; }; + A277DA0B0C693D9C00DA2CD4 /* ActionOn.png in Resources */ = {isa = PBXBuildFile; fileRef = A277DA090C693D9C00DA2CD4 /* ActionOn.png */; }; + A277DA0C0C693D9C00DA2CD4 /* ActionOff.png in Resources */ = {isa = PBXBuildFile; fileRef = A277DA0A0C693D9C00DA2CD4 /* ActionOff.png */; }; A27A53570A06A76400E1F16F /* StatusSep.png in Resources */ = {isa = PBXBuildFile; fileRef = A27A53560A06A76400E1F16F /* StatusSep.png */; }; A27ABC240A6ADE410020EC71 /* ImageBackgroundView.m in Sources */ = {isa = PBXBuildFile; fileRef = A27ABC220A6ADE410020EC71 /* ImageBackgroundView.m */; }; A289EB0C0A33C56D00B082A3 /* ButtonBorder.png in Resources */ = {isa = PBXBuildFile; fileRef = A289EB0B0A33C56D00B082A3 /* ButtonBorder.png */; }; @@ -423,6 +425,8 @@ A2710E750A86796000CE4F7D /* PrefsWindow.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = PrefsWindow.m; path = macosx/PrefsWindow.m; sourceTree = ""; }; A27431D80A68538400FA780A /* FilterBarButton.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = FilterBarButton.h; path = macosx/FilterBarButton.h; sourceTree = ""; }; A27431D90A68538400FA780A /* FilterBarButton.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = FilterBarButton.m; path = macosx/FilterBarButton.m; sourceTree = ""; }; + A277DA090C693D9C00DA2CD4 /* ActionOn.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ActionOn.png; path = macosx/Images/ActionOn.png; sourceTree = ""; }; + A277DA0A0C693D9C00DA2CD4 /* ActionOff.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ActionOff.png; path = macosx/Images/ActionOff.png; sourceTree = ""; }; A27A53420A06A62500E1F16F /* StatusSep.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = StatusSep.png; path = macosx/Images/StatusSep.png; sourceTree = ""; }; A27A53560A06A76400E1F16F /* StatusSep.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = StatusSep.png; path = macosx/Images/StatusSep.png; sourceTree = ""; }; A27ABC210A6ADE410020EC71 /* ImageBackgroundView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ImageBackgroundView.h; path = macosx/ImageBackgroundView.h; sourceTree = ""; }; @@ -723,6 +727,8 @@ A2E9AA750C249AF400085DCF /* Create.png */, A2F011980C27418800576FC0 /* CreateLarge.png */, 4DF7500908A103AD007B0D70 /* Remove.png */, + A277DA090C693D9C00DA2CD4 /* ActionOn.png */, + A277DA0A0C693D9C00DA2CD4 /* ActionOff.png */, 35B037F90AC5B53800A10FDF /* ResumeNoWaitOn.png */, 35B037FA0AC5B53800A10FDF /* ResumeNoWaitOff.png */, 4D6DAAC4090CE00500F43C22 /* RevealOff.png */, @@ -1240,6 +1246,8 @@ A2085E3F0C53C949000BC3B7 /* LICENSE in Resources */, A22BC9A30C5BBCF100F5FB72 /* BottomBorder.png in Resources */, A2AE68330C628A35008753C9 /* Creator.nib in Resources */, + A277DA0B0C693D9C00DA2CD4 /* ActionOn.png in Resources */, + A277DA0C0C693D9C00DA2CD4 /* ActionOff.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/macosx/Images/ActionOff.png b/macosx/Images/ActionOff.png new file mode 100644 index 0000000000000000000000000000000000000000..c1c40df953f300af10e587abb2ed73b31a498ed9 GIT binary patch literal 454 zcmV;%0XhDOP)zI9T6_VBzW@Xf3)E*AmhIWIX99@b+1c3v6R)bOQZ6qq zuK=-KTwDrBu#^RA#~FYCVuA)E3pQ1Je0(act*vuld=MKX#y}nb*`WXsKupj$LjfR{ zBm3;$y?Z-A7{&+5kr<>fAOa9TAi@D1|3?CM@7~=G69=)8Iu; w0FWII00M~a86O~k7>Oy`C;%8m8$f^o00ub8QkP^p4gdfE07*qoM6N<$g16D6C;$Ke literal 0 HcmV?d00001 diff --git a/macosx/Images/ActionOn.png b/macosx/Images/ActionOn.png new file mode 100644 index 0000000000000000000000000000000000000000..9b1be3f6a6db7c94cb05530a07fd1149a7f2734d GIT binary patch literal 457 zcmV;)0XF`LP)IM0%Rn0V0mOHJ_&5-M0to;F5F=DV6o|u+EmBZW z0J9%Fc<|%@|NlK;#f*$4$l@egyb6e40|XEg)Mpr$9Xoa`6NJOU!lYp0AT~@KW-*a~ z18N5!Kmaj8gAuD{Nl8iRl`B^k!T2CHNQ{9z0J6gpAb^;lafSjw!BtRDuoA{UdGh3G z5QgzVawG;R45$DE5GW3d(M4f#2D8kr;{Hc_b zR6n}e00G3rKm`Eut(BG4bdV)5%Rqc=Y5@WW3X zSg?@+Kz1Al2q3y=e1HIAB&KMi0ALht009O7mk*;4E4pp800000NkvXXu0mjfW*({} literal 0 HcmV?d00001 diff --git a/macosx/Torrent.h b/macosx/Torrent.h index 1e4bfee34..a317e3656 100644 --- a/macosx/Torrent.h +++ b/macosx/Torrent.h @@ -55,6 +55,8 @@ tr_file_stat_t * fileStat; NSArray * fFileList, * fFlatFileList; + NSMenu * fTorrentMenu; + float fRatioLimit; int fRatioSetting; BOOL fFinishedSeeding, fWaitToStart, fError, fChecking, fStalled; @@ -208,6 +210,8 @@ - (BOOL) hasFilePriority: (int) priority forIndexes: (NSIndexSet *) indexSet; - (NSSet *) filePrioritiesForIndexes: (NSIndexSet *) indexSet; +- (NSMenu *) torrentMenu; + - (NSDate *) dateAdded; - (NSDate *) dateCompleted; - (NSDate *) dateActivity; diff --git a/macosx/Torrent.m b/macosx/Torrent.m index 7dc7639c5..7f1748f47 100644 --- a/macosx/Torrent.m +++ b/macosx/Torrent.m @@ -183,6 +183,8 @@ static uint32_t kRed = BE(0xFF6450FF), //255, 100, 80 [fFileList release]; [fFlatFileList release]; + [fTorrentMenu release]; + [fQuickPauseDict release]; [fBitmap release]; @@ -1342,6 +1344,7 @@ static uint32_t kRed = BE(0xFF6450FF), //255, 100, 80 return NO; } +#warning rename to match priorities - (NSSet *) filePrioritiesForIndexes: (NSIndexSet *) indexSet { BOOL low = NO, normal = NO, high = NO; @@ -1380,6 +1383,16 @@ static uint32_t kRed = BE(0xFF6450FF), //255, 100, 80 return priorities; } +- (NSMenu *) torrentMenu +{ + if (!fTorrentMenu) + { + fTorrentMenu = [[NSMenu alloc] initWithTitle: [@"TorrentMenu:" stringByAppendingString: [self name]]]; + [fTorrentMenu setAutoenablesItems: NO]; + } + return fTorrentMenu; +} + - (NSDate *) dateAdded { return fDateAdded; diff --git a/macosx/TorrentCell.m b/macosx/TorrentCell.m index 4cb397dbc..02ba38d1e 100644 --- a/macosx/TorrentCell.m +++ b/macosx/TorrentCell.m @@ -183,7 +183,7 @@ [paragraphStyle release]; NSPoint pen = cellFrame.origin; - const float PADDING = 3.0, LINE_PADDING = 2.0, EXTRA_NAME_SHIFT = 1.0; + const float LINE_PADDING = 2.0, EXTRA_NAME_SHIFT = 1.0; //standard padding defined in TorrentCell.h NSDictionary * info = [self objectValue]; @@ -194,7 +194,8 @@ NSSize iconSize = [icon size]; pen.x += PADDING; - pen.y += (cellFrame.size.height - iconSize.height) * 0.5; + #warning use constant + pen.y += (cellFrame.size.height - (iconSize.height + ACTION_BUTTON_HEIGHT)) * 0.5; [icon drawAtPoint: pen fromRect: NSMakeRect(0, 0, iconSize.width, iconSize.height) operation: NSCompositeSourceOver fraction: 1.0]; diff --git a/macosx/TorrentTableView.h b/macosx/TorrentTableView.h index f2c80c24c..761c98fd0 100644 --- a/macosx/TorrentTableView.h +++ b/macosx/TorrentTableView.h @@ -25,8 +25,15 @@ #import #import +#define PADDING 3.0 + +//button layout (from end of bar) is: padding, button, padding, button, padding +#define BUTTON_WIDTH 14.0 #define BUTTONS_TOTAL_WIDTH 39.0 +#define ACTION_BUTTON_HEIGHT 12.0 +#define ACTION_BUTTON_WIDTH 28.0 + @class Controller; @interface TorrentTableView : NSTableView @@ -39,15 +46,18 @@ NSUserDefaults * fDefaults; IBOutlet NSMenu * fContextRow, * fContextNoRow; - NSImage * fResumeOnIcon, * fResumeOffIcon, - * fPauseOnIcon, * fPauseOffIcon, - * fResumeNoWaitOnIcon, * fResumeNoWaitOffIcon, - * fRevealOnIcon, * fRevealOffIcon; + NSImage * fResumeOnIcon, * fResumeOffIcon, * fPauseOnIcon, * fPauseOffIcon, + * fResumeNoWaitOnIcon, * fResumeNoWaitOffIcon, * fRevealOnIcon, * fRevealOffIcon, + * fActionOnIcon, * fActionOffIcon; NSMutableArray * fKeyStrokes; NSDictionary * fSmallStatusAttributes; } + - (void) setTorrents: (NSArray *) torrents; +- (void) displayTorrentMenuForEvent: (NSEvent *) event; +- (void) checkFile: (id) sender; + @end diff --git a/macosx/TorrentTableView.m b/macosx/TorrentTableView.m index 78e0f51b7..11749a65c 100644 --- a/macosx/TorrentTableView.m +++ b/macosx/TorrentTableView.m @@ -30,20 +30,21 @@ #define BUTTON_TO_TOP_REGULAR 33.0 #define BUTTON_TO_TOP_SMALL 20.0 -//button layout (from end of bar) is: padding, button, padding, button, padding -//change BUTTONS_TOTAL_WIDTH in .h when changing these values, add 2.0 to that value -#define BUTTON_WIDTH 14.0 -#define PADDING 3.0 +#define ACTION_BUTTON_TO_TOP 47.0 @interface TorrentTableView (Private) - (NSRect) pauseRectForRow: (int) row; - (NSRect) revealRectForRow: (int) row; -- (BOOL) pointInPauseRect: (NSPoint) point; -- (BOOL) pointInRevealRect: (NSPoint) point; +- (NSRect) actionRectForRow: (int) row; + - (BOOL) pointInIconRect: (NSPoint) point; - (BOOL) pointInMinimalStatusRect: (NSPoint) point; +- (BOOL) pointInPauseRect: (NSPoint) point; +- (BOOL) pointInRevealRect: (NSPoint) point; +- (BOOL) pointInActionRect: (NSPoint) point; + @end @implementation TorrentTableView @@ -55,12 +56,16 @@ fResumeOnIcon = [NSImage imageNamed: @"ResumeOn.png"]; fResumeOffIcon = [NSImage imageNamed: @"ResumeOff.png"]; fPauseOnIcon = [NSImage imageNamed: @"PauseOn.png"]; + fPauseOffIcon = [NSImage imageNamed: @"PauseOff.png"]; fResumeNoWaitOnIcon = [NSImage imageNamed: @"ResumeNoWaitOn.png"]; fResumeNoWaitOffIcon = [NSImage imageNamed: @"ResumeNoWaitOff.png"]; - fPauseOffIcon = [NSImage imageNamed: @"PauseOff.png"]; + fRevealOnIcon = [NSImage imageNamed: @"RevealOn.png"]; fRevealOffIcon = [NSImage imageNamed: @"RevealOff.png"]; + fActionOnIcon = [NSImage imageNamed: @"ActionOn.png"]; + fActionOffIcon = [NSImage imageNamed: @"ActionOff.png"]; + fClickPoint = NSZeroPoint; fKeyStrokes = [[NSMutableArray alloc] init]; @@ -96,7 +101,14 @@ { fClickPoint = [self convertPoint: [event locationInWindow] fromView: nil]; - if (![self pointInPauseRect: fClickPoint] && ![self pointInRevealRect: fClickPoint]) + if ([self pointInActionRect: fClickPoint]) + { + #warning use icon that doesn't change? + [self display]; //ensure button is pushed down + [self displayTorrentMenuForEvent: event]; + #warning get icon to change back + } + else if (![self pointInPauseRect: fClickPoint] && ![self pointInRevealRect: fClickPoint]) { if ([event modifierFlags] & NSAlternateKeyMask) { @@ -234,6 +246,101 @@ [self scrollRowToVisible: row]; } +- (void) displayTorrentMenuForEvent: (NSEvent *) event +{ + int row = [self rowAtPoint: [self convertPoint: [event locationInWindow] fromView: nil]]; + if (row < 0) + return; + + NSMenu * torrentMenu = [[fTorrents objectAtIndex: row] torrentMenu]; + [torrentMenu setDelegate: self]; + + NSRect rect = [self actionRectForRow: row]; + NSPoint location = rect.origin; + location.y += rect.size.height + 5.0; + location = [self convertPoint: location toView: nil]; + + NSEvent * newEvent = [NSEvent mouseEventWithType: [event type] location: location + modifierFlags: [event modifierFlags] timestamp: [event timestamp] windowNumber: [event windowNumber] + context: [event context] eventNumber: [event eventNumber] clickCount: [event clickCount] pressure: [event pressure]]; + + [NSMenu popUpContextMenu: torrentMenu withEvent: newEvent forView: self]; +} + +- (void) menuNeedsUpdate: (NSMenu *) menu +{ + BOOL create = [menu numberOfItems] <= 0, folder; + + Torrent * torrent = [fTorrents objectAtIndex: [self rowAtPoint: fClickPoint]]; + + NSMenu * supermenu = [menu supermenu]; + NSArray * items; + if (supermenu) + items = [[[supermenu itemAtIndex: [supermenu indexOfItemWithSubmenu: menu]] representedObject] objectForKey: @"Children"]; + else + items = [torrent fileList]; + NSEnumerator * enumerator = [items objectEnumerator]; + NSDictionary * dict; + while ((dict = [enumerator nextObject])) + { + NSMenuItem * item; + NSString * name = [dict objectForKey: @"Name"]; + + folder = [[dict objectForKey: @"IsFolder"] boolValue]; + + if (create) + { + item = [[NSMenuItem alloc] initWithTitle: name action: NULL keyEquivalent: @""]; + [menu addItem: item]; + [item release]; + + NSImage * icon; + if (!folder) + { + [item setAction: @selector(checkFile:)]; + + icon = [[dict objectForKey: @"Icon"] copy]; + [icon setFlipped: NO]; + } + else + { + NSMenu * menu = [[NSMenu alloc] initWithTitle: name]; + [menu setAutoenablesItems: NO]; + [item setSubmenu: menu]; + [menu setDelegate: self]; + + icon = [[[NSWorkspace sharedWorkspace] iconForFileType: NSFileTypeForHFSTypeCode('fldr')] copy]; + } + + [item setRepresentedObject: dict]; + + [icon setScalesWhenResized: YES]; + [icon setSize: NSMakeSize(16.0, 16.0)]; + [item setImage: icon]; + [icon release]; + } + else + item = [menu itemWithTitle: name]; + + if (!folder) + { + NSIndexSet * indexSet = [dict objectForKey: @"Indexes"]; + [item setState: [torrent checkForFiles: indexSet]]; + [item setEnabled: [torrent canChangeDownloadCheckForFiles: indexSet]]; + } + } +} + +- (void) checkFile: (id) sender +{ + NSIndexSet * indexes = [[sender representedObject] objectForKey: @"Indexes"]; + Torrent * torrent = [fTorrents objectAtIndex: [self rowAtPoint: fClickPoint]]; + + [torrent setFileCheckState: [sender state] != NSOnState ? NSOnState : NSOffState forIndexes: indexes]; + #warning reload inspector -> files +} + +#warning only update shown - (void) drawRect: (NSRect) r { NSRect rect; @@ -271,6 +378,10 @@ rect = [self revealRectForRow: i]; image = NSPointInRect(fClickPoint, rect) ? fRevealOnIcon : fRevealOffIcon; [image compositeToPoint: NSMakePoint(rect.origin.x, NSMaxY(rect)) operation: NSCompositeSourceOver]; + + #warning make change + rect = [self actionRectForRow: i]; + [fActionOffIcon compositeToPoint: NSMakePoint(rect.origin.x, NSMaxY(rect)) operation: NSCompositeSourceOver]; } } @@ -298,18 +409,33 @@ cellRect.origin.y + buttonToTop, BUTTON_WIDTH, BUTTON_WIDTH); } +- (NSRect) actionRectForRow: (int) row +{ + #warning return small icon rect + if ([fDefaults boolForKey: @"SmallView"]) + return NSZeroRect; + + NSRect cellRect = [self frameOfCellAtColumn: [self columnWithIdentifier: @"Torrent"] row: row]; + + #warning constant + return NSMakeRect(cellRect.origin.x + PADDING + + ([[[fTorrents objectAtIndex: row] iconFlipped] size].width - ACTION_BUTTON_WIDTH) * 0.5, + cellRect.origin.y + ACTION_BUTTON_TO_TOP, ACTION_BUTTON_WIDTH, ACTION_BUTTON_HEIGHT); +} + - (BOOL) pointInIconRect: (NSPoint) point { int row = [self rowAtPoint: point]; if (row < 0) return NO; - + + #warning move to own method NSRect cellRect = [self frameOfCellAtColumn: [self columnWithIdentifier: @"Torrent"] row: row]; NSSize iconSize = [fDefaults boolForKey: @"SmallView"] ? [[[fTorrents objectAtIndex: row] iconSmall] size] : [[[fTorrents objectAtIndex: row] iconFlipped] size]; - NSRect iconRect = NSMakeRect(cellRect.origin.x + 3.0, cellRect.origin.y - + (cellRect.size.height - iconSize.height) * 0.5, iconSize.width, iconSize.height); + NSRect iconRect = NSMakeRect(cellRect.origin.x + 3.0, cellRect.origin.y + (cellRect.size.height - iconSize.height) * 0.5, + iconSize.width, iconSize.height); return NSPointInRect(point, iconRect); } @@ -335,12 +461,29 @@ - (BOOL) pointInPauseRect: (NSPoint) point { - return NSPointInRect(point, [self pauseRectForRow: [self rowAtPoint: point]]); + int row = [self rowAtPoint: point]; + if (row < 0) + return NO; + + return NSPointInRect(point, [self pauseRectForRow: row]); } - (BOOL) pointInRevealRect: (NSPoint) point { - return NSPointInRect(point, [self revealRectForRow: [self rowAtPoint: point]]); + int row = [self rowAtPoint: point]; + if (row < 0) + return NO; + + return NSPointInRect(point, [self revealRectForRow: row]); +} + +- (BOOL) pointInActionRect: (NSPoint) point +{ + int row = [self rowAtPoint: point]; + if (row < 0) + return NO; + + return NSPointInRect(point, [self actionRectForRow: row]); } @end