diff --git a/SpacesRenamer/AppDelegate.swift b/SpacesRenamer/AppDelegate.swift
index 8d77773..ef8ce0c 100644
--- a/SpacesRenamer/AppDelegate.swift
+++ b/SpacesRenamer/AppDelegate.swift
@@ -7,13 +7,14 @@
//
import Cocoa
+import Foundation
@NSApplicationMain
@objc
class AppDelegate: NSObject, NSApplicationDelegate {
-
let statusItem = NSStatusBar.system.statusItem(withLength:NSStatusItem.squareLength)
- let popover = NSPopover()
+ var nameChangeWindow: NameChangeWindow = NameChangeWindow()
+ let hiddenPopover = NSPopover()
var eventMonitor: EventMonitor?
var workspace: NSWorkspace?
@@ -37,6 +38,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
)
}
+ // Watches the file to determine if the spaces update (new one added or deleted)
fileprivate func configureSpaceMonitor() {
let fullPath = (Utils.spacesPath as NSString).expandingTildeInPath
let queue = DispatchQueue.global(qos: .default)
@@ -64,23 +66,42 @@ class AppDelegate: NSObject, NSApplicationDelegate {
source.resume()
}
+ // Runs when a space is moved or switched, which confirms that the current list is in the right order
@objc func updateActiveSpaces() {
let info = CGSCopyManagedDisplaySpaces(conn) as! [NSDictionary]
let spacesDict = NSMutableDictionary()
spacesDict.setValue(info, forKey: "Monitors")
spacesDict.write(toFile: Utils.listOfSpacesPlist, atomically: true)
+
+ if (nameChangeWindow.isVisible) {
+ nameChangeWindow.refresh()
+ }
}
func applicationDidFinishLaunching(_ aNotification: Notification) {
if let button = statusItem.button {
button.image = NSImage(named:NSImage.Name("StatusBarIcon"))
- button.action = #selector(togglePopover(_:))
}
- popover.contentViewController = ViewController.freshController()
+
+ // Listen for left click
+ NSEvent.addLocalMonitorForEvents(matching: .leftMouseDown) { [weak self] event in
+ if event.window == self?.statusItem.button?.window {
+ self?.togglePopover(self?.statusItem.button)
+ return nil
+ }
+
+ return event
+ }
+
+ nameChangeWindow.contentViewController = ViewController.freshController()
+ hiddenPopover.contentViewController = ViewController.freshController()
+ hiddenPopover.animates = false
eventMonitor = EventMonitor(mask: [.leftMouseDown, .rightMouseDown]) { [weak self] event in
- if let strongSelf = self, strongSelf.popover.isShown {
- strongSelf.closePopover(sender: event)
+ if let strongSelf = self {
+ if (strongSelf.nameChangeWindow.isVisible) {
+ strongSelf.closeNameChangeWindow(sender: event)
+ }
}
}
@@ -100,24 +121,35 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}
@objc func togglePopover(_ sender: Any?) {
- if popover.isShown {
- closePopover(sender: sender)
+ if nameChangeWindow.isVisible {
+ closeNameChangeWindow(sender: sender)
} else {
- showPopover(sender: sender)
+ showNameChangeWindow(sender: sender)
}
}
- func showPopover(sender: Any?) {
+ func showNameChangeWindow(sender: Any?) {
NSApplication.shared.activate(ignoringOtherApps: true)
eventMonitor?.start()
+ self.statusItem.button?.isHighlighted = true
if let button = statusItem.button {
- popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY)
+ // Use the hidden popover to get the dimensions, and then immediately hide it
+ hiddenPopover.show(relativeTo: button.bounds, of: button, preferredEdge: .minY)
+ if let frame = hiddenPopover.contentViewController?.view.window?.frame {
+ nameChangeWindow.setFrame(frame, display: true)
+ }
+ hiddenPopover.close()
+
+ nameChangeWindow.makeKeyAndOrderFront(nil)
+ NSApp.activate(ignoringOtherApps: true)
}
}
- func closePopover(sender: Any?) {
- popover.performClose(sender)
+ @objc func closeNameChangeWindow(sender: Any?) {
+ nameChangeWindow.setIsVisible(false)
+ DispatchQueue.main.async {
+ self.statusItem.button?.isHighlighted = false
+ }
eventMonitor?.stop()
}
}
-
diff --git a/SpacesRenamer/Info.plist b/SpacesRenamer/Info.plist
index c3bfe6c..5440f28 100644
--- a/SpacesRenamer/Info.plist
+++ b/SpacesRenamer/Info.plist
@@ -19,7 +19,7 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 1.3.0
+ 1.3.1
CFBundleVersion
1
LSMinimumSystemVersion
diff --git a/SpacesRenamer/NameChangeWindow.swift b/SpacesRenamer/NameChangeWindow.swift
new file mode 100644
index 0000000..4ac2e66
--- /dev/null
+++ b/SpacesRenamer/NameChangeWindow.swift
@@ -0,0 +1,52 @@
+//
+// NameChangeWindow.swift
+// SpacesRenamer
+//
+// Created by Alex Beals on 4/1/18.
+// Copyright © 2018 Alex Beals. All rights reserved.
+//
+
+import Cocoa
+
+class NameChangeWindow: NSWindow {
+ override init(contentRect: NSRect, styleMask style: NSWindow.StyleMask, backing backingStoreType: NSWindow.BackingStoreType, defer flag: Bool) {
+ super.init(contentRect: contentRect, styleMask: style, backing: backingStoreType, defer: flag)
+ self.title = "Spaces Renamer"
+ self.isOpaque = false
+ self.isMovable = false
+ self.backgroundColor = NSColor(calibratedHue: 0, saturation: 0.0, brightness: 100, alpha: 0.95)
+ // To make it auto-hide on F3
+ self.collectionBehavior = [.transient, .ignoresCycle, .canJoinAllSpaces]
+ self.level = .modalPanel
+
+ // Adapted from https://stackoverflow.com/a/27613308/3951475 for rounded corners
+ self.styleMask = [.resizable, .titled, .fullSizeContentView]
+ self.titlebarAppearsTransparent = true
+ self.titleVisibility = .hidden
+ self.showsToolbarButton = false
+
+ self.standardWindowButton(.miniaturizeButton)?.isHidden = true
+ self.standardWindowButton(.closeButton)?.isHidden = true
+ self.standardWindowButton(.zoomButton)?.isHidden = true
+ }
+
+ func refresh() {
+ DispatchQueue.main.async {
+ if let appDelegate = NSApplication.shared.delegate as? AppDelegate, let button = appDelegate.statusItem.button {
+ // Use the hidden popover to get the dimensions, and then immediately hide it
+ appDelegate.hiddenPopover.show(relativeTo: button.bounds, of: button, preferredEdge: .minY)
+ if let frame = appDelegate.hiddenPopover.contentViewController?.view.window?.frame {
+ appDelegate.nameChangeWindow.setFrame(frame, display: true)
+ }
+ appDelegate.hiddenPopover.close()
+
+ if let viewController = appDelegate.nameChangeWindow.contentViewController as? ViewController {
+ viewController.refreshViews()
+ }
+
+ appDelegate.nameChangeWindow.makeKeyAndOrderFront(nil)
+ NSApp.activate(ignoringOtherApps: true)
+ }
+ }
+ }
+}
diff --git a/SpacesRenamer/ViewController.swift b/SpacesRenamer/ViewController.swift
index 0604bb3..b8cb74a 100644
--- a/SpacesRenamer/ViewController.swift
+++ b/SpacesRenamer/ViewController.swift
@@ -9,7 +9,6 @@
import Cocoa
class ViewController: NSViewController {
-
@IBOutlet var updateButton: NSButton!
var desktops: [String: NSTextField] = [String: NSTextField]()
@@ -43,7 +42,7 @@ class ViewController: NSViewController {
var prev: DesktopSnippet?
var above: NSView?
- print(spacesDict)
+ let maxSpacesPerMonitor = allMonitors.reduce(Int.min, { max($0, (($1 as? NSDictionary)?.value(forKey: "Spaces") as! NSArray).count) })
for j in 1...allMonitors.count {
let allSpaces = (allMonitors[j-1] as? NSDictionary)?.value(forKey: "Spaces") as! NSArray
@@ -82,7 +81,6 @@ class ViewController: NSViewController {
let snippet = DesktopSnippet.instanceFromNib()
if (uuid == currentSpace) {
snippet.monitorImage.image = NSImage(named: NSImage.Name("MonitorSelected") )
- // snippet.starImage.isHidden = false
}
snippet.label.stringValue = "\(i)"
@@ -113,9 +111,11 @@ class ViewController: NSViewController {
}
above = prev
- let horizontalLayout = NSLayoutConstraint(item: self.view, attribute: .trailing, relatedBy: .greaterThanOrEqual, toItem: prev!, attribute: .trailing, multiplier: 1.0, constant: 10)
- constraints.append(horizontalLayout)
- self.view.addConstraints([horizontalLayout])
+ if (allSpaces.count == maxSpacesPerMonitor) {
+ let horizontalLayout = NSLayoutConstraint(item: self.view, attribute: .trailing, relatedBy: .equal, toItem: prev!, attribute: .trailing, multiplier: 1.0, constant: 10)
+ constraints.append(horizontalLayout)
+ self.view.addConstraints([horizontalLayout])
+ }
}
let verticalConstraint = NSLayoutConstraint(item: updateButton, attribute: .top, relatedBy: .equal, toItem: prev!, attribute: .bottom, multiplier: 1.0, constant: 10)
@@ -124,9 +124,7 @@ class ViewController: NSViewController {
self.view.addConstraints([verticalConstraint])
}
- override func viewWillAppear() {
- super.viewWillAppear()
-
+ func refreshViews() {
teardownViews()
setupViews()
@@ -135,7 +133,7 @@ class ViewController: NSViewController {
let spacesRemaining = preferencesDict.value(forKey: "spaces_renaming") as? NSMutableDictionary {
currentMapping = spacesRemaining
}
-
+
// Update with the current names
for (uuid, textField) in desktops {
if let newName = currentMapping.value(forKey: uuid) {
@@ -144,6 +142,12 @@ class ViewController: NSViewController {
}
}
+ override func viewWillAppear() {
+ super.viewWillAppear()
+
+ refreshViews()
+ }
+
@IBAction func quitMenuApp(_ sender: Any) {
NSApp.terminate(nil)
}
@@ -165,7 +169,7 @@ class ViewController: NSViewController {
// Close the popup
let delegate = NSApplication.shared.delegate as! AppDelegate
- delegate.closePopover(sender: delegate)
+ delegate.closeNameChangeWindow(sender: delegate)
}
}
diff --git a/build/spaces-renamer.zip b/build/spaces-renamer.zip
index 084b821..8b8169a 100644
Binary files a/build/spaces-renamer.zip and b/build/spaces-renamer.zip differ
diff --git a/spaces-renamer.xcodeproj/project.pbxproj b/spaces-renamer.xcodeproj/project.pbxproj
index bbbe14a..d8c4eba 100755
--- a/spaces-renamer.xcodeproj/project.pbxproj
+++ b/spaces-renamer.xcodeproj/project.pbxproj
@@ -15,6 +15,7 @@
A80DDE3C1FBCEBDE00794F8F /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80DDE3B1FBCEBDE00794F8F /* Utils.swift */; };
A80DDE421FBE2D9C00794F8F /* DesktopSnippet.xib in Resources */ = {isa = PBXBuildFile; fileRef = A80DDE411FBE2D9C00794F8F /* DesktopSnippet.xib */; };
A80DDE441FBE2ECA00794F8F /* DesktopSnippet.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80DDE431FBE2ECA00794F8F /* DesktopSnippet.swift */; };
+ A81F4EFC2070AEED00660338 /* NameChangeWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A81F4EFB2070AEED00660338 /* NameChangeWindow.swift */; };
C398D84715BD8B0700543187 /* spacesRenamer.m in Sources */ = {isa = PBXBuildFile; fileRef = C398D84615BD8B0700543187 /* spacesRenamer.m */; };
FBAE21EE1CFCCA4F007E5A8E /* ZKSwizzle.m in Sources */ = {isa = PBXBuildFile; fileRef = FBAE21ED1CFCCA4F007E5A8E /* ZKSwizzle.m */; };
/* End PBXBuildFile section */
@@ -34,6 +35,7 @@
A80DDE411FBE2D9C00794F8F /* DesktopSnippet.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DesktopSnippet.xib; sourceTree = ""; };
A80DDE431FBE2ECA00794F8F /* DesktopSnippet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DesktopSnippet.swift; sourceTree = ""; };
A81F4EFA206C012500660338 /* SpacesRenamerBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SpacesRenamerBridge.h; sourceTree = ""; };
+ A81F4EFB2070AEED00660338 /* NameChangeWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NameChangeWindow.swift; sourceTree = ""; };
C398D84615BD8B0700543187 /* spacesRenamer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = spacesRenamer.m; path = "spaces-renamer/spacesRenamer.m"; sourceTree = ""; };
FBAE21EC1CFCCA4F007E5A8E /* ZKSwizzle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ZKSwizzle.h; path = "spaces-renamer/ZKSwizzle.h"; sourceTree = ""; };
FBAE21ED1CFCCA4F007E5A8E /* ZKSwizzle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ZKSwizzle.m; path = "spaces-renamer/ZKSwizzle.m"; sourceTree = ""; };
@@ -99,6 +101,7 @@
isa = PBXGroup;
children = (
A80DDE2B1FBCE4D600794F8F /* AppDelegate.swift */,
+ A81F4EFB2070AEED00660338 /* NameChangeWindow.swift */,
A81F4EFA206C012500660338 /* SpacesRenamerBridge.h */,
A80DDE391FBCE89B00794F8F /* EventMonitor.swift */,
A80DDE2D1FBCE4D600794F8F /* ViewController.swift */,
@@ -221,6 +224,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ A81F4EFC2070AEED00660338 /* NameChangeWindow.swift in Sources */,
A80DDE3A1FBCE89B00794F8F /* EventMonitor.swift in Sources */,
A80DDE441FBE2ECA00794F8F /* DesktopSnippet.swift in Sources */,
A80DDE2E1FBCE4D600794F8F /* ViewController.swift in Sources */,
diff --git a/spaces-renamer.xcodeproj/project.xcworkspace/xcuserdata/alexbeals.xcuserdatad/UserInterfaceState.xcuserstate b/spaces-renamer.xcodeproj/project.xcworkspace/xcuserdata/alexbeals.xcuserdatad/UserInterfaceState.xcuserstate
index 0b94671..2507816 100644
Binary files a/spaces-renamer.xcodeproj/project.xcworkspace/xcuserdata/alexbeals.xcuserdatad/UserInterfaceState.xcuserstate and b/spaces-renamer.xcodeproj/project.xcworkspace/xcuserdata/alexbeals.xcuserdatad/UserInterfaceState.xcuserstate differ