JXA からの Objective-c バインディングを再勉強。
Building OS X Apps with JavaScript by Tyler Gaw
今回はボタンを押した時のハンドラ指定でも。
target にインスタンス化したデリゲートを指定。
action にハンドラ名を文字列にて指定。
でいいみたい、何だか変な指定方法だけど従うしかない。
ところで現在の JXA は ES6 が使えるので var より let のほうがいい。
ただ全部グローバル変数だとコードが長くなった時にワケワカメになるのよね。
やっぱり class にしたいなぁ。
ObjC.import("Cocoa"); class ButtonWindow extends $.NSWindow { } //TypeError: The value of the superclass's //prototype property is not an object. (-2700)
駄目だ。
ぶっちゃけ Cocoa の API はこう継承するメリットは無さそうだし。
this.window みたいな感じで class にくっつけておけばいいかなと。
それと忘れていたけどアプリにするなら起動パラメーターも得ないと。
まあ少しづつやっていくつもり。
#!/usr/bin/osascript ObjC.import("Cocoa"); class ButtonWindow { constructor(app) { ObjC.registerSubclass({ name: 'WinDelegate', protocols: ['NSWindowDelegate'], methods: { 'windowWillClose:': { types: ['void', ['id']], implementation: function(notification) { return app.terminate(0); } } } }); ObjC.registerSubclass({ name: 'AppDelegate', methods: { 'onButtonClicked': { types: ['void', ['id']], implementation: (button)=> { // parameter ? button.title = "Click!Click!Click!Click!Click!"; // this ? this.window.title = "Click!"; } } } }); let appDelegate = $.AppDelegate.new; // NSButton this.button = $.NSButton.alloc.initWithFrame($.NSMakeRect(10, 10, 150, 50)); this.button.title = "Click!"; this.button.bezelStyle = $.NSRoundedBezelStyle; this.button.buttonType = $.NSMomentaryLightButton; this.button.target = appDelegate; this.button.action = "onButtonClicked"; // NSWindow this.window = $.NSWindow.alloc.initWithContentRectStyleMaskBackingDefer( $.NSMakeRect(0, 0, 320, 120), $.NSTitledWindowMask | $.NSClosableWindowMask | $.NSMiniaturizableWindowMask | $.NSResizableWindowMask, $.NSBackingStoreBuffered, false ); this.window.title = $("JXA NSButton"); this.window.orderFrontRegardless; this.window.delegate = $.WinDelegate.new; this.window.contentView.addSubview(this.button); this.window.makeKeyAndOrderFront(this.window); } } function run(argv) { let app = $.NSApplication.sharedApplication; app.setActivationPolicy($.NSApplicationActivationPolicyRegular); app.mainMenu = function() { function newMenu(title, action, key) { return $.NSMenuItem.alloc.initWithTitleActionKeyEquivalent(title, action, key); } const mainMenu = $.NSMenu.alloc.initWithTitle("Test"); const itemApp = $.NSMenuItem.new; const menuApp = $.NSMenu.alloc.initWithTitle("Test2"); itemApp.submenu = menuApp; mainMenu.addItem(itemApp); menuApp.addItem(newMenu('Quit', 'terminate:', 'q') ); return mainMenu; }(); let window = new ButtonWindow(app); app.run; }
で
ボタンをクリックするとタイトルバーとボタンの文字が変わります。
よしハンドラ指定方法はコレでいいようだ。
で、やはり絶対位置配置なのでボタン文字列のはみ出しが起こります。
macOS って見た目は洗練されているけど API は古臭いな。
constructor(app) の app ポインタは保持されるようです。
app.terminate(0) をどうしようかと思ったけど試してみるもんです。
class と run を使ったらいかにもアプリのコードって感じになった。
アロー関数で this が保持され一般的な class のように使える。
やっぱり class にしたほうが理解しやすい、this だらけになってもーたけど。