Improve resizing with draggable and hotkeys
This commit is contained in:
@@ -28,6 +28,36 @@ struct HotkeyRecorderView: View {
|
||||
}
|
||||
}
|
||||
|
||||
struct OptionalHotkeyRecorderView: View {
|
||||
let label: String
|
||||
@Binding var binding: HotkeyBinding?
|
||||
|
||||
@State private var isRecording = false
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
Text(label)
|
||||
.frame(width: 140, alignment: .leading)
|
||||
|
||||
OptionalHotkeyRecorderField(binding: $binding, isRecording: $isRecording)
|
||||
.frame(width: 120, height: 24)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 6)
|
||||
.fill(isRecording ? Color.accentColor.opacity(0.15) : Color.secondary.opacity(0.1))
|
||||
)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 6)
|
||||
.stroke(isRecording ? Color.accentColor : Color.secondary.opacity(0.3), lineWidth: 1)
|
||||
)
|
||||
|
||||
Button("Clear") {
|
||||
binding = nil
|
||||
}
|
||||
.disabled(binding == nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// NSViewRepresentable that captures key events when focused.
|
||||
struct HotkeyRecorderField: NSViewRepresentable {
|
||||
@Binding var binding: HotkeyBinding
|
||||
@@ -52,6 +82,29 @@ struct HotkeyRecorderField: NSViewRepresentable {
|
||||
}
|
||||
}
|
||||
|
||||
struct OptionalHotkeyRecorderField: NSViewRepresentable {
|
||||
@Binding var binding: HotkeyBinding?
|
||||
@Binding var isRecording: Bool
|
||||
|
||||
func makeNSView(context: Context) -> HotkeyNSView {
|
||||
let view = HotkeyNSView()
|
||||
view.onKeyRecorded = { newBinding in
|
||||
binding = newBinding
|
||||
isRecording = false
|
||||
}
|
||||
view.onFocusChanged = { focused in
|
||||
isRecording = focused
|
||||
}
|
||||
return view
|
||||
}
|
||||
|
||||
func updateNSView(_ nsView: HotkeyNSView, context: Context) {
|
||||
nsView.currentLabel = binding?.displayString ?? "Not set"
|
||||
nsView.showRecording = isRecording
|
||||
nsView.needsDisplay = true
|
||||
}
|
||||
}
|
||||
|
||||
/// The actual NSView that handles key capture.
|
||||
class HotkeyNSView: NSView {
|
||||
var currentLabel: String = ""
|
||||
@@ -59,21 +112,32 @@ class HotkeyNSView: NSView {
|
||||
var onKeyRecorded: ((HotkeyBinding) -> Void)?
|
||||
var onFocusChanged: ((Bool) -> Void)?
|
||||
|
||||
private let label: NSTextField = {
|
||||
let field = NSTextField(labelWithString: "")
|
||||
field.alignment = .center
|
||||
field.font = NSFont.monospacedSystemFont(ofSize: 12, weight: .medium)
|
||||
field.translatesAutoresizingMaskIntoConstraints = false
|
||||
field.backgroundColor = .clear
|
||||
field.isBezeled = false
|
||||
field.lineBreakMode = .byTruncatingTail
|
||||
return field
|
||||
}()
|
||||
|
||||
override init(frame frameRect: NSRect) {
|
||||
super.init(frame: frameRect)
|
||||
setupLabel()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
setupLabel()
|
||||
}
|
||||
|
||||
override var acceptsFirstResponder: Bool { true }
|
||||
|
||||
override func draw(_ dirtyRect: NSRect) {
|
||||
let text = showRecording ? "Press keys…" : currentLabel
|
||||
let attrs: [NSAttributedString.Key: Any] = [
|
||||
.font: NSFont.monospacedSystemFont(ofSize: 12, weight: .medium),
|
||||
.foregroundColor: showRecording ? NSColor.controlAccentColor : NSColor.labelColor
|
||||
]
|
||||
let str = NSAttributedString(string: text, attributes: attrs)
|
||||
let size = str.size()
|
||||
let point = NSPoint(
|
||||
x: (bounds.width - size.width) / 2,
|
||||
y: (bounds.height - size.height) / 2
|
||||
)
|
||||
str.draw(at: point)
|
||||
override func layout() {
|
||||
super.layout()
|
||||
updateLabelAppearance()
|
||||
}
|
||||
|
||||
override func mouseDown(with event: NSEvent) {
|
||||
@@ -108,4 +172,19 @@ class HotkeyNSView: NSView {
|
||||
// Resign first responder after recording
|
||||
window?.makeFirstResponder(nil)
|
||||
}
|
||||
|
||||
private func setupLabel() {
|
||||
addSubview(label)
|
||||
NSLayoutConstraint.activate([
|
||||
label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 6),
|
||||
label.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -6),
|
||||
label.centerYAnchor.constraint(equalTo: centerYAnchor)
|
||||
])
|
||||
updateLabelAppearance()
|
||||
}
|
||||
|
||||
private func updateLabelAppearance() {
|
||||
label.stringValue = showRecording ? "Press keys..." : currentLabel
|
||||
label.textColor = showRecording ? .controlAccentColor : .labelColor
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user