mirror of
https://github.com/transmission/transmission.git
synced 2025-12-20 02:18:42 +00:00
macos: View-based FileOutlineView (#7760)
Signed-off-by: Dzmitry Neviadomski <nevack.d@gmail.com>
This commit is contained in:
committed by
GitHub
parent
909fdad807
commit
d1985b05c6
@@ -16,7 +16,6 @@
|
|||||||
2856E0656A49F2665D69E760 /* benc.h in Headers */ = {isa = PBXBuildFile; fileRef = 2856E0656A49F2665D69E761 /* benc.h */; };
|
2856E0656A49F2665D69E760 /* benc.h in Headers */ = {isa = PBXBuildFile; fileRef = 2856E0656A49F2665D69E761 /* benc.h */; };
|
||||||
2B9BA6C508B488FE586A0AB0 /* torrents.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2B9BA6C508B488FE586A0AB1 /* torrents.cc */; };
|
2B9BA6C508B488FE586A0AB0 /* torrents.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2B9BA6C508B488FE586A0AB1 /* torrents.cc */; };
|
||||||
2B9BA6C508B488FE586A0AB2 /* torrents.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B9BA6C508B488FE586A0AB3 /* torrents.h */; };
|
2B9BA6C508B488FE586A0AB2 /* torrents.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B9BA6C508B488FE586A0AB3 /* torrents.h */; };
|
||||||
35F373030C2DA89000DAA8F2 /* FilePriorityCell.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35F373010C2DA88F00DAA8F2 /* FilePriorityCell.mm */; };
|
|
||||||
37D5E15E2AEFE47B00D1ADB3 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
|
37D5E15E2AEFE47B00D1ADB3 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
|
||||||
3C7A11970D0B2EE300B5701F /* getgateway.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C7A11910D0B2EE300B5701F /* getgateway.c */; };
|
3C7A11970D0B2EE300B5701F /* getgateway.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C7A11910D0B2EE300B5701F /* getgateway.c */; };
|
||||||
3C7A11980D0B2EE300B5701F /* getgateway.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C7A11920D0B2EE300B5701F /* getgateway.h */; };
|
3C7A11980D0B2EE300B5701F /* getgateway.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C7A11920D0B2EE300B5701F /* getgateway.h */; };
|
||||||
@@ -125,7 +124,6 @@
|
|||||||
A222E9870E6B21D9009FB003 /* BlocklistDownloaderViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A222E9860E6B21D9009FB003 /* BlocklistDownloaderViewController.mm */; };
|
A222E9870E6B21D9009FB003 /* BlocklistDownloaderViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A222E9860E6B21D9009FB003 /* BlocklistDownloaderViewController.mm */; };
|
||||||
A222EA7B0E6C32C4009FB003 /* BlocklistScheduler.mm in Sources */ = {isa = PBXBuildFile; fileRef = A222EA7A0E6C32C4009FB003 /* BlocklistScheduler.mm */; };
|
A222EA7B0E6C32C4009FB003 /* BlocklistScheduler.mm in Sources */ = {isa = PBXBuildFile; fileRef = A222EA7A0E6C32C4009FB003 /* BlocklistScheduler.mm */; };
|
||||||
A225A4C0187E369C00CDE823 /* ShareToolbarItem.mm in Sources */ = {isa = PBXBuildFile; fileRef = A225A4BF187E369C00CDE823 /* ShareToolbarItem.mm */; };
|
A225A4C0187E369C00CDE823 /* ShareToolbarItem.mm in Sources */ = {isa = PBXBuildFile; fileRef = A225A4BF187E369C00CDE823 /* ShareToolbarItem.mm */; };
|
||||||
A2265F420B5EF5F40093DDA5 /* FileNameCell.mm in Sources */ = {isa = PBXBuildFile; fileRef = A2265F400B5EF5F40093DDA5 /* FileNameCell.mm */; };
|
|
||||||
A226FDAC0D0CDF20005A7F71 /* libnatpmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C7A118D0D0B2EB800B5701F /* libnatpmp.a */; };
|
A226FDAC0D0CDF20005A7F71 /* libnatpmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C7A118D0D0B2EB800B5701F /* libnatpmp.a */; };
|
||||||
A22A8D560AEEAFA5007E9CB9 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A22A8D540AEEAFA5007E9CB9 /* Localizable.strings */; };
|
A22A8D560AEEAFA5007E9CB9 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A22A8D540AEEAFA5007E9CB9 /* Localizable.strings */; };
|
||||||
A22B00B2116A9E9F003315FC /* connecthostport.h in Headers */ = {isa = PBXBuildFile; fileRef = A22B00AF116A9E90003315FC /* connecthostport.h */; };
|
A22B00B2116A9E9F003315FC /* connecthostport.h in Headers */ = {isa = PBXBuildFile; fileRef = A22B00AF116A9E90003315FC /* connecthostport.h */; };
|
||||||
@@ -458,6 +456,9 @@
|
|||||||
ED5E0F0F2CD31BC20071433B /* NSStringAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4DE5CC9C0980656F00BE280E /* NSStringAdditions.mm */; };
|
ED5E0F0F2CD31BC20071433B /* NSStringAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4DE5CC9C0980656F00BE280E /* NSStringAdditions.mm */; };
|
||||||
ED67FB422B70FCE400D8A037 /* settings.cc in Sources */ = {isa = PBXBuildFile; fileRef = ED67FB402B70FCE400D8A037 /* settings.cc */; };
|
ED67FB422B70FCE400D8A037 /* settings.cc in Sources */ = {isa = PBXBuildFile; fileRef = ED67FB402B70FCE400D8A037 /* settings.cc */; };
|
||||||
ED67FB432B70FCE400D8A037 /* settings.h in Headers */ = {isa = PBXBuildFile; fileRef = ED67FB412B70FCE400D8A037 /* settings.h */; };
|
ED67FB432B70FCE400D8A037 /* settings.h in Headers */ = {isa = PBXBuildFile; fileRef = ED67FB412B70FCE400D8A037 /* settings.h */; };
|
||||||
|
ED6F16B52EB8F1EB007CD864 /* FileNameCellView.mm in Sources */ = {isa = PBXBuildFile; fileRef = ED6F16B22EB8F1EB007CD864 /* FileNameCellView.mm */; };
|
||||||
|
ED6F16B62EB8F1EB007CD864 /* FilePriorityCellView.mm in Sources */ = {isa = PBXBuildFile; fileRef = ED6F16B42EB8F1EB007CD864 /* FilePriorityCellView.mm */; };
|
||||||
|
ED6F16B72EB8F1EB007CD864 /* FileCheckCellView.mm in Sources */ = {isa = PBXBuildFile; fileRef = ED6F16B02EB8F1EB007CD864 /* FileCheckCellView.mm */; };
|
||||||
ED86936F2ADAE34D00342B1A /* DefaultAppHelper.mm in Sources */ = {isa = PBXBuildFile; fileRef = ED86936E2ADAE34D00342B1A /* DefaultAppHelper.mm */; };
|
ED86936F2ADAE34D00342B1A /* DefaultAppHelper.mm in Sources */ = {isa = PBXBuildFile; fileRef = ED86936E2ADAE34D00342B1A /* DefaultAppHelper.mm */; };
|
||||||
ED8A16412735A8AA000D61F9 /* peer-mgr-wishlist.h in Headers */ = {isa = PBXBuildFile; fileRef = ED8A163D2735A8AA000D61F9 /* peer-mgr-wishlist.h */; };
|
ED8A16412735A8AA000D61F9 /* peer-mgr-wishlist.h in Headers */ = {isa = PBXBuildFile; fileRef = ED8A163D2735A8AA000D61F9 /* peer-mgr-wishlist.h */; };
|
||||||
ED8A16422735A8AA000D61F9 /* peer-mgr-wishlist.cc in Sources */ = {isa = PBXBuildFile; fileRef = ED8A163E2735A8AA000D61F9 /* peer-mgr-wishlist.cc */; };
|
ED8A16422735A8AA000D61F9 /* peer-mgr-wishlist.cc in Sources */ = {isa = PBXBuildFile; fileRef = ED8A163E2735A8AA000D61F9 /* peer-mgr-wishlist.cc */; };
|
||||||
@@ -686,8 +687,6 @@
|
|||||||
29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||||
2B9BA6C508B488FE586A0AB1 /* torrents.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = torrents.cc; sourceTree = "<group>"; };
|
2B9BA6C508B488FE586A0AB1 /* torrents.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = torrents.cc; sourceTree = "<group>"; };
|
||||||
2B9BA6C508B488FE586A0AB3 /* torrents.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; path = torrents.h; sourceTree = "<group>"; };
|
2B9BA6C508B488FE586A0AB3 /* torrents.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; path = torrents.h; sourceTree = "<group>"; };
|
||||||
35F373000C2DA88F00DAA8F2 /* FilePriorityCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FilePriorityCell.h; sourceTree = "<group>"; };
|
|
||||||
35F373010C2DA88F00DAA8F2 /* FilePriorityCell.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FilePriorityCell.mm; sourceTree = "<group>"; };
|
|
||||||
3C7A118D0D0B2EB800B5701F /* libnatpmp.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libnatpmp.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
3C7A118D0D0B2EB800B5701F /* libnatpmp.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libnatpmp.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
3C7A11910D0B2EE300B5701F /* getgateway.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = getgateway.c; sourceTree = "<group>"; };
|
3C7A11910D0B2EE300B5701F /* getgateway.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = getgateway.c; sourceTree = "<group>"; };
|
||||||
3C7A11920D0B2EE300B5701F /* getgateway.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = getgateway.h; sourceTree = "<group>"; };
|
3C7A11920D0B2EE300B5701F /* getgateway.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = getgateway.h; sourceTree = "<group>"; };
|
||||||
@@ -921,8 +920,6 @@
|
|||||||
A223AA800D220CEB00840069 /* nl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; };
|
A223AA800D220CEB00840069 /* nl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
A225A4BE187E369C00CDE823 /* ShareToolbarItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ShareToolbarItem.h; sourceTree = "<group>"; };
|
A225A4BE187E369C00CDE823 /* ShareToolbarItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ShareToolbarItem.h; sourceTree = "<group>"; };
|
||||||
A225A4BF187E369C00CDE823 /* ShareToolbarItem.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ShareToolbarItem.mm; sourceTree = "<group>"; };
|
A225A4BF187E369C00CDE823 /* ShareToolbarItem.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ShareToolbarItem.mm; sourceTree = "<group>"; };
|
||||||
A2265F3F0B5EF5F40093DDA5 /* FileNameCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FileNameCell.h; sourceTree = "<group>"; };
|
|
||||||
A2265F400B5EF5F40093DDA5 /* FileNameCell.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FileNameCell.mm; sourceTree = "<group>"; };
|
|
||||||
A22B00AE116A9E90003315FC /* connecthostport.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = connecthostport.c; sourceTree = "<group>"; };
|
A22B00AE116A9E90003315FC /* connecthostport.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = connecthostport.c; sourceTree = "<group>"; };
|
||||||
A22B00AF116A9E90003315FC /* connecthostport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = connecthostport.h; sourceTree = "<group>"; };
|
A22B00AF116A9E90003315FC /* connecthostport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = connecthostport.h; sourceTree = "<group>"; };
|
||||||
A22BAE261388040500FB022F /* NSMutableArrayAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSMutableArrayAdditions.h; sourceTree = "<group>"; };
|
A22BAE261388040500FB022F /* NSMutableArrayAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSMutableArrayAdditions.h; sourceTree = "<group>"; };
|
||||||
@@ -1450,6 +1447,12 @@
|
|||||||
ED5E0F0E2CD3164D0071433B /* zh-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-TW"; path = "zh-TW.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
ED5E0F0E2CD3164D0071433B /* zh-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-TW"; path = "zh-TW.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||||
ED67FB402B70FCE400D8A037 /* settings.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = settings.cc; sourceTree = "<group>"; };
|
ED67FB402B70FCE400D8A037 /* settings.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = settings.cc; sourceTree = "<group>"; };
|
||||||
ED67FB412B70FCE400D8A037 /* settings.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = settings.h; sourceTree = "<group>"; };
|
ED67FB412B70FCE400D8A037 /* settings.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = settings.h; sourceTree = "<group>"; };
|
||||||
|
ED6F16AF2EB8F1EB007CD864 /* FileCheckCellView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FileCheckCellView.h; sourceTree = "<group>"; };
|
||||||
|
ED6F16B02EB8F1EB007CD864 /* FileCheckCellView.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FileCheckCellView.mm; sourceTree = "<group>"; };
|
||||||
|
ED6F16B12EB8F1EB007CD864 /* FileNameCellView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FileNameCellView.h; sourceTree = "<group>"; };
|
||||||
|
ED6F16B22EB8F1EB007CD864 /* FileNameCellView.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FileNameCellView.mm; sourceTree = "<group>"; };
|
||||||
|
ED6F16B32EB8F1EB007CD864 /* FilePriorityCellView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FilePriorityCellView.h; sourceTree = "<group>"; };
|
||||||
|
ED6F16B42EB8F1EB007CD864 /* FilePriorityCellView.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FilePriorityCellView.mm; sourceTree = "<group>"; };
|
||||||
ED86936D2ADAE34D00342B1A /* DefaultAppHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DefaultAppHelper.h; sourceTree = "<group>"; };
|
ED86936D2ADAE34D00342B1A /* DefaultAppHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DefaultAppHelper.h; sourceTree = "<group>"; };
|
||||||
ED86936E2ADAE34D00342B1A /* DefaultAppHelper.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DefaultAppHelper.mm; sourceTree = "<group>"; };
|
ED86936E2ADAE34D00342B1A /* DefaultAppHelper.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DefaultAppHelper.mm; sourceTree = "<group>"; };
|
||||||
ED8A163D2735A8AA000D61F9 /* peer-mgr-wishlist.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = "peer-mgr-wishlist.h"; sourceTree = "<group>"; };
|
ED8A163D2735A8AA000D61F9 /* peer-mgr-wishlist.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = "peer-mgr-wishlist.h"; sourceTree = "<group>"; };
|
||||||
@@ -2142,10 +2145,12 @@
|
|||||||
A26AF2190D2DA35A00FF7140 /* FileOutlineController.mm */,
|
A26AF2190D2DA35A00FF7140 /* FileOutlineController.mm */,
|
||||||
A2AF1C360A3D0F6200F1575D /* FileOutlineView.h */,
|
A2AF1C360A3D0F6200F1575D /* FileOutlineView.h */,
|
||||||
A2AF1C370A3D0F6200F1575D /* FileOutlineView.mm */,
|
A2AF1C370A3D0F6200F1575D /* FileOutlineView.mm */,
|
||||||
A2265F3F0B5EF5F40093DDA5 /* FileNameCell.h */,
|
ED6F16AF2EB8F1EB007CD864 /* FileCheckCellView.h */,
|
||||||
A2265F400B5EF5F40093DDA5 /* FileNameCell.mm */,
|
ED6F16B02EB8F1EB007CD864 /* FileCheckCellView.mm */,
|
||||||
35F373000C2DA88F00DAA8F2 /* FilePriorityCell.h */,
|
ED6F16B12EB8F1EB007CD864 /* FileNameCellView.h */,
|
||||||
35F373010C2DA88F00DAA8F2 /* FilePriorityCell.mm */,
|
ED6F16B22EB8F1EB007CD864 /* FileNameCellView.mm */,
|
||||||
|
ED6F16B32EB8F1EB007CD864 /* FilePriorityCellView.h */,
|
||||||
|
ED6F16B42EB8F1EB007CD864 /* FilePriorityCellView.mm */,
|
||||||
);
|
);
|
||||||
name = "File Outline View";
|
name = "File Outline View";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -3545,14 +3550,15 @@
|
|||||||
A2AA579D0ADFCAB400CA59F6 /* PiecesView.mm in Sources */,
|
A2AA579D0ADFCAB400CA59F6 /* PiecesView.mm in Sources */,
|
||||||
A25E74650AF5097C006F11AE /* ExpandedPathToPathTransformer.mm in Sources */,
|
A25E74650AF5097C006F11AE /* ExpandedPathToPathTransformer.mm in Sources */,
|
||||||
A25E74660AF5097D006F11AE /* ExpandedPathToIconTransformer.mm in Sources */,
|
A25E74660AF5097D006F11AE /* ExpandedPathToIconTransformer.mm in Sources */,
|
||||||
A2265F420B5EF5F40093DDA5 /* FileNameCell.mm in Sources */,
|
|
||||||
A2A1CB7A0BF29D5500AE959F /* PeerProgressIndicatorCell.mm in Sources */,
|
A2A1CB7A0BF29D5500AE959F /* PeerProgressIndicatorCell.mm in Sources */,
|
||||||
457AF8EB28604AFC00BCF74F /* Toolbar.mm in Sources */,
|
457AF8EB28604AFC00BCF74F /* Toolbar.mm in Sources */,
|
||||||
A2385DD40BFE06C800B24EF6 /* DragOverlayWindow.mm in Sources */,
|
A2385DD40BFE06C800B24EF6 /* DragOverlayWindow.mm in Sources */,
|
||||||
A2FB057F0BFEB6800095564D /* DragOverlayView.mm in Sources */,
|
A2FB057F0BFEB6800095564D /* DragOverlayView.mm in Sources */,
|
||||||
E138A9780C04D88F00C5426C /* ProgressGradients.mm in Sources */,
|
E138A9780C04D88F00C5426C /* ProgressGradients.mm in Sources */,
|
||||||
|
ED6F16B52EB8F1EB007CD864 /* FileNameCellView.mm in Sources */,
|
||||||
|
ED6F16B62EB8F1EB007CD864 /* FilePriorityCellView.mm in Sources */,
|
||||||
|
ED6F16B72EB8F1EB007CD864 /* FileCheckCellView.mm in Sources */,
|
||||||
A2DF37070C220D03006523C1 /* CreatorWindowController.mm in Sources */,
|
A2DF37070C220D03006523C1 /* CreatorWindowController.mm in Sources */,
|
||||||
35F373030C2DA89000DAA8F2 /* FilePriorityCell.mm in Sources */,
|
|
||||||
A2085DDC0C53BC74000BC3B7 /* AboutWindowController.mm in Sources */,
|
A2085DDC0C53BC74000BC3B7 /* AboutWindowController.mm in Sources */,
|
||||||
A21282A80CA6C66800EAEE0F /* StatusBarView.mm in Sources */,
|
A21282A80CA6C66800EAEE0F /* StatusBarView.mm in Sources */,
|
||||||
A257C1820CAD3003004E121C /* PeerTableView.mm in Sources */,
|
A257C1820CAD3003004E121C /* PeerTableView.mm in Sources */,
|
||||||
|
|||||||
@@ -309,7 +309,7 @@ typedef NS_ENUM(NSUInteger, PopupPriority) {
|
|||||||
{
|
{
|
||||||
//check buttons
|
//check buttons
|
||||||
//keep synced with identical code in InfoFileViewController.m
|
//keep synced with identical code in InfoFileViewController.m
|
||||||
NSInteger const filesCheckState = [self.torrent
|
NSControlStateValue const filesCheckState = [self.torrent
|
||||||
checkForFiles:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.torrent.fileCount)]];
|
checkForFiles:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.torrent.fileCount)]];
|
||||||
self.fCheckAllButton.enabled = filesCheckState != NSControlStateValueOn; //if anything is unchecked
|
self.fCheckAllButton.enabled = filesCheckState != NSControlStateValueOn; //if anything is unchecked
|
||||||
self.fUncheckAllButton.enabled = !self.torrent.allDownloaded; //if there are any checked files that aren't finished
|
self.fUncheckAllButton.enabled = !self.torrent.allDownloaded; //if there are any checked files that aren't finished
|
||||||
@@ -352,7 +352,7 @@ typedef NS_ENUM(NSUInteger, PopupPriority) {
|
|||||||
{
|
{
|
||||||
[self.torrent update];
|
[self.torrent update];
|
||||||
|
|
||||||
[self.fFileController refresh];
|
[self.fFileController reloadVisibleRows];
|
||||||
|
|
||||||
[self updateCheckButtons:nil]; //call in case button state changed by checking
|
[self updateCheckButtons:nil]; //call in case button state changed by checking
|
||||||
|
|
||||||
|
|||||||
@@ -75,14 +75,16 @@ target_sources(${TR_NAME}-mac
|
|||||||
ExpandedPathToPathTransformer.mm
|
ExpandedPathToPathTransformer.mm
|
||||||
FileListNode.h
|
FileListNode.h
|
||||||
FileListNode.mm
|
FileListNode.mm
|
||||||
FileNameCell.h
|
FileCheckCellView.h
|
||||||
FileNameCell.mm
|
FileCheckCellView.mm
|
||||||
|
FileNameCellView.h
|
||||||
|
FileNameCellView.mm
|
||||||
FileOutlineController.h
|
FileOutlineController.h
|
||||||
FileOutlineController.mm
|
FileOutlineController.mm
|
||||||
FileOutlineView.h
|
FileOutlineView.h
|
||||||
FileOutlineView.mm
|
FileOutlineView.mm
|
||||||
FilePriorityCell.h
|
FilePriorityCellView.h
|
||||||
FilePriorityCell.mm
|
FilePriorityCellView.mm
|
||||||
FileRenameSheetController.h
|
FileRenameSheetController.h
|
||||||
FileRenameSheetController.mm
|
FileRenameSheetController.mm
|
||||||
FilterBarController.h
|
FilterBarController.h
|
||||||
|
|||||||
13
macosx/FileCheckCellView.h
Normal file
13
macosx/FileCheckCellView.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// This file Copyright © Transmission authors and contributors.
|
||||||
|
// It may be used under the MIT (SPDX: MIT) license.
|
||||||
|
// License text can be found in the licenses/ folder.
|
||||||
|
|
||||||
|
#import <AppKit/AppKit.h>
|
||||||
|
|
||||||
|
@class FileListNode;
|
||||||
|
|
||||||
|
@interface FileCheckCellView : NSTableCellView
|
||||||
|
|
||||||
|
@property(nonatomic, weak) FileListNode* node;
|
||||||
|
|
||||||
|
@end
|
||||||
113
macosx/FileCheckCellView.mm
Normal file
113
macosx/FileCheckCellView.mm
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
// This file Copyright © Transmission authors and contributors.
|
||||||
|
// It may be used under the MIT (SPDX: MIT) license.
|
||||||
|
// License text can be found in the licenses/ folder.
|
||||||
|
|
||||||
|
#import "FileCheckCellView.h"
|
||||||
|
#import "FileListNode.h"
|
||||||
|
#import "Torrent.h"
|
||||||
|
|
||||||
|
@interface FileCheckCellView ()
|
||||||
|
@property(nonatomic, weak) NSButton* checkButton;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation FileCheckCellView
|
||||||
|
|
||||||
|
- (instancetype)initWithFrame:(NSRect)frameRect
|
||||||
|
{
|
||||||
|
if ((self = [super initWithFrame:frameRect]))
|
||||||
|
{
|
||||||
|
// Create checkbox button
|
||||||
|
NSButton* checkButton = [[NSButton alloc] initWithFrame:NSZeroRect];
|
||||||
|
checkButton.translatesAutoresizingMaskIntoConstraints = NO;
|
||||||
|
[checkButton setButtonType:NSButtonTypeSwitch];
|
||||||
|
checkButton.title = @"";
|
||||||
|
checkButton.allowsMixedState = YES;
|
||||||
|
checkButton.target = self;
|
||||||
|
checkButton.action = @selector(checkButtonClicked:);
|
||||||
|
[self addSubview:checkButton];
|
||||||
|
_checkButton = checkButton;
|
||||||
|
|
||||||
|
// Setup constraints
|
||||||
|
[NSLayoutConstraint activateConstraints:@[
|
||||||
|
[checkButton.centerXAnchor constraintEqualToAnchor:self.centerXAnchor],
|
||||||
|
[checkButton.centerYAnchor constraintEqualToAnchor:self.centerYAnchor],
|
||||||
|
]];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setNode:(FileListNode*)node
|
||||||
|
{
|
||||||
|
_node = node;
|
||||||
|
[self updateDisplay];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)updateDisplay
|
||||||
|
{
|
||||||
|
if (!self.node)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileListNode* node = self.node;
|
||||||
|
Torrent* torrent = node.torrent;
|
||||||
|
|
||||||
|
// Update checkbox state
|
||||||
|
self.checkButton.state = [torrent checkForFiles:node.indexes];
|
||||||
|
self.checkButton.enabled = [torrent canChangeDownloadCheckForFiles:node.indexes];
|
||||||
|
|
||||||
|
// Update tooltip
|
||||||
|
[self updateTooltip];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)updateTooltip
|
||||||
|
{
|
||||||
|
if (!self.node)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString* tooltip = nil;
|
||||||
|
switch (self.checkButton.state)
|
||||||
|
{
|
||||||
|
case NSControlStateValueOff:
|
||||||
|
tooltip = NSLocalizedString(@"Don't Download", "files tab -> tooltip");
|
||||||
|
break;
|
||||||
|
case NSControlStateValueOn:
|
||||||
|
tooltip = NSLocalizedString(@"Download", "files tab -> tooltip");
|
||||||
|
break;
|
||||||
|
case NSControlStateValueMixed:
|
||||||
|
tooltip = NSLocalizedString(@"Download Some", "files tab -> tooltip");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
self.checkButton.toolTip = tooltip;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)checkButtonClicked:(NSButton*)sender
|
||||||
|
{
|
||||||
|
if (!self.node)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileListNode* node = self.node;
|
||||||
|
Torrent* torrent = node.torrent;
|
||||||
|
|
||||||
|
NSIndexSet* indexSet;
|
||||||
|
if (NSEvent.modifierFlags & NSEventModifierFlagOption)
|
||||||
|
{
|
||||||
|
indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, torrent.fileCount)];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
indexSet = node.indexes;
|
||||||
|
}
|
||||||
|
|
||||||
|
[torrent setFileCheckState:sender.state != NSControlStateValueOff ? NSControlStateValueOn : NSControlStateValueOff
|
||||||
|
forIndexes:indexSet];
|
||||||
|
|
||||||
|
// Notify that we need to refresh
|
||||||
|
[NSNotificationCenter.defaultCenter postNotificationName:@"UpdateUI" object:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
// This file Copyright © Transmission authors and contributors.
|
|
||||||
// It may be used under the MIT (SPDX: MIT) license.
|
|
||||||
// License text can be found in the licenses/ folder.
|
|
||||||
|
|
||||||
#import <AppKit/AppKit.h>
|
|
||||||
|
|
||||||
typedef NS_ENUM(NSInteger, AttributesStyle) {
|
|
||||||
AttributesStyleNormal,
|
|
||||||
AttributesStyleEmphasized,
|
|
||||||
AttributesStyleDisabled,
|
|
||||||
};
|
|
||||||
|
|
||||||
@interface FileNameCell : NSActionCell
|
|
||||||
|
|
||||||
- (NSRect)imageRectForBounds:(NSRect)bounds;
|
|
||||||
|
|
||||||
@end
|
|
||||||
@@ -1,218 +0,0 @@
|
|||||||
// This file Copyright © Transmission authors and contributors.
|
|
||||||
// It may be used under the MIT (SPDX: MIT) license.
|
|
||||||
// License text can be found in the licenses/ folder.
|
|
||||||
|
|
||||||
#include <libtransmission/transmission.h>
|
|
||||||
#include <libtransmission/utils.h>
|
|
||||||
|
|
||||||
#import "FileNameCell.h"
|
|
||||||
#import "FileOutlineView.h"
|
|
||||||
#import "Torrent.h"
|
|
||||||
#import "FileListNode.h"
|
|
||||||
#import "NSStringAdditions.h"
|
|
||||||
|
|
||||||
static CGFloat const kPaddingHorizontal = 2.0;
|
|
||||||
static CGFloat const kImageFolderSize = 16.0;
|
|
||||||
static CGFloat const kImageIconSize = 32.0;
|
|
||||||
static CGFloat const kPaddingBetweenImageAndTitle = 4.0;
|
|
||||||
static CGFloat const kPaddingAboveTitleFile = 2.0;
|
|
||||||
static CGFloat const kPaddingBelowStatusFile = 2.0;
|
|
||||||
static CGFloat const kPaddingBetweenNameAndFolderStatus = 4.0;
|
|
||||||
static CGFloat const kPaddingExpansionFrame = 2.0;
|
|
||||||
|
|
||||||
static NSMutableParagraphStyle* sParagraphStyle()
|
|
||||||
{
|
|
||||||
NSMutableParagraphStyle* paragraphStyle = [NSParagraphStyle.defaultParagraphStyle mutableCopy];
|
|
||||||
paragraphStyle.lineBreakMode = NSLineBreakByTruncatingMiddle;
|
|
||||||
return paragraphStyle;
|
|
||||||
}
|
|
||||||
static NSMutableParagraphStyle* sStatusParagraphStyle()
|
|
||||||
{
|
|
||||||
NSMutableParagraphStyle* paragraphStyle = [NSParagraphStyle.defaultParagraphStyle mutableCopy];
|
|
||||||
paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;
|
|
||||||
return paragraphStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NSDictionary<NSAttributedStringKey, id>* const kTitleAttributes = @{
|
|
||||||
NSFontAttributeName : [NSFont messageFontOfSize:12.0],
|
|
||||||
NSParagraphStyleAttributeName : sParagraphStyle(),
|
|
||||||
NSForegroundColorAttributeName : NSColor.controlTextColor
|
|
||||||
};
|
|
||||||
static NSDictionary<NSAttributedStringKey, id>* const kStatusAttributes = @{
|
|
||||||
NSFontAttributeName : [NSFont messageFontOfSize:9.0],
|
|
||||||
NSParagraphStyleAttributeName : sStatusParagraphStyle(),
|
|
||||||
NSForegroundColorAttributeName : NSColor.secondaryLabelColor
|
|
||||||
};
|
|
||||||
static NSDictionary<NSAttributedStringKey, id>* const kTitleEmphasizedAttributes = @{
|
|
||||||
NSFontAttributeName : [NSFont messageFontOfSize:12.0],
|
|
||||||
NSParagraphStyleAttributeName : sParagraphStyle(),
|
|
||||||
NSForegroundColorAttributeName : NSColor.whiteColor
|
|
||||||
};
|
|
||||||
static NSDictionary<NSAttributedStringKey, id>* const kStatusEmphasizedAttributes = @{
|
|
||||||
NSFontAttributeName : [NSFont messageFontOfSize:9.0],
|
|
||||||
NSParagraphStyleAttributeName : sStatusParagraphStyle(),
|
|
||||||
NSForegroundColorAttributeName : NSColor.whiteColor
|
|
||||||
};
|
|
||||||
static NSDictionary<NSAttributedStringKey, id>* const kTitleDisabledAttributes = @{
|
|
||||||
NSFontAttributeName : [NSFont messageFontOfSize:12.0],
|
|
||||||
NSParagraphStyleAttributeName : sParagraphStyle(),
|
|
||||||
NSForegroundColorAttributeName : NSColor.disabledControlTextColor
|
|
||||||
};
|
|
||||||
static NSDictionary<NSAttributedStringKey, id>* const kStatusDisabledAttributes = @{
|
|
||||||
NSFontAttributeName : [NSFont messageFontOfSize:9.0],
|
|
||||||
NSParagraphStyleAttributeName : sStatusParagraphStyle(),
|
|
||||||
NSForegroundColorAttributeName : NSColor.disabledControlTextColor
|
|
||||||
};
|
|
||||||
|
|
||||||
@implementation FileNameCell
|
|
||||||
|
|
||||||
- (NSImage*)image
|
|
||||||
{
|
|
||||||
FileListNode* node = (FileListNode*)self.objectValue;
|
|
||||||
return node.icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSRect)imageRectForBounds:(NSRect)bounds
|
|
||||||
{
|
|
||||||
NSRect result = bounds;
|
|
||||||
|
|
||||||
result.origin.x += kPaddingHorizontal;
|
|
||||||
|
|
||||||
CGFloat const IMAGE_SIZE = ((FileListNode*)self.objectValue).isFolder ? kImageFolderSize : kImageIconSize;
|
|
||||||
result.origin.y += (result.size.height - IMAGE_SIZE) * 0.5;
|
|
||||||
result.size = NSMakeSize(IMAGE_SIZE, IMAGE_SIZE);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView
|
|
||||||
{
|
|
||||||
//icon
|
|
||||||
[self.image drawInRect:[self imageRectForBounds:cellFrame] fromRect:NSZeroRect operation:NSCompositingOperationSourceOver
|
|
||||||
fraction:1.0
|
|
||||||
respectFlipped:YES
|
|
||||||
hints:nil];
|
|
||||||
|
|
||||||
FileListNode* node = self.objectValue;
|
|
||||||
AttributesStyle style;
|
|
||||||
if (self.backgroundStyle == NSBackgroundStyleEmphasized)
|
|
||||||
{
|
|
||||||
style = AttributesStyleEmphasized;
|
|
||||||
}
|
|
||||||
else if ([node.torrent checkForFiles:node.indexes] == NSControlStateValueOff)
|
|
||||||
{
|
|
||||||
style = AttributesStyleDisabled;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
style = AttributesStyleNormal;
|
|
||||||
}
|
|
||||||
|
|
||||||
//title
|
|
||||||
NSAttributedString* titleString = [self attributedTitleWithStyle:style];
|
|
||||||
NSRect titleRect = [self rectForTitleWithStringSize:[titleString size] inBounds:cellFrame];
|
|
||||||
[titleString drawInRect:titleRect];
|
|
||||||
|
|
||||||
//status
|
|
||||||
NSAttributedString* statusString = [self attributedStatusWithStyle:style];
|
|
||||||
NSRect statusRect = [self rectForStatusWithString:statusString withTitleRect:titleRect inBounds:cellFrame];
|
|
||||||
[statusString drawInRect:statusRect];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSRect)expansionFrameWithFrame:(NSRect)cellFrame inView:(NSView*)view
|
|
||||||
{
|
|
||||||
NSAttributedString* titleString = [self attributedTitleWithStyle:AttributesStyleNormal];
|
|
||||||
NSRect realRect = [self rectForTitleWithStringSize:[titleString size] inBounds:cellFrame];
|
|
||||||
|
|
||||||
if ([titleString size].width > NSWidth(realRect) &&
|
|
||||||
NSMouseInRect([view convertPoint:view.window.mouseLocationOutsideOfEventStream fromView:nil], realRect, view.flipped))
|
|
||||||
{
|
|
||||||
realRect.size.width = [titleString size].width;
|
|
||||||
return NSInsetRect(realRect, -kPaddingExpansionFrame, -kPaddingExpansionFrame);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NSZeroRect;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)drawWithExpansionFrame:(NSRect)cellFrame inView:(NSView*)view
|
|
||||||
{
|
|
||||||
cellFrame.origin.x += kPaddingExpansionFrame;
|
|
||||||
cellFrame.origin.y += kPaddingExpansionFrame;
|
|
||||||
|
|
||||||
NSAttributedString* titleString = [self attributedTitleWithStyle:AttributesStyleNormal];
|
|
||||||
[titleString drawInRect:cellFrame];
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - Private
|
|
||||||
|
|
||||||
- (NSRect)rectForTitleWithStringSize:(NSSize)stringSize inBounds:(NSRect)bounds
|
|
||||||
{
|
|
||||||
NSSize const titleSize = stringSize;
|
|
||||||
|
|
||||||
//no right padding, so that there's not too much space between this and the priority image
|
|
||||||
NSRect result;
|
|
||||||
if (!((FileListNode*)self.objectValue).isFolder)
|
|
||||||
{
|
|
||||||
result.origin.x = NSMinX(bounds) + kPaddingHorizontal + kImageIconSize + kPaddingBetweenImageAndTitle;
|
|
||||||
result.origin.y = NSMinY(bounds) + kPaddingAboveTitleFile;
|
|
||||||
result.size.width = NSMaxX(bounds) - NSMinX(result);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.origin.x = NSMinX(bounds) + kPaddingHorizontal + kImageFolderSize + kPaddingBetweenImageAndTitle;
|
|
||||||
result.origin.y = NSMidY(bounds) - titleSize.height * 0.5;
|
|
||||||
result.size.width = MIN(titleSize.width, NSMaxX(bounds) - NSMinX(result));
|
|
||||||
}
|
|
||||||
result.size.height = titleSize.height;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSRect)rectForStatusWithString:(NSAttributedString*)string withTitleRect:(NSRect)titleRect inBounds:(NSRect)bounds
|
|
||||||
{
|
|
||||||
NSSize const statusSize = [string size];
|
|
||||||
|
|
||||||
NSRect result;
|
|
||||||
if (!((FileListNode*)self.objectValue).isFolder)
|
|
||||||
{
|
|
||||||
result.origin.x = NSMinX(titleRect);
|
|
||||||
result.origin.y = NSMaxY(bounds) - kPaddingBelowStatusFile - statusSize.height;
|
|
||||||
result.size.width = NSWidth(titleRect);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.origin.x = NSMaxX(titleRect) + kPaddingBetweenNameAndFolderStatus;
|
|
||||||
result.origin.y = NSMaxY(titleRect) - statusSize.height - 1.0;
|
|
||||||
result.size.width = NSMaxX(bounds) - NSMaxX(titleRect);
|
|
||||||
}
|
|
||||||
result.size.height = statusSize.height;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSAttributedString*)attributedTitleWithStyle:(AttributesStyle)style
|
|
||||||
{
|
|
||||||
NSString* title = ((FileListNode*)self.objectValue).name;
|
|
||||||
return [[NSAttributedString alloc] initWithString:title attributes:style == AttributesStyleEmphasized ? kTitleEmphasizedAttributes :
|
|
||||||
style == AttributesStyleDisabled ? kTitleDisabledAttributes :
|
|
||||||
kTitleAttributes];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSAttributedString*)attributedStatusWithStyle:(AttributesStyle)style
|
|
||||||
{
|
|
||||||
FileListNode* node = (FileListNode*)self.objectValue;
|
|
||||||
Torrent* torrent = node.torrent;
|
|
||||||
|
|
||||||
CGFloat const progress = [torrent fileProgress:node];
|
|
||||||
NSString* percentString = [NSString percentString:progress longDecimals:YES];
|
|
||||||
|
|
||||||
NSString* status = [NSString stringWithFormat:NSLocalizedString(@"%@ of %@", "Inspector -> Files tab -> file status string"),
|
|
||||||
percentString,
|
|
||||||
[NSString stringForFileSize:node.size]];
|
|
||||||
|
|
||||||
return [[NSAttributedString alloc] initWithString:status attributes:style == AttributesStyleEmphasized ? kStatusEmphasizedAttributes :
|
|
||||||
style == AttributesStyleDisabled ? kStatusDisabledAttributes :
|
|
||||||
kStatusAttributes];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
13
macosx/FileNameCellView.h
Normal file
13
macosx/FileNameCellView.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// This file Copyright © Transmission authors and contributors.
|
||||||
|
// It may be used under the MIT (SPDX: MIT) license.
|
||||||
|
// License text can be found in the licenses/ folder.
|
||||||
|
|
||||||
|
#import <AppKit/AppKit.h>
|
||||||
|
|
||||||
|
@class FileListNode;
|
||||||
|
|
||||||
|
@interface FileNameCellView : NSTableCellView
|
||||||
|
|
||||||
|
@property(nonatomic, weak) FileListNode* node;
|
||||||
|
|
||||||
|
@end
|
||||||
228
macosx/FileNameCellView.mm
Normal file
228
macosx/FileNameCellView.mm
Normal file
@@ -0,0 +1,228 @@
|
|||||||
|
// This file Copyright © Transmission authors and contributors.
|
||||||
|
// It may be used under the MIT (SPDX: MIT) license.
|
||||||
|
// License text can be found in the licenses/ folder.
|
||||||
|
|
||||||
|
#include <libtransmission/transmission.h>
|
||||||
|
#include <libtransmission/utils.h>
|
||||||
|
|
||||||
|
#import "FileNameCellView.h"
|
||||||
|
#import "FileListNode.h"
|
||||||
|
#import "Torrent.h"
|
||||||
|
#import "NSStringAdditions.h"
|
||||||
|
|
||||||
|
static CGFloat const kPaddingHorizontal = 2.0;
|
||||||
|
static CGFloat const kImageFolderSize = 16.0;
|
||||||
|
static CGFloat const kImageIconSize = 32.0;
|
||||||
|
static CGFloat const kPaddingBetweenImageAndTitle = 4.0;
|
||||||
|
static CGFloat const kPaddingAboveTitleFile = 2.0;
|
||||||
|
static CGFloat const kPaddingBelowStatusFile = 2.0;
|
||||||
|
static CGFloat const kPaddingBetweenNameAndFolderStatus = 4.0;
|
||||||
|
|
||||||
|
@interface FileNameCellView ()
|
||||||
|
@property(nonatomic, weak) NSImageView* iconView;
|
||||||
|
@property(nonatomic, weak) NSTextField* nameField;
|
||||||
|
@property(nonatomic, weak) NSTextField* statusField;
|
||||||
|
@property(nonatomic, strong) NSArray<NSLayoutConstraint*>* dynamicConstraints;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation FileNameCellView
|
||||||
|
|
||||||
|
- (instancetype)initWithFrame:(NSRect)frameRect
|
||||||
|
{
|
||||||
|
if ((self = [super initWithFrame:frameRect]))
|
||||||
|
{
|
||||||
|
// Create icon view
|
||||||
|
NSImageView* iconView = [[NSImageView alloc] initWithFrame:NSZeroRect];
|
||||||
|
iconView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||||
|
iconView.imageScaling = NSImageScaleProportionallyDown;
|
||||||
|
[self addSubview:iconView];
|
||||||
|
_iconView = iconView;
|
||||||
|
|
||||||
|
// Create name field
|
||||||
|
NSTextField* nameField = [[NSTextField alloc] initWithFrame:NSZeroRect];
|
||||||
|
nameField.translatesAutoresizingMaskIntoConstraints = NO;
|
||||||
|
nameField.editable = NO;
|
||||||
|
nameField.selectable = NO;
|
||||||
|
nameField.bordered = NO;
|
||||||
|
nameField.backgroundColor = NSColor.clearColor;
|
||||||
|
nameField.font = [NSFont messageFontOfSize:12.0];
|
||||||
|
nameField.lineBreakMode = NSLineBreakByTruncatingMiddle;
|
||||||
|
[self addSubview:nameField];
|
||||||
|
_nameField = nameField;
|
||||||
|
self.textField = nameField;
|
||||||
|
|
||||||
|
// Create status field
|
||||||
|
NSTextField* statusField = [[NSTextField alloc] initWithFrame:NSZeroRect];
|
||||||
|
statusField.translatesAutoresizingMaskIntoConstraints = NO;
|
||||||
|
statusField.editable = NO;
|
||||||
|
statusField.selectable = NO;
|
||||||
|
statusField.bordered = NO;
|
||||||
|
statusField.backgroundColor = NSColor.clearColor;
|
||||||
|
statusField.font = [NSFont messageFontOfSize:9.0];
|
||||||
|
statusField.textColor = NSColor.secondaryLabelColor;
|
||||||
|
statusField.lineBreakMode = NSLineBreakByTruncatingTail;
|
||||||
|
[self addSubview:statusField];
|
||||||
|
_statusField = statusField;
|
||||||
|
|
||||||
|
// Setup constraints
|
||||||
|
[self setupConstraints];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setupConstraints
|
||||||
|
{
|
||||||
|
NSImageView* iconView = self.iconView;
|
||||||
|
NSTextField* nameField = self.nameField;
|
||||||
|
|
||||||
|
// Fixed constraints that don't change
|
||||||
|
[NSLayoutConstraint activateConstraints:@[
|
||||||
|
// Icon view constraints
|
||||||
|
[iconView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:kPaddingHorizontal],
|
||||||
|
[iconView.centerYAnchor constraintEqualToAnchor:self.centerYAnchor],
|
||||||
|
[iconView.widthAnchor constraintEqualToConstant:kImageIconSize],
|
||||||
|
[iconView.heightAnchor constraintEqualToConstant:kImageIconSize],
|
||||||
|
|
||||||
|
// Name field leading constraint
|
||||||
|
[nameField.leadingAnchor constraintEqualToAnchor:iconView.trailingAnchor constant:kPaddingBetweenImageAndTitle],
|
||||||
|
]];
|
||||||
|
|
||||||
|
self.dynamicConstraints = @[];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setNode:(FileListNode*)node
|
||||||
|
{
|
||||||
|
_node = node;
|
||||||
|
[self updateDisplay];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)updateDisplay
|
||||||
|
{
|
||||||
|
if (!self.node)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileListNode* node = self.node;
|
||||||
|
|
||||||
|
// Update icon
|
||||||
|
self.iconView.image = node.icon;
|
||||||
|
|
||||||
|
// Update icon size constraints based on folder/file
|
||||||
|
CGFloat const imageSize = node.isFolder ? kImageFolderSize : kImageIconSize;
|
||||||
|
for (NSLayoutConstraint* constraint in self.iconView.constraints)
|
||||||
|
{
|
||||||
|
if (constraint.firstAttribute == NSLayoutAttributeWidth || constraint.firstAttribute == NSLayoutAttributeHeight)
|
||||||
|
{
|
||||||
|
constraint.constant = imageSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update name
|
||||||
|
self.nameField.stringValue = node.name;
|
||||||
|
|
||||||
|
// Update status
|
||||||
|
Torrent* torrent = node.torrent;
|
||||||
|
CGFloat const progress = [torrent fileProgress:node];
|
||||||
|
NSString* percentString = [NSString percentString:progress longDecimals:YES];
|
||||||
|
|
||||||
|
NSString* status = [NSString stringWithFormat:NSLocalizedString(@"%@ of %@", "Inspector -> Files tab -> file status string"),
|
||||||
|
percentString,
|
||||||
|
[NSString stringForFileSize:node.size]];
|
||||||
|
self.statusField.stringValue = status;
|
||||||
|
|
||||||
|
// Update layout constraints based on folder vs file
|
||||||
|
[NSLayoutConstraint deactivateConstraints:self.dynamicConstraints];
|
||||||
|
|
||||||
|
NSTextField* nameField = self.nameField;
|
||||||
|
NSTextField* statusField = self.statusField;
|
||||||
|
|
||||||
|
if (node.isFolder)
|
||||||
|
{
|
||||||
|
// For folders, status appears next to name, both centered
|
||||||
|
self.statusField.hidden = NO;
|
||||||
|
self.dynamicConstraints = @[
|
||||||
|
[nameField.centerYAnchor constraintEqualToAnchor:self.centerYAnchor],
|
||||||
|
[nameField.trailingAnchor constraintLessThanOrEqualToAnchor:statusField.leadingAnchor
|
||||||
|
constant:-kPaddingBetweenNameAndFolderStatus],
|
||||||
|
|
||||||
|
[statusField.leadingAnchor constraintEqualToAnchor:nameField.trailingAnchor constant:kPaddingBetweenNameAndFolderStatus],
|
||||||
|
[statusField.centerYAnchor constraintEqualToAnchor:self.centerYAnchor],
|
||||||
|
[statusField.trailingAnchor constraintLessThanOrEqualToAnchor:self.trailingAnchor],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// For files, status appears below name
|
||||||
|
self.statusField.hidden = NO;
|
||||||
|
self.dynamicConstraints = @[
|
||||||
|
[nameField.topAnchor constraintEqualToAnchor:self.topAnchor constant:kPaddingAboveTitleFile],
|
||||||
|
[nameField.trailingAnchor constraintLessThanOrEqualToAnchor:self.trailingAnchor],
|
||||||
|
|
||||||
|
[statusField.leadingAnchor constraintEqualToAnchor:nameField.leadingAnchor],
|
||||||
|
[statusField.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
|
||||||
|
[statusField.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:-kPaddingBelowStatusFile],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
[NSLayoutConstraint activateConstraints:self.dynamicConstraints];
|
||||||
|
|
||||||
|
// Update colors based on background style and check state
|
||||||
|
[self updateColors];
|
||||||
|
|
||||||
|
// Update tooltip
|
||||||
|
[self updateTooltip];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)updateTooltip
|
||||||
|
{
|
||||||
|
if (!self.node)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileListNode* node = self.node;
|
||||||
|
Torrent* torrent = node.torrent;
|
||||||
|
|
||||||
|
NSString* path = [torrent fileLocation:node];
|
||||||
|
if (!path)
|
||||||
|
{
|
||||||
|
path = [node.path stringByAppendingPathComponent:node.name];
|
||||||
|
}
|
||||||
|
self.toolTip = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setBackgroundStyle:(NSBackgroundStyle)backgroundStyle
|
||||||
|
{
|
||||||
|
[super setBackgroundStyle:backgroundStyle];
|
||||||
|
[self updateColors];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)updateColors
|
||||||
|
{
|
||||||
|
if (!self.node)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileListNode* node = self.node;
|
||||||
|
Torrent* torrent = node.torrent;
|
||||||
|
|
||||||
|
if (self.backgroundStyle == NSBackgroundStyleEmphasized)
|
||||||
|
{
|
||||||
|
self.nameField.textColor = NSColor.whiteColor;
|
||||||
|
self.statusField.textColor = NSColor.whiteColor;
|
||||||
|
}
|
||||||
|
else if ([torrent checkForFiles:node.indexes] == NSControlStateValueOff)
|
||||||
|
{
|
||||||
|
self.nameField.textColor = NSColor.disabledControlTextColor;
|
||||||
|
self.statusField.textColor = NSColor.disabledControlTextColor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self.nameField.textColor = NSColor.controlTextColor;
|
||||||
|
self.statusField.textColor = NSColor.secondaryLabelColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
@property(nonatomic) Torrent* torrent;
|
@property(nonatomic) Torrent* torrent;
|
||||||
@property(nonatomic) NSString* filterText;
|
@property(nonatomic) NSString* filterText;
|
||||||
|
|
||||||
- (void)refresh;
|
- (void)reloadVisibleRows;
|
||||||
|
|
||||||
- (void)setCheck:(id)sender;
|
- (void)setCheck:(id)sender;
|
||||||
- (void)setOnlySelectedCheck:(id)sender;
|
- (void)setOnlySelectedCheck:(id)sender;
|
||||||
|
|||||||
@@ -6,7 +6,9 @@
|
|||||||
#import "Torrent.h"
|
#import "Torrent.h"
|
||||||
#import "FileListNode.h"
|
#import "FileListNode.h"
|
||||||
#import "FileOutlineView.h"
|
#import "FileOutlineView.h"
|
||||||
#import "FilePriorityCell.h"
|
#import "FileNameCellView.h"
|
||||||
|
#import "FilePriorityCellView.h"
|
||||||
|
#import "FileCheckCellView.h"
|
||||||
#import "FileRenameSheetController.h"
|
#import "FileRenameSheetController.h"
|
||||||
#import "NSMutableArrayAdditions.h"
|
#import "NSMutableArrayAdditions.h"
|
||||||
#import "NSStringAdditions.h"
|
#import "NSStringAdditions.h"
|
||||||
@@ -24,7 +26,7 @@ typedef NS_ENUM(NSUInteger, FilePriorityMenuTag) { //
|
|||||||
FilePriorityMenuTagLow
|
FilePriorityMenuTagLow
|
||||||
};
|
};
|
||||||
|
|
||||||
@interface FileOutlineController ()
|
@interface FileOutlineController ()<NSOutlineViewDelegate, NSOutlineViewDataSource, NSMenuItemValidation>
|
||||||
|
|
||||||
@property(nonatomic) NSMutableArray<FileListNode*>* fFileList;
|
@property(nonatomic) NSMutableArray<FileListNode*>* fFileList;
|
||||||
|
|
||||||
@@ -186,18 +188,18 @@ typedef NS_ENUM(NSUInteger, FilePriorityMenuTag) { //
|
|||||||
_filterText = text;
|
_filterText = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)refresh
|
- (void)reloadVisibleRows
|
||||||
{
|
{
|
||||||
self.fOutline.needsDisplay = YES;
|
NSRect visibleRect = self.fOutline.visibleRect;
|
||||||
|
NSRange range = [self.fOutline rowsInRect:visibleRect];
|
||||||
|
|
||||||
|
NSIndexSet* rowIndexes = [NSIndexSet indexSetWithIndexesInRange:range];
|
||||||
|
NSIndexSet* columnIndexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.fOutline.numberOfColumns)];
|
||||||
|
|
||||||
|
[self.fOutline reloadDataForRowIndexes:rowIndexes columnIndexes:columnIndexes];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)outlineViewSelectionDidChange:(NSNotification*)notification
|
#pragma mark - NSOutlineViewDataSource
|
||||||
{
|
|
||||||
if ([QLPreviewPanel sharedPreviewPanelExists] && [QLPreviewPanel sharedPreviewPanel].visible)
|
|
||||||
{
|
|
||||||
[[QLPreviewPanel sharedPreviewPanel] reloadData];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSInteger)outlineView:(NSOutlineView*)outlineView numberOfChildrenOfItem:(id)item
|
- (NSInteger)outlineView:(NSOutlineView*)outlineView numberOfChildrenOfItem:(id)item
|
||||||
{
|
{
|
||||||
@@ -222,61 +224,51 @@ typedef NS_ENUM(NSUInteger, FilePriorityMenuTag) { //
|
|||||||
return (item ? ((FileListNode*)item).children : self.fFileList)[index];
|
return (item ? ((FileListNode*)item).children : self.fFileList)[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)outlineView:(NSOutlineView*)outlineView objectValueForTableColumn:(NSTableColumn*)tableColumn byItem:(id)item
|
#pragma mark - NSOutlineViewDelegate
|
||||||
{
|
|
||||||
if ([tableColumn.identifier isEqualToString:@"Check"])
|
|
||||||
{
|
|
||||||
return @([self.torrent checkForFiles:((FileListNode*)item).indexes]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)outlineView:(NSOutlineView*)outlineView
|
- (NSView*)outlineView:(NSOutlineView*)outlineView viewForTableColumn:(NSTableColumn*)tableColumn item:(id)item
|
||||||
willDisplayCell:(id)cell
|
|
||||||
forTableColumn:(NSTableColumn*)tableColumn
|
|
||||||
item:(id)item
|
|
||||||
{
|
{
|
||||||
NSString* identifier = tableColumn.identifier;
|
NSString* identifier = tableColumn.identifier;
|
||||||
if ([identifier isEqualToString:@"Check"])
|
FileListNode* node = (FileListNode*)item;
|
||||||
|
|
||||||
|
if ([identifier isEqualToString:@"Name"])
|
||||||
{
|
{
|
||||||
[cell setEnabled:[self.torrent canChangeDownloadCheckForFiles:((FileListNode*)item).indexes]];
|
FileNameCellView* cellView = [outlineView makeViewWithIdentifier:@"NameCell" owner:self];
|
||||||
|
if (!cellView)
|
||||||
|
{
|
||||||
|
cellView = [[FileNameCellView alloc] initWithFrame:NSZeroRect];
|
||||||
|
cellView.identifier = @"NameCell";
|
||||||
|
}
|
||||||
|
cellView.node = node;
|
||||||
|
|
||||||
|
return cellView;
|
||||||
}
|
}
|
||||||
else if ([identifier isEqualToString:@"Priority"])
|
else if ([identifier isEqualToString:@"Priority"])
|
||||||
{
|
{
|
||||||
[cell setRepresentedObject:item];
|
FilePriorityCellView* cellView = [outlineView makeViewWithIdentifier:@"PriorityCell" owner:self];
|
||||||
|
if (!cellView)
|
||||||
NSInteger hoveredRow = self.fOutline.hoveredRow;
|
|
||||||
((FilePriorityCell*)cell).hovered = hoveredRow != -1 && hoveredRow == [self.fOutline rowForItem:item];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)outlineView:(NSOutlineView*)outlineView
|
|
||||||
setObjectValue:(id)object
|
|
||||||
forTableColumn:(NSTableColumn*)tableColumn
|
|
||||||
byItem:(id)item
|
|
||||||
{
|
|
||||||
NSString* identifier = tableColumn.identifier;
|
|
||||||
if ([identifier isEqualToString:@"Check"])
|
|
||||||
{
|
{
|
||||||
NSIndexSet* indexSet;
|
cellView = [[FilePriorityCellView alloc] initWithFrame:NSZeroRect];
|
||||||
if (NSEvent.modifierFlags & NSEventModifierFlagOption)
|
cellView.identifier = @"PriorityCell";
|
||||||
{
|
|
||||||
indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.torrent.fileCount)];
|
|
||||||
}
|
}
|
||||||
else
|
cellView.node = node;
|
||||||
|
|
||||||
|
return cellView;
|
||||||
|
}
|
||||||
|
else if ([identifier isEqualToString:@"Check"])
|
||||||
{
|
{
|
||||||
indexSet = ((FileListNode*)item).indexes;
|
FileCheckCellView* cellView = [outlineView makeViewWithIdentifier:@"CheckCell" owner:self];
|
||||||
|
if (!cellView)
|
||||||
|
{
|
||||||
|
cellView = [[FileCheckCellView alloc] initWithFrame:NSZeroRect];
|
||||||
|
cellView.identifier = @"CheckCell";
|
||||||
|
}
|
||||||
|
cellView.node = node;
|
||||||
|
|
||||||
|
return cellView;
|
||||||
}
|
}
|
||||||
|
|
||||||
[self.torrent setFileCheckState:[object intValue] != NSControlStateValueOff ? NSControlStateValueOn : NSControlStateValueOff
|
return nil;
|
||||||
forIndexes:indexSet];
|
|
||||||
self.fOutline.needsDisplay = YES;
|
|
||||||
|
|
||||||
[NSNotificationCenter.defaultCenter postNotificationName:@"UpdateUI" object:nil];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString*)outlineView:(NSOutlineView*)outlineView typeSelectStringForTableColumn:(NSTableColumn*)tableColumn item:(id)item
|
- (NSString*)outlineView:(NSOutlineView*)outlineView typeSelectStringForTableColumn:(NSTableColumn*)tableColumn item:(id)item
|
||||||
@@ -284,60 +276,13 @@ typedef NS_ENUM(NSUInteger, FilePriorityMenuTag) { //
|
|||||||
return ((FileListNode*)item).name;
|
return ((FileListNode*)item).name;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString*)outlineView:(NSOutlineView*)outlineView
|
- (void)outlineViewSelectionDidChange:(NSNotification*)notification
|
||||||
toolTipForCell:(NSCell*)cell
|
|
||||||
rect:(NSRectPointer)rect
|
|
||||||
tableColumn:(NSTableColumn*)tableColumn
|
|
||||||
item:(id)item
|
|
||||||
mouseLocation:(NSPoint)mouseLocation
|
|
||||||
{
|
{
|
||||||
NSString* ident = tableColumn.identifier;
|
[self reloadVisibleRows];
|
||||||
if ([ident isEqualToString:@"Name"])
|
if ([QLPreviewPanel sharedPreviewPanelExists] && [QLPreviewPanel sharedPreviewPanel].visible)
|
||||||
{
|
{
|
||||||
NSString* path = [self.torrent fileLocation:item];
|
[[QLPreviewPanel sharedPreviewPanel] reloadData];
|
||||||
if (!path)
|
|
||||||
{
|
|
||||||
FileListNode* node = (FileListNode*)item;
|
|
||||||
path = [node.path stringByAppendingPathComponent:node.name];
|
|
||||||
}
|
}
|
||||||
return path;
|
|
||||||
}
|
|
||||||
else if ([ident isEqualToString:@"Check"])
|
|
||||||
{
|
|
||||||
switch (cell.state)
|
|
||||||
{
|
|
||||||
case NSControlStateValueOff:
|
|
||||||
return NSLocalizedString(@"Don't Download", "files tab -> tooltip");
|
|
||||||
case NSControlStateValueOn:
|
|
||||||
return NSLocalizedString(@"Download", "files tab -> tooltip");
|
|
||||||
case NSControlStateValueMixed:
|
|
||||||
return NSLocalizedString(@"Download Some", "files tab -> tooltip");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ([ident isEqualToString:@"Priority"])
|
|
||||||
{
|
|
||||||
NSSet* priorities = [self.torrent filePrioritiesForIndexes:((FileListNode*)item).indexes];
|
|
||||||
switch (priorities.count)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
return NSLocalizedString(@"Priority Not Available", "files tab -> tooltip");
|
|
||||||
case 1:
|
|
||||||
switch ([[priorities anyObject] intValue])
|
|
||||||
{
|
|
||||||
case TR_PRI_LOW:
|
|
||||||
return NSLocalizedString(@"Low Priority", "files tab -> tooltip");
|
|
||||||
case TR_PRI_HIGH:
|
|
||||||
return NSLocalizedString(@"High Priority", "files tab -> tooltip");
|
|
||||||
case TR_PRI_NORMAL:
|
|
||||||
return NSLocalizedString(@"Normal Priority", "files tab -> tooltip");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return NSLocalizedString(@"Multiple Priorities", "files tab -> tooltip");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGFloat)outlineView:(NSOutlineView*)outlineView heightOfRowByItem:(id)item
|
- (CGFloat)outlineView:(NSOutlineView*)outlineView heightOfRowByItem:(id)item
|
||||||
@@ -352,9 +297,11 @@ typedef NS_ENUM(NSUInteger, FilePriorityMenuTag) { //
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - Actions
|
||||||
|
|
||||||
- (void)setCheck:(id)sender
|
- (void)setCheck:(id)sender
|
||||||
{
|
{
|
||||||
NSInteger state = [sender tag] == FileCheckMenuTagUncheck ? NSControlStateValueOff : NSControlStateValueOn;
|
NSControlStateValue state = [sender tag] == FileCheckMenuTagUncheck ? NSControlStateValueOff : NSControlStateValueOn;
|
||||||
|
|
||||||
NSIndexSet* indexSet = self.fOutline.selectedRowIndexes;
|
NSIndexSet* indexSet = self.fOutline.selectedRowIndexes;
|
||||||
NSMutableIndexSet* itemIndexes = [NSMutableIndexSet indexSet];
|
NSMutableIndexSet* itemIndexes = [NSMutableIndexSet indexSet];
|
||||||
@@ -365,7 +312,8 @@ typedef NS_ENUM(NSUInteger, FilePriorityMenuTag) { //
|
|||||||
}
|
}
|
||||||
|
|
||||||
[self.torrent setFileCheckState:state forIndexes:itemIndexes];
|
[self.torrent setFileCheckState:state forIndexes:itemIndexes];
|
||||||
self.fOutline.needsDisplay = YES;
|
|
||||||
|
[self reloadVisibleRows];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setOnlySelectedCheck:(id)sender
|
- (void)setOnlySelectedCheck:(id)sender
|
||||||
@@ -384,21 +332,23 @@ typedef NS_ENUM(NSUInteger, FilePriorityMenuTag) { //
|
|||||||
[remainingItemIndexes removeIndexes:itemIndexes];
|
[remainingItemIndexes removeIndexes:itemIndexes];
|
||||||
[self.torrent setFileCheckState:NSControlStateValueOff forIndexes:remainingItemIndexes];
|
[self.torrent setFileCheckState:NSControlStateValueOff forIndexes:remainingItemIndexes];
|
||||||
|
|
||||||
self.fOutline.needsDisplay = YES;
|
[self reloadVisibleRows];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)checkAll
|
- (void)checkAll
|
||||||
{
|
{
|
||||||
NSIndexSet* indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.torrent.fileCount)];
|
NSIndexSet* indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.torrent.fileCount)];
|
||||||
[self.torrent setFileCheckState:NSControlStateValueOn forIndexes:indexSet];
|
[self.torrent setFileCheckState:NSControlStateValueOn forIndexes:indexSet];
|
||||||
self.fOutline.needsDisplay = YES;
|
|
||||||
|
[self reloadVisibleRows];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)uncheckAll
|
- (void)uncheckAll
|
||||||
{
|
{
|
||||||
NSIndexSet* indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.torrent.fileCount)];
|
NSIndexSet* indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.torrent.fileCount)];
|
||||||
[self.torrent setFileCheckState:NSControlStateValueOff forIndexes:indexSet];
|
[self.torrent setFileCheckState:NSControlStateValueOff forIndexes:indexSet];
|
||||||
self.fOutline.needsDisplay = YES;
|
|
||||||
|
[self reloadVisibleRows];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setPriority:(id)sender
|
- (void)setPriority:(id)sender
|
||||||
@@ -429,7 +379,8 @@ typedef NS_ENUM(NSUInteger, FilePriorityMenuTag) { //
|
|||||||
}
|
}
|
||||||
|
|
||||||
[self.torrent setFilePriority:priority forIndexes:itemIndexes];
|
[self.torrent setFilePriority:priority forIndexes:itemIndexes];
|
||||||
self.fOutline.needsDisplay = YES;
|
|
||||||
|
[self reloadVisibleRows];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)revealFile:(id)sender
|
- (void)revealFile:(id)sender
|
||||||
@@ -480,6 +431,8 @@ typedef NS_ENUM(NSUInteger, FilePriorityMenuTag) { //
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - NSMenuItemValidation
|
||||||
|
|
||||||
#warning make real view controller (Leopard-only) so that Command-R will work
|
#warning make real view controller (Leopard-only) so that Command-R will work
|
||||||
- (BOOL)validateMenuItem:(NSMenuItem*)menuItem
|
- (BOOL)validateMenuItem:(NSMenuItem*)menuItem
|
||||||
{
|
{
|
||||||
@@ -518,7 +471,7 @@ typedef NS_ENUM(NSUInteger, FilePriorityMenuTag) { //
|
|||||||
[itemIndexes addIndexes:node.indexes];
|
[itemIndexes addIndexes:node.indexes];
|
||||||
}
|
}
|
||||||
|
|
||||||
NSInteger state = (menuItem.tag == FileCheckMenuTagCheck) ? NSControlStateValueOn : NSControlStateValueOff;
|
NSControlStateValue state = (menuItem.tag == FileCheckMenuTagCheck) ? NSControlStateValueOn : NSControlStateValueOff;
|
||||||
return [self.torrent checkForFiles:itemIndexes] != state && [self.torrent canChangeDownloadCheckForFiles:itemIndexes];
|
return [self.torrent checkForFiles:itemIndexes] != state && [self.torrent canChangeDownloadCheckForFiles:itemIndexes];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,6 @@
|
|||||||
|
|
||||||
@interface FileOutlineView : NSOutlineView
|
@interface FileOutlineView : NSOutlineView
|
||||||
|
|
||||||
@property(nonatomic, readonly) NSInteger hoveredRow;
|
|
||||||
|
|
||||||
- (NSRect)iconRectForRow:(NSInteger)row;
|
- (NSRect)iconRectForRow:(NSInteger)row;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -4,15 +4,13 @@
|
|||||||
|
|
||||||
#import "InfoWindowController.h"
|
#import "InfoWindowController.h"
|
||||||
#import "FileListNode.h"
|
#import "FileListNode.h"
|
||||||
#import "FileNameCell.h"
|
#import "FileNameCellView.h"
|
||||||
#import "FileOutlineView.h"
|
#import "FileOutlineView.h"
|
||||||
#import "FilePriorityCell.h"
|
#import "FilePriorityCellView.h"
|
||||||
#import "Torrent.h"
|
#import "Torrent.h"
|
||||||
|
|
||||||
@interface FileOutlineView ()
|
@interface FileOutlineView ()
|
||||||
|
|
||||||
@property(nonatomic) NSInteger hoveredRow;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation FileOutlineView
|
@implementation FileOutlineView
|
||||||
@@ -20,16 +18,9 @@
|
|||||||
- (void)awakeFromNib
|
- (void)awakeFromNib
|
||||||
{
|
{
|
||||||
[super awakeFromNib];
|
[super awakeFromNib];
|
||||||
FileNameCell* nameCell = [[FileNameCell alloc] init];
|
|
||||||
[self tableColumnWithIdentifier:@"Name"].dataCell = nameCell;
|
|
||||||
|
|
||||||
FilePriorityCell* priorityCell = [[FilePriorityCell alloc] init];
|
|
||||||
[self tableColumnWithIdentifier:@"Priority"].dataCell = priorityCell;
|
|
||||||
|
|
||||||
self.autoresizesOutlineColumn = NO;
|
self.autoresizesOutlineColumn = NO;
|
||||||
self.indentationPerLevel = 14.0;
|
self.indentationPerLevel = 14.0;
|
||||||
|
|
||||||
self.hoveredRow = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)mouseDown:(NSEvent*)event
|
- (void)mouseDown:(NSEvent*)event
|
||||||
@@ -59,61 +50,22 @@
|
|||||||
|
|
||||||
- (NSRect)iconRectForRow:(NSInteger)row
|
- (NSRect)iconRectForRow:(NSInteger)row
|
||||||
{
|
{
|
||||||
FileNameCell* cell = (FileNameCell*)[self preparedCellAtColumn:[self columnWithIdentifier:@"Name"] row:row];
|
NSView* view = [self viewAtColumn:[self columnWithIdentifier:@"Name"] row:row makeIfNecessary:NO];
|
||||||
NSRect iconRect = [cell imageRectForBounds:[self rectOfRow:row]];
|
if (![view isKindOfClass:[FileNameCellView class]])
|
||||||
|
{
|
||||||
|
return NSZeroRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileNameCellView* cellView = (FileNameCellView*)view;
|
||||||
|
NSImageView* iconView = [cellView valueForKey:@"iconView"];
|
||||||
|
if (!iconView)
|
||||||
|
{
|
||||||
|
return NSZeroRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSRect iconRect = [self convertRect:iconView.frame fromView:cellView];
|
||||||
iconRect.origin.x += self.indentationPerLevel * (CGFloat)([self levelForRow:row] + 1);
|
iconRect.origin.x += self.indentationPerLevel * (CGFloat)([self levelForRow:row] + 1);
|
||||||
return iconRect;
|
return iconRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateTrackingAreas
|
|
||||||
{
|
|
||||||
[super updateTrackingAreas];
|
|
||||||
|
|
||||||
for (NSTrackingArea* area in self.trackingAreas)
|
|
||||||
{
|
|
||||||
if (area.owner == self && area.userInfo[@"Row"])
|
|
||||||
{
|
|
||||||
[self removeTrackingArea:area];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NSRange visibleRows = [self rowsInRect:self.visibleRect];
|
|
||||||
if (visibleRows.length == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
NSPoint mouseLocation = [self convertPoint:self.window.mouseLocationOutsideOfEventStream fromView:nil];
|
|
||||||
|
|
||||||
for (NSInteger row = visibleRows.location, col = [self columnWithIdentifier:@"Priority"]; (NSUInteger)row < NSMaxRange(visibleRows); row++)
|
|
||||||
{
|
|
||||||
FilePriorityCell* cell = (FilePriorityCell*)[self preparedCellAtColumn:col row:row];
|
|
||||||
|
|
||||||
NSDictionary* userInfo = @{ @"Row" : @(row) };
|
|
||||||
[cell addTrackingAreasForView:self inRect:[self frameOfCellAtColumn:col row:row] withUserInfo:userInfo
|
|
||||||
mouseLocation:mouseLocation];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)mouseEntered:(NSEvent*)event
|
|
||||||
{
|
|
||||||
NSNumber* row;
|
|
||||||
if ((row = ((NSDictionary*)event.userData)[@"Row"]))
|
|
||||||
{
|
|
||||||
self.hoveredRow = row.intValue;
|
|
||||||
[self setNeedsDisplayInRect:[self frameOfCellAtColumn:[self columnWithIdentifier:@"Priority"] row:self.hoveredRow]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)mouseExited:(NSEvent*)event
|
|
||||||
{
|
|
||||||
NSNumber* row;
|
|
||||||
if ((row = ((NSDictionary*)event.userData)[@"Row"]))
|
|
||||||
{
|
|
||||||
[self setNeedsDisplayInRect:[self frameOfCellAtColumn:[self columnWithIdentifier:@"Priority"] row:row.intValue]];
|
|
||||||
self.hoveredRow = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
// This file Copyright © Transmission authors and contributors.
|
|
||||||
// It may be used under the MIT (SPDX: MIT) license.
|
|
||||||
// License text can be found in the licenses/ folder.
|
|
||||||
|
|
||||||
#import <AppKit/AppKit.h>
|
|
||||||
|
|
||||||
@interface FilePriorityCell : NSSegmentedCell
|
|
||||||
|
|
||||||
@property(nonatomic) BOOL hovered;
|
|
||||||
|
|
||||||
- (void)addTrackingAreasForView:(NSView*)controlView
|
|
||||||
inRect:(NSRect)cellFrame
|
|
||||||
withUserInfo:(NSDictionary*)userInfo
|
|
||||||
mouseLocation:(NSPoint)mouseLocation;
|
|
||||||
|
|
||||||
@end
|
|
||||||
@@ -1,171 +0,0 @@
|
|||||||
// This file Copyright © Transmission authors and contributors.
|
|
||||||
// It may be used under the MIT (SPDX: MIT) license.
|
|
||||||
// License text can be found in the licenses/ folder.
|
|
||||||
|
|
||||||
#import "FilePriorityCell.h"
|
|
||||||
#import "FileOutlineView.h"
|
|
||||||
#import "FileListNode.h"
|
|
||||||
#import "NSImageAdditions.h"
|
|
||||||
#import "Torrent.h"
|
|
||||||
|
|
||||||
static CGFloat const kImageOverlap = 1.0;
|
|
||||||
|
|
||||||
@implementation FilePriorityCell
|
|
||||||
|
|
||||||
- (instancetype)init
|
|
||||||
{
|
|
||||||
if ((self = [super init]))
|
|
||||||
{
|
|
||||||
self.trackingMode = NSSegmentSwitchTrackingSelectAny;
|
|
||||||
self.controlSize = NSControlSizeMini;
|
|
||||||
self.segmentCount = 3;
|
|
||||||
|
|
||||||
for (NSInteger i = 0; i < self.segmentCount; i++)
|
|
||||||
{
|
|
||||||
[self setLabel:@"" forSegment:i];
|
|
||||||
[self setWidth:9.0f forSegment:i]; //9 is minimum size to get proper look
|
|
||||||
}
|
|
||||||
|
|
||||||
[self setImage:[NSImage imageNamed:@"PriorityControlLow"] forSegment:0];
|
|
||||||
[self setImage:[NSImage imageNamed:@"PriorityControlNormal"] forSegment:1];
|
|
||||||
[self setImage:[NSImage imageNamed:@"PriorityControlHigh"] forSegment:2];
|
|
||||||
|
|
||||||
_hovered = NO;
|
|
||||||
}
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id)copyWithZone:(NSZone*)zone
|
|
||||||
{
|
|
||||||
FilePriorityCell* copy = [super copyWithZone:zone];
|
|
||||||
[copy setRepresentedObject:self.representedObject];
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)setSelected:(BOOL)flag forSegment:(NSInteger)segment
|
|
||||||
{
|
|
||||||
[super setSelected:flag forSegment:segment];
|
|
||||||
|
|
||||||
//only for when clicking manually
|
|
||||||
tr_priority_t priority;
|
|
||||||
switch (segment)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
priority = TR_PRI_LOW;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
priority = TR_PRI_NORMAL;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
priority = TR_PRI_HIGH;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
NSAssert1(NO, @"Unknown segment: %ld", segment);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileListNode* node = self.representedObject;
|
|
||||||
Torrent* torrent = node.torrent;
|
|
||||||
[torrent setFilePriority:priority forIndexes:node.indexes];
|
|
||||||
|
|
||||||
FileOutlineView* controlView = (FileOutlineView*)self.controlView;
|
|
||||||
controlView.needsDisplay = YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)addTrackingAreasForView:(NSView*)controlView
|
|
||||||
inRect:(NSRect)cellFrame
|
|
||||||
withUserInfo:(NSDictionary*)userInfo
|
|
||||||
mouseLocation:(NSPoint)mouseLocation
|
|
||||||
{
|
|
||||||
NSTrackingAreaOptions options = NSTrackingEnabledDuringMouseDrag | NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways;
|
|
||||||
|
|
||||||
if (NSMouseInRect(mouseLocation, cellFrame, controlView.flipped))
|
|
||||||
{
|
|
||||||
options |= NSTrackingAssumeInside;
|
|
||||||
[controlView setNeedsDisplayInRect:cellFrame];
|
|
||||||
}
|
|
||||||
|
|
||||||
NSTrackingArea* area = [[NSTrackingArea alloc] initWithRect:cellFrame options:options owner:controlView userInfo:userInfo];
|
|
||||||
[controlView addTrackingArea:area];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView
|
|
||||||
{
|
|
||||||
FileListNode* node = self.representedObject;
|
|
||||||
Torrent* torrent = node.torrent;
|
|
||||||
NSSet* priorities = [torrent filePrioritiesForIndexes:node.indexes];
|
|
||||||
|
|
||||||
NSUInteger const count = priorities.count;
|
|
||||||
if (self.hovered && count > 0)
|
|
||||||
{
|
|
||||||
[super setSelected:[priorities containsObject:@(TR_PRI_LOW)] forSegment:0];
|
|
||||||
[super setSelected:[priorities containsObject:@(TR_PRI_NORMAL)] forSegment:1];
|
|
||||||
[super setSelected:[priorities containsObject:@(TR_PRI_HIGH)] forSegment:2];
|
|
||||||
|
|
||||||
[super drawWithFrame:cellFrame inView:controlView];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NSMutableArray* images = [NSMutableArray arrayWithCapacity:MAX(count, 1u)];
|
|
||||||
CGFloat totalWidth;
|
|
||||||
|
|
||||||
if (count == 0)
|
|
||||||
{
|
|
||||||
//if ([self backgroundStyle] != NSBackgroundStyleEmphasized)
|
|
||||||
{
|
|
||||||
NSImage* image = [[NSImage imageNamed:@"PriorityNormalTemplate"] imageWithColor:NSColor.lightGrayColor];
|
|
||||||
[images addObject:image];
|
|
||||||
totalWidth = image.size.width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NSColor* priorityColor = self.backgroundStyle == NSBackgroundStyleEmphasized ? NSColor.whiteColor : NSColor.darkGrayColor;
|
|
||||||
|
|
||||||
totalWidth = 0.0;
|
|
||||||
if ([priorities containsObject:@(TR_PRI_LOW)])
|
|
||||||
{
|
|
||||||
NSImage* image = [[NSImage imageNamed:@"PriorityLowTemplate"] imageWithColor:priorityColor];
|
|
||||||
[images addObject:image];
|
|
||||||
totalWidth += image.size.width;
|
|
||||||
}
|
|
||||||
if ([priorities containsObject:@(TR_PRI_NORMAL)])
|
|
||||||
{
|
|
||||||
NSImage* image = [[NSImage imageNamed:@"PriorityNormalTemplate"] imageWithColor:priorityColor];
|
|
||||||
[images addObject:image];
|
|
||||||
totalWidth += image.size.width;
|
|
||||||
}
|
|
||||||
if ([priorities containsObject:@(TR_PRI_HIGH)])
|
|
||||||
{
|
|
||||||
NSImage* image = [[NSImage imageNamed:@"PriorityHighTemplate"] imageWithColor:priorityColor];
|
|
||||||
[images addObject:image];
|
|
||||||
totalWidth += image.size.width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count > 1)
|
|
||||||
{
|
|
||||||
totalWidth -= kImageOverlap * (count - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
CGFloat currentWidth = floor(NSMidX(cellFrame) - totalWidth * 0.5);
|
|
||||||
|
|
||||||
for (NSImage* image in images)
|
|
||||||
{
|
|
||||||
NSSize const imageSize = image.size;
|
|
||||||
NSRect const imageRect = NSMakeRect(
|
|
||||||
currentWidth,
|
|
||||||
floor(NSMidY(cellFrame) - imageSize.height * 0.5),
|
|
||||||
imageSize.width,
|
|
||||||
imageSize.height);
|
|
||||||
|
|
||||||
[image drawInRect:imageRect fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:1.0
|
|
||||||
respectFlipped:YES
|
|
||||||
hints:nil];
|
|
||||||
|
|
||||||
currentWidth += imageSize.width - kImageOverlap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
14
macosx/FilePriorityCellView.h
Normal file
14
macosx/FilePriorityCellView.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
// This file Copyright © Transmission authors and contributors.
|
||||||
|
// It may be used under the MIT (SPDX: MIT) license.
|
||||||
|
// License text can be found in the licenses/ folder.
|
||||||
|
|
||||||
|
#import <AppKit/AppKit.h>
|
||||||
|
|
||||||
|
@class FileListNode;
|
||||||
|
|
||||||
|
@interface FilePriorityCellView : NSTableCellView
|
||||||
|
|
||||||
|
@property(nonatomic, weak) FileListNode* node;
|
||||||
|
@property(nonatomic) BOOL hovered;
|
||||||
|
|
||||||
|
@end
|
||||||
313
macosx/FilePriorityCellView.mm
Normal file
313
macosx/FilePriorityCellView.mm
Normal file
@@ -0,0 +1,313 @@
|
|||||||
|
// This file Copyright © Transmission authors and contributors.
|
||||||
|
// It may be used under the MIT (SPDX: MIT) license.
|
||||||
|
// License text can be found in the licenses/ folder.
|
||||||
|
|
||||||
|
#import "FilePriorityCellView.h"
|
||||||
|
#import "FileListNode.h"
|
||||||
|
#import "NSImageAdditions.h"
|
||||||
|
#import "Torrent.h"
|
||||||
|
|
||||||
|
static CGFloat const kImageOverlap = 1.0;
|
||||||
|
|
||||||
|
@interface FilePriorityCellView ()
|
||||||
|
@property(nonatomic, weak) NSSegmentedControl* segmentedControl;
|
||||||
|
@property(nonatomic, weak) NSView* iconsContainerView;
|
||||||
|
@property(nonatomic, strong) NSTrackingArea* trackingArea;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation FilePriorityCellView
|
||||||
|
|
||||||
|
- (instancetype)initWithFrame:(NSRect)frameRect
|
||||||
|
{
|
||||||
|
if ((self = [super initWithFrame:frameRect]))
|
||||||
|
{
|
||||||
|
// Create segmented control for hover state
|
||||||
|
NSSegmentedControl* segmentedControl = [[NSSegmentedControl alloc] initWithFrame:NSZeroRect];
|
||||||
|
segmentedControl.translatesAutoresizingMaskIntoConstraints = NO;
|
||||||
|
segmentedControl.trackingMode = NSSegmentSwitchTrackingSelectAny;
|
||||||
|
segmentedControl.controlSize = NSControlSizeMini;
|
||||||
|
segmentedControl.segmentCount = 3;
|
||||||
|
|
||||||
|
for (NSInteger i = 0; i < segmentedControl.segmentCount; i++)
|
||||||
|
{
|
||||||
|
[segmentedControl setLabel:@"" forSegment:i];
|
||||||
|
[segmentedControl setWidth:9.0f forSegment:i];
|
||||||
|
}
|
||||||
|
|
||||||
|
[segmentedControl setImage:[NSImage imageNamed:@"PriorityControlLow"] forSegment:0];
|
||||||
|
[segmentedControl setImage:[NSImage imageNamed:@"PriorityControlNormal"] forSegment:1];
|
||||||
|
[segmentedControl setImage:[NSImage imageNamed:@"PriorityControlHigh"] forSegment:2];
|
||||||
|
|
||||||
|
segmentedControl.target = self;
|
||||||
|
segmentedControl.action = @selector(segmentedControlClicked:);
|
||||||
|
segmentedControl.hidden = YES;
|
||||||
|
|
||||||
|
[self addSubview:segmentedControl];
|
||||||
|
_segmentedControl = segmentedControl;
|
||||||
|
|
||||||
|
// Create container view for priority icons
|
||||||
|
NSView* iconsContainerView = [[NSView alloc] initWithFrame:NSZeroRect];
|
||||||
|
iconsContainerView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||||
|
[self addSubview:iconsContainerView];
|
||||||
|
_iconsContainerView = iconsContainerView;
|
||||||
|
|
||||||
|
// Setup constraints
|
||||||
|
[NSLayoutConstraint activateConstraints:@[
|
||||||
|
[segmentedControl.centerXAnchor constraintEqualToAnchor:self.centerXAnchor],
|
||||||
|
[segmentedControl.centerYAnchor constraintEqualToAnchor:self.centerYAnchor],
|
||||||
|
|
||||||
|
[iconsContainerView.centerXAnchor constraintEqualToAnchor:self.centerXAnchor],
|
||||||
|
[iconsContainerView.centerYAnchor constraintEqualToAnchor:self.centerYAnchor],
|
||||||
|
[iconsContainerView.widthAnchor constraintLessThanOrEqualToAnchor:self.widthAnchor],
|
||||||
|
[iconsContainerView.heightAnchor constraintLessThanOrEqualToAnchor:self.heightAnchor],
|
||||||
|
]];
|
||||||
|
|
||||||
|
_hovered = NO;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setNode:(FileListNode*)node
|
||||||
|
{
|
||||||
|
_node = node;
|
||||||
|
|
||||||
|
[self updateDisplay];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setHovered:(BOOL)hovered
|
||||||
|
{
|
||||||
|
_hovered = hovered;
|
||||||
|
|
||||||
|
[self updateDisplay];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)updateDisplay
|
||||||
|
{
|
||||||
|
if (!self.node)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileListNode* node = self.node;
|
||||||
|
Torrent* torrent = node.torrent;
|
||||||
|
NSSet* priorities = [torrent filePrioritiesForIndexes:node.indexes];
|
||||||
|
|
||||||
|
NSUInteger const count = priorities.count;
|
||||||
|
if (self.hovered && count > 0)
|
||||||
|
{
|
||||||
|
// Show segmented control
|
||||||
|
self.segmentedControl.hidden = NO;
|
||||||
|
self.iconsContainerView.hidden = YES;
|
||||||
|
|
||||||
|
[self.segmentedControl setSelected:[priorities containsObject:@(TR_PRI_LOW)] forSegment:0];
|
||||||
|
[self.segmentedControl setSelected:[priorities containsObject:@(TR_PRI_NORMAL)] forSegment:1];
|
||||||
|
[self.segmentedControl setSelected:[priorities containsObject:@(TR_PRI_HIGH)] forSegment:2];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Show static priority icons
|
||||||
|
self.segmentedControl.hidden = YES;
|
||||||
|
self.iconsContainerView.hidden = NO;
|
||||||
|
|
||||||
|
[self updatePriorityIcons:priorities];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update tooltip
|
||||||
|
[self updateTooltip];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)updatePriorityIcons:(NSSet*)priorities
|
||||||
|
{
|
||||||
|
// Remove all existing image views
|
||||||
|
for (NSView* subview in self.iconsContainerView.subviews)
|
||||||
|
{
|
||||||
|
[subview removeFromSuperview];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSUInteger const count = priorities.count;
|
||||||
|
NSMutableArray* images = [NSMutableArray arrayWithCapacity:MAX(count, 1u)];
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
|
{
|
||||||
|
NSImage* image = [[NSImage imageNamed:@"PriorityNormalTemplate"] imageWithColor:NSColor.lightGrayColor];
|
||||||
|
[images addObject:image];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSColor* priorityColor = self.backgroundStyle == NSBackgroundStyleEmphasized ? NSColor.whiteColor : NSColor.darkGrayColor;
|
||||||
|
|
||||||
|
if ([priorities containsObject:@(TR_PRI_LOW)])
|
||||||
|
{
|
||||||
|
NSImage* image = [[NSImage imageNamed:@"PriorityLowTemplate"] imageWithColor:priorityColor];
|
||||||
|
[images addObject:image];
|
||||||
|
}
|
||||||
|
if ([priorities containsObject:@(TR_PRI_NORMAL)])
|
||||||
|
{
|
||||||
|
NSImage* image = [[NSImage imageNamed:@"PriorityNormalTemplate"] imageWithColor:priorityColor];
|
||||||
|
[images addObject:image];
|
||||||
|
}
|
||||||
|
if ([priorities containsObject:@(TR_PRI_HIGH)])
|
||||||
|
{
|
||||||
|
NSImage* image = [[NSImage imageNamed:@"PriorityHighTemplate"] imageWithColor:priorityColor];
|
||||||
|
[images addObject:image];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NSView* previousView = nil;
|
||||||
|
|
||||||
|
for (NSImage* image in images)
|
||||||
|
{
|
||||||
|
NSImageView* imageView = [[NSImageView alloc] initWithFrame:NSZeroRect];
|
||||||
|
imageView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||||
|
imageView.image = image;
|
||||||
|
[self.iconsContainerView addSubview:imageView];
|
||||||
|
|
||||||
|
NSSize const imageSize = image.size;
|
||||||
|
|
||||||
|
[NSLayoutConstraint activateConstraints:@[
|
||||||
|
[imageView.widthAnchor constraintEqualToConstant:imageSize.width],
|
||||||
|
[imageView.heightAnchor constraintEqualToConstant:imageSize.height],
|
||||||
|
[imageView.centerYAnchor constraintEqualToAnchor:self.iconsContainerView.centerYAnchor],
|
||||||
|
]];
|
||||||
|
|
||||||
|
if (previousView == nil)
|
||||||
|
{
|
||||||
|
[imageView.leadingAnchor constraintEqualToAnchor:self.iconsContainerView.leadingAnchor].active = YES;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[imageView.leadingAnchor constraintEqualToAnchor:previousView.trailingAnchor constant:-kImageOverlap].active = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
previousView = imageView;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previousView)
|
||||||
|
{
|
||||||
|
[previousView.trailingAnchor constraintEqualToAnchor:self.iconsContainerView.trailingAnchor].active = YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)segmentedControlClicked:(NSSegmentedControl*)sender
|
||||||
|
{
|
||||||
|
NSInteger segment = sender.selectedSegment;
|
||||||
|
if (segment == -1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr_priority_t priority;
|
||||||
|
switch (segment)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
priority = TR_PRI_LOW;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
priority = TR_PRI_NORMAL;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
priority = TR_PRI_HIGH;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
NSAssert1(NO, @"Unknown segment: %ld", segment);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileListNode* node = self.node;
|
||||||
|
Torrent* torrent = node.torrent;
|
||||||
|
[torrent setFilePriority:priority forIndexes:node.indexes];
|
||||||
|
|
||||||
|
// Notify that we need to refresh
|
||||||
|
[NSNotificationCenter.defaultCenter postNotificationName:@"UpdateUI" object:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setBackgroundStyle:(NSBackgroundStyle)backgroundStyle
|
||||||
|
{
|
||||||
|
[super setBackgroundStyle:backgroundStyle];
|
||||||
|
[self updateDisplay];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)updateTrackingAreas
|
||||||
|
{
|
||||||
|
[super updateTrackingAreas];
|
||||||
|
|
||||||
|
if (self.trackingArea)
|
||||||
|
{
|
||||||
|
[self removeTrackingArea:self.trackingArea];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited | NSTrackingActiveInActiveApp;
|
||||||
|
|
||||||
|
// Check if mouse is currently inside the bounds
|
||||||
|
NSPoint mouseLocation = [self.window mouseLocationOutsideOfEventStream];
|
||||||
|
NSPoint localPoint = [self convertPoint:mouseLocation fromView:nil];
|
||||||
|
if (NSPointInRect(localPoint, self.bounds))
|
||||||
|
{
|
||||||
|
options |= NSTrackingAssumeInside;
|
||||||
|
if (!self.hovered)
|
||||||
|
{
|
||||||
|
self.hovered = YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Mouse is not inside, reset hovered state
|
||||||
|
if (self.hovered)
|
||||||
|
{
|
||||||
|
self.hovered = NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.trackingArea = [[NSTrackingArea alloc] initWithRect:self.bounds options:options owner:self userInfo:nil];
|
||||||
|
[self addTrackingArea:self.trackingArea];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mouseEntered:(NSEvent*)event
|
||||||
|
{
|
||||||
|
self.hovered = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mouseExited:(NSEvent*)event
|
||||||
|
{
|
||||||
|
self.hovered = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)updateTooltip
|
||||||
|
{
|
||||||
|
if (!self.node)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileListNode* node = self.node;
|
||||||
|
Torrent* torrent = node.torrent;
|
||||||
|
NSSet* priorities = [torrent filePrioritiesForIndexes:node.indexes];
|
||||||
|
|
||||||
|
NSString* tooltip = nil;
|
||||||
|
switch (priorities.count)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
tooltip = NSLocalizedString(@"Priority Not Available", "files tab -> tooltip");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
switch ([[priorities anyObject] intValue])
|
||||||
|
{
|
||||||
|
case TR_PRI_LOW:
|
||||||
|
tooltip = NSLocalizedString(@"Low Priority", "files tab -> tooltip");
|
||||||
|
break;
|
||||||
|
case TR_PRI_HIGH:
|
||||||
|
tooltip = NSLocalizedString(@"High Priority", "files tab -> tooltip");
|
||||||
|
break;
|
||||||
|
case TR_PRI_NORMAL:
|
||||||
|
tooltip = NSLocalizedString(@"Normal Priority", "files tab -> tooltip");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
tooltip = NSLocalizedString(@"Multiple Priorities", "files tab -> tooltip");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
self.toolTip = tooltip;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="20037" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="24412" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="macosx"/>
|
<deployment identifier="macosx"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="20037"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="24412"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<objects>
|
<objects>
|
||||||
@@ -20,8 +20,8 @@
|
|||||||
<customView clipsToBounds="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2" userLabel="Files">
|
<customView clipsToBounds="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2" userLabel="Files">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="340" height="365"/>
|
<rect key="frame" x="0.0" y="0.0" width="340" height="365"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<searchField wantsLayer="YES" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3">
|
<searchField wantsLayer="YES" focusRingType="none" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3">
|
||||||
<rect key="frame" x="12" y="12" width="110" height="19"/>
|
<rect key="frame" x="12" y="12" width="110" height="20"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="width" constant="110" id="sKS-V5-H9b"/>
|
<constraint firstAttribute="width" constant="110" id="sKS-V5-H9b"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
@@ -35,19 +35,19 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</searchField>
|
</searchField>
|
||||||
<scrollView horizontalLineScroll="36" horizontalPageScroll="10" verticalLineScroll="36" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4">
|
<scrollView horizontalLineScroll="36" horizontalPageScroll="10" verticalLineScroll="36" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4">
|
||||||
<rect key="frame" x="12" y="39" width="316" height="314"/>
|
<rect key="frame" x="12" y="40" width="316" height="313"/>
|
||||||
<clipView key="contentView" id="l96-jk-uz9">
|
<clipView key="contentView" id="l96-jk-uz9">
|
||||||
<rect key="frame" x="1" y="1" width="314" height="312"/>
|
<rect key="frame" x="1" y="1" width="301" height="311"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<outlineView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnReordering="NO" columnResizing="NO" autosaveColumns="NO" rowHeight="34" indentationPerLevel="16" autoresizesOutlineColumn="YES" outlineTableColumn="10" id="7" customClass="FileOutlineView">
|
<outlineView verticalHuggingPriority="750" allowsExpansionToolTips="YES" alternatingRowBackgroundColors="YES" columnReordering="NO" columnResizing="NO" autosaveColumns="NO" rowHeight="34" rowSizeStyle="automatic" viewBased="YES" indentationPerLevel="16" autoresizesOutlineColumn="YES" outlineTableColumn="10" id="7" customClass="FileOutlineView">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="314" height="312"/>
|
<rect key="frame" x="0.0" y="0.0" width="301" height="311"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<size key="intercellSpacing" width="3" height="2"/>
|
<size key="intercellSpacing" width="3" height="2"/>
|
||||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
|
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
|
||||||
<tableColumns>
|
<tableColumns>
|
||||||
<tableColumn identifier="Name" editable="NO" width="231" minWidth="38.599119999999999" maxWidth="1000" id="10">
|
<tableColumn identifier="Name" editable="NO" width="218" minWidth="38.599119999999999" maxWidth="1000" id="10">
|
||||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Name">
|
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Name">
|
||||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
||||||
<color key="backgroundColor" white="0.33333299" alpha="1" colorSpace="calibratedWhite"/>
|
<color key="backgroundColor" white="0.33333299" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
@@ -58,6 +58,26 @@
|
|||||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
</textFieldCell>
|
</textFieldCell>
|
||||||
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES"/>
|
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES"/>
|
||||||
|
<prototypeCellViews>
|
||||||
|
<tableCellView id="ddm-cs-nIR">
|
||||||
|
<rect key="frame" x="1" y="1" width="223" height="34"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<subviews>
|
||||||
|
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="HIK-di-9tP">
|
||||||
|
<rect key="frame" x="0.0" y="9" width="223" height="16"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
|
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="D7f-0h-h8A">
|
||||||
|
<font key="font" usesAppearanceFont="YES"/>
|
||||||
|
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
</textFieldCell>
|
||||||
|
</textField>
|
||||||
|
</subviews>
|
||||||
|
<connections>
|
||||||
|
<outlet property="textField" destination="HIK-di-9tP" id="bHT-uH-6AK"/>
|
||||||
|
</connections>
|
||||||
|
</tableCellView>
|
||||||
|
</prototypeCellViews>
|
||||||
</tableColumn>
|
</tableColumn>
|
||||||
<tableColumn identifier="Priority" editable="NO" width="34" minWidth="10" maxWidth="1000" id="8">
|
<tableColumn identifier="Priority" editable="NO" width="34" minWidth="10" maxWidth="1000" id="8">
|
||||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Rank">
|
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Rank">
|
||||||
@@ -69,6 +89,26 @@
|
|||||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
</textFieldCell>
|
</textFieldCell>
|
||||||
|
<prototypeCellViews>
|
||||||
|
<tableCellView id="4RH-Kf-WF8">
|
||||||
|
<rect key="frame" x="227" y="1" width="34" height="34"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<subviews>
|
||||||
|
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DCs-8X-Mcb">
|
||||||
|
<rect key="frame" x="0.0" y="9" width="34" height="16"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
|
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="Doc-xO-gx2">
|
||||||
|
<font key="font" usesAppearanceFont="YES"/>
|
||||||
|
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
</textFieldCell>
|
||||||
|
</textField>
|
||||||
|
</subviews>
|
||||||
|
<connections>
|
||||||
|
<outlet property="textField" destination="DCs-8X-Mcb" id="ad1-R3-pcd"/>
|
||||||
|
</connections>
|
||||||
|
</tableCellView>
|
||||||
|
</prototypeCellViews>
|
||||||
</tableColumn>
|
</tableColumn>
|
||||||
<tableColumn identifier="Check" editable="NO" width="31" minWidth="10" maxWidth="1000" id="9">
|
<tableColumn identifier="Check" editable="NO" width="31" minWidth="10" maxWidth="1000" id="9">
|
||||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="DL">
|
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="DL">
|
||||||
@@ -79,6 +119,26 @@
|
|||||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||||
<font key="font" metaFont="cellTitle"/>
|
<font key="font" metaFont="cellTitle"/>
|
||||||
</buttonCell>
|
</buttonCell>
|
||||||
|
<prototypeCellViews>
|
||||||
|
<tableCellView id="l8k-SJ-e7E">
|
||||||
|
<rect key="frame" x="264" y="1" width="35" height="34"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<subviews>
|
||||||
|
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="CkN-iw-rOX">
|
||||||
|
<rect key="frame" x="0.0" y="9" width="35" height="16"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
|
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="a2Y-Cf-rdu">
|
||||||
|
<font key="font" usesAppearanceFont="YES"/>
|
||||||
|
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
</textFieldCell>
|
||||||
|
</textField>
|
||||||
|
</subviews>
|
||||||
|
<connections>
|
||||||
|
<outlet property="textField" destination="CkN-iw-rOX" id="Thn-jw-ARn"/>
|
||||||
|
</connections>
|
||||||
|
</tableCellView>
|
||||||
|
</prototypeCellViews>
|
||||||
</tableColumn>
|
</tableColumn>
|
||||||
</tableColumns>
|
</tableColumns>
|
||||||
<connections>
|
<connections>
|
||||||
@@ -98,12 +158,12 @@
|
|||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
</scroller>
|
</scroller>
|
||||||
<scroller key="verticalScroller" wantsLayer="YES" verticalHuggingPriority="750" controlSize="small" horizontal="NO" id="6">
|
<scroller key="verticalScroller" wantsLayer="YES" verticalHuggingPriority="750" controlSize="small" horizontal="NO" id="6">
|
||||||
<rect key="frame" x="301" y="1" width="14" height="312"/>
|
<rect key="frame" x="302" y="1" width="13" height="311"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
</scroller>
|
</scroller>
|
||||||
</scrollView>
|
</scrollView>
|
||||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="25">
|
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="25">
|
||||||
<rect key="frame" x="286" y="12" width="42" height="17"/>
|
<rect key="frame" x="280" y="12" width="48" height="20"/>
|
||||||
<buttonCell key="cell" type="roundRect" title="None" bezelStyle="roundedRect" alignment="center" controlSize="small" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="26">
|
<buttonCell key="cell" type="roundRect" title="None" bezelStyle="roundedRect" alignment="center" controlSize="small" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="26">
|
||||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
<font key="font" metaFont="smallSystem"/>
|
<font key="font" metaFont="smallSystem"/>
|
||||||
@@ -113,7 +173,7 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="27">
|
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="27">
|
||||||
<rect key="frame" x="236" y="12" width="42" height="17"/>
|
<rect key="frame" x="224" y="12" width="48" height="20"/>
|
||||||
<buttonCell key="cell" type="roundRect" title="All" bezelStyle="roundedRect" alignment="center" controlSize="small" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="28">
|
<buttonCell key="cell" type="roundRect" title="All" bezelStyle="roundedRect" alignment="center" controlSize="small" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="28">
|
||||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
<font key="font" metaFont="smallSystem"/>
|
<font key="font" metaFont="smallSystem"/>
|
||||||
|
|||||||
@@ -88,13 +88,13 @@
|
|||||||
|
|
||||||
if (self.fTorrents.count == 1)
|
if (self.fTorrents.count == 1)
|
||||||
{
|
{
|
||||||
[self.fFileController refresh];
|
[self.fFileController reloadVisibleRows];
|
||||||
|
|
||||||
#warning use TorrentFileCheckChange notification as well
|
#warning use TorrentFileCheckChange notification as well
|
||||||
Torrent* torrent = self.fTorrents[0];
|
Torrent* torrent = self.fTorrents[0];
|
||||||
if (torrent.folder)
|
if (torrent.folder)
|
||||||
{
|
{
|
||||||
NSInteger const filesCheckState = [torrent
|
NSControlStateValue const filesCheckState = [torrent
|
||||||
checkForFiles:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, torrent.fileCount)]];
|
checkForFiles:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, torrent.fileCount)]];
|
||||||
self.fCheckAllButton.enabled = filesCheckState != NSControlStateValueOn; //if anything is unchecked
|
self.fCheckAllButton.enabled = filesCheckState != NSControlStateValueOn; //if anything is unchecked
|
||||||
self.fUncheckAllButton.enabled = !torrent.allDownloaded; //if there are any checked files that aren't finished
|
self.fUncheckAllButton.enabled = !torrent.allDownloaded; //if there are any checked files that aren't finished
|
||||||
|
|||||||
@@ -195,8 +195,8 @@ extern NSString* const kTorrentDidChangeGroupNotification;
|
|||||||
- (CGFloat)fileProgress:(FileListNode*)node;
|
- (CGFloat)fileProgress:(FileListNode*)node;
|
||||||
- (BOOL)canChangeDownloadCheckForFile:(NSUInteger)index;
|
- (BOOL)canChangeDownloadCheckForFile:(NSUInteger)index;
|
||||||
- (BOOL)canChangeDownloadCheckForFiles:(NSIndexSet*)indexSet;
|
- (BOOL)canChangeDownloadCheckForFiles:(NSIndexSet*)indexSet;
|
||||||
- (NSInteger)checkForFiles:(NSIndexSet*)indexSet;
|
- (NSControlStateValue)checkForFiles:(NSIndexSet*)indexSet;
|
||||||
- (void)setFileCheckState:(NSInteger)state forIndexes:(NSIndexSet*)indexSet;
|
- (void)setFileCheckState:(NSControlStateValue)state forIndexes:(NSIndexSet*)indexSet;
|
||||||
- (void)setFilePriority:(tr_priority_t)priority forIndexes:(NSIndexSet*)indexSet;
|
- (void)setFilePriority:(tr_priority_t)priority forIndexes:(NSIndexSet*)indexSet;
|
||||||
- (BOOL)hasFilePriority:(tr_priority_t)priority forIndexes:(NSIndexSet*)indexSet;
|
- (BOOL)hasFilePriority:(tr_priority_t)priority forIndexes:(NSIndexSet*)indexSet;
|
||||||
- (NSSet*)filePrioritiesForIndexes:(NSIndexSet*)indexSet;
|
- (NSSet*)filePrioritiesForIndexes:(NSIndexSet*)indexSet;
|
||||||
|
|||||||
@@ -1547,7 +1547,7 @@ bool trashDataFile(char const* filename, void* /*user_data*/, tr_error* error)
|
|||||||
return canChange;
|
return canChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSInteger)checkForFiles:(NSIndexSet*)indexSet
|
- (NSControlStateValue)checkForFiles:(NSIndexSet*)indexSet
|
||||||
{
|
{
|
||||||
BOOL onState = NO, offState = NO;
|
BOOL onState = NO, offState = NO;
|
||||||
for (NSUInteger index = indexSet.firstIndex; index != NSNotFound; index = [indexSet indexGreaterThanIndex:index])
|
for (NSUInteger index = indexSet.firstIndex; index != NSNotFound; index = [indexSet indexGreaterThanIndex:index])
|
||||||
@@ -1570,7 +1570,7 @@ bool trashDataFile(char const* filename, void* /*user_data*/, tr_error* error)
|
|||||||
return onState ? NSControlStateValueOn : NSControlStateValueOff;
|
return onState ? NSControlStateValueOn : NSControlStateValueOff;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setFileCheckState:(NSInteger)state forIndexes:(NSIndexSet*)indexSet
|
- (void)setFileCheckState:(NSControlStateValue)state forIndexes:(NSIndexSet*)indexSet
|
||||||
{
|
{
|
||||||
NSUInteger count = indexSet.count;
|
NSUInteger count = indexSet.count;
|
||||||
tr_file_index_t* files = static_cast<tr_file_index_t*>(malloc(count * sizeof(tr_file_index_t)));
|
tr_file_index_t* files = static_cast<tr_file_index_t*>(malloc(count * sizeof(tr_file_index_t)));
|
||||||
|
|||||||
Reference in New Issue
Block a user