diff --git a/Chinese Time.xcodeproj/project.pbxproj b/Chinese Time.xcodeproj/project.pbxproj index 960f8f5..0a8f76e 100644 --- a/Chinese Time.xcodeproj/project.pbxproj +++ b/Chinese Time.xcodeproj/project.pbxproj @@ -304,7 +304,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 38; + CURRENT_PROJECT_VERSION = 39; DEVELOPMENT_TEAM = 28HU5A7B46; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = ChineseTime/Info.plist; @@ -315,7 +315,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 2.5; + MARKETING_VERSION = 3.0; PRODUCT_BUNDLE_IDENTIFIER = "Chinese-Time"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; @@ -331,7 +331,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 38; + CURRENT_PROJECT_VERSION = 39; DEVELOPMENT_TEAM = 28HU5A7B46; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = ChineseTime/Info.plist; @@ -342,7 +342,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 2.5; + MARKETING_VERSION = 3.0; PRODUCT_BUNDLE_IDENTIFIER = "Chinese-Time"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; diff --git a/ChineseTime/AppDelegate.swift b/ChineseTime/AppDelegate.swift index 70ff3c0..9cc2ce1 100644 --- a/ChineseTime/AppDelegate.swift +++ b/ChineseTime/AppDelegate.swift @@ -17,50 +17,38 @@ func updateStatusTitle(title: String) { statusItem?.length = button.intrinsicContentSize.width } } +func updatePosition() { + if let frame = statusItem?.button?.window?.frame { + WatchFace.currentInstance?.moveTopCenter(to: NSMakePoint(NSMidX(frame), NSMinY(frame))) + } +} @main class AppDelegate: NSObject, NSApplicationDelegate, CLLocationManagerDelegate { - @IBOutlet weak var lockedMenuItem: NSMenuItem! - @IBOutlet weak var keepTopMenuItem: NSMenuItem! - @IBOutlet weak var statusBarItem: NSMenuItem! - - @IBAction func toggleLocked(_ sender: Any) { - if let watchFace = WatchFace.currentInstance { - watchFace.locked(!watchFace.isLocked) - lockedMenuItem.state = watchFace.isLocked ? .on : .off - } - } - @IBAction func togglekeepTop(_ sender: Any) { - if let watchFace = WatchFace.currentInstance { - watchFace.setTop(!watchFace.isTop) - keepTopMenuItem.state = watchFace.isTop ? .on : .off - } - } - @IBAction func bringCenter(_ sender: Any) { - WatchFace.currentInstance?.setCenter() - } - - @IBAction func showHelp(_ sender: Any) { - NSWorkspace.shared.open(URL(string: "https://github.com/LEOYoon-Tsaw/ChineseTime")!) - } - - @IBAction func toggleStatusBar(_ sender: Any) { - if statusItem == nil { - statusItem = NSStatusBar.system.statusItem(withLength: 0) - WatchFace.currentInstance?._view.updateStatusBar() - statusBarItem.state = .on - } else { - statusItem = nil - statusBarItem.state = .off - } - } - func applicationWillFinishLaunching(_ aNotification: Notification) { locManager = CLLocationManager() locManager?.delegate = self locManager?.desiredAccuracy = kCLLocationAccuracyKilometer statusItem = NSStatusBar.system.statusItem(withLength: 0) + statusItem?.button?.action = #selector(self.toggleDisplay(sender:)) + statusItem?.button?.sendAction(on: [.leftMouseDown]) + } + + @objc func toggleDisplay(sender: NSStatusItem) { + if let watchFace = WatchFace.currentInstance { + if watchFace.isVisible { + watchFace.hide() + } else { + watchFace.show() + updatePosition() + NSApp.activate(ignoringOtherApps: true) + } + } + } + + func applicationDidResignActive(_ notification: Notification) { + WatchFace.currentInstance?.hide() } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { diff --git a/ChineseTime/GradientSlider.xib b/ChineseTime/GradientSlider.xib index 18e233d..056a630 100644 --- a/ChineseTime/GradientSlider.xib +++ b/ChineseTime/GradientSlider.xib @@ -6,10 +6,10 @@ - + - + diff --git a/ChineseTime/Info.plist b/ChineseTime/Info.plist index d702dae..49b30c0 100644 --- a/ChineseTime/Info.plist +++ b/ChineseTime/Info.plist @@ -32,5 +32,7 @@ Main NSPrincipalClass NSApplication + LSUIElement + diff --git a/ChineseTime/WatchFace.swift b/ChineseTime/WatchFace.swift index 775e1cb..84be55c 100644 --- a/ChineseTime/WatchFace.swift +++ b/ChineseTime/WatchFace.swift @@ -176,7 +176,7 @@ class RoundedRect { thirdArc.append(((lambda * totalLength-(innerWidth*1.5+2*arcLength+innerHeight)) / arcLength, i)) case (innerWidth*1.5+3*arcLength+innerHeight)..<(innerWidth*1.5+3*arcLength+2*innerHeight): fourthLine.append((lambda * totalLength - (innerWidth*1.5+3*arcLength+innerHeight), i)) - case (innerWidth*1.5+3*arcLength+2*innerHeight)..<(totalLength-innerWidth/2): + case (innerWidth*1.5+3*arcLength+2*innerHeight)..<(innerWidth*1.5+4*arcLength+2*innerHeight): fourthArc.append(((lambda * totalLength-(innerWidth*1.5+3*arcLength+2*innerHeight)) / arcLength, i)) case (totalLength-innerWidth/2)...totalLength: fifthLine.append((lambda * totalLength - (totalLength-innerWidth/2), i)) @@ -273,6 +273,7 @@ class RoundedRect { class WatchFaceView: NSView { private static let majorUpdateInterval: CGFloat = 3600 private static let minorUpdateInterval: CGFloat = majorUpdateInterval / 12 + static let frameOffset: CGFloat = 5 class GraphicArtifects { var outerBound: RoundedRect? @@ -394,8 +395,7 @@ class WatchFaceView: NSView { } override func draw(_ rawRect: NSRect) { - let frameOffset = 0.05 * min(rawRect.width, rawRect.height) - let dirtyRect = rawRect.insetBy(dx: frameOffset, dy: frameOffset) + let dirtyRect = rawRect.insetBy(dx: Self.frameOffset, dy: Self.frameOffset) let isDark = self.isDark func angleMask(angle: CGFloat, startingAngle: CGFloat, in circle: RoundedRect) -> CAShapeLayer { @@ -731,20 +731,20 @@ class WatchFaceView: NSView { func getVagueShapes(shortEdge: CGFloat, longEdge: CGFloat) { // Basic paths - graphicArtifects.outerBound = RoundedRect(rect: dirtyRect, nodePos: cornerSize, ankorPos: cornerSize*0.2) - graphicArtifects.firstRingOuter = graphicArtifects.outerBound!.shrink(by: 0.05 * shortEdge) - graphicArtifects.firstRingInner = graphicArtifects.firstRingOuter!.shrink(by: 0.07 * shortEdge) + graphicArtifects.outerBound = RoundedRect(rect: dirtyRect, nodePos: cornerSize, ankorPos: cornerSize*0.2).shrink(by: 0.02 * shortEdge) + graphicArtifects.firstRingOuter = graphicArtifects.outerBound!.shrink(by: 0.047 * shortEdge) + graphicArtifects.firstRingInner = graphicArtifects.firstRingOuter!.shrink(by: 0.066 * shortEdge) - graphicArtifects.secondRingOuter = graphicArtifects.firstRingInner!.shrink(by: 0.01 * shortEdge) - graphicArtifects.secondRingInner = graphicArtifects.secondRingOuter!.shrink(by: 0.07 * shortEdge) + graphicArtifects.secondRingOuter = graphicArtifects.firstRingInner!.shrink(by: 0.00946 * shortEdge) + graphicArtifects.secondRingInner = graphicArtifects.secondRingOuter!.shrink(by: 0.066 * shortEdge) - graphicArtifects.thirdRingOuter = graphicArtifects.secondRingInner!.shrink(by: 0.01 * shortEdge) - graphicArtifects.thirdRingInner = graphicArtifects.thirdRingOuter!.shrink(by: 0.07 * shortEdge) + graphicArtifects.thirdRingOuter = graphicArtifects.secondRingInner!.shrink(by: 0.00946 * shortEdge) + graphicArtifects.thirdRingInner = graphicArtifects.thirdRingOuter!.shrink(by: 0.066 * shortEdge) - graphicArtifects.fourthRingOuter = graphicArtifects.thirdRingInner!.shrink(by: 0.01 * shortEdge) - graphicArtifects.fourthRingInner = graphicArtifects.fourthRingOuter!.shrink(by: 0.07 * shortEdge) + graphicArtifects.fourthRingOuter = graphicArtifects.thirdRingInner!.shrink(by: 0.00946 * shortEdge) + graphicArtifects.fourthRingInner = graphicArtifects.fourthRingOuter!.shrink(by: 0.066 * shortEdge) - graphicArtifects.innerBound = graphicArtifects.fourthRingInner!.shrink(by: 0.01 * shortEdge) + graphicArtifects.innerBound = graphicArtifects.fourthRingInner!.shrink(by: 0.00946 * shortEdge) graphicArtifects.outerBoundPath = graphicArtifects.outerBound!.path graphicArtifects.firstRingOuterPath = graphicArtifects.firstRingOuter!.path @@ -766,13 +766,8 @@ class WatchFaceView: NSView { graphicArtifects.innerBoundPath = graphicArtifects.innerBound!.path // Will be used from outside this View - shape.path = graphicArtifects.firstRingOuterPath! - shape.fillColor = NSColor(deviceWhite: 1.0, alpha: watchLayout.backAlpha).cgColor - shape.shadowPath = graphicArtifects.outerBoundPath! - shape.shadowColor = shape.fillColor - shape.shadowOpacity = 1 - shape.shadowOffset = NSMakeSize(0, 0) - shape.shadowRadius = frameOffset / 2 + let shortEdge = min(dirtyRect.width, dirtyRect.height) + shape.path = RoundedRect(rect: dirtyRect, nodePos: shortEdge * 0.08, ankorPos: shortEdge*0.08*0.2).path } let shortEdge = min(dirtyRect.width, dirtyRect.height) @@ -876,7 +871,6 @@ class WatchFaceView: NSView { class WatchFace: NSWindow { let _view: WatchFaceView let _backView: NSVisualEffectView - private var _visible = false private var _timer: Timer? static var currentInstance: WatchFace? = nil private static let updateInterval: CGFloat = 14.4 @@ -885,54 +879,52 @@ class WatchFace: NSWindow { _view = WatchFaceView(frame: position) let blurView = NSVisualEffectView() blurView.blendingMode = .behindWindow - blurView.material = .fullScreenUI + blurView.material = .popover blurView.state = .active blurView.wantsLayer = true _backView = blurView super.init(contentRect: position, styleMask: .borderless, backing: .buffered, defer: true) self.alphaValue = 1 self.level = NSWindow.Level.floating - self.hasShadow = false + self.hasShadow = true self.isOpaque = false self.backgroundColor = .clear let contentView = NSView() self.contentView = contentView contentView.addSubview(_backView) contentView.addSubview(_view) - self.isMovableByWindowBackground = true + self.isMovableByWindowBackground = false } override var isVisible: Bool { - _visible - } - - var isLocked: Bool { - !self.isMovableByWindowBackground - } - var isTop: Bool { - self.level == NSWindow.Level.floating - } - - func locked(_ on: Bool) { - if on { - self.isMovableByWindowBackground = false - } else { - self.isMovableByWindowBackground = true - } - } - func setTop(_ on: Bool) { - if on { - self.level = NSWindow.Level.floating - } else { - self.level = NSWindow.Level(rawValue: NSWindow.Level.normal.rawValue - 1) + get { + contentView != nil && !contentView!.isHidden + } set { + contentView?.isHidden = !newValue } } + func setCenter() { let windowRect = self.getCurrentScreen() self.setFrame(NSMakeRect( - windowRect.midX - _view.watchLayout.watchSize.width / 2, - windowRect.midY - _view.watchLayout.watchSize.height / 2, - _view.watchLayout.watchSize.width, _view.watchLayout.watchSize.height), display: true) + windowRect.midX - _view.watchLayout.watchSize.width / 2, + windowRect.midY - _view.watchLayout.watchSize.height / 2, + _view.watchLayout.watchSize.width, _view.watchLayout.watchSize.height), display: true) + } + + func moveTopCenter(to: CGPoint) { + let windowRect = self.getCurrentScreen() + var frame = NSMakeRect( + to.x - _view.watchLayout.watchSize.width / 2, + to.y - _view.watchLayout.watchSize.height, + _view.watchLayout.watchSize.width, _view.watchLayout.watchSize.height + ) + if NSMaxX(frame) >= NSMaxX(windowRect) { + frame.origin.x = NSMaxX(windowRect) - frame.width + } else if NSMinX(frame) <= NSMinX(windowRect) { + frame.origin.x = NSMinX(windowRect) + } + self.setFrame(frame, display: true) } func getCurrentScreen() -> NSRect { @@ -940,7 +932,7 @@ class WatchFace: NSWindow { let screens = NSScreen.screens for i in 0.. - - - - - - - - - - - - - - - - - - - - - - @@ -668,13 +646,7 @@ - - - - - - - + diff --git a/layout.txt b/layout.txt index e3a97d7..995159d 100644 --- a/layout.txt +++ b/layout.txt @@ -1,7 +1,7 @@ globalMonth: true apparentTime: true backAlpha: 1.0 -firstRing: locations: 0.0, 0.25, 0.5, 0.75; colors: 0xFFDB8174, 0xFF6173BC, 0xFF7033E7, 0xFFAE74B9; loop: true +firstRing: locations: 0.0, 0.25, 0.5, 0.75; colors: 0xFFDB8174, 0xFFAE74B9, 0xFF7033E7, 0xFF6173BC; loop: true secondRing: locations: 0.0, 0.25, 0.5, 0.75; colors: 0xFFB765B7, 0xFF4B5FC1, 0xFF4598D9, 0xFF4B5FC1; loop: true thirdRing: locations: 0.0, 0.5; colors: 0xFFCB6693, 0xFF5E44D3; loop: true innerColor: 0x66FFFFFF