Using the Choose From List command of Standard Additions, I came across 2 significant flaws. 1) The first is the impossibility of obtaining the index of an element selected by the user (NOTE: list contains duplicates too). And I want to continue the process, starting with the selected list item and further, without returning to the already processed ones. 2) The second problem concerns the impossibility of customizing and adding buttons.
I asked for help in post Get index of element, chozen in choose from list dialog and got a positive solution from Shane Stanley - to use his “Myriad Tables Lib”. It solves the above problems fine, so I was interested in how Shane does it. Unfortunately, this script library is run-only, so I was not able to look into the “little secrets” of this library. Fortunately, I found another script that was written by a Japanese Takaaki Naganoya (Macscripter user maro). I edited it a bit and provide it here. The script does not use third-party software, although it may be slightly slower than the library from Shane Stanley. So, the script:
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
use framework "AppKit"
property |⌘| : a reference to current application
property aList : {3, "None", "Apple", 3, 4, "Chick", "Gyouza", "Snagi also", "Apple", "Peaches"}
property aMainMessage : "IMPROVED CHOOSE FROM LIST DIALOG"
property aSubMessage : "Please select the appropriate one from the following"
property theAlert : missing value
property theResult : 0
property returnCode : 0
property theDataSource : {}
my performSelectorOnMainThread:"createAlert" withObject:(missing value) waitUntilDone:true
my performSelectorOnMainThread:"displayAlert" withObject:(missing value) waitUntilDone:true
if theResult = (|⌘|'s NSAlertSecondButtonReturn) then error number -128
set aResult to my chooseItemByTableView()
on createAlert()
set my theAlert to |⌘|'s NSAlert's alloc()'s init()
my performSelectorOnMainThread:"displayAlert:" withObject:theAlert waitUntilDone:true
end createAlert
on chooseItemByTableView()
-- define the matrix size where you’ll put the radio buttons
set aScrollWithTable to makeTableView(300, 150) of me
-- set up alert
tell theAlert
its setMessageText:aMainMessage
its setInformativeText:aSubMessage
its addButtonWithTitle:"OK"
its addButtonWithTitle:"Cancel"
its setAccessoryView:aScrollWithTable
end tell
-- show alert in modal loop
|⌘|'s NSRunningApplication's currentApplication()'s activateWithOptions:0
my performSelectorOnMainThread:"doModal:" withObject:(theAlert) waitUntilDone:true
if (my returnCode as number) = 1001 then error number -128
return (aScrollWithTable's documentView's selectedRow()) + 1
end chooseItemByTableView
on doModal:aParam
set (my returnCode) to aParam's runModal()
end doModal:
on makeTableView(aWidth as number, aHeight as number)
set aOffset to 40
set sourceList to {}
repeat with i in aList
set the end of sourceList to {dataItem:(contents of i)}
end repeat
set theDataSource to |⌘|'s NSMutableArray's alloc()'s init()
theDataSource's addObjectsFromArray:sourceList
set aScroll to |⌘|'s NSScrollView's alloc()'s initWithFrame:(|⌘|'s NSMakeRect(0, aOffset, aWidth, aHeight))
set aView to |⌘|'s NSTableView's alloc()'s initWithFrame:(|⌘|'s NSMakeRect(0, aOffset, aWidth, aHeight))
set aColumn to (|⌘|'s NSTableColumn's alloc()'s initWithIdentifier:"dataItem")
(aColumn's setWidth:aWidth)
(aColumn's headerCell()'s setStringValue:"dataItem")
(aView's addTableColumn:aColumn)
aView's setDelegate:me
aView's setDataSource:me
aView's reloadData()
aScroll's setDocumentView:aView
aView's enclosingScrollView()'s setHasVerticalScroller:true
-- Select line
set aIndexSet to |⌘|'s NSIndexSet's indexSetWithIndex:0
aView's selectRowIndexes:aIndexSet byExtendingSelection:false
-- Force scroll to top
-- set maxHeight to aScroll’s documentView()’s |bounds|()’s |size|()’s height
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 aPoint to |⌘|'s NSMakePoint(0.0, -40.0)
aScroll's documentView()'s scrollPoint:aPoint
return aScroll
end makeTableView
-- TableView Event Handlers
on numberOfRowsInTableView:aView
return my theDataSource's |count|()
end numberOfRowsInTableView:
on tableView:aView objectValueForTableColumn:aColumn row:aRow
set aRecord to (my theDataSource)'s objectAtIndex:(aRow as number)
set aTitle to (aColumn's headerCell()'s title()) as string
set aResult to (aRecord's valueForKey:aTitle)
return aResult
end tableView:objectValueForTableColumn:row: