From 9b202622071c25856218fcc07356385bc7bffd08 Mon Sep 17 00:00:00 2001 From: relikd Date: Fri, 17 Jan 2020 14:07:14 +0100 Subject: [PATCH] Menu bar icon tint (10.14+) --- baRSS.xcodeproj/project.pbxproj | 14 +++++-- baRSS/Helper/DrawImage.m | 14 +++---- baRSS/Info.plist | 2 +- baRSS/NSCategories/NSColor+Ext.h | 36 ++++++++++++++++++ baRSS/NSCategories/NSColor+Ext.m | 55 +++++++++++++++++++++++++++ baRSS/Status Bar Menu/BarStatusItem.m | 17 ++++++++- 6 files changed, 122 insertions(+), 16 deletions(-) create mode 100644 baRSS/NSCategories/NSColor+Ext.h create mode 100644 baRSS/NSCategories/NSColor+Ext.m diff --git a/baRSS.xcodeproj/project.pbxproj b/baRSS.xcodeproj/project.pbxproj index be33bad..631e312 100644 --- a/baRSS.xcodeproj/project.pbxproj +++ b/baRSS.xcodeproj/project.pbxproj @@ -47,6 +47,7 @@ 54BF444A22D0F4F300660096 /* AppIcon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 54BF444922D0F4F300660096 /* AppIcon.icns */; }; 54D55D7322E624CD00057B98 /* SettingsFeeds+DragDrop.m in Sources */ = {isa = PBXBuildFile; fileRef = 54D55D7222E624CD00057B98 /* SettingsFeeds+DragDrop.m */; }; 54D857CE227C5785001BA1C8 /* RefreshStatisticsView.m in Sources */ = {isa = PBXBuildFile; fileRef = 54D857CD227C5785001BA1C8 /* RefreshStatisticsView.m */; }; + 54DD9F1323D1D6B000B1EAA6 /* NSColor+Ext.m in Sources */ = {isa = PBXBuildFile; fileRef = 54DD9F1223D1D6B000B1EAA6 /* NSColor+Ext.m */; }; 54E3C02122EE076D006E2E24 /* opml-icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 54E3C02022EE076D006E2E24 /* opml-icon.icns */; }; 54E4446C2329AE0600BBF481 /* NSError+Ext.m in Sources */ = {isa = PBXBuildFile; fileRef = 54E4446B2329AE0600BBF481 /* NSError+Ext.m */; }; 54E88320211B509D00064188 /* ModalFeedEdit.m in Sources */ = {isa = PBXBuildFile; fileRef = 54E8831E211B509D00064188 /* ModalFeedEdit.m */; }; @@ -181,6 +182,8 @@ 54D857CD227C5785001BA1C8 /* RefreshStatisticsView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RefreshStatisticsView.m; sourceTree = ""; }; 54D857D022802309001BA1C8 /* SettingsGeneralView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SettingsGeneralView.h; sourceTree = ""; }; 54D857D122802309001BA1C8 /* SettingsGeneralView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SettingsGeneralView.m; sourceTree = ""; }; + 54DD9F1123D1D6B000B1EAA6 /* NSColor+Ext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSColor+Ext.h"; sourceTree = ""; }; + 54DD9F1223D1D6B000B1EAA6 /* NSColor+Ext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSColor+Ext.m"; sourceTree = ""; }; 54E3C02022EE076D006E2E24 /* opml-icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = "opml-icon.icns"; sourceTree = ""; }; 54E4446A2329AE0600BBF481 /* NSError+Ext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSError+Ext.h"; sourceTree = ""; }; 54E4446B2329AE0600BBF481 /* NSError+Ext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSError+Ext.m"; sourceTree = ""; }; @@ -226,10 +229,8 @@ 544936F721F1E51E00DEE9AA /* NSCategories */ = { isa = PBXGroup; children = ( - 54B517052270E8C6006C1B29 /* NSView+Ext.h */, - 54B517062270E92A006C1B29 /* NSView+Ext.m */, - 54AD4E0A2301853D000AE386 /* NSString+Ext.h */, - 54AD4E0B2301853D000AE386 /* NSString+Ext.m */, + 54DD9F1123D1D6B000B1EAA6 /* NSColor+Ext.h */, + 54DD9F1223D1D6B000B1EAA6 /* NSColor+Ext.m */, 54BB048721FD2AB500C303A5 /* NSDate+Ext.h */, 54BB048821FD2AB500C303A5 /* NSDate+Ext.m */, 54E4446A2329AE0600BBF481 /* NSError+Ext.h */, @@ -238,6 +239,10 @@ 548C6D09230C33DE003A1AAF /* NSURL+Ext.m */, 54B6F14C23155E1A002C94C9 /* NSURLRequest+Ext.h */, 54B6F14D23155E1A002C94C9 /* NSURLRequest+Ext.m */, + 54AD4E0A2301853D000AE386 /* NSString+Ext.h */, + 54AD4E0B2301853D000AE386 /* NSString+Ext.m */, + 54B517052270E8C6006C1B29 /* NSView+Ext.h */, + 54B517062270E92A006C1B29 /* NSView+Ext.m */, ); path = NSCategories; sourceTree = ""; @@ -577,6 +582,7 @@ 544B011D2114EE9100386E5C /* AppHook.m in Sources */, 546FC44321189975007CC3A3 /* SettingsGeneral.m in Sources */, 546A6A2922C583390034E806 /* SettingsGeneralView.m in Sources */, + 54DD9F1323D1D6B000B1EAA6 /* NSColor+Ext.m in Sources */, 54ACC29521061E270020715F /* UpdateScheduler.m in Sources */, 54BB048921FD2AB500C303A5 /* NSDate+Ext.m in Sources */, 5477D34E21233C62002BA27F /* FeedGroup+Ext.m in Sources */, diff --git a/baRSS/Helper/DrawImage.m b/baRSS/Helper/DrawImage.m index 610806f..f8f060e 100644 --- a/baRSS/Helper/DrawImage.m +++ b/baRSS/Helper/DrawImage.m @@ -22,7 +22,7 @@ #import "DrawImage.h" #import "Constants.h" -#import "UserPrefs.h" +#import "NSColor+Ext.h" @implementation DrawSeparator @@ -312,15 +312,11 @@ static void Register(CGFloat size, NSImageName name, NSString *description, BOOL /// Register all icons that require custom drawing in @c ImageNamed cache void RegisterImageViewNames(void) { - NSColor *orange = [NSColor colorWithCalibratedRed:251/255.f green:163/255.f blue:58/255.f alpha:1.f]; // #FBA33A - NSColor *c1 = UserPrefsColor(Pref_colorStatusIconTint, orange); - NSColor *c2 = UserPrefsColor(Pref_colorUnreadIndicator, [NSColor systemBlueColor]); - - Register(16, RSSImageDefaultRSSIcon, NSLocalizedString(@"RSS icon", nil), ^(NSRect r) { DrawRSSGradientIcon(r, orange); return YES; }); + Register(16, RSSImageDefaultRSSIcon, NSLocalizedString(@"RSS icon", nil), ^(NSRect r) { DrawRSSGradientIcon(r, [NSColor rssOrange]); return YES; }); Register(16, RSSImageSettingsGlobal, NSLocalizedString(@"Global settings", nil), ^(NSRect r) { DrawGlobalIcon(r, [NSColor controlTextColor].CGColor, NO); return YES; }); Register(16, RSSImageSettingsGroup, NSLocalizedString(@"Group settings", nil), ^(NSRect r) { DrawGroupIcon(r, [NSColor controlTextColor].CGColor, NO); return YES; }); Register(16, RSSImageSettingsFeed, NSLocalizedString(@"Feed settings", nil), ^(NSRect r) { DrawRSSIcon(r, [NSColor controlTextColor].CGColor, NO, YES); return YES; }); - Register(16, RSSImageMenuBarIconActive, NSLocalizedString(@"RSS menu bar icon", nil), ^(NSRect r) { DrawRSSIcon(r, c1.CGColor, YES, YES); return YES; }); - Register(16, RSSImageMenuBarIconPaused, NSLocalizedString(@"RSS menu bar icon, paused", nil), ^(NSRect r) { DrawRSSIcon(r, c1.CGColor, YES, NO); return YES; }); - Register(14, RSSImageMenuItemUnread, NSLocalizedString(@"Unread icon", nil), ^(NSRect r) { DrawUnreadIcon(r, c2); return YES; }); + Register(16, RSSImageMenuBarIconActive, NSLocalizedString(@"RSS menu bar icon", nil), ^(NSRect r) { DrawRSSIcon(r, [NSColor menuBarIconColor].CGColor, YES, YES); return YES; }); + Register(16, RSSImageMenuBarIconPaused, NSLocalizedString(@"RSS menu bar icon, paused", nil), ^(NSRect r) { DrawRSSIcon(r, [NSColor menuBarIconColor].CGColor, YES, NO); return YES; }); + Register(14, RSSImageMenuItemUnread, NSLocalizedString(@"Unread icon", nil), ^(NSRect r) { DrawUnreadIcon(r, [NSColor unreadIndicatorColor]); return YES; }); } diff --git a/baRSS/Info.plist b/baRSS/Info.plist index e9809b2..ab909dc 100644 --- a/baRSS/Info.plist +++ b/baRSS/Info.plist @@ -70,7 +70,7 @@ CFBundleVersion - 14505 + 14598 LSApplicationCategoryType public.app-category.news LSMinimumSystemVersion diff --git a/baRSS/NSCategories/NSColor+Ext.h b/baRSS/NSCategories/NSColor+Ext.h new file mode 100644 index 0000000..e0d39ab --- /dev/null +++ b/baRSS/NSCategories/NSColor+Ext.h @@ -0,0 +1,36 @@ +// +// The MIT License (MIT) +// Copyright (c) 2020 Oleg Geier +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +@import Cocoa; + +NS_ASSUME_NONNULL_BEGIN + +@interface NSColor (Ext) +/** @return @c RGB(251,163,58) @c (#FBA33A) */ ++ (instancetype)rssOrange; +/** @return User preferred color; default: @c rssOrange */ ++ (instancetype)menuBarIconColor; +/** @return User preferred color; default: @c systemBlueColor */ ++ (instancetype)unreadIndicatorColor; +@end + +NS_ASSUME_NONNULL_END diff --git a/baRSS/NSCategories/NSColor+Ext.m b/baRSS/NSCategories/NSColor+Ext.m new file mode 100644 index 0000000..8cb9daf --- /dev/null +++ b/baRSS/NSCategories/NSColor+Ext.m @@ -0,0 +1,55 @@ +// +// The MIT License (MIT) +// Copyright (c) 2020 Oleg Geier +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#import "NSColor+Ext.h" +#import "UserPrefs.h" + +@implementation NSColor (Ext) + ++ (instancetype)rssOrange { + static NSColor *color; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + color = [NSColor colorWithCalibratedRed:251/255.f green:163/255.f blue:58/255.f alpha:1.f]; // #FBA33A + }); + return color; +} + ++ (instancetype)menuBarIconColor { + static NSColor *color; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + color = UserPrefsColor(Pref_colorStatusIconTint, [self rssOrange]); + }); + return color; +} + ++ (instancetype)unreadIndicatorColor { + static NSColor *color; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + color = UserPrefsColor(Pref_colorUnreadIndicator, [NSColor systemBlueColor]); + }); + return color; +} + +@end diff --git a/baRSS/Status Bar Menu/BarStatusItem.m b/baRSS/Status Bar Menu/BarStatusItem.m index 7ebb1cd..f3eabef 100644 --- a/baRSS/Status Bar Menu/BarStatusItem.m +++ b/baRSS/Status Bar Menu/BarStatusItem.m @@ -28,6 +28,7 @@ #import "BarMenu.h" #import "AppHook.h" #import "NSView+Ext.h" +#import "NSColor+Ext.h" @interface BarStatusItem() @property (strong) BarMenu *barMenu; @@ -119,8 +120,20 @@ BOOL hasNet = [UpdateScheduler allowNetworkConnection]; BOOL tint = (self.unreadCountTotal > 0 && hasNet && UserPrefsBool(Pref_globalTintMenuIcon)); self.statusItem.button.image = [NSImage imageNamed:(hasNet ? RSSImageMenuBarIconActive : RSSImageMenuBarIconPaused)]; - self.statusItem.button.image.template = !tint; - // TODO: use macOS 10.14 contentTintColor, if (@available(macOS 10.14, *)) {} else {} + + if (@available(macOS 10.14, *)) { +// There is no proper way to display tinted icon WITHOUT tinted text! +// - using alternate image instead of tint: +// icon & text stays black on highlight (but only in light mode) +// - using tint and attributed titles: +// with controlTextColor the tint is applied regardless +// with controlColor the color doesnt match (either normal or on highlight) +// also, setting attributed title kills tint on icon + self.statusItem.button.image.template = YES; + self.statusItem.button.contentTintColor = tint ? [NSColor menuBarIconColor] : nil; + } else { + self.statusItem.button.image.template = !tint; + } BOOL showCount = (self.unreadCountTotal > 0 && UserPrefsBool(Pref_globalUnreadCount)); self.statusItem.button.title = (showCount ? [NSString stringWithFormat:@"%ld", self.unreadCountTotal] : @"");