statusItem.isVisible = true
statusItem.menu = NSMenu()
- let recordItem = NSMenuItem(title: "record", action: #selector(CapturaAppDelegate.onClickStartRecording), keyEquivalent: "6")
+ let recordItem = NSMenuItem(title: "Record", action: #selector(CapturaAppDelegate.onClickStartRecording), keyEquivalent: "6")
recordItem.keyEquivalentModifierMask = [.command, .shift]
statusItem.menu?.addItem(recordItem)
+ statusItem.menu?.addItem(NSMenuItem.separator())
+
+ let preferencesItem = NSMenuItem(title: "Preferences", action: #selector(CapturaAppDelegate.onOpenPreferences), keyEquivalent: "")
+ statusItem.menu?.addItem(preferencesItem)
+
+ let quitItem = NSMenuItem(title: "Quit", action: #selector(CapturaAppDelegate.onQuit), keyEquivalent: "")
+ statusItem.menu?.addItem(quitItem)
}
private func closeWindow() {
NotificationCenter.default.post(name: .startAreaSelection, object: nil, userInfo: nil)
}
+ @objc private func onOpenPreferences() {
+ print("Preferences pressed")
+ }
+
+ @objc private func onQuit() {
+ NSApplication.shared.terminate(self)
+ }
+
// MARK: - App State Event Listeners
if captureState != .selectingArea {
captureState = .selectingArea
recordingWindow = RecordingWindow()
- print("Recording")
}
}
func reset() {
captureState = .idle
+ recordingWindow?.close()
+ self.recordingWindow = nil
}
}
backing: .buffered,
defer: false)
+ self.isReleasedWhenClosed = false
self.center()
self.isMovableByWindowBackground = false
self.isMovable = false
override var canBecomeMain: Bool {
return true
}
+
+ override func resignMain() {
+ super.resignMain()
+ self.ignoresMouseEvents = false
+ }
+
+ override func becomeMain() {
+ super.becomeMain()
+ (self.contentView as? RecordingContentView)?.state = .idle
+ }
+}
+
+enum RecordingWindowState {
+ case passthrough, idle, drawing, moving, resizing;
}
class RecordingContentView: NSView {
- var isDrawing = false
- var isMoving = false
- var isResizing = false
+ var state: RecordingWindowState = .idle
var box: NSRect? = nil
var mouseLocation: NSPoint = NSPoint()
var origin: NSPoint = NSPoint()
override func mouseDragged(with event: NSEvent) {
self.mouseLocation = self.convert(event.locationInWindow, from: nil)
- if isDrawing {
+ if state == .drawing {
box = NSRect(
x: round(min(origin.x, mouseLocation.x)),
y: round(min(origin.y, mouseLocation.y)),
)
}
- if isMoving && box != nil {
- NSCursor.closedHand.set()
- box!.origin = NSPoint(
- x: self.boxOrigin.x - self.origin.x + self.mouseLocation.x,
- y: self.boxOrigin.y - self.origin.y + self.mouseLocation.y)
+ if box != nil {
+ if state == .moving {
+ NSCursor.closedHand.set()
+ box!.origin = NSPoint(
+ x: self.boxOrigin.x - self.origin.x + self.mouseLocation.x,
+ y: self.boxOrigin.y - self.origin.y + self.mouseLocation.y)
+ }
+
+ if state == .resizing {
+ box = NSRect(
+ x: round(min(origin.x, mouseLocation.x)),
+ y: round(min(origin.y, mouseLocation.y)),
+ width: round(abs(mouseLocation.x - origin.x)),
+ height: round(abs(mouseLocation.y - origin.y))
+ )
+ }
}
self.setNeedsDisplay(self.bounds)
}
}
override func hitTest(_ point: NSPoint) -> NSView? {
- return self
+ return state == .passthrough ? nil : self
}
override var acceptsFirstResponder: Bool {
override func mouseDown(with event: NSEvent) {
self.origin = self.convert(event.locationInWindow, from: nil)
if let box {
+ if resizeBox!.contains(origin) {
+ self.origin = NSPoint(x: box.minX, y: box.maxY)
+ state = .resizing
+ return
+ }
if box.contains(origin) {
- isMoving = true
+ state = .moving
self.boxOrigin = NSPoint(x: box.origin.x, y: box.origin.y)
return
}
}
- isDrawing = true
+ state = .drawing
}
override func mouseUp(with event: NSEvent) {
- isDrawing = false
- isMoving = false
+ state = .idle
+ }
+
+ override func keyDown(with event: NSEvent) {
+ print("key down")
+ switch event.keyCode {
+ case 53: // Escape key
+ NotificationCenter.default.post(name: .reset, object: nil, userInfo: nil)
+ default:
+ super.keyDown(with: event)
+ }
+ }
+
+ override func flagsChanged(with event: NSEvent) {
+ if event.modifierFlags.contains(.shift) {
+ state = .passthrough
+ window?.ignoresMouseEvents = true
+ } else {
+ state = .idle
+ window?.ignoresMouseEvents = false
+ }
}
override func draw(_ dirtyRect: NSRect) {
- NSColor(white: 1.0, alpha: 0.001).setFill()
+ if state == .passthrough {
+ NSColor.clear.setFill()
+ } else {
+ NSColor(white: 1.0, alpha: 0.001).setFill()
+ }
dirtyRect.fill()
let dashLength: CGFloat = 5.0
let lineWidth = 0.5
- if !isDrawing && box == nil {
+ if state == .idle && box == nil {
let blackLine = NSBezierPath()
blackLine.lineWidth = lineWidth
blackLine.setLineDash([dashLength, dashLength], count: 2, phase: 0)
clearBox.fill()
}
- if box.contains(mouseLocation) && !isResizing {
+ if state == .moving {
+ let string = "\(Int(box.minX)), \(Int(box.maxY))" as NSString
+ drawText(string, NSPoint(
+ x: box.minX,
+ y: box.maxY
+ ), true)
+ }
+
+ if state == .resizing {
+ let string = "\(Int(mouseLocation.x)), \(Int(mouseLocation.y))" as NSString
+ drawText(string, mouseLocation)
+ }
+
+ if box.contains(mouseLocation) && state != .resizing {
return;
}
}
// Draw text
-
- let offset = NSPoint(x: 10, y: 10)
- let padding = NSPoint(x: 5, y: 2)
+
+ let string = "\(Int(mouseLocation.x)), \(Int(mouseLocation.y))" as NSString
+ drawText(string, mouseLocation)
+ }
+
+ private func drawText(_ text: NSString, _ location: NSPoint, _ isBottomRight: Bool = false) {
let textAttributes = [
NSAttributedString.Key.font: NSFont(name: "Hiragino Mincho ProN", size: 12) ?? NSFont.systemFont(ofSize: 12),
NSAttributedString.Key.foregroundColor: NSColor.white,
]
-
- let string = "\(Int(mouseLocation.x)), \(Int(mouseLocation.y))" as NSString
- let size = string.size(withAttributes: textAttributes)
- let rect = NSRect(x: mouseLocation.x + offset.x, y: mouseLocation.y + offset.y, width: size.width + 2 * padding.x, height: size.height + 2 * padding.y)
- let textRect = NSRect(x: mouseLocation.x + offset.x + padding.x, y: mouseLocation.y + offset.y + padding.y, width: size.width, height: size.height)
+ let offset = NSPoint(x: 10, y: 10)
+ let padding = NSPoint(x: 5, y: 2)
+ let size = text.size(withAttributes: textAttributes)
+ var rect = NSRect(x: location.x + offset.x, y: location.y + offset.y, width: size.width + 2 * padding.x, height: size.height + 2 * padding.y)
+ var textRect = NSRect(x: location.x + offset.x + padding.x, y: location.y + offset.y + padding.y, width: size.width, height: size.height)
+
+ if (isBottomRight) {
+ rect = rect.offsetBy(dx: -size.width - 2 * offset.x, dy: 0)
+ textRect = textRect.offsetBy(dx: -size.width - 2 * offset.x, dy: 0)
+ }
NSColor.black.set()
rect.fill()
- string.draw(in: textRect, withAttributes: textAttributes)
+ text.draw(in: textRect, withAttributes: textAttributes)
}
}