From 54f0417f42ba26259e27842c03bac5820d212b46 Mon Sep 17 00:00:00 2001 From: Dzmitry Neviadomski Date: Thu, 20 Nov 2025 05:30:55 +0300 Subject: [PATCH] Simplify "bars" logic in Main Window (#7840) * Adopt NSTitlebarAccessoryViewController for filter and status bars Also remove custom views as separator is drawn with Horizontal Line. Simplifies maintainance a bit. * Unembed main content and status bar from NSStackView Stack is no longer needed, as bars are moved into titlebar. --- Transmission.xcodeproj/project.pbxproj | 12 - macosx/Base.lproj/MainMenu.xib | 945 ++++++++++++------------- macosx/CMakeLists.txt | 4 - macosx/Controller.h | 2 +- macosx/Controller.mm | 136 ++-- macosx/FilterBar.xib | 49 +- macosx/FilterBarController.h | 2 +- macosx/FilterBarView.h | 9 - macosx/FilterBarView.mm | 42 -- macosx/StatusBar.xib | 30 +- macosx/StatusBarController.h | 2 +- macosx/StatusBarView.h | 9 - macosx/StatusBarView.mm | 39 - 13 files changed, 582 insertions(+), 699 deletions(-) delete mode 100644 macosx/FilterBarView.h delete mode 100644 macosx/FilterBarView.mm delete mode 100644 macosx/StatusBarView.h delete mode 100644 macosx/StatusBarView.mm diff --git a/Transmission.xcodeproj/project.pbxproj b/Transmission.xcodeproj/project.pbxproj index e348dff8b..d5fefb058 100644 --- a/Transmission.xcodeproj/project.pbxproj +++ b/Transmission.xcodeproj/project.pbxproj @@ -107,7 +107,6 @@ A209EC12114301C6002B02D1 /* InfoOptionsView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A209EC11114301C6002B02D1 /* InfoOptionsView.xib */; }; A209ECA2114319C3002B02D1 /* InfoWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = A209ECA1114319C3002B02D1 /* InfoWindow.xib */; }; A209EE5D1144B51E002B02D1 /* history.h in Headers */ = {isa = PBXBuildFile; fileRef = A209EE5B1144B51E002B02D1 /* history.h */; }; - A21282A80CA6C66800EAEE0F /* StatusBarView.mm in Sources */ = {isa = PBXBuildFile; fileRef = A21282A60CA6C66800EAEE0F /* StatusBarView.mm */; }; A215BF5C0F02EBB800350CDB /* GroupRules.xib in Resources */ = {isa = PBXBuildFile; fileRef = A215BF5B0F02EBB800350CDB /* GroupRules.xib */; }; A219798B0D07B78400438EA7 /* GroupToolbarItem.mm in Sources */ = {isa = PBXBuildFile; fileRef = A219798A0D07B78400438EA7 /* GroupToolbarItem.mm */; }; A21A9BE2106D86A800F1C3C1 /* TrackerNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = A21A9BE1106D86A800F1C3C1 /* TrackerNode.mm */; }; @@ -178,7 +177,6 @@ A25E74660AF5097D006F11AE /* ExpandedPathToIconTransformer.mm in Sources */ = {isa = PBXBuildFile; fileRef = A25E74460AF5089E006F11AE /* ExpandedPathToIconTransformer.mm */; }; A263C6B1F6718E2486DB20E0 /* tr-buffer.h in Headers */ = {isa = PBXBuildFile; fileRef = A263C6B1F6718E2486DB20E1 /* tr-buffer.h */; }; A263CFC010DD67670038DE27 /* InfoTextField.mm in Sources */ = {isa = PBXBuildFile; fileRef = A263CFBF10DD67670038DE27 /* InfoTextField.mm */; }; - A2661D6112D0E8D9004F69D5 /* FilterBarView.mm in Sources */ = {isa = PBXBuildFile; fileRef = A2661D3B12D0E51B004F69D5 /* FilterBarView.mm */; }; A267927C130DFF2700CB7464 /* libutp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A2E38544130DFEE3001F501B /* libutp.a */; }; A2679294130E00A000CB7464 /* tr-utp.cc in Sources */ = {isa = PBXBuildFile; fileRef = A2679292130E00A000CB7464 /* tr-utp.cc */; }; A2679295130E00A000CB7464 /* tr-utp.h in Headers */ = {isa = PBXBuildFile; fileRef = A2679293130E00A000CB7464 /* tr-utp.h */; }; @@ -895,8 +893,6 @@ A209EBF81142FEEE002B02D1 /* InfoOptionsViewController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = InfoOptionsViewController.mm; sourceTree = ""; }; A209ECA1114319C3002B02D1 /* InfoWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = InfoWindow.xib; sourceTree = ""; }; A209EE5B1144B51E002B02D1 /* history.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; path = history.h; sourceTree = ""; }; - A21282A50CA6C66800EAEE0F /* StatusBarView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StatusBarView.h; sourceTree = ""; }; - A21282A60CA6C66800EAEE0F /* StatusBarView.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = StatusBarView.mm; sourceTree = ""; }; A21979890D07B78400438EA7 /* GroupToolbarItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GroupToolbarItem.h; sourceTree = ""; }; A219798A0D07B78400438EA7 /* GroupToolbarItem.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = GroupToolbarItem.mm; sourceTree = ""; }; A21A9BE0106D86A800F1C3C1 /* TrackerNode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TrackerNode.h; sourceTree = ""; }; @@ -988,8 +984,6 @@ A263C6B1F6718E2486DB20E1 /* tr-buffer.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; path = "tr-buffer.h"; sourceTree = ""; }; A263CFBE10DD67670038DE27 /* InfoTextField.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InfoTextField.h; sourceTree = ""; }; A263CFBF10DD67670038DE27 /* InfoTextField.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = InfoTextField.mm; sourceTree = ""; }; - A2661D3A12D0E51A004F69D5 /* FilterBarView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FilterBarView.h; sourceTree = ""; }; - A2661D3B12D0E51B004F69D5 /* FilterBarView.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FilterBarView.mm; sourceTree = ""; }; A2679292130E00A000CB7464 /* tr-utp.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "tr-utp.cc"; sourceTree = ""; }; A2679293130E00A000CB7464 /* tr-utp.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; path = "tr-utp.h"; sourceTree = ""; }; A267C2832E9F2B23003B87D7 /* Transmission_Tahoe.icon */ = {isa = PBXFileReference; lastKnownFileType = folder.iconcomposer.icon; name = Transmission_Tahoe.icon; path = Images/Transmission_Tahoe.icon; sourceTree = ""; }; @@ -1756,12 +1750,8 @@ E138A9760C04D88F00C5426C /* ProgressGradients.mm */, A2E57AB91310822C00A7DAB1 /* StatusBarController.h */, A2E57ABA1310822C00A7DAB1 /* StatusBarController.mm */, - A21282A50CA6C66800EAEE0F /* StatusBarView.h */, - A21282A60CA6C66800EAEE0F /* StatusBarView.mm */, A2E57BA513109E6B00A7DAB1 /* FilterBarController.h */, A2E57BA613109E6B00A7DAB1 /* FilterBarController.mm */, - A2661D3A12D0E51A004F69D5 /* FilterBarView.h */, - A2661D3B12D0E51B004F69D5 /* FilterBarView.mm */, A2ED7D8D0CEF431B00970975 /* FilterButton.h */, A2ED7D8E0CEF431B00970975 /* FilterButton.mm */, A2C89D5F0CFCBF57004CC2BC /* ButtonToolbarItem.mm */, @@ -3560,7 +3550,6 @@ ED6F16B72EB8F1EB007CD864 /* FileCheckCellView.mm in Sources */, A2DF37070C220D03006523C1 /* CreatorWindowController.mm in Sources */, A2085DDC0C53BC74000BC3B7 /* AboutWindowController.mm in Sources */, - A21282A80CA6C66800EAEE0F /* StatusBarView.mm in Sources */, A257C1820CAD3003004E121C /* PeerTableView.mm in Sources */, 45489C5429AF6FB20098A812 /* TorrentCellActionButton.mm in Sources */, A2A6321B0CD9751700E3DA60 /* BadgeView.mm in Sources */, @@ -3601,7 +3590,6 @@ A209EBF91142FEEE002B02D1 /* InfoOptionsViewController.mm in Sources */, ED9862972B979AA2002F3035 /* Utils.mm in Sources */, A21F15AC11729A8B00CF5A9C /* AddMagnetWindowController.mm in Sources */, - A2661D6112D0E8D9004F69D5 /* FilterBarView.mm in Sources */, A2F7CF5F13035FFD0016FF10 /* URLSheetWindowController.mm in Sources */, A2E57ABB1310822C00A7DAB1 /* StatusBarController.mm in Sources */, A2E57BA713109E6B00A7DAB1 /* FilterBarController.mm in Sources */, diff --git a/macosx/Base.lproj/MainMenu.xib b/macosx/Base.lproj/MainMenu.xib index 02547952b..e2398acda 100644 --- a/macosx/Base.lproj/MainMenu.xib +++ b/macosx/Base.lproj/MainMenu.xib @@ -1,8 +1,10 @@ - + - + + + @@ -13,513 +15,507 @@ - - + + - - + + - + - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + - - - - - - - - - + - - - - + + + + + + + + + - + @@ -1063,7 +1059,6 @@ CA - diff --git a/macosx/CMakeLists.txt b/macosx/CMakeLists.txt index db7b8cf04..ce22180e4 100644 --- a/macosx/CMakeLists.txt +++ b/macosx/CMakeLists.txt @@ -89,8 +89,6 @@ target_sources(${TR_NAME}-mac FileRenameSheetController.mm FilterBarController.h FilterBarController.mm - FilterBarView.h - FilterBarView.mm FilterButton.h FilterButton.mm GlobalOptionsPopoverViewController.h @@ -170,8 +168,6 @@ target_sources(${TR_NAME}-mac StatsWindowController.mm StatusBarController.h StatusBarController.mm - StatusBarView.h - StatusBarView.mm Toolbar.h Toolbar.mm Torrent.h diff --git a/macosx/Controller.h b/macosx/Controller.h index f4aeef754..cd58c2ef3 100644 --- a/macosx/Controller.h +++ b/macosx/Controller.h @@ -164,7 +164,7 @@ typedef NS_ENUM(NSUInteger, AddType) { // - (void)setWindowSizeToFit; - (void)updateForAutoSize; - (void)updateWindowAfterToolbarChange; -- (void)removeStackViewHeightConstraints; +- (void)removeHeightConstraints; @property(nonatomic, readonly) CGFloat minScrollViewHeightAllowed; @property(nonatomic, readonly) CGFloat toolbarHeight; @property(nonatomic, readonly) CGFloat mainWindowComponentHeight; diff --git a/macosx/Controller.mm b/macosx/Controller.mm index 0dee59447..fb24443a3 100644 --- a/macosx/Controller.mm +++ b/macosx/Controller.mm @@ -112,8 +112,8 @@ static NSString* const kTorrentTableViewDataType = @"TorrentTableViewDataType"; static CGFloat const kRowHeightRegular = 62.0; static CGFloat const kRowHeightSmall = 22.0; -static CGFloat const kStatusBarHeight = 21.0; -static CGFloat const kFilterBarHeight = 23.0; +static CGFloat const kStatusBarHeight = 24.0; +static CGFloat const kFilterBarHeight = 24.0; static CGFloat const kBottomBarHeight = 24.0; static NSTimeInterval const kUpdateUISeconds = 1.0; @@ -268,8 +268,8 @@ static void removeKeRangerRansomware() @interface Controller () @property(nonatomic) IBOutlet NSWindow* fWindow; -@property(nonatomic) IBOutlet NSStackView* fStackView; -@property(nonatomic) NSArray* fStackViewHeightConstraints; +@property(nonatomic) NSLayoutConstraint* fMinHeightConstraint; +@property(nonatomic) NSLayoutConstraint* fFixedHeightConstraint; @property(nonatomic) IBOutlet TorrentTableView* fTableView; @property(nonatomic) IBOutlet NSMenuItem* fOpenIgnoreDownloadFolder; @@ -643,7 +643,6 @@ void onTorrentCompletenessChanged(tr_torrent* tor, tr_completeness status, bool self.fTableView.floatsGroupRows = YES; //self.fTableView.usesAlternatingRowBackgroundColors = !small; - [self.fWindow setContentBorderThickness:NSMinY(self.fTableView.enclosingScrollView.frame) forEdge:NSMinYEdge]; self.fWindow.movableByWindowBackground = YES; self.fTotalTorrentsField.cell.backgroundStyle = NSBackgroundStyleRaised; @@ -4028,14 +4027,14 @@ void onTorrentCompletenessChanged(tr_torrent* tor, tr_completeness status, bool - (void)toggleStatusBar:(id)sender { - BOOL const show = self.fStatusBar == nil; + BOOL const show = self.fStatusBar == nil || self.fStatusBar.isHidden; [self.fDefaults setBool:show forKey:@"StatusBar"]; [self updateMainWindow]; } - (void)toggleFilterBar:(id)sender { - BOOL const show = self.fFilterBar == nil; + BOOL const show = self.fFilterBar == nil || self.fFilterBar.isHidden; //disable filtering when hiding (have to do before updateMainWindow:) if (!show) @@ -4054,7 +4053,7 @@ void onTorrentCompletenessChanged(tr_torrent* tor, tr_completeness status, bool - (void)focusFilterField { - if (!self.fFilterBar) + if (self.fFilterBar == nil || self.fFilterBar.isHidden) { [self toggleFilterBar:self]; } @@ -4555,7 +4554,8 @@ void onTorrentCompletenessChanged(tr_torrent* tor, tr_completeness status, bool //set filter item if ([ident isEqualToString:ToolbarItemIdentifierFilter]) { - ((NSButton*)toolbarItem.view).state = self.fFilterBar != nil; + BOOL shown = !(self.fFilterBar == nil || self.fFilterBar.isHidden); + ((NSButton*)toolbarItem.view).state = shown ? NSControlStateValueOn : NSControlStateValueOff; return YES; } @@ -5079,59 +5079,41 @@ void onTorrentCompletenessChanged(tr_torrent* tor, tr_completeness status, bool - (void)updateMainWindow { - NSArray* subViews = self.fStackView.arrangedSubviews; - NSUInteger idx = 0; + if (self.fStatusBar == nil) + { + self.fStatusBar = [[StatusBarController alloc] initWithLib:self.fLib]; + self.fStatusBar.layoutAttribute = NSLayoutAttributeBottom; + self.fStatusBar.automaticallyAdjustsSize = NO; + + [self.fWindow addTitlebarAccessoryViewController:self.fStatusBar]; + } - //update layout if ([self.fDefaults boolForKey:@"StatusBar"]) { - if (self.fStatusBar == nil) - { - self.fStatusBar = [[StatusBarController alloc] initWithLib:self.fLib]; - } - - [self.fStackView insertArrangedSubview:self.fStatusBar.view atIndex:idx]; - - NSDictionary* views = @{ @"fStatusBar" : self.fStatusBar.view }; - [self.fStackView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[fStatusBar(==21)]" options:0 - metrics:nil - views:views]]; - idx = 1; + self.fStatusBar.hidden = NO; } else { - if ([subViews containsObject:self.fStatusBar.view]) - { - [self.fStackView removeView:self.fStatusBar.view]; - self.fStatusBar = nil; - } + self.fStatusBar.hidden = YES; + } + + if (self.fFilterBar == nil) + { + self.fFilterBar = [[FilterBarController alloc] init]; + self.fFilterBar.layoutAttribute = NSLayoutAttributeBottom; + self.fFilterBar.automaticallyAdjustsSize = NO; + + [self.fWindow addTitlebarAccessoryViewController:self.fFilterBar]; } if ([self.fDefaults boolForKey:@"FilterBar"]) { - if (self.fFilterBar == nil) - { - self.fFilterBar = [[FilterBarController alloc] init]; - } - - [self.fStackView insertArrangedSubview:self.fFilterBar.view atIndex:idx]; - - NSDictionary* views = @{ @"fFilterBar" : self.fFilterBar.view }; - [self.fStackView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[fFilterBar(==23)]" options:0 - metrics:nil - views:views]]; - + self.fFilterBar.hidden = NO; [self focusFilterField]; } else { - if ([subViews containsObject:self.fFilterBar.view]) - { - [self.fStackView removeView:self.fFilterBar.view]; - self.fFilterBar = nil; - - [self.fWindow makeFirstResponder:self.fTableView]; - } + self.fFilterBar.hidden = YES; } [self fullUpdateUI]; @@ -5146,40 +5128,47 @@ void onTorrentCompletenessChanged(tr_torrent* tor, tr_completeness status, bool scrollView.hasVerticalScroller = NO; - [self removeStackViewHeightConstraints]; - - NSDictionary* views = @{ @"scrollView" : scrollView }; + [self removeHeightConstraints]; if (![self.fDefaults boolForKey:@"AutoSize"]) { // Only set a minimum height constraint CGFloat height = self.minScrollViewHeightAllowed; - NSString* constraintsString = [NSString stringWithFormat:@"V:[scrollView(>=%f)]", height]; - self.fStackViewHeightConstraints = [NSLayoutConstraint constraintsWithVisualFormat:constraintsString options:0 - metrics:nil - views:views]; + if (self.fMinHeightConstraint == nil) + { + self.fMinHeightConstraint = [scrollView.heightAnchor constraintGreaterThanOrEqualToConstant:height]; + } + else + { + self.fMinHeightConstraint.constant = height; + } + + self.fMinHeightConstraint.active = YES; } else { // Set a fixed height constraint CGFloat height = [self calculateScrollViewHeightWithDockAdjustment]; - NSString* constraintsString = [NSString stringWithFormat:@"V:[scrollView(==%f)]", height]; - self.fStackViewHeightConstraints = [NSLayoutConstraint constraintsWithVisualFormat:constraintsString options:0 - metrics:nil - views:views]; + if (self.fFixedHeightConstraint == nil) + { + self.fFixedHeightConstraint = [scrollView.heightAnchor constraintEqualToConstant:height]; + } + else + { + self.fFixedHeightConstraint.constant = height; + } // Redraw table to avoid empty cells [self.fTableView reloadData]; - } - // Add height constraint to fStackView - [self.fStackView addConstraints:self.fStackViewHeightConstraints]; + self.fFixedHeightConstraint.active = YES; + } scrollView.hasVerticalScroller = YES; } else { - [self removeStackViewHeightConstraints]; + [self removeHeightConstraints]; } } @@ -5207,7 +5196,7 @@ void onTorrentCompletenessChanged(tr_torrent* tor, tr_completeness status, bool } else { - [self removeStackViewHeightConstraints]; + [self removeHeightConstraints]; } } @@ -5220,7 +5209,7 @@ void onTorrentCompletenessChanged(tr_torrent* tor, tr_completeness status, bool //and we only need to "fix" the layout when showing the toolbar if (!self.fWindow.toolbar.isVisible) { - [self removeStackViewHeightConstraints]; + [self removeHeightConstraints]; } //this fixes a macOS bug where on toggling the toolbar item bezels will show @@ -5241,11 +5230,15 @@ void onTorrentCompletenessChanged(tr_torrent* tor, tr_completeness status, bool } } -- (void)removeStackViewHeightConstraints +- (void)removeHeightConstraints { - if (self.fStackViewHeightConstraints) + if (self.fFixedHeightConstraint != nil) { - [self.fStackView removeConstraints:self.fStackViewHeightConstraints]; + self.fFixedHeightConstraint.active = NO; + } + if (self.fMinHeightConstraint != nil) + { + self.fMinHeightConstraint.active = NO; } } @@ -5263,12 +5256,13 @@ void onTorrentCompletenessChanged(tr_torrent* tor, tr_completeness status, bool - (CGFloat)mainWindowComponentHeight { CGFloat height = kBottomBarHeight; - if (self.fStatusBar) + + if (self.fStatusBar != nil && !self.fStatusBar.isHidden) { height += kStatusBarHeight; } - if (self.fFilterBar) + if (self.fFilterBar != nil && !self.fFilterBar.isHidden) { height += kFilterBarHeight; } @@ -5329,7 +5323,7 @@ void onTorrentCompletenessChanged(tr_torrent* tor, tr_completeness status, bool - (void)windowWillEnterFullScreen:(NSNotification*)notification { - [self removeStackViewHeightConstraints]; + [self removeHeightConstraints]; } - (void)windowDidExitFullScreen:(NSNotification*)notification diff --git a/macosx/FilterBar.xib b/macosx/FilterBar.xib index 377b3f174..e9150ed1a 100644 --- a/macosx/FilterBar.xib +++ b/macosx/FilterBar.xib @@ -1,8 +1,8 @@ - + - + @@ -22,15 +22,12 @@ - - + + - - - - + @@ -51,18 +48,21 @@ + + + - + - +