diff --git a/Transmission.xcodeproj/project.pbxproj b/Transmission.xcodeproj/project.pbxproj index 5d7bdb8dc..7fe7c2c98 100644 --- a/Transmission.xcodeproj/project.pbxproj +++ b/Transmission.xcodeproj/project.pbxproj @@ -10,6 +10,10 @@ 002C9EE60C19CD2500C2F6F4 /* fastresume.c in Sources */ = {isa = PBXBuildFile; fileRef = 002C9EE50C19CD2500C2F6F4 /* fastresume.c */; }; 35B038130AC5B6EB00A10FDF /* ResumeNoWaitOn.png in Resources */ = {isa = PBXBuildFile; fileRef = 35B037F90AC5B53800A10FDF /* ResumeNoWaitOn.png */; }; 35B038140AC5B6EC00A10FDF /* ResumeNoWaitOff.png in Resources */ = {isa = PBXBuildFile; fileRef = 35B037FA0AC5B53800A10FDF /* ResumeNoWaitOff.png */; }; + 35F372140C2D780600DAA8F2 /* InfoWindow.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 35F372120C2D780500DAA8F2 /* InfoWindow.h */; }; + 35F372150C2D780600DAA8F2 /* InfoWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 35F372130C2D780600DAA8F2 /* InfoWindow.m */; }; + 35F373020C2DA88F00DAA8F2 /* FilePriorityCell.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 35F373000C2DA88F00DAA8F2 /* FilePriorityCell.h */; }; + 35F373030C2DA89000DAA8F2 /* FilePriorityCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 35F373010C2DA88F00DAA8F2 /* FilePriorityCell.m */; }; 4D043A7F090AE979009FEDA8 /* TransmissionDocument.icns in Resources */ = {isa = PBXBuildFile; fileRef = 4D043A7E090AE979009FEDA8 /* TransmissionDocument.icns */; }; 4D118E1A08CB46B20033958F /* PrefsController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D118E1908CB46B20033958F /* PrefsController.m */; }; 4D1838DD09DEC0E80047D688 /* libtransmission.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D18389709DEC0030047D688 /* libtransmission.a */; }; @@ -250,6 +254,8 @@ A261F1E40A69A1B10002815A /* Growl.framework in CopyFiles */, A24F19210A3A796800C9C145 /* Sparkle.framework in CopyFiles */, A2DF37060C220D03006523C1 /* CreatorWindowController.h in CopyFiles */, + 35F372140C2D780600DAA8F2 /* InfoWindow.h in CopyFiles */, + 35F373020C2DA88F00DAA8F2 /* FilePriorityCell.h in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -267,6 +273,10 @@ 32CA4F630368D1EE00C91783 /* Transmission_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Transmission_Prefix.pch; path = macosx/Transmission_Prefix.pch; sourceTree = ""; }; 35B037F90AC5B53800A10FDF /* ResumeNoWaitOn.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ResumeNoWaitOn.png; path = macosx/Images/ResumeNoWaitOn.png; sourceTree = ""; }; 35B037FA0AC5B53800A10FDF /* ResumeNoWaitOff.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ResumeNoWaitOff.png; path = macosx/Images/ResumeNoWaitOff.png; sourceTree = ""; }; + 35F372120C2D780500DAA8F2 /* InfoWindow.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = InfoWindow.h; path = macosx/InfoWindow.h; sourceTree = ""; }; + 35F372130C2D780600DAA8F2 /* InfoWindow.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = InfoWindow.m; path = macosx/InfoWindow.m; sourceTree = ""; }; + 35F373000C2DA88F00DAA8F2 /* FilePriorityCell.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = FilePriorityCell.h; path = macosx/FilePriorityCell.h; sourceTree = ""; }; + 35F373010C2DA88F00DAA8F2 /* FilePriorityCell.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = FilePriorityCell.m; path = macosx/FilePriorityCell.m; sourceTree = ""; }; 4C9F8F060BC5B68A002E5433 /* French */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = French; path = macosx/French.lproj/InfoPlist.strings; sourceTree = ""; }; 4C9F8F070BC5B68A002E5433 /* French */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = French; path = macosx/French.lproj/InfoWindow.nib; sourceTree = ""; }; 4C9F8F080BC5B68A002E5433 /* French */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = French; path = macosx/French.lproj/Localizable.strings; sourceTree = ""; }; @@ -612,6 +622,10 @@ E1B6FC000C0D72A00015FE4D /* Overlay Window */, E138A9720C04D88F00C5426C /* CTGradient */, E1B6FBEB0C0D70AC0015FE4D /* UKKQueue */, + 35F372120C2D780500DAA8F2 /* InfoWindow.h */, + 35F372130C2D780600DAA8F2 /* InfoWindow.m */, + 35F373000C2DA88F00DAA8F2 /* FilePriorityCell.h */, + 35F373010C2DA88F00DAA8F2 /* FilePriorityCell.m */, ); name = Sources; sourceTree = ""; @@ -1278,6 +1292,8 @@ A24838820C0BA608005CC3FE /* FilterBarView.m in Sources */, A215760B0C0D449A0057A26A /* BezierPathAdditions.m in Sources */, A2DF37070C220D03006523C1 /* CreatorWindowController.m in Sources */, + 35F372150C2D780600DAA8F2 /* InfoWindow.m in Sources */, + 35F373030C2DA89000DAA8F2 /* FilePriorityCell.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/macosx/English.lproj/InfoWindow.nib/classes.nib b/macosx/English.lproj/InfoWindow.nib/classes.nib index 0c096a969..baa630998 100644 --- a/macosx/English.lproj/InfoWindow.nib/classes.nib +++ b/macosx/English.lproj/InfoWindow.nib/classes.nib @@ -2,6 +2,7 @@ IBClasses = ( {CLASS = FileOutlineView; LANGUAGE = ObjC; SUPERCLASS = NSOutlineView; }, {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + {CLASS = InfoWindow; LANGUAGE = ObjC; SUPERCLASS = NSPanel; }, { ACTIONS = { revealDataFile = id; diff --git a/macosx/English.lproj/InfoWindow.nib/info.nib b/macosx/English.lproj/InfoWindow.nib/info.nib index deb3e720f..d5f83ea10 100644 --- a/macosx/English.lproj/InfoWindow.nib/info.nib +++ b/macosx/English.lproj/InfoWindow.nib/info.nib @@ -3,7 +3,7 @@ IBDocumentLocation - 35 67 356 240 0 0 1152 842 + 29 56 356 240 0 0 1024 746 IBEditorPositions 549 diff --git a/macosx/English.lproj/InfoWindow.nib/keyedobjects.nib b/macosx/English.lproj/InfoWindow.nib/keyedobjects.nib index 88b55fa13..cf4729498 100644 Binary files a/macosx/English.lproj/InfoWindow.nib/keyedobjects.nib and b/macosx/English.lproj/InfoWindow.nib/keyedobjects.nib differ diff --git a/macosx/FileBrowserCell.m b/macosx/FileBrowserCell.m index 036a01c9c..ab588ef55 100644 --- a/macosx/FileBrowserCell.m +++ b/macosx/FileBrowserCell.m @@ -51,9 +51,7 @@ - (void) drawWithFrame: (NSRect) cellFrame inView: (NSView *) controlView { - NSMutableDictionary * item; - if (!(item = [self objectValue])) - return; + NSMutableDictionary * item = [self objectValue]; //image float imageHeight = cellFrame.size.height - 2.0; diff --git a/macosx/FileOutlineView.h b/macosx/FileOutlineView.h index 8909b4819..505896ee2 100644 --- a/macosx/FileOutlineView.h +++ b/macosx/FileOutlineView.h @@ -27,6 +27,11 @@ @interface FileOutlineView : NSOutlineView { NSColor * fNormalColor, * fHighPriorityColor, * fLowPriorityColor; + + int fHoverRow; } +- (void) setHoverRowForEvent: (NSEvent *) event; +- (int) hoverRow; + @end diff --git a/macosx/FileOutlineView.m b/macosx/FileOutlineView.m index d9dd79edc..1d3eb0329 100644 --- a/macosx/FileOutlineView.m +++ b/macosx/FileOutlineView.m @@ -39,6 +39,8 @@ fNormalColor = [self backgroundColor]; fHighPriorityColor = [[NSColor colorWithCalibratedRed: 0.678 green: 0.937 blue: 0.451 alpha: 1.0] retain]; fLowPriorityColor = [[NSColor colorWithCalibratedRed: 0.984 green: 0.878 blue: 0.431 alpha: 1.0] retain]; + + fHoverRow = -1; } - (void) dealloc @@ -70,6 +72,31 @@ return [self menu]; } +- (void) setHoverRowForEvent: (NSEvent *) event +{ + int row = -1; + if (event) + { + NSPoint point = [self convertPoint: [event locationInWindow] fromView: nil]; + if (NSPointInRect(point, [self frame])) + row = [self rowAtPoint: point]; + } + + if (row != fHoverRow) + { + if (fHoverRow != -1) + [self reloadItem: [self itemAtRow: fHoverRow]]; + fHoverRow = row; + if (fHoverRow != -1) + [self reloadItem: [self itemAtRow: fHoverRow]]; + } +} + +- (int) hoverRow +{ + return fHoverRow; +} + - (void) drawRow: (int) row clipRect: (NSRect) clipRect { if (![self isRowSelected: row]) diff --git a/macosx/FilePriorityCell.h b/macosx/FilePriorityCell.h new file mode 100644 index 000000000..7954e76ca --- /dev/null +++ b/macosx/FilePriorityCell.h @@ -0,0 +1,15 @@ +/* FilePriorityCell */ + +#import +#import "FileOutlineView.h" + +@interface FilePriorityCell : NSSegmentedCell +{ + FileOutlineView * fParentView; + NSMutableDictionary * fItem; +} + +- (id) initForParentView: (FileOutlineView *) parentView; +- (void) setItem: (NSMutableDictionary *) item; + +@end diff --git a/macosx/FilePriorityCell.m b/macosx/FilePriorityCell.m new file mode 100644 index 000000000..eb9e4f809 --- /dev/null +++ b/macosx/FilePriorityCell.m @@ -0,0 +1,102 @@ +#import "FilePriorityCell.h" +#import "Torrent.h" + +@implementation FilePriorityCell + +- (id) initForParentView: (FileOutlineView *) parentView +{ + if ((self = [super init])) + { + [self setTrackingMode: NSSegmentSwitchTrackingSelectAny]; + [self setControlSize: NSMiniControlSize]; + [self setSegmentCount: 3]; + + int i; + for (i = 0; i < [self segmentCount]; i++) + { + [self setLabel: @"" forSegment: i]; + [self setWidth: 6.0 forSegment: i]; + } + + #warning better way? + fParentView = parentView; + } + return self; +} + +- (void) setItem: (NSMutableDictionary *) item +{ + fItem = item; +} + +- (void) setSelected: (BOOL) flag forSegment: (int) segment +{ + [super setSelected: flag forSegment: segment]; + + //only for when clicking manually + Torrent * torrent = [fItem objectForKey: @"Torrent"]; + if (![torrent canChangeDownloadCheckForFiles: [fItem objectForKey: @"Indexes"]]) + return; + + int priority = segment, actualPriority; + if (priority == 0) + actualPriority = PRIORITY_LOW; + else if (priority == 2) + actualPriority = PRIORITY_HIGH; + else + actualPriority = PRIORITY_NORMAL; + + [torrent setFilePriority: actualPriority forIndexes: [fItem objectForKey: @"Indexes"]]; + [fParentView reloadData]; +} + +- (void) drawWithFrame: (NSRect) cellFrame inView: (NSView *) controlView +{ + Torrent * torrent = [fItem objectForKey: @"Torrent"]; + NSIndexSet * indexSet = [fItem objectForKey: @"Indexes"]; + + if (![torrent canChangeDownloadCheckForFiles: indexSet]) + return; + + BOOL low = [torrent hasFilePriority: PRIORITY_LOW forIndexes: indexSet], + normal = [torrent hasFilePriority: PRIORITY_NORMAL forIndexes: indexSet], + high = [torrent hasFilePriority: PRIORITY_HIGH forIndexes: indexSet]; + + int row = [fParentView hoverRow]; + if (row != -1 && [fParentView itemAtRow: row] == fItem) + { + [super setSelected: low forSegment: 0]; + [super setSelected: normal forSegment: 1]; + [super setSelected: high forSegment: 2]; + + [super drawWithFrame: cellFrame inView: controlView]; + } + else + { + if (high || low) + { + BOOL highlighted = [self isHighlighted] && [[self highlightColorWithFrame: cellFrame inView: controlView] + isEqual: [NSColor alternateSelectedControlColor]]; + NSDictionary * attributes = [[NSDictionary alloc] initWithObjectsAndKeys: + highlighted ? [NSColor whiteColor] : [NSColor controlTextColor], NSForegroundColorAttributeName, + [NSFont messageFontOfSize: 18.0], NSFontAttributeName, nil]; + + NSString * text; + if (low && !normal && !high) + text = @"-"; + else if (!low && !normal && high) + text = @"+"; + else + text = @"*"; + + NSSize textSize = [text sizeWithAttributes: attributes]; + NSRect textRect = NSMakeRect(cellFrame.origin.x + (cellFrame.size.width - textSize.width) * 0.5, + cellFrame.origin.y + (cellFrame.size.height - textSize.height) * 0.5, + textSize.width, textSize.height); + + [text drawInRect: textRect withAttributes: attributes]; + } + } +} + +@end diff --git a/macosx/InfoWindow.h b/macosx/InfoWindow.h new file mode 100644 index 000000000..7899767d8 --- /dev/null +++ b/macosx/InfoWindow.h @@ -0,0 +1,8 @@ +/* InfoWindow */ + +#import + +@interface InfoWindow : NSPanel +{ +} +@end diff --git a/macosx/InfoWindow.m b/macosx/InfoWindow.m new file mode 100644 index 000000000..89caf9596 --- /dev/null +++ b/macosx/InfoWindow.m @@ -0,0 +1,17 @@ +#import "InfoWindow.h" +#import "InfoWindowController.h" + +@implementation InfoWindow + +- (void) awakeFromNib +{ + [self setBecomesKeyOnlyIfNeeded: YES]; + [self setAcceptsMouseMovedEvents: YES]; +} + +- (void) mouseMoved: (NSEvent *) event +{ + [(InfoWindowController *)[self windowController] setFileOutlineHoverRowForEvent: event]; +} + +@end diff --git a/macosx/InfoWindowController.h b/macosx/InfoWindowController.h index faa0de8ba..59c45ab41 100644 --- a/macosx/InfoWindowController.h +++ b/macosx/InfoWindowController.h @@ -24,6 +24,7 @@ #import #import "Torrent.h" +#import "FileOutlineView.h" #import "PiecesView.h" #import @@ -53,7 +54,7 @@ IBOutlet PiecesView * fPiecesView; IBOutlet NSSegmentedControl * fPiecesControl; - IBOutlet NSOutlineView * fFileOutline; + IBOutlet FileOutlineView * fFileOutline; IBOutlet NSTextField * fFileTableStatusField; IBOutlet NSMenuItem * fFileCheckItem, * fFileUncheckItem, * fFilePriorityNormal, * fFilePriorityHigh, * fFilePriorityLow; @@ -61,7 +62,7 @@ IBOutlet NSPopUpButton * fRatioPopUp, * fUploadLimitPopUp, * fDownloadLimitPopUp; IBOutlet NSTextField * fUploadLimitField, * fDownloadLimitField, * fRatioLimitField, * fUploadLimitLabel, * fDownloadLimitLabel; - IBOutlet NSButton * fPexCheck; + IBOutlet NSButton * fPexCheck; } - (void) updateInfoForTorrents: (NSArray *) torrents; @@ -72,6 +73,8 @@ - (void) setNextTab; - (void) setPreviousTab; +- (void) setFileOutlineHoverRowForEvent: (NSEvent *) event; + - (void) setPiecesView: (id) sender; - (void) setPiecesViewForAvailable: (BOOL) available; diff --git a/macosx/InfoWindowController.m b/macosx/InfoWindowController.m index 71692e5da..4dade5fb3 100644 --- a/macosx/InfoWindowController.m +++ b/macosx/InfoWindowController.m @@ -24,6 +24,7 @@ #import "InfoWindowController.h" #import "FileBrowserCell.h" +#import "FilePriorityCell.h" #import "StringAdditions.h" #define MIN_WINDOW_WIDTH 300 @@ -87,8 +88,6 @@ //window location and size NSPanel * window = (NSPanel *)[self window]; - [window setBecomesKeyOnlyIfNeeded: YES]; - [window setFrameAutosaveName: @"InspectorWindowFrame"]; [window setFrameUsingName: @"InspectorWindowFrame"]; @@ -109,13 +108,8 @@ [fFileOutline setDoubleAction: @selector(revealFile:)]; //set file outline - NSSegmentedCell * priorityCell = [[fFileOutline tableColumnWithIdentifier: @"Priority"] dataCell]; - int i; - for (i = 0; i < [priorityCell segmentCount]; i++) - { - [priorityCell setLabel: @"" forSegment: i]; - [priorityCell setWidth: 6.0 forSegment: i]; - } + FilePriorityCell * priorityCell = [[[FilePriorityCell alloc] initForParentView: fFileOutline] autorelease]; + [[fFileOutline tableColumnWithIdentifier: @"Priority"] setDataCell: priorityCell]; //set blank inspector [self updateInfoForTorrents: [NSArray array]]; @@ -884,15 +878,7 @@ else if ([identifier isEqualToString: @"Check"]) [cell setEnabled: [[fTorrents objectAtIndex: 0] canChangeDownloadCheckForFiles: [item objectForKey: @"Indexes"]]]; else if ([identifier isEqualToString: @"Priority"]) - { - Torrent * torrent = [fTorrents objectAtIndex: 0]; - NSIndexSet * indexeSet = [item objectForKey: @"Indexes"]; - [(NSSegmentedCell *)cell setSelected: [torrent hasFilePriority: PRIORITY_LOW forIndexes: indexeSet] forSegment: 0]; - [(NSSegmentedCell *)cell setSelected: [torrent hasFilePriority: PRIORITY_NORMAL forIndexes: indexeSet] forSegment: 1]; - [(NSSegmentedCell *)cell setSelected: [torrent hasFilePriority: PRIORITY_HIGH forIndexes: indexeSet] forSegment: 2]; - - [cell setEnabled: [[fTorrents objectAtIndex: 0] canChangeDownloadCheckForFiles: [item objectForKey: @"Indexes"]]]; - } + [(FilePriorityCell *)cell setItem: item]; else; } @@ -907,22 +893,6 @@ forIndexes: [item objectForKey: @"Indexes"]]; [fFileOutline reloadData]; } - else if ([identifier isEqualToString: @"Priority"]) - { - if (![[fTorrents objectAtIndex: 0] canChangeDownloadCheckForFiles: [item objectForKey: @"Indexes"]]) - return; - - int priority = [object intValue], actualPriority; - if (priority == 0) - actualPriority = PRIORITY_LOW; - else if (priority == 2) - actualPriority = PRIORITY_HIGH; - else - actualPriority = PRIORITY_NORMAL; - - [[fTorrents objectAtIndex: 0] setFilePriority: actualPriority forIndexes: [item objectForKey: @"Indexes"]]; - [fFileOutline reloadData]; - } else; } @@ -944,6 +914,7 @@ } else if ([ident isEqualToString: @"Priority"]) { + #warning consider hidden Torrent * torrent = [fTorrents objectAtIndex: 0]; NSIndexSet * indexSet = [item objectForKey: @"Indexes"]; BOOL low = [torrent hasFilePriority: PRIORITY_LOW forIndexes: indexSet], @@ -971,6 +942,12 @@ return [outlineView rowHeight]; } +#warning need? +- (void) setFileOutlineHoverRowForEvent: (NSEvent *) event +{ + [fFileOutline setHoverRowForEvent: [[[fTabView selectedTabViewItem] identifier] isEqualToString: TAB_FILES_IDENT] ? event : nil]; +} + - (NSArray *) peerSortDescriptors { NSMutableArray * descriptors = [NSMutableArray array]; diff --git a/macosx/PeerProgressIndicatorCell.h b/macosx/PeerProgressIndicatorCell.h index cb2fb21be..89a86a95c 100644 --- a/macosx/PeerProgressIndicatorCell.h +++ b/macosx/PeerProgressIndicatorCell.h @@ -26,6 +26,6 @@ @interface PeerProgressIndicatorCell : NSLevelIndicatorCell { - BOOL isHidden; + BOOL fIsHidden; } @end diff --git a/macosx/PeerProgressIndicatorCell.m b/macosx/PeerProgressIndicatorCell.m index 0844f4523..79046dae5 100644 --- a/macosx/PeerProgressIndicatorCell.m +++ b/macosx/PeerProgressIndicatorCell.m @@ -28,17 +28,17 @@ - (BOOL) hidden { - return isHidden; + return fIsHidden; } -- (void) setHidden: (BOOL) hidden +- (void) setHidden: (BOOL) isHidden { - isHidden = hidden; + fIsHidden = isHidden; } - (void) drawWithFrame: (NSRect) cellFrame inView: (NSView *) controlView { - if (!isHidden) + if (!fIsHidden) [super drawWithFrame: cellFrame inView: controlView]; } diff --git a/macosx/Torrent.m b/macosx/Torrent.m index 54ecf0e5e..53877c29c 100644 --- a/macosx/Torrent.m +++ b/macosx/Torrent.m @@ -1674,6 +1674,7 @@ static uint32_t kRed = BE(0xFF6450FF), //255, 100, 80 [NSNumber numberWithBool: isFolder], @"IsFolder", currentPath, @"Path", nil]; [siblings addObject: dict]; + [dict setObject: self forKey: @"Torrent"]; if (isFolder) { [dict setObject: [NSMutableArray array] forKey: @"Children"]; @@ -1685,7 +1686,6 @@ static uint32_t kRed = BE(0xFF6450FF), //255, 100, 80 [dict setObject: [NSNumber numberWithUnsignedLongLong: size] forKey: @"Size"]; [dict setObject: [[NSWorkspace sharedWorkspace] iconForFileType: [name pathExtension]] forKey: @"Icon"]; [dict setObject: [NSNumber numberWithInt: priority] forKey: @"Priority"]; - [dict setObject: self forKey: @"Torrent"]; [flatList addObject: dict]; }