How to create a display dialog with scrollbars


Am trying to create an AppleScript program that uses a display dialog box that has scrollbars so you can see what is in a very long list of sometimes very wide items? And also is there a way to adjust the size of the display dialog that is created?

A Google search didn’t give much help so thought someone here might have a suggestion.

The AppleScript program I’m trying to write creates a sorted list of all Safari windows and tabs, and now want to display the list of them that would allow me to scroll around in, as well as be able to select a group of them and then copy to copy/paste buffer for pasting into another app as just text later. I can do some of what I want with a “set whichtab to choose from list of sortedlist” statement (it has scrollbars and lets you change window width and height, but only allows selecting of one item in the list – and I want to select any number or even all). If I try using a “display dialog” statement I get a very narrow dialog window (the list of items is typically much wider so one item spans several lines and makes it hard to read) but has no scrollbars and no ability to change window width and height. I’ve read about the trick of making a button name very wide using extra space characters in the name, but hoping that there is a better way.

Ideally, there would be a search button that allows me to find the first/next occurrence of any desired substring within the text items as well, but that’s not critical.

Ideas/suggestions are appreciated???


For displaying lists Standard Additions has choose from list.
It will display items of any length, and show a scrollbar when the display gets as tall as your screen.
You cannot copy from the list, so you’ll have to do that in your script.

How about this?

You can select multiple items in a choose-from-list dialog as follows:

set sortedList to {"a", "b", "c", "d"}
choose from list sortedList with multiple selections allowed

The above script returns a list, so you would need to format this list in some way before copying it to the clipboard. A simple example is:

set sortedList to {"a", "b", "c", "d"}
set selectedItems to choose from list sortedList with multiple selections allowed
set the clipboard to (selectedItems as text)
the clipboard -- to show contents of the clipboard not to include in the final script

Thanks to everyone for your suggestions…

peavine’s suggestion about using the “with multiple selections allowed” allows multiple selections as well as the scroll bar feature and the dialog window resizing, but the “Copy” item in the Edit menu is greyed out so can’t do anything with the selection except by writing more AppleScript to parse what is returned I would guess - so this is a possible solution.

maro’s program does not compile for me using either AppleScript Editor or Script Debugger (perhaps it would under Xcode ?), and since I’m just an AppleScript beginner, not sure what to do to even begin right now. Can you give a suggestion/hint on how to compile it? Thanks.

alastor933’s comment is what I had already tried, but thanks for trying to help.

Thanks again for all your input.

My programs on my blog have to click “★Click Here to Open This Script” link located at bottom of them.

The script written by Takaaki Naganoya contains some errors. So I fixed them. Working script:

use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
use framework "AppKit"

property NSAlert : a reference to current application's NSAlert
property NSIndexSet : a reference to current application's NSIndexSet
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 NSMutableArray : a reference to current application's NSMutableArray
property NSRunningApplication : a reference to current application's NSRunningApplication
property NSAlertSecondButtonReturn : a reference to current application's NSAlertSecondButtonReturn

property theAlert : missing value
property theResult : 0
property returnCode : 0
property theDataSource : {}

on createAlert()
	-- Create an alert
	set my theAlert to current application's NSAlert's alloc()'s init()
	my performSelectorOnMainThread:"displayAlert:" withObject:theAlert waitUntilDone:true
end createAlert

my performSelectorOnMainThread:"createAlert" withObject:(missing value) waitUntilDone:true
my performSelectorOnMainThread:"displayAlert" withObject:(missing value) waitUntilDone:true
if theResult = (current application's NSAlertSecondButtonReturn) then error number -128

set paramObj to {myMessage:"Item selection", mySubMessage:"Please select the appropriate one from the following", aTableList:{"None", "Apple", "Chick", "Gyouza", "Snagi also", "Alone", "Peaches"}}
set aRes to my chooseItemByTableView:paramObj

on chooseItemByTableView:paramObj
	set aMainMes to myMessage of paramObj
	set aSubMes to mySubMessage of paramObj
	set aTList to (aTableList of paramObj) as list
	-- define the matrix size where you’ll put the radio buttons
	set aScrollWithTable to makeTableView(aTList, 300, 150) of me
	-- set up alert
	tell theAlert
		its setMessageText:aMainMes
		its setInformativeText:aSubMes
		its addButtonWithTitle:"OK"
		its addButtonWithTitle:"Cancel"
		its setAccessoryView:aScrollWithTable
	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
	return (aScrollWithTable's documentView's selectedRow()) + 1
end chooseItemByTableView:

on doModal:aParam
	set (my returnCode) to aParam's runModal()
end doModal:

on makeTableView(aList as list, 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 NSMutableArray's alloc()'s init()
	theDataSource's addObjectsFromArray:sourceList
	set aScroll to NSScrollView's alloc()'s initWithFrame:(current application's NSMakeRect(0, aOffset, aWidth, aHeight))
	set aView to NSTableView's alloc()'s initWithFrame:(current application's NSMakeRect(0, aOffset, aWidth, aHeight))
	set aColumn to (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 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
		-- macOS 10.10….10.12
		set maxHeight to height of |size| of aDBounds
	end if
	set aPT to current application's NSMakePoint(0.0, -40.0) -- (aScroll’s documentView()’s |bounds|()’s |size|()’s height))
	aScroll's documentView()'s scrollPoint:aPT
	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 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:

Thank you for your confirmation. The script I wrote had to run with Command-Control-R on Script Editor to run in “foreground” (main thread) :slight_smile:

I’m grad to see many scripters use cocoa-scripting. It is my pleasure!! (Maybe Shane, too)

P.S. Your Japanese-English translation seems wrong. I’ll show the right answer.

before: aTableList:{“None”, “Apple”, “Chick”, “Gyouza”, “Snagi also”, “Alone”, “Peaches”}

after: aTableList:{“Peach”, “Apple”, “Chick”, “Chinese dumpling”, “Chiken’s gizzard”, “Chicken’s Hip”, “Chicken’s thigh”}

The last 3 items are included in “Yakitori”, grilled chicken skewered on a bamboo stick.

Japanese language is very strange, having very few phoneme (about 100). So, we have a lot of homonym.