Improve optional checking in native selector

This commit is contained in:
hensm
2019-08-26 15:00:09 +01:00
parent d96b45cca8
commit de8cc96faf
4 changed files with 104 additions and 88 deletions

View File

@@ -2,47 +2,30 @@ import Cocoa
class AppDelegate : NSObject, NSApplicationDelegate { class AppDelegate : NSObject, NSApplicationDelegate {
var initData: InitData!
var mainWindow: NSWindow? var mainWindow: NSWindow?
var mainWindowController: NSWindowController? var mainWindowController: NSWindowController?
var mainWindowViewController: ViewController? var mainWindowViewController: ViewController?
func applicationDidFinishLaunching (_ aNotification: Notification) { func applicationDidFinishLaunching (_ aNotification: Notification) {
if CommandLine.argc < 2 {
fputs("Error: Not enough args\n", stderr)
exit(1)
}
guard let data = CommandLine.arguments[1].data(using: .utf8) else {
fputs("Error: Failed to convert input to data\n", stderr)
exit(1)
}
do {
// Decode and store initialization JSON data
self.initData = try JSONDecoder().decode(InitData.self, from: data)
} catch {
fputs("Error: Failed to parse input data\n (\(error))", stderr)
exit(1)
}
let window = NSWindow( let window = NSWindow(
contentRect: NSZeroRect contentRect: NSZeroRect
, styleMask: [ .titled, .closable ] , styleMask: [ .titled, .closable ]
, backing: .buffered , backing: .buffered
, defer: false) , defer: false)
let screenHeight = NSScreen.main!.frame.height
window.titleVisibility = .hidden window.titleVisibility = .hidden
window.isMovableByWindowBackground = true window.isMovableByWindowBackground = true
window.orderFrontRegardless() window.orderFrontRegardless()
window.setFrameTopLeftPoint(NSPoint(
x: self.initData.windowPositionX if let screen = NSScreen.main {
, y: Int(screenHeight - CGFloat(self.initData.windowPositionY)))) let windowX = InitDataProvider.shared.data.windowPositionX
let windowY = Int(screen.frame.height - CGFloat(
InitDataProvider.shared.data.windowPositionY))
window.setFrameTopLeftPoint(NSPoint(x: windowX, y: windowY))
}
let windowController = NSWindowController(window: window) let windowController = NSWindowController(window: window)
windowController.showWindow(window) windowController.showWindow(window)
@@ -59,7 +42,7 @@ class AppDelegate : NSObject, NSApplicationDelegate {
} }
func applicationDidResignActive (_ aNotification: Notification) { func applicationDidResignActive (_ aNotification: Notification) {
if self.initData.closeIfFocusLost { if InitDataProvider.shared.data.closeIfFocusLost {
self.mainWindow?.performClose(aNotification) self.mainWindow?.performClose(aNotification)
} }
} }

View File

@@ -0,0 +1,20 @@
import Cocoa
class InitDataProvider {
static let shared = InitDataProvider()
let data: InitData
private init() {
if CommandLine.argc < 2 {
fatalError("Missing init data")
}
if let input = CommandLine.arguments[1].data(using: .utf8)
, let parsed = try? JSONDecoder().decode(InitData.self, from: input) {
self.data = parsed
} else {
fatalError("Failed to convert and parse init data")
}
}
}

View File

@@ -32,7 +32,7 @@ class ReceiverView : NSStackView {
super.init(coder: coder) super.init(coder: coder)
} }
init (receiver: Receiver, initData: InitData) { init (receiver: Receiver) {
super.init(frame: NSZeroRect) super.init(frame: NSZeroRect)
self.receiver = receiver self.receiver = receiver
@@ -63,7 +63,7 @@ class ReceiverView : NSStackView {
self.castButton = NSButton( self.castButton = NSButton(
title: initData.i18n_castButtonTitle title: InitDataProvider.shared.data.i18n_castButtonTitle
, target: self , target: self
, action: #selector(ReceiverView.onCast)) , action: #selector(ReceiverView.onCast))
@@ -89,12 +89,14 @@ class ReceiverView : NSStackView {
if !constraintsSet { if !constraintsSet {
self.translatesAutoresizingMaskIntoConstraints = false self.translatesAutoresizingMaskIntoConstraints = false
if let superview = self.superview {
self.leadingAnchor.constraint( self.leadingAnchor.constraint(
equalTo: superview!.leadingAnchor equalTo: superview.leadingAnchor
, constant: 8).isActive = true , constant: 8).isActive = true
self.trailingAnchor.constraint( self.trailingAnchor.constraint(
equalTo: superview!.trailingAnchor equalTo: superview.trailingAnchor
, constant: -8).isActive = true , constant: -8).isActive = true
}
constraintsSet = true constraintsSet = true
} }

View File

@@ -2,8 +2,6 @@ import Cocoa
class ViewController : NSViewController { class ViewController : NSViewController {
var initData: InitData!
var mediaTypePopUpButton: NSPopUpButton! var mediaTypePopUpButton: NSPopUpButton!
var receiverViews = [ReceiverView]() var receiverViews = [ReceiverView]()
@@ -21,7 +19,7 @@ class ViewController : NSViewController {
override func viewDidLoad () { override func viewDidLoad () {
super.viewDidLoad() super.viewDidLoad()
self.initData = (NSApplication.shared.delegate as! AppDelegate).initData let initData = InitDataProvider.shared.data
/** /**
* View Hierarchy * View Hierarchy
@@ -59,27 +57,27 @@ class ViewController : NSViewController {
, initData.i18n_mediaTypeFile , initData.i18n_mediaTypeFile
]) ])
let mediaTypePopUpButtonMenu = self.mediaTypePopUpButton.menu! if let appItem = self.mediaTypePopUpButton
.item(withTitle: initData.i18n_mediaTypeApp)
, let tabItem = self.mediaTypePopUpButton
.item(withTitle: initData.i18n_mediaTypeTab)
, let screenItem = self.mediaTypePopUpButton
.item(withTitle: initData.i18n_mediaTypeScreen)
, let fileItem = self.mediaTypePopUpButton
.item(withTitle: initData.i18n_mediaTypeFile) {
if let mediaTypePopUpButtonMenu = self.mediaTypePopUpButton.menu {
mediaTypePopUpButtonMenu.delegate = self mediaTypePopUpButtonMenu.delegate = self
mediaTypePopUpButtonMenu.insertItem(NSMenuItem.separator()
let appItem = self.mediaTypePopUpButton
.item(withTitle: initData.i18n_mediaTypeApp)!
let tabItem = self.mediaTypePopUpButton
.item(withTitle: initData.i18n_mediaTypeTab)!
let screenItem = self.mediaTypePopUpButton
.item(withTitle: initData.i18n_mediaTypeScreen)!
let fileItem = self.mediaTypePopUpButton
.item(withTitle: initData.i18n_mediaTypeFile)!
mediaTypePopUpButtonMenu
.insertItem(NSMenuItem.separator()
, at: mediaTypePopUpButtonMenu.index(of: fileItem)) , at: mediaTypePopUpButtonMenu.index(of: fileItem))
}
// Set tags to enum value // Set tags to enum value
appItem.tag = MediaType.app.rawValue appItem.tag = MediaType.app.rawValue
tabItem.tag = MediaType.tab.rawValue tabItem.tag = MediaType.tab.rawValue
screenItem.tag = MediaType.screen.rawValue screenItem.tag = MediaType.screen.rawValue
fileItem.tag = MediaType.file.rawValue fileItem.tag = MediaType.file.rawValue
}
for item in self.mediaTypePopUpButton.itemArray { for item in self.mediaTypePopUpButton.itemArray {
if (initData.availableMediaTypes & item.tag) == 0 { if (initData.availableMediaTypes & item.tag) == 0 {
@@ -121,15 +119,12 @@ class ViewController : NSViewController {
let receiverSeparator = NSBox() let receiverSeparator = NSBox()
receiverSeparator.boxType = .separator receiverSeparator.boxType = .separator
let receiverView = ReceiverView( let receiverView = ReceiverView(receiver: receiver)
receiver: receiver
, initData: self.initData)
receiverView.receiverViewDelegate = self receiverView.receiverViewDelegate = self
if UInt(initData!.availableMediaTypes) == 0 if UInt(initData.availableMediaTypes) == 0
|| (initData!.availableMediaTypes || (initData.availableMediaTypes
& initData!.defaultMediaType.rawValue) == 0 { & initData.defaultMediaType.rawValue) == 0 {
receiverView.isEnabled = false receiverView.isEnabled = false
} }
@@ -149,26 +144,33 @@ class ViewController : NSViewController {
override func viewDidAppear () { override func viewDidAppear () {
// Set window title and update visibility // Set window title and update visibility
let window = self.view.window! if let window = self.view.window {
window.title = initData.i18n_extensionName window.title = InitDataProvider.shared.data.i18n_extensionName
window.titleVisibility = .visible window.titleVisibility = .visible
} }
} }
}
extension ViewController : NSMenuDelegate { extension ViewController : NSMenuDelegate {
func menuDidClose (_ menu: NSMenu) { func menuDidClose (_ menu: NSMenu) {
let mediaType = MediaType( let initData = InitDataProvider.shared.data
rawValue: self.mediaTypePopUpButton.selectedItem!.tag)!
if self.initData.availableMediaTypes & mediaType.rawValue != 0 { guard let selectedItem = self.mediaTypePopUpButton.selectedItem
, let mediaType = MediaType(rawValue: selectedItem.tag) else {
return
}
if initData.availableMediaTypes & mediaType.rawValue != 0 {
for receiverView in self.receiverViews { for receiverView in self.receiverViews {
receiverView.isEnabled = true receiverView.isEnabled = true
} }
} }
let fileItem = self.mediaTypePopUpButton guard let fileItem = self.mediaTypePopUpButton
.item(at: self.mediaTypePopUpButton.indexOfItem( .item(at: self.mediaTypePopUpButton.indexOfItem(
withTag: MediaType.file.rawValue))! withTag: MediaType.file.rawValue)) else {
return
}
if (mediaType == .file) { if (mediaType == .file) {
let panel = NSOpenPanel() let panel = NSOpenPanel()
@@ -178,7 +180,9 @@ extension ViewController : NSMenuDelegate {
panel.canCreateDirectories = false panel.canCreateDirectories = false
panel.canChooseFiles = true panel.canChooseFiles = true
panel.beginSheetModal(for: self.view.window!) { (result) in guard let window = self.view.window else { return }
panel.beginSheetModal(for: window) { (result) in
if (result == .OK) { if (result == .OK) {
let url = panel.urls[0] let url = panel.urls[0]
let fileName = url.lastPathComponent let fileName = url.lastPathComponent
@@ -194,14 +198,21 @@ extension ViewController : NSMenuDelegate {
} else { } else {
// Re-select the default media type item // Re-select the default media type item
self.mediaTypePopUpButton.selectItem( self.mediaTypePopUpButton.selectItem(
withTag: self.initData.defaultMediaType.rawValue) withTag: initData.defaultMediaType.rawValue)
let defaultMediaTypeAvailable = initData.availableMediaTypes
& initData.defaultMediaType.rawValue != 0
for receiverView in self.receiverViews {
receiverView.isEnabled = defaultMediaTypeAvailable
}
} }
} }
} }
// Reset file item // Reset file item
fileItem.title = self.initData.i18n_mediaTypeFile fileItem.title = initData.i18n_mediaTypeFile
self.filePath = nil self.filePath = nil
} }
} }
@@ -217,23 +228,23 @@ extension ViewController : ReceiverViewDelegate {
receiverView.isEnabled = false receiverView.isEnabled = false
} }
do {
let mediaType = MediaType( guard let selectedItem = self.mediaTypePopUpButton.selectedItem
rawValue: self.mediaTypePopUpButton.selectedItem!.tag)! , let mediaType = MediaType(rawValue: selectedItem.tag) else {
return
}
let selection = ReceiverSelection( let selection = ReceiverSelection(
receiver: receiver receiver: receiver
, mediaType: mediaType , mediaType: mediaType
, filePath: self.filePath ?? nil) , filePath: self.filePath ?? nil)
let jsonData = try JSONEncoder().encode(selection) if let jsonData = try? JSONEncoder().encode(selection)
let jsonString = String(data: jsonData, encoding: .utf8) , let jsonString = String(data: jsonData, encoding: .utf8) {
print(jsonString)
print(jsonString!)
fflush(stdout) fflush(stdout)
} catch { } else {
fputs("Error: Failed to encode output data", stderr) fatalError("Error: Failed to encode output data")
exit(1)
} }
} }
} }