mirror of
https://github.com/MonitorControl/MonitorControl.git
synced 2026-05-25 22:01:10 -06:00
UI: Refine Custom HUD and Menu Slider aesthetics
- Make Custom HUD background transparent to avoid square opaque corners - Update custom HUD icon and slider colors for better macOS integration - Adjust Menu Slider icon padding and layout constraints
This commit is contained in:
parent
248c256141
commit
a96f654948
2 changed files with 35 additions and 16 deletions
|
|
@ -41,7 +41,7 @@ class CustomHUDManager {
|
|||
private func createHUDWindow(displayID: CGDirectDisplayID) -> NSWindow {
|
||||
let window = NSPanel(
|
||||
contentRect: NSRect(x: 0, y: 0, width: 260, height: 56),
|
||||
styleMask: [.nonactivatingPanel, .hudWindow],
|
||||
styleMask: [.nonactivatingPanel],
|
||||
backing: .buffered,
|
||||
defer: false
|
||||
)
|
||||
|
|
@ -96,6 +96,13 @@ class CustomHUDManager {
|
|||
private func createHUDContentView(type: HUDType, value: Float, maxValue: Float) -> NSView {
|
||||
let w: CGFloat = 260
|
||||
let h: CGFloat = 56
|
||||
|
||||
// Wrap the visual effect view in a transparent root view.
|
||||
// This ensures the NSWindow doesn't force a square opaque background on the corners.
|
||||
let rootView = NSView(frame: NSRect(x: 0, y: 0, width: w, height: h))
|
||||
rootView.wantsLayer = true
|
||||
rootView.layer?.backgroundColor = NSColor.clear.cgColor
|
||||
|
||||
let containerView = NSVisualEffectView(frame: NSRect(x: 0, y: 0, width: w, height: h))
|
||||
containerView.material = .hudWindow
|
||||
containerView.blendingMode = .behindWindow
|
||||
|
|
@ -103,6 +110,8 @@ class CustomHUDManager {
|
|||
containerView.wantsLayer = true
|
||||
containerView.layer?.cornerRadius = h / 2
|
||||
containerView.layer?.masksToBounds = true
|
||||
|
||||
rootView.addSubview(containerView)
|
||||
|
||||
let iconSize: CGFloat = 26
|
||||
let iconView = NSImageView(frame: NSRect(x: 18, y: (h - iconSize) / 2, width: iconSize, height: iconSize))
|
||||
|
|
@ -149,7 +158,7 @@ class CustomHUDManager {
|
|||
let normalizedValue = CGFloat(min(max(value / maxValue, 0), 1))
|
||||
let progressFill = NSView(frame: NSRect(x: barX, y: barY, width: max(barH, barW * normalizedValue), height: barH))
|
||||
progressFill.wantsLayer = true
|
||||
progressFill.layer?.backgroundColor = NSColor.white.cgColor
|
||||
progressFill.layer?.backgroundColor = NSColor.white.withAlphaComponent(0.9).cgColor
|
||||
progressFill.layer?.cornerRadius = barH / 2
|
||||
containerView.addSubview(progressFill)
|
||||
|
||||
|
|
@ -161,7 +170,7 @@ class CustomHUDManager {
|
|||
label.alignment = .right
|
||||
containerView.addSubview(label)
|
||||
|
||||
return containerView
|
||||
return rootView
|
||||
}
|
||||
|
||||
private var fadeTimers: [CGDirectDisplayID: Timer] = [:]
|
||||
|
|
@ -229,9 +238,9 @@ enum HUDType {
|
|||
|
||||
var iconNSColor: NSColor {
|
||||
switch self {
|
||||
case .brightness: return .systemYellow
|
||||
case .volume, .volumeMuted: return .systemBlue
|
||||
case .contrast: return .systemGray
|
||||
case .brightness: return .white.withAlphaComponent(0.9)
|
||||
case .volume, .volumeMuted: return .white.withAlphaComponent(0.9)
|
||||
case .contrast: return .white.withAlphaComponent(0.8)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class SliderHandler {
|
|||
let offsetY: CGFloat = -1.5
|
||||
|
||||
let tickMarkKnobExtraInset: CGFloat = 4
|
||||
let tickMarkKnobExtraRadiusMultiplier: CGFloat = 0.25
|
||||
let tickMarkKnobExtraRadiusMultiplier: CGFloat = 0.75
|
||||
|
||||
var numOfTickmarks: Int = 0
|
||||
var isHighlightDisplayItems: Bool = false
|
||||
|
|
@ -226,7 +226,7 @@ class SliderHandler {
|
|||
if #available(macOS 12.0, *) {
|
||||
let paletteColor: NSColor
|
||||
switch command {
|
||||
case .brightness: paletteColor = .systemYellow
|
||||
case .brightness: paletteColor = .labelColor.withAlphaComponent(0.85)
|
||||
default: paletteColor = .labelColor.withAlphaComponent(0.72)
|
||||
}
|
||||
let palette = NSImage.SymbolConfiguration(paletteColors: [paletteColor])
|
||||
|
|
@ -247,13 +247,23 @@ class SliderHandler {
|
|||
}
|
||||
self.slider = slider
|
||||
if !DEBUG_MACOS10, #available(macOS 11.0, *) {
|
||||
slider.frame.size.width = 196
|
||||
let iconSize: CGFloat = 18
|
||||
let iconPadding: CGFloat = 10
|
||||
slider.frame.size.width = 180
|
||||
var sliderFrame = slider.frame
|
||||
sliderFrame.size.height = max(sliderFrame.size.height, 22)
|
||||
slider.frame = sliderFrame
|
||||
slider.frame.origin = NSPoint(x: 15, y: 8)
|
||||
let view = NSView(frame: NSRect(x: 0, y: 0, width: slider.frame.width + 30 + (showPercent ? 38 : 0), height: slider.frame.height + 42))
|
||||
|
||||
// Horizontal layout: Icon then Slider
|
||||
let iconX: CGFloat = 15
|
||||
let sliderX = iconX + iconSize + iconPadding
|
||||
slider.frame.origin = NSPoint(x: sliderX, y: 8)
|
||||
|
||||
let viewWidth = sliderX + slider.frame.width + 15 + (showPercent ? 38 : 0)
|
||||
let viewHeight = slider.frame.height + 16
|
||||
let view = NSView(frame: NSRect(x: 0, y: 0, width: viewWidth, height: viewHeight))
|
||||
view.frame.origin = NSPoint(x: 12, y: 0)
|
||||
|
||||
var iconName = "circle.dashed"
|
||||
switch command {
|
||||
case .audioSpeakerVolume: iconName = "speaker.wave.2.fill"
|
||||
|
|
@ -262,23 +272,23 @@ class SliderHandler {
|
|||
default: break
|
||||
}
|
||||
let icon = SliderHandler.ClickThroughImageView()
|
||||
let iconSize: CGFloat = 18
|
||||
icon.image = SliderHandler.menuSymbolImage(named: iconName, pointSize: iconSize, command: command)
|
||||
icon.imageScaling = .scaleProportionallyDown
|
||||
if #available(macOS 12.0, *) {
|
||||
icon.contentTintColor = nil
|
||||
} else {
|
||||
icon.contentTintColor = command == .brightness ? NSColor.systemYellow : NSColor.labelColor.withAlphaComponent(0.72)
|
||||
icon.contentTintColor = .labelColor.withAlphaComponent(0.72)
|
||||
}
|
||||
// Position icon at horizontal left (start), 8px above slider
|
||||
icon.frame = NSRect(x: slider.frame.origin.x, y: slider.frame.origin.y + slider.frame.height + 8, width: iconSize, height: iconSize)
|
||||
|
||||
// Position icon to the left of the slider, vertically centered
|
||||
icon.frame = NSRect(x: iconX, y: slider.frame.origin.y + (slider.frame.height - iconSize) / 2, width: iconSize, height: iconSize)
|
||||
icon.imageAlignment = .alignCenter
|
||||
icon.configureForMenuSymbol()
|
||||
view.addSubview(slider)
|
||||
view.addSubview(icon)
|
||||
self.icon = icon
|
||||
if showPercent {
|
||||
let percentageBox = NSTextField(frame: NSRect(x: 15 + slider.frame.size.width - 2, y: slider.frame.origin.y + (slider.frame.height - 12) / 2, width: 40, height: 12))
|
||||
let percentageBox = NSTextField(frame: NSRect(x: sliderX + slider.frame.size.width + 2, y: slider.frame.origin.y + (slider.frame.height - 12) / 2, width: 40, height: 12))
|
||||
self.setupPercentageBox(percentageBox)
|
||||
self.percentageBox = percentageBox
|
||||
view.addSubview(percentageBox)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue