アラートダイアログ上にチェックボックスで選択肢の入力を求めるAppleScriptです。
▲macOS 10.14上のLight Mode(Left)、Dark Mode(Right)
ラジオボタンで項目選択を行うのと同じぐらい、チェックボックスで項目選択を行うのは「よくある処理」です。ただ、それだけのためにXcode上でAppleScriptのプログラムを作るのは大袈裟なのと、できることはなるべく普通のAppleScript(Xcode上ではない)のランタイム環境上でできたほうがよいとの考えから、こうして箱庭UIをちまちま作っているものです。
本AppleScriptは、スクリプトエディタ上、スクリプトメニュー、AppleScriptアプレット、Script Debugger上などのランタイム環境で動作します。他のAppleScriptのバンドル中に入れてAppleScript Librariesとして呼び出して使うことを前提に整備してあります。
チェックした項目の番号がリストで返ってきます。各項目番号は1始まり(1-based index)です。
▲「?」ボタン(Help Button)をクリックすると、すべてのチェックボックスをオン/オフにするかを指定できる(ないと不便そうだったので)
ボタンのタイプはいくつか変更して試していますが、このあたりは最近のOSアップデートでいろいろ変更が加わっており、実際に指定しても有意な結果が得られない(なんで存在するのかよくわからない)ものもあり、実際に指定して試してみることをおすすめします。
本Scriptにはいくつか制約事項があります。選択肢の個数が奇数の場合にうやむやにする処理はつけていません。また、選択肢の文字数が長い場合への対処も一切していません。このあたりは真面目にプログラムを組む際には問題になってくることでしょう。
▲NSButtonTypeOnOff
▲NSButtonTypePushOnPushOff
▲NSButtonTypeRadio
▲NSButtonTypeSwitch
▲NSButtonTypeToggle(クリックすると遅れてステートが変化する。なにこれ?)
実際には、ライブラリ化してこんな風に呼び出して使うことを想定しています。
— Created 2019-08-07 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.5"
use scripting additions
use checkLib : script "checkboxLib"
set paramObj to {myMessage:"Select target Item", mySubMessage:"適切なものを以下からえらんでください", mySuppression:"", myColNum:2, matrixTitleList:{"にんじん", "ごぼう", "だいこん", "りんご", "キャベツ", "レタス", "じゃがいも", "にんじん", "小松菜", "青梗菜", "しいたけ", "舞茸"}}
set aRes to dispCheckBoxMain(paramObj) of checkLib
–> {1, 2}
★Click Here to Open This Script
AppleScript名:アラートダイアログ上にcheckboxを表示 v2 |
— Created 2019-08-07 by Takaaki Naganoya — 2019 Piyomaru Software use AppleScript version "2.5" use scripting additions use framework "Foundation" use framework "AppKit" property NSView : a reference to current application’s NSView property NSAlert : a reference to current application’s NSAlert property NSButton : a reference to current application’s NSButton property NSOnState : a reference to current application’s NSOnState property NSOffState : a reference to current application’s NSOffState property NSMutableArray : a reference to current application’s NSMutableArray property NSButtonTypeSwitch : a reference to current application’s NSButtonTypeSwitch property NSRunningApplication : a reference to current application’s NSRunningApplication property theResult : 0 property returnCode : 0 property bArray : {} –Checkbox button object array on run set paramObj to {myMessage:"Select target Item", mySubMessage:"適切なものを以下からえらんでください", mySuppression:"", myColNum:2, matrixTitleList:{"にんじん", "ごぼう", "だいこん", "りんご", "キャベツ", "レタス", "じゃがいも", "にんじん", "小松菜", "青梗菜", "しいたけ", "舞茸"}} –my chooseItemByCheckBox:paramObj –for Debugging my performSelectorOnMainThread:"chooseItemByCheckBox:" withObject:(paramObj) waitUntilDone:true return my sort1DNumList:theResult ascOrder:true –> {1, 3, 5, 7, 9, 11} end run on chooseItemByCheckBox:(paramObj) set aMainMes to myMessage of paramObj set aSubMes to mySubMessage of paramObj set aMatList to (matrixTitleList of paramObj) as list set aLen to length of aMatList set aSupMes to mySuppression of paramObj set colNum to (myColNum of paramObj) as integer set rowNum to (aLen div colNum) + (aLen mod colNum) set aButtonCellWidth to 150 set aButtonCellHeight to 24 set viewWidth to aButtonCellWidth * colNum set viewHeight to aButtonCellHeight * rowNum –define the matrix size where you’ll put the radio buttons set matrixRect to current application’s NSMakeRect(0.0, 0.0, viewWidth, viewHeight) set aView to NSView’s alloc()’s initWithFrame:(matrixRect) set aCount to 1 set bArray to current application’s NSMutableArray’s new() repeat with y from 1 to rowNum repeat with x from 1 to colNum if aCount ≤ aLen then set j to contents of item aCount of aMatList set tmpB to (NSButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(((x – 1) * aButtonCellWidth), ((aLen – aCount) div colNum) * aButtonCellHeight, aButtonCellWidth, aButtonCellHeight))) (tmpB’s setTitle:j) (tmpB’s setShowsBorderOnlyWhileMouseInside:true) (tmpB’s setTag:(aCount)) (tmpB’s setTarget:me) (tmpB’s setAction:("clicked:")) (tmpB’s setButtonType:(NSButtonTypeSwitch)) (bArray’s addObject:tmpB) end if set aCount to aCount + 1 end repeat end repeat –Select the first radio button item –(tmpArray’s objectAtIndex:0)’s setState:(current application’s NSOnState) set theResult to {} (aView’s setSubviews:bArray) — set up alert set theAlert to NSAlert’s alloc()’s init() tell theAlert its setMessageText:aMainMes its setInformativeText:aSubMes its addButtonWithTitle:"OK" its addButtonWithTitle:"Cancel" its setAccessoryView:aView –for Help Button its setShowsHelp:(true) its setDelegate:(me) –for suppression check box ( No use for this case? ) if (aSupMes as string) is not equal to "" then its setShowsSuppressionButton:(true) –「今後このメッセージを表示しない」チェックボックスを表示 set suppressionB to its suppressionButton suppressionB’s setTitle:(aSupMes) else its setShowsSuppressionButton:(false) end if end tell — show alert in modal loop NSRunningApplication’s currentApplication()’s activateWithOptions:0 my performSelectorOnMainThread:"doModal:" withObject:(theAlert) waitUntilDone:true if (my returnCode as number) = 1001 then error number -128 set theResult to (tmpArray’s valueForKeyPath:"status") as list end chooseItemByCheckBox: on doModal:aParam set (my returnCode) to aParam’s runModal() end doModal: on clicked:aParam set aTag to (tag of aParam) as integer if aTag is not in (theResult as list) then set the end of theResult to aTag else set theResult to my deleteItem:aTag fromList:theResult end if end clicked: on deleteItem:anItem fromList:theList set theArray to NSMutableArray’s arrayWithArray:theList theArray’s removeObject:anItem return theArray as list end deleteItem:fromList: –1D List(数値)をsort / ascOrderがtrueだと昇順ソート、falseだと降順ソート on sort1DNumList:theList ascOrder:aBool tell current application’s NSSet to set theSet to setWithArray_(theList) tell current application’s NSSortDescriptor to set theDescriptor to sortDescriptorWithKey_ascending_(missing value, true) set sortedList to theSet’s sortedArrayUsingDescriptors:{theDescriptor} return (sortedList) as list end sort1DNumList:ascOrder: –Help Button Clicked Event Handler on alertShowHelp:aNotification set aRes to display dialog "Do you change all checkbox state?" buttons {"All Off", "All On", "Cancel"} default button 3 with icon 1 set bRes to (button returned of aRes) as string if bRes = "All Off" then set bLen to bArray’s |count|() set theResult to {} repeat with i from 0 to bLen ((bArray’s objectAtIndex:i)’s setState:(current application’s NSOffState)) end repeat else if bRes = "All On" then set bLen to bArray’s |count|() set theResult to {} repeat with i from 0 to bLen ((bArray’s objectAtIndex:i)’s setState:(current application’s NSOnState)) set the end of theResult to i + 1 end repeat end if return false –trueを返すと親ウィンドウ(アラートダイアログ)がクローズする end alertShowHelp: |
checkboxで項目選択するScriptにsdefをつけてみる – AppleScriptの穴 says:
[…] 内容は、先日書いた「アラートダイアログ上にcheckboxを表示 v2」そのものです。この手のScriptは、機能の割に行数が多くて、そんなに難しくない(単にCocoaの仕様にもとづいて書いている […]