diff --git a/ZeroTier One.xcodeproj/project.pbxproj b/ZeroTier One.xcodeproj/project.pbxproj index d6b38dd8d..657f5150c 100644 --- a/ZeroTier One.xcodeproj/project.pbxproj +++ b/ZeroTier One.xcodeproj/project.pbxproj @@ -11,6 +11,8 @@ 932D472F1D1CD499004BCFE2 /* ZeroTierIcon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 932D472E1D1CD499004BCFE2 /* ZeroTierIcon.icns */; }; 932D47321D1CD861004BCFE2 /* PreferencesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 932D47301D1CD861004BCFE2 /* PreferencesViewController.swift */; }; 932D47331D1CD861004BCFE2 /* PreferencesViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 932D47311D1CD861004BCFE2 /* PreferencesViewController.xib */; }; + 932D47361D1CDC9B004BCFE2 /* AboutViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 932D47341D1CDC9B004BCFE2 /* AboutViewController.swift */; }; + 932D47371D1CDC9B004BCFE2 /* AboutViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 932D47351D1CDC9B004BCFE2 /* AboutViewController.xib */; }; 9330F1351CEAB4C400687EC8 /* ServiceCom.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9330F1341CEAB4C400687EC8 /* ServiceCom.swift */; }; 9330F1371CEBF87200687EC8 /* Network.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9330F1361CEBF87200687EC8 /* Network.swift */; }; 9330F13B1CF534E500687EC8 /* NetworkInfoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9330F13A1CF534E500687EC8 /* NetworkInfoCell.swift */; }; @@ -29,6 +31,8 @@ 932D472E1D1CD499004BCFE2 /* ZeroTierIcon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = ZeroTierIcon.icns; sourceTree = ""; }; 932D47301D1CD861004BCFE2 /* PreferencesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferencesViewController.swift; sourceTree = ""; }; 932D47311D1CD861004BCFE2 /* PreferencesViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PreferencesViewController.xib; sourceTree = ""; }; + 932D47341D1CDC9B004BCFE2 /* AboutViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AboutViewController.swift; sourceTree = ""; }; + 932D47351D1CDC9B004BCFE2 /* AboutViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AboutViewController.xib; sourceTree = ""; }; 9330F1341CEAB4C400687EC8 /* ServiceCom.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceCom.swift; sourceTree = ""; }; 9330F1361CEBF87200687EC8 /* Network.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Network.swift; sourceTree = ""; }; 9330F13A1CF534E500687EC8 /* NetworkInfoCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkInfoCell.swift; sourceTree = ""; }; @@ -94,6 +98,8 @@ 932D472C1D138B0C004BCFE2 /* NetworkMonitor.swift */, 932D47301D1CD861004BCFE2 /* PreferencesViewController.swift */, 932D47311D1CD861004BCFE2 /* PreferencesViewController.xib */, + 932D47341D1CDC9B004BCFE2 /* AboutViewController.swift */, + 932D47351D1CDC9B004BCFE2 /* AboutViewController.xib */, ); path = "ZeroTier One"; sourceTree = ""; @@ -157,6 +163,7 @@ buildActionMask = 2147483647; files = ( 93326BEF1CE7DA30005CA2AC /* ShowNetworksViewController.xib in Resources */, + 932D47371D1CDC9B004BCFE2 /* AboutViewController.xib in Resources */, 93326BEB1CE7D9B9005CA2AC /* JoinNetworkViewController.xib in Resources */, 93326BDE1CE7C816005CA2AC /* Assets.xcassets in Resources */, 93326BE11CE7C816005CA2AC /* MainMenu.xib in Resources */, @@ -180,6 +187,7 @@ 9330F13B1CF534E500687EC8 /* NetworkInfoCell.swift in Sources */, 93326BEA1CE7D9B9005CA2AC /* JoinNetworkViewController.swift in Sources */, 93326BEE1CE7DA30005CA2AC /* ShowNetworksViewController.swift in Sources */, + 932D47361D1CDC9B004BCFE2 /* AboutViewController.swift in Sources */, 9330F1351CEAB4C400687EC8 /* ServiceCom.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/ZeroTier One/AboutViewController.swift b/ZeroTier One/AboutViewController.swift new file mode 100644 index 000000000..bbca975a9 --- /dev/null +++ b/ZeroTier One/AboutViewController.swift @@ -0,0 +1,18 @@ +// +// AboutViewController.swift +// ZeroTier One +// +// Created by Grant Limberg on 6/23/16. +// Copyright © 2016 ZeroTier, Inc. All rights reserved. +// + +import Cocoa + +class AboutViewController: NSViewController { + + override func viewDidLoad() { + super.viewDidLoad() + // Do view setup here. + } + +} diff --git a/ZeroTier One/AboutViewController.xib b/ZeroTier One/AboutViewController.xib new file mode 100644 index 000000000..8722929fe --- /dev/null +++ b/ZeroTier One/AboutViewController.xib @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/ZeroTier One/AppDelegate.swift b/ZeroTier One/AppDelegate.swift index f37eba731..2ca97f3c1 100644 --- a/ZeroTier One/AppDelegate.swift +++ b/ZeroTier One/AppDelegate.swift @@ -19,6 +19,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { let networkListPopover = NSPopover() let joinNetworkPopover = NSPopover() let preferencesPopover = NSPopover() + let aboutPopover = NSPopover() var transientMonitor: AnyObject? = nil @@ -51,6 +52,13 @@ class AppDelegate: NSObject, NSApplicationDelegate { preferencesPopover.behavior = .Transient preferencesPopover.appearance = NSAppearance(named: NSAppearanceNameAqua) + + aboutPopover.contentViewController = AboutViewController( + nibName: "AboutViewController", bundle: nil) + aboutPopover.behavior = .Transient + + aboutPopover.appearance = NSAppearance(named: NSAppearanceNameAqua) + } func applicationWillTerminate(aNotification: NSNotification) { @@ -109,6 +117,22 @@ class AppDelegate: NSObject, NSApplicationDelegate { } } + func showAbout() { + if let button = statusItem.button { + aboutPopover.showRelativeToRect(button.bounds, ofView: button, preferredEdge: .MinY) + + if transientMonitor == nil { + transientMonitor = NSEvent.addGlobalMonitorForEventsMatchingMask( + [.LeftMouseDownMask, .RightMouseDownMask, .OtherMouseDownMask]) { (event: NSEvent) -> Void in + + NSEvent.removeMonitor(self.transientMonitor!) + self.transientMonitor = nil + self.aboutPopover.close() + } + } + } + } + func quit() { NSApp.performSelector(#selector(NSApp.terminate(_:)), withObject: nil, afterDelay: 0.0) } @@ -157,6 +181,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { menu.addItem(NSMenuItem.separatorItem()) } + menu.addItem(NSMenuItem(title: "About ZeroTier One...", action: #selector(AppDelegate.showAbout), keyEquivalent: "")) menu.addItem(NSMenuItem(title: "Preferences...", action: #selector(AppDelegate.showPreferences), keyEquivalent: ",")) menu.addItem(NSMenuItem.separatorItem())