アラートダイアログ上にTableViewを表示し、複数キーの組み合わせによって項目抽出。選択項目のデータを返すAppleScriptです。
あくまで試作品なので、あちらこちらに「お可愛らしい」実装が転がっています。NSBoxがまだまともに使いこなせていないあたりとか(Xcode上で部品として配置するのは楽勝ですが、プログラムから動的に生成して使用するのは別なので)。
抽出キー数は可変で外部から指定できるとよいのですが、本Scriptでは固定です。また、各抽出条件も外部から供給するのが本来あるべき姿ですが、ハードコーディングしています。
あと、TableViewの下側に謎の余白があるのは、めんどくさくなってそのまま放置しています。これで外部から各種パラメータを指定できるようにして、sdefつけて1命令で呼び出せるようにしておけば、レコード数の多い選択項目から条件抽出しつつ項目選択できてよいでしょう。
プログラム内容自体は、高度でもなければ高尚でもありません。実にダラダラとGUI部品のパラメータを設定しているだけです。
AppleScript名:アラートダイアログ上にTable Viewを表示 v5_複数キー抽出つき |
— Created 2019-12-22 by Takaaki Naganoya — 2019 Piyomaru Software set aRes to displayCondTable() of filterTableDialogView –> {field3:"3.0GHz 6コア Intel Core i5(Turbo Boost使用時最大4.1GHz)", field2:198800, field1:"iMac 5K 27"} script filterTableDialogView use scripting additions use framework "Foundation" use framework "AppKit" property parent : AppleScript property NSBox : a reference to current application’s NSBox property NSView : a reference to current application’s NSView property NSAlert : a reference to current application’s NSAlert property NSColor : a reference to current application’s NSColor property NSIndexSet : a reference to current application’s NSIndexSet property NSPredicate : a reference to current application’s NSPredicate property NSScrollView : a reference to current application’s NSScrollView property NSTableView : a reference to current application’s NSTableView property NSTableColumn : a reference to current application’s NSTableColumn property NSPopUpButton : a reference to current application’s NSPopUpButton property NSMutableArray : a reference to current application’s NSMutableArray property NSRunningApplication : a reference to current application’s NSRunningApplication property NSCompoundPredicate : a reference to current application’s NSCompoundPredicate property NSModalPanelWindowLevel : a reference to current application’s NSModalPanelWindowLevel property NSAlertSecondButtonReturn : a reference to current application’s NSAlertSecondButtonReturn property theResult : 0 property returnCode : 0 property theDataSource : {} property tView : missing value property aDataList : {} property aSel : 0 property bSel : 0 property cSel : 0 property predList : {} property a1Button : missing value property a2Button : missing value property a3Button : missing value on displayCondTable() set (my theResult) to 0 –initialize set aDataList to {{field1:"MacBook Air", field2:119800, field3:"1.6GHzデュアルコアIntel Core i5(Turbo Boost使用時最大3.6GHz)、4MB L3キャッシュ"}, {field1:"MacBook Pro 13", field2:139800, field3:"1.4GHzクアッドコアIntel Core i5(Turbo Boost使用時最大3.9GHz)、128MB eDRAM"}, {field1:"MacBook Pro 15", field2:258800, field3:"2.6GHz 6コアIntel Core i7(Turbo Boost使用時最大4.5GHz)、12MB共有L3キャッシュ"}, {field1:"Mac mini", field2:122800, field3:"3.0GHz 6コアIntel Core i5 Turbo Boost使用時最大4.1GHz 9MB共有L3キャッシュ"}, {field1:"iMac 21.5", field2:120800, field3:"2.3GHzデュアルコアIntel Core i5(Turbo Boost使用時最大3.6GHz)"}, {field1:"iMac 4K 21.5", field2:142800, field3:"3.6GHzクアッドコアIntel Core i3"}, {field1:"iMac 5K 27", field2:198800, field3:"3.0GHz 6コア Intel Core i5(Turbo Boost使用時最大4.1GHz)"}, {field1:"iMac Pro", field2:558800, field3:"3.2GHz Intel Xeon W Turbo Boost使用時最大4.2GHz 19MBキャッシュ"}, {field1:"Mac Pro 2019", field2:599800, field3:"3.5GHz 8コアIntel Xeon Wプロセッサ(Turbo Boost使用時最大4.0GHz)"}} set paramObj to {myMessage:"項目の選択", mySubMessage:"適切なものを以下からえらんでください", aTableList:aDataList, aSortOrder:{"field1", "field2", "field3"}} –my chooseItemByTableView:paramObj –for debug my performSelectorOnMainThread:"chooseItemByTableView:" withObject:paramObj waitUntilDone:true return (my theResult) end displayCondTable on chooseItemByTableView:paramObj set aMainMes to myMessage of paramObj set aSubMes to mySubMessage of paramObj set aTList to (aTableList of paramObj) as list set labelSortList to (aSortOrder of paramObj) as list set aWidth to 800 set aHeight to 400 set my aSel to 0 set my bSel to 0 –Viewをつくる set parentView to NSView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight)) –BOX Aをつくる set aBox to (NSBox’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, aHeight – 60, aWidth, 60))) (aBox’s setTitle:("Filter Condition")) –このあたり、項目数に合わせてUIを可変で生成するように(本Scriptは試作品なので、決め打ちでUI生成) set a1Button to (NSPopUpButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, 200, 30)) pullsDown:false) a1Button’s removeAllItems() (a1Button’s addItemsWithTitles:{"▼Select Item", "MacBook", "iMac", "mini", "Air", "Pro"}) a1Button’s setTarget:(me) a1Button’s setAction:("mySelector:") a1Button’s setEnabled:(true) set a2Button to (NSPopUpButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(220, 0, 200, 30)) pullsDown:false) a2Button’s removeAllItems() (a2Button’s addItemsWithTitles:{"▼Select Item", "150000", "200000", "300000", "400000", "600000"}) a2Button’s setTarget:(me) a2Button’s setAction:("mySelector:") a2Button’s setEnabled:(true) set a3Button to (NSPopUpButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(440, 0, 200, 30)) pullsDown:false) a3Button’s removeAllItems() (a3Button’s addItemsWithTitles:{"▼Select Item", "デュアルコア", "クアッドコア", "6コア", "8コア"}) a3Button’s setTarget:(me) a3Button’s setAction:("mySelector:") a3Button’s setEnabled:(true) (aBox’s addSubview:a1Button) (aBox’s addSubview:a2Button) (aBox’s addSubview:a3Button) –BOX Bをつくる set bBox to (NSBox’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight – 80))) (bBox’s setTitle:("Data")) set aScroll to makeTableView(aTList, aWidth, aHeight – 150, labelSortList) of me (bBox’s addSubview:aScroll) parentView’s setSubviews:{aBox, bBox} — 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:(parentView) set myWindow to its |window| end tell myWindow’s setLevel:(NSModalPanelWindowLevel) — show alert in modal loop NSRunningApplication’s currentApplication()’s activateWithOptions:0 my performSelectorOnMainThread:"doModal:" withObject:(theAlert) waitUntilDone:true if (my returnCode) = 1001 then error number -128 set tmpResult to (aScroll’s documentView’s selectedRow()) + 1 set (my theResult) to contents of item tmpResult of ((my theDataSource) as list) end chooseItemByTableView: on doModal:aParam set (my returnCode) to (aParam’s runModal()) as number end doModal: –TableView Event Handlers on numberOfRowsInTableView:aView return (my theDataSource)’s |count|() end numberOfRowsInTableView: on tableView:aView objectValueForTableColumn:aColumn row:aRow set aRec to (my theDataSource)’s objectAtIndex:(aRow as number) set aTitle to (aColumn’s headerCell()’s title()) as string set aRes to (aRec’s valueForKey:aTitle) return aRes end tableView:objectValueForTableColumn:row: on makeTableView(aDicList, aWidth, aHeight, labelSortList) set aOffset to 40 set theDataSource to NSMutableArray’s alloc()’s init() theDataSource’s addObjectsFromArray:aDicList set aScroll to NSScrollView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, aOffset, aWidth, aHeight)) set tView to NSTableView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, aOffset, aWidth, aHeight)) set aLen to length of labelSortList repeat with i in labelSortList set j to contents of i set aColumn to (NSTableColumn’s alloc()’s initWithIdentifier:j) (aColumn’s setWidth:(aWidth div aLen)) (aColumn’s headerCell()’s setStringValue:j) (tView’s addTableColumn:aColumn) end repeat tView’s setDelegate:me tView’s setDataSource:me tView’s reloadData() aScroll’s setDocumentView:tView tView’s enclosingScrollView()’s setHasVerticalScroller:true aScroll’s setVerticalLineScroll:(30.0 as real) –1行目を選択 set aIndexSet to NSIndexSet’s indexSetWithIndex:0 tView’s selectRowIndexes:aIndexSet byExtendingSelection:false –強制的にトップにスクロール set aDBounds to aScroll’s documentView()’s |bounds|() if class of aDBounds = list then –macOS 10.13 or later set maxHeight to item 2 of item 1 of aDBounds else –macOS 10.10….10.12 set maxHeight to height of |size| of aDBounds end if set aPT to current application’s NSMakePoint(0.0, -1 * (maxHeight as real)) aScroll’s documentView()’s scrollPoint:aPT return aScroll end makeTableView on alertShowHelp:aNotification display dialog "Help Me!" buttons {"OK"} default button 1 with icon 1 return false –trueを返すと親ウィンドウ(アラートダイアログ)がクローズする end alertShowHelp: on mySelector:aObject set aIndex to (aObject’s indexOfSelectedItem()) as number filterByMultipleCondition() of me end mySelector: on filterByMultipleCondition() set prediCatesArray to {} set aInd to (my a1Button’s indexOfSelectedItem()) as number set bInd to (my a2Button’s indexOfSelectedItem()) as number set cInd to (my a3Button’s indexOfSelectedItem()) as number if {aInd, bInd, cInd} = {0, 0, 0} then set (my theDataSource) to NSMutableArray’s arrayWithArray:(my aDataList) tView’s reloadData() return end if –このあたり、複数条件をハードコーディングしているのは超絶頭悪い。項目数の増減に対応できるべき if aInd > 0 then set aTitle to (my a1Button’s title()) as string set the end of prediCatesArray to "field1 contains ’" & aTitle & "’" end if if bInd > 0 then set bTitle to (my a2Button’s title()) as string set the end of prediCatesArray to "field2.integerValue < " & bTitle end if if cInd > 0 then set cTitle to (my a3Button’s title()) as string set the end of prediCatesArray to "field3 contains ’" & cTitle & "’" end if –データ 抽出 set tmpList to filterDictArrayByLabel3((my aDataList), prediCatesArray) of me –データ 再表示 set (my theDataSource) to NSMutableArray’s arrayWithArray:(tmpList) tView’s reloadData() end filterByMultipleCondition –リストに入れたレコードを、指定の属性ラベルの値で抽出(複数PredicatesをANDで合成) on filterDictArrayByLabel3(origArray as list, aPredicateList as list) set aArray to NSMutableArray’s arrayWithArray:origArray set predArray to NSMutableArray’s new() repeat with i in aPredicateList (predArray’s addObject:(NSPredicate’s predicateWithFormat:(contents of i))) end repeat set pred to current application’s NSCompoundPredicate’s andPredicateWithSubpredicates:predArray set filteredArray to aArray’s filteredArrayUsingPredicate:pred return filteredArray end filterDictArrayByLabel3 end script |