From 87e2020606793372610650a39af3770b979eaf1a Mon Sep 17 00:00:00 2001 From: hrbrmstr Date: Tue, 3 Sep 2019 17:06:57 -0400 Subject: [PATCH] dock icon --- RSwitch.xcodeproj/project.pbxproj | 4 ++ RSwitch/RSwitch.entitlements | 2 + RSwitch/Swift/AboutViewController.swift | 10 +++++ RSwitch/Swift/AppDelegate.swift | 42 +++++++++++++++--- RSwitch/Swift/Menu.swift | 21 +++++++++ RSwitch/Swift/Utils/Globals.swift | 1 - RSwitch/Swift/Utils/Preferences.swift | 79 +++++++++++++++++++++++++++++++++ guide/_site/acknowledgements.html | 13 ++++++ guide/_site/index.html | 1 + guide/acknowledgements.Rmd | 7 +++ guide/index.Rmd | 1 + 11 files changed, 174 insertions(+), 7 deletions(-) create mode 100644 RSwitch/Swift/Utils/Preferences.swift diff --git a/RSwitch.xcodeproj/project.pbxproj b/RSwitch.xcodeproj/project.pbxproj index 31ff4b8..9460da6 100644 --- a/RSwitch.xcodeproj/project.pbxproj +++ b/RSwitch.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 01073F1D2311E64E007162C9 /* DownloadRStudio.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01073F1C2311E64E007162C9 /* DownloadRStudio.swift */; }; 01073F1F2311E67D007162C9 /* HandleUpdate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01073F1E2311E67D007162C9 /* HandleUpdate.swift */; }; 01073F212311E6BD007162C9 /* HandleRSwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01073F202311E6BD007162C9 /* HandleRSwitch.swift */; }; + 011951B4231F00A000B62C3A /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011951B3231F00A000B62C3A /* Preferences.swift */; }; 0178970D230ED25100F8F5BC /* AboutViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0178970C230ED25100F8F5BC /* AboutViewController.swift */; }; 018A8C3B2312C7BC0006E87D /* libprocInfo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 018A8C3A2312C7BC0006E87D /* libprocInfo.a */; }; 018A8C3F2312CB480006E87D /* procHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 018A8C3E2312CB480006E87D /* procHelper.m */; }; @@ -42,6 +43,7 @@ 01073F1C2311E64E007162C9 /* DownloadRStudio.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadRStudio.swift; sourceTree = ""; }; 01073F1E2311E67D007162C9 /* HandleUpdate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandleUpdate.swift; sourceTree = ""; }; 01073F202311E6BD007162C9 /* HandleRSwitch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandleRSwitch.swift; sourceTree = ""; }; + 011951B3231F00A000B62C3A /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = ""; }; 016750FB2319A7A4009E2FD6 /* RSwitch.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RSwitch.entitlements; sourceTree = ""; }; 0178970C230ED25100F8F5BC /* AboutViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutViewController.swift; sourceTree = ""; }; 018A8C392312C7BC0006E87D /* procInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = procInfo.h; sourceTree = ""; }; @@ -160,6 +162,7 @@ 0198B9A723197CBA003F7578 /* Launch.swift */, 01975549231BD919003FAD7B /* RVersions.swift */, 0198B9A923197D3A003F7578 /* Running.swift */, + 011951B3231F00A000B62C3A /* Preferences.swift */, ); path = Utils; sourceTree = ""; @@ -329,6 +332,7 @@ files = ( 01073F212311E6BD007162C9 /* HandleRSwitch.swift in Sources */, 0198B9A0231970ED003F7578 /* AppAlerts.swift in Sources */, + 011951B4231F00A000B62C3A /* Preferences.swift in Sources */, 018A8C3F2312CB480006E87D /* procHelper.m in Sources */, 01073F1F2311E67D007162C9 /* HandleUpdate.swift in Sources */, 01073F1B2311E613007162C9 /* DownloadTarball.swift in Sources */, diff --git a/RSwitch/RSwitch.entitlements b/RSwitch/RSwitch.entitlements index 8cc185a..1551075 100644 --- a/RSwitch/RSwitch.entitlements +++ b/RSwitch/RSwitch.entitlements @@ -2,6 +2,8 @@ + com.apple.security.automation.apple-events + com.apple.security.cs.disable-library-validation diff --git a/RSwitch/Swift/AboutViewController.swift b/RSwitch/Swift/AboutViewController.swift index 862cc82..484b886 100644 --- a/RSwitch/Swift/AboutViewController.swift +++ b/RSwitch/Swift/AboutViewController.swift @@ -1,3 +1,10 @@ +// +// AboutViewController.swift +// RSwitch +// +// Created by hrbrmstr on 8/24/19. +// Copyright © 2019 Bob Rudis. All rights reserved. +// import Cocoa @@ -6,6 +13,9 @@ extension AppDelegate { // Show about dialog @objc func about(_ sender: NSMenuItem?) { abtController.showWindow(self) } + @objc + func updateTimer(_ sender: Timer) { print("timer fired") } + } class AboutViewController: NSViewController { diff --git a/RSwitch/Swift/AppDelegate.swift b/RSwitch/Swift/AppDelegate.swift index 6a5015c..4435495 100644 --- a/RSwitch/Swift/AppDelegate.swift +++ b/RSwitch/Swift/AppDelegate.swift @@ -1,3 +1,11 @@ +// +// AppDelegate.swift +// RSwitch +// +// Created by hrbrmstr on 8/24/19. +// Copyright © 2019 Bob Rudis. All rights reserved. +// + import Cocoa @NSApplicationMain @@ -11,6 +19,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { var rdevel_enabled: Bool! var rstudio_enabled: Bool! + var timer: Timer? = nil; override init() { @@ -18,6 +27,26 @@ class AppDelegate: NSObject, NSApplicationDelegate { statusMenu.delegate = self + rdevel_enabled = true + rstudio_enabled = true + + URLCache.shared = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: nil) + + } + + func applicationWillFinishLaunching(_ aNotification: Notification) { + + if Preferences.firstRunGone == false { + Preferences.firstRunGone = true + Preferences.restore() + } + + DockIcon.standard.setVisibility(Preferences.showDockIcon) + + } + + func applicationDidFinishLaunching(_ aNotification: Notification) { + // dial by IconMark from the Noun Project statusItem.button?.image = #imageLiteral(resourceName: "RSwitch") statusItem.menu = statusMenu @@ -25,14 +54,15 @@ class AppDelegate: NSObject, NSApplicationDelegate { mainStoryboard = NSStoryboard(name: "Main", bundle: nil) abtController = (mainStoryboard.instantiateController(withIdentifier: "aboutPanelController") as! NSWindowController) - rdevel_enabled = true - rstudio_enabled = true + timer = Timer.scheduledTimer( + timeInterval: 3600, + target: self, + selector: #selector(updateTimer), + userInfo: nil, + repeats: true + ) - URLCache.shared = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: nil) - } - - func applicationDidFinishLaunching(_ aNotification: Notification) { } func applicationWillTerminate(_ aNotification: Notification) { } diff --git a/RSwitch/Swift/Menu.swift b/RSwitch/Swift/Menu.swift index 3dbd848..6c68831 100644 --- a/RSwitch/Swift/Menu.swift +++ b/RSwitch/Swift/Menu.swift @@ -10,6 +10,19 @@ import Foundation import Cocoa extension AppDelegate: NSMenuDelegate { + + @objc + func toggle_dock_icon(_ sender: NSMenuItem) { + + Preferences.showDockIcon = !Preferences.showDockIcon + + DockIcon.standard.setVisibility(Preferences.showDockIcon) + + if let menu = statusItem.menu, let item = menu.item(withTag: 99) { + item.state = Preferences.showDockIcon.stateValue + } + + } func menuWillOpen(_ menu: NSMenu) { @@ -65,6 +78,14 @@ extension AppDelegate: NSMenuDelegate { menu.addItem(NSMenuItem.separator()) menu.addItem(NSMenuItem(title: "About RSwitch…", action: #selector(about), keyEquivalent: "")) menu.addItem(NSMenuItem(title: "RSwitch Help…", action: #selector(rswitch_help), keyEquivalent: "")) + + // Toggle Dock Icon + menu.addItem(NSMenuItem.separator()) + let item = NSMenuItem(title: "Toggle Dock Icon", action: #selector(toggle_dock_icon), keyEquivalent: "") + item.tag = 99 + item.target = self + item.state = Preferences.showDockIcon.stateValue + menu.addItem(item) // Add a Quit item menu.addItem(NSMenuItem.separator()) diff --git a/RSwitch/Swift/Utils/Globals.swift b/RSwitch/Swift/Utils/Globals.swift index 19f895c..503d9ac 100644 --- a/RSwitch/Swift/Utils/Globals.swift +++ b/RSwitch/Swift/Utils/Globals.swift @@ -9,7 +9,6 @@ import Foundation import Cocoa - extension AppDelegate { struct app_urls { diff --git a/RSwitch/Swift/Utils/Preferences.swift b/RSwitch/Swift/Utils/Preferences.swift new file mode 100644 index 0000000..d22f861 --- /dev/null +++ b/RSwitch/Swift/Utils/Preferences.swift @@ -0,0 +1,79 @@ +// +// Preferences.swift +// RSwitch +// +// Created by hrbrmstr on 9/3/19. +// Copyright © 2019 Bob Rudis. All rights reserved. +// + +import Foundation +import AppKit + +fileprivate let defaults: UserDefaults = UserDefaults.standard + +extension Bool { + var stateValue: NSControl.StateValue { return self.toStateValue() } + private func toStateValue() -> NSControl.StateValue { return(self ? .on : .off) } +} + +extension UserDefaults { + + enum Key: String { + case showDockIcon = "showDockIcon" + case firstRunGone = "firstRunGone" + } + + func set(_ value: T, forKey key: Key) { set(value, forKey: key.rawValue) } + func bool(forKey key: Key) -> Bool { return(bool(forKey: key.rawValue)) } + func string(forKey key: Key) -> String? { return(string(forKey: key.rawValue)) } + func integer(forKey key: Key) -> Int? { return(integer(forKey: key.rawValue)) } + func url(forKey key: Key) -> URL? { return(url(forKey: key.rawValue)) } + +} + +struct DockIcon { + + static var standard = DockIcon() + + var isVisible: Bool { + get { return(NSApp.activationPolicy() == .regular) } + set { setVisibility(newValue) } + } + + @discardableResult + func setVisibility(_ state: Bool) -> Bool { + NSApp.setActivationPolicy(state ? .regular : .accessory) + return(isVisible) + } + +} + +struct Preferences { + + static var showDockIcon: Bool { + + get { return(defaults.bool(forKey: .showDockIcon)) } + + set { + defaults.set(newValue, forKey: .showDockIcon) + defaults.synchronize() + } + + } + + + static var firstRunGone: Bool { + + get { return(defaults.bool(forKey: .firstRunGone)) } + + set { + defaults.set(newValue, forKey: .firstRunGone) + defaults.synchronize() + } + + } + + static func restore() { Preferences.showDockIcon = false } + +} + diff --git a/guide/_site/acknowledgements.html b/guide/_site/acknowledgements.html index 478ed44..4e15fe0 100644 --- a/guide/_site/acknowledgements.html +++ b/guide/_site/acknowledgements.html @@ -300,6 +300,11 @@ $(document).ready(function () { +

RSwitch wasn’t my idea. It’s been around forever on the R for macOS Developer’s Page but stopped working on Catalina since it hadn’t been updated in ages, was only 32-bit (which is a no-go for Catalina), and had no available source code to modify.

Despite having found and old-old copy of the source code by hacking URLs via the Internet Archive, none of that code was used to make this incarnation of RSwitch.

@@ -310,6 +315,14 @@ $(document).ready(function () {
  • VersionCompare by DragonCherry
  • The current (but, likely not final) app icon and menubar icon is based on the ‘dial’ Noun Project font icon created by Icon Mark.

    +
    +

    Extra Credits

    +

    Many thanks to the following folks for their contributions to the project to help make RSwitch better for everyone:

    + +

    Copyright © 2019 Bob Rudis. All rights reserved.

    diff --git a/guide/_site/index.html b/guide/_site/index.html index b3489ad..aebaa90 100644 --- a/guide/_site/index.html +++ b/guide/_site/index.html @@ -377,6 +377,7 @@ div.tocify {

    Many thanks to the following folks for their contributions to the project to help make RSwitch better for everyone:

    diff --git a/guide/acknowledgements.Rmd b/guide/acknowledgements.Rmd index be85d45..8694664 100644 --- a/guide/acknowledgements.Rmd +++ b/guide/acknowledgements.Rmd @@ -13,3 +13,10 @@ RSwitch uses three external frameworks to accomplish its tasks: - [VersionCompare](https://github.com/DragonCherry/VersionCompare/) by DragonCherry The current (but, likely not final) app icon and menubar icon is based on the ['dial' Noun Project font icon](https://thenounproject.com/search/?q=dial&i=866019#) created by Icon Mark. + +## Extra Credits + +Many thanks to the following folks for their contributions to the project to help make RSwitch better for everyone: + +- [Benjamin Guiastrennec](https://github.com/guiastrennec) for suggesting improvements to the documentation regarding how to use the installer packages from the [R for macOS Developer's Page](https://mac.r-project.org/) without clobbering existing R Framework installs. +- [Xavier Adam](https://github.com/xvrdm) for [adding books to the RSwitch library](https://github.com/hrbrmstr/RSwitch/pull/4). diff --git a/guide/index.Rmd b/guide/index.Rmd index 9f322cd..0694145 100644 --- a/guide/index.Rmd +++ b/guide/index.Rmd @@ -18,6 +18,7 @@ RSwitch is a macOS menubar application that works on macOS 10.14+ and provides h Many thanks to the following folks for their contributions to the project to help make RSwitch better for everyone: - [Benjamin Guiastrennec](https://github.com/guiastrennec) for suggesting improvements to the documentation regarding how to use the installer packages from the [R for macOS Developer's Page](https://mac.r-project.org/) without clobbering existing R Framework installs. +- [Xavier Adam](https://github.com/xvrdm) for [adding books to the RSwitch library](https://github.com/hrbrmstr/RSwitch/pull/4). ## Basic/Core Usage