|
@@ -2520,11 +2520,14 @@ private extension ViewController {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private func makeScheduleFilterDropdown() -> NSPopUpButton {
|
|
private func makeScheduleFilterDropdown() -> NSPopUpButton {
|
|
|
- let button = NSPopUpButton(frame: .zero, pullsDown: false)
|
|
|
|
|
|
|
+ let button = HoverPopUpButton(frame: .zero, pullsDown: false)
|
|
|
button.translatesAutoresizingMaskIntoConstraints = false
|
|
button.translatesAutoresizingMaskIntoConstraints = false
|
|
|
button.autoenablesItems = false
|
|
button.autoenablesItems = false
|
|
|
|
|
+ button.isBordered = false
|
|
|
|
|
+ button.bezelStyle = .regularSquare
|
|
|
button.wantsLayer = true
|
|
button.wantsLayer = true
|
|
|
button.layer?.cornerRadius = 8
|
|
button.layer?.cornerRadius = 8
|
|
|
|
|
+ button.layer?.masksToBounds = true
|
|
|
button.layer?.backgroundColor = palette.inputBackground.cgColor
|
|
button.layer?.backgroundColor = palette.inputBackground.cgColor
|
|
|
button.layer?.borderColor = palette.inputBorder.cgColor
|
|
button.layer?.borderColor = palette.inputBorder.cgColor
|
|
|
button.layer?.borderWidth = 1
|
|
button.layer?.borderWidth = 1
|
|
@@ -2545,6 +2548,17 @@ private extension ViewController {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ let baseColor = palette.inputBackground
|
|
|
|
|
+ let baseBorder = palette.inputBorder
|
|
|
|
|
+ let hoverBlend = darkModeEnabled ? NSColor.white : NSColor.black
|
|
|
|
|
+ let hoverColor = baseColor.blended(withFraction: 0.10, of: hoverBlend) ?? baseColor
|
|
|
|
|
+ let hoverBorder = baseBorder.blended(withFraction: 0.16, of: hoverBlend) ?? baseBorder
|
|
|
|
|
+ button.onHoverChanged = { [weak button] hovering in
|
|
|
|
|
+ button?.layer?.backgroundColor = (hovering ? hoverColor : baseColor).cgColor
|
|
|
|
|
+ button?.layer?.borderColor = (hovering ? hoverBorder : baseBorder).cgColor
|
|
|
|
|
+ }
|
|
|
|
|
+ button.onHoverChanged?(false)
|
|
|
|
|
+
|
|
|
scheduleFilterDropdown = button
|
|
scheduleFilterDropdown = button
|
|
|
return button
|
|
return button
|
|
|
}
|
|
}
|
|
@@ -2573,7 +2587,7 @@ private extension ViewController {
|
|
|
button.isBordered = false
|
|
button.isBordered = false
|
|
|
button.bezelStyle = .regularSquare
|
|
button.bezelStyle = .regularSquare
|
|
|
button.wantsLayer = true
|
|
button.wantsLayer = true
|
|
|
- button.layer?.cornerRadius = 21
|
|
|
|
|
|
|
+ button.layer?.cornerRadius = 16
|
|
|
button.layer?.borderWidth = 1
|
|
button.layer?.borderWidth = 1
|
|
|
button.font = NSFont.systemFont(ofSize: 14, weight: .semibold)
|
|
button.font = NSFont.systemFont(ofSize: 14, weight: .semibold)
|
|
|
button.imagePosition = .imageLeading
|
|
button.imagePosition = .imageLeading
|
|
@@ -2599,24 +2613,36 @@ private extension ViewController {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private func makeScheduleRefreshButton() -> NSButton {
|
|
private func makeScheduleRefreshButton() -> NSButton {
|
|
|
- let button = NSButton(title: "", target: self, action: #selector(scheduleReloadButtonPressed(_:)))
|
|
|
|
|
|
|
+ let diameter: CGFloat = 30
|
|
|
|
|
+ let button = HoverButton(title: "", target: self, action: #selector(scheduleReloadButtonPressed(_:)))
|
|
|
button.translatesAutoresizingMaskIntoConstraints = false
|
|
button.translatesAutoresizingMaskIntoConstraints = false
|
|
|
button.isBordered = false
|
|
button.isBordered = false
|
|
|
button.bezelStyle = .regularSquare
|
|
button.bezelStyle = .regularSquare
|
|
|
button.wantsLayer = true
|
|
button.wantsLayer = true
|
|
|
- button.layer?.cornerRadius = 21
|
|
|
|
|
|
|
+ button.layer?.cornerRadius = diameter / 2
|
|
|
|
|
+ button.layer?.masksToBounds = true
|
|
|
button.layer?.backgroundColor = palette.inputBackground.cgColor
|
|
button.layer?.backgroundColor = palette.inputBackground.cgColor
|
|
|
button.layer?.borderColor = palette.inputBorder.cgColor
|
|
button.layer?.borderColor = palette.inputBorder.cgColor
|
|
|
button.layer?.borderWidth = 1
|
|
button.layer?.borderWidth = 1
|
|
|
button.setButtonType(.momentaryChange)
|
|
button.setButtonType(.momentaryChange)
|
|
|
button.contentTintColor = palette.textSecondary
|
|
button.contentTintColor = palette.textSecondary
|
|
|
button.image = NSImage(systemSymbolName: "arrow.clockwise", accessibilityDescription: "Refresh meetings")
|
|
button.image = NSImage(systemSymbolName: "arrow.clockwise", accessibilityDescription: "Refresh meetings")
|
|
|
- button.symbolConfiguration = NSImage.SymbolConfiguration(pointSize: 18, weight: .semibold)
|
|
|
|
|
|
|
+ button.symbolConfiguration = NSImage.SymbolConfiguration(pointSize: 14, weight: .semibold)
|
|
|
button.imagePosition = .imageOnly
|
|
button.imagePosition = .imageOnly
|
|
|
button.imageScaling = .scaleProportionallyDown
|
|
button.imageScaling = .scaleProportionallyDown
|
|
|
button.focusRingType = .none
|
|
button.focusRingType = .none
|
|
|
- button.heightAnchor.constraint(equalToConstant: 42).isActive = true
|
|
|
|
|
- button.widthAnchor.constraint(equalToConstant: 42).isActive = true
|
|
|
|
|
|
|
+ button.heightAnchor.constraint(equalToConstant: diameter).isActive = true
|
|
|
|
|
+ button.widthAnchor.constraint(equalToConstant: diameter).isActive = true
|
|
|
|
|
+ let baseColor = palette.inputBackground
|
|
|
|
|
+ let baseBorder = palette.inputBorder
|
|
|
|
|
+ let hoverBlend = darkModeEnabled ? NSColor.white : NSColor.black
|
|
|
|
|
+ let hoverColor = baseColor.blended(withFraction: 0.10, of: hoverBlend) ?? baseColor
|
|
|
|
|
+ let hoverBorder = baseBorder.blended(withFraction: 0.16, of: hoverBlend) ?? baseBorder
|
|
|
|
|
+ button.onHoverChanged = { [weak button] hovering in
|
|
|
|
|
+ button?.layer?.backgroundColor = (hovering ? hoverColor : baseColor).cgColor
|
|
|
|
|
+ button?.layer?.borderColor = (hovering ? hoverBorder : baseBorder).cgColor
|
|
|
|
|
+ }
|
|
|
|
|
+ button.onHoverChanged?(false)
|
|
|
return button
|
|
return button
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -3111,6 +3137,43 @@ private final class HoverButton: NSButton {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+private final class HoverPopUpButton: NSPopUpButton {
|
|
|
|
|
+ var onHoverChanged: ((Bool) -> Void)?
|
|
|
|
|
+
|
|
|
|
|
+ private var trackingAreaRef: NSTrackingArea?
|
|
|
|
|
+ private var isHovering = false {
|
|
|
|
|
+ didSet {
|
|
|
|
|
+ guard isHovering != oldValue else { return }
|
|
|
|
|
+ onHoverChanged?(isHovering)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ override func updateTrackingAreas() {
|
|
|
|
|
+ super.updateTrackingAreas()
|
|
|
|
|
+ if let trackingAreaRef {
|
|
|
|
|
+ removeTrackingArea(trackingAreaRef)
|
|
|
|
|
+ }
|
|
|
|
|
+ let options: NSTrackingArea.Options = [
|
|
|
|
|
+ .activeInKeyWindow,
|
|
|
|
|
+ .inVisibleRect,
|
|
|
|
|
+ .mouseEnteredAndExited
|
|
|
|
|
+ ]
|
|
|
|
|
+ let tracking = NSTrackingArea(rect: bounds, options: options, owner: self, userInfo: nil)
|
|
|
|
|
+ addTrackingArea(tracking)
|
|
|
|
|
+ trackingAreaRef = tracking
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ override func mouseEntered(with event: NSEvent) {
|
|
|
|
|
+ super.mouseEntered(with: event)
|
|
|
|
|
+ isHovering = true
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ override func mouseExited(with event: NSEvent) {
|
|
|
|
|
+ super.mouseExited(with: event)
|
|
|
|
|
+ isHovering = false
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
private func circularNSImage(_ image: NSImage, diameter: CGFloat) -> NSImage {
|
|
private func circularNSImage(_ image: NSImage, diameter: CGFloat) -> NSImage {
|
|
|
let size = NSSize(width: diameter, height: diameter)
|
|
let size = NSSize(width: diameter, height: diameter)
|
|
|
let result = NSImage(size: size)
|
|
let result = NSImage(size: size)
|