78 lines
3.1 KiB
Swift
78 lines
3.1 KiB
Swift
import AppKit
|
|
|
|
/// SPEC §9 — empty-state drop zone. Accepts multiple `.tif` / `.tiff` files
|
|
/// and `.targetjob` JSON.
|
|
|
|
final class DropZoneView: NSView {
|
|
var onFiles: (([URL]) -> Void)?
|
|
|
|
private let titleLabel = NSTextField(labelWithString: "Drop TIFF targets")
|
|
private let bodyLabel = NSTextField(wrappingLabelWithString:
|
|
"Standalone mode accepts multi-page .tif / .tiff files, or a TargetJob JSON from ICCery.")
|
|
private let openButton = NSButton(title: "Open files…", target: nil, action: nil)
|
|
|
|
override init(frame frameRect: NSRect) {
|
|
super.init(frame: frameRect)
|
|
wantsLayer = true
|
|
layer?.backgroundColor = NSColor.windowBackgroundColor.cgColor
|
|
registerForDraggedTypes([.fileURL])
|
|
|
|
titleLabel.font = NSFont.systemFont(ofSize: 22, weight: .semibold)
|
|
titleLabel.alignment = .center
|
|
bodyLabel.font = NSFont.systemFont(ofSize: 13)
|
|
bodyLabel.alignment = .center
|
|
bodyLabel.textColor = NSColor.secondaryLabelColor
|
|
openButton.bezelStyle = .rounded
|
|
openButton.target = self
|
|
openButton.action = #selector(openClicked)
|
|
|
|
[titleLabel, bodyLabel, openButton].forEach {
|
|
$0.translatesAutoresizingMaskIntoConstraints = false
|
|
addSubview($0)
|
|
}
|
|
NSLayoutConstraint.activate([
|
|
titleLabel.centerXAnchor.constraint(equalTo: centerXAnchor),
|
|
titleLabel.centerYAnchor.constraint(equalTo: centerYAnchor, constant: -24),
|
|
bodyLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 8),
|
|
bodyLabel.centerXAnchor.constraint(equalTo: centerXAnchor),
|
|
bodyLabel.widthAnchor.constraint(lessThanOrEqualToConstant: 420),
|
|
openButton.topAnchor.constraint(equalTo: bodyLabel.bottomAnchor, constant: 18),
|
|
openButton.centerXAnchor.constraint(equalTo: centerXAnchor),
|
|
])
|
|
}
|
|
|
|
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
|
|
|
|
@objc private func openClicked() {
|
|
PreviewWindowController.presentOpenPanel { [weak self] urls in
|
|
if !urls.isEmpty { self?.onFiles?(urls) }
|
|
}
|
|
}
|
|
|
|
override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation {
|
|
DropZoneView.containsSupportedFiles(sender) ? .copy : []
|
|
}
|
|
|
|
override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
|
|
let urls = DropZoneView.urls(from: sender)
|
|
if urls.isEmpty { return false }
|
|
onFiles?(urls)
|
|
return true
|
|
}
|
|
|
|
static func containsSupportedFiles(_ sender: NSDraggingInfo) -> Bool {
|
|
!urls(from: sender).isEmpty
|
|
}
|
|
|
|
static func urls(from sender: NSDraggingInfo) -> [URL] {
|
|
let pb = sender.draggingPasteboard
|
|
let urls = pb.readObjects(forClasses: [NSURL.self], options: [.urlReadingFileURLsOnly: true]) as? [URL] ?? []
|
|
return urls.filter { isSupported($0) }
|
|
}
|
|
|
|
static func isSupported(_ url: URL) -> Bool {
|
|
let ext = url.pathExtension.lowercased()
|
|
return ["tif", "tiff", "targetjob", "json"].contains(ext)
|
|
}
|
|
}
|