Progress bars, incrementors – can we expect those?


Will progress bars, incrementors and sliders be ever added to the Dialog Toolkit+?

No. Apart from anything else, I want to keep the amount of code to a size that avoids potential problems.

I wrote it in 7 years ago.



You script crashed Script Editor on my system (Mojave). Additionally, I didn’t succeed finding its classes and commands dictionary. Is it a script or a script library?

I ensured that my script runs on macOS 12.5beta. You have to run this script with Script Editor and operate Control-Command-R to execute this script in main thread.

It is a script calling cocoa functions. After macOS 10.10, we can use most of macOS’s APIs directly from AppleScript.

So, you can generate a window without other application’s help.

@Piyomaru I tested this both in Script Debugger and Script Editor and it fails on

(aWin's initWithContentRect:aFrame styleMask:aBacking backing:aDefer defer:false screen:aScreen)

with error
NSWindow drag regions should only be invalidated on the Main Thread!

You have to understand a function to run script in main thread with Script Editor.
Normal script execution command is command-r .
Main thread execution is control-command-r. OK?

Doesn’t run in 10.14.6 for me. Crashes Script Editor and Reports the error in Debugger. Isn’t there a way to perform it on main thread? I tried playing with code but no luck.

Another macOS 10.14.6 env can run this script without any crash. I ensured now.

I believe it likely runs on another copy of Mojave you have. It may just be my copy or the fact I had Script Debugger running also. Can you recommend code change to ensure it always runs in main thread?

I tried simply changing this:

(aWin's initWithContentRect:aFrame styleMask:aBacking backing:aDefer defer:false screen:aScreen)

to this:

    if NSThread's isMainThread() as boolean then
		(aWin's initWithContentRect:aFrame styleMask:aBacking backing:aDefer defer:false screen:aScreen)
		my performSelectorOnMainThread:"progressBarTest:" withObject:{aFrame, aBacking, aDefer, false, aScreen} waitUntilDone:true
	end if

and adding this to end:

on progressBarTest:theArg
set {aFrame, styleMask, backing, defer, screen} to theArg as list

set aWin to NSWindow's alloc()
(aWin's initWithContentRect:aFrame styleMask:aBacking backing:aDefer defer:false screen:(aScreen))
return aWin

end progressBarTest:

With no success. Your work is excellent and appreciate all of your contributions to our world! Any recommendation is appreciated.

This is modified version of my script ( I forgot ).

-- Created 2015-12-11 by Takaaki Naganoya
-- 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"

property NSWindowController : a reference to current application's NSWindowController
property NSWindow : a reference to current application's NSWindow

property windisp : false
property aPBar : missing value
property aWin : missing value

set aWidth to 400
set aHeight to 40

set aMaxVal to 100
set aButtonMSG to "Abort"
set aTitle to "Progress..."

--set aWin to makeProgressWindow(aMaxVal, aButtonMSG, aTitle, aWidth, aHeight) of me
set paramObj to {myMax:aMaxVal, myMSG:aButtonMSG, myTitle:aTitle, myWidth:aWidth, myHeight:aHeight}
my performSelectorOnMainThread:"makeProgressWindow:" withObject:(paramObj) waitUntilDone:true

repeat with i from 1 to aMaxVal by 1
	if (my windisp) = false then
		exit repeat
	end if
	(aPBar's setDoubleValue:(i as real))
	--call main routine here
	delay 0.1
end repeat

if i is not equal to aMaxVal then
	tell current application
		display notification "Aborted"
	end tell
end if
my closeWin:aWin
set my aPBar to missing value
set aWin to missing value

on makeProgressWindow:paramObj
	set aMaxVal to (myMax of paramObj) as integer
	set aButtonMSG to (myMSG of paramObj) as string
	set aTitle to (myTitle of paramObj) as string
	set aWidth to (myWidth of paramObj) as integer
	set aHeight to (myHeight of paramObj) as integer
	set (my windisp) to true
	set aSlider to makeProgressIndicator(aMaxVal, aWidth) of me
	set bButton to (current application's NSButton's alloc()'s initWithFrame:(current application's NSMakeRect(aWidth / 4, 0, aWidth / 2, 40)))
	bButton's setTitle:aButtonMSG
	bButton's setButtonType:(current application's NSMomentaryLightButton)
	bButton's setBezelStyle:(current application's NSRoundedBezelStyle)
	bButton's setTarget:me
	bButton's setAction:("clicked:")
	set aView to current application's NSView's alloc()'s initWithFrame:(current application's NSMakeRect(0, 0, aWidth, aHeight))
	aView's addSubview:aSlider
	aView's addSubview:bButton
	aView's setNeedsDisplay:true
	set (my aWin) to (my makeDockLevelWinWithView(aView, 400, 70, aTitle))
	set wController to NSWindowController's alloc()
	wController's initWithWindow:aWin
	(my aWin)'s makeFirstResponder:aView
	wController's showWindow:me
	(my aWin)'s makeKeyAndOrderFront:me
end makeProgressWindow:

on clicked:aSender
	set (my windisp) to false
end clicked:

--make Window for Display
on makeDockLevelWinWithView(aView, aWinWidth, aWinHeight, aTitle)
	set aScreen to current application's NSScreen's mainScreen()
	set aFrame to {{0, 0}, {aWinWidth, aWinHeight}}
	set aBacking to current application's NSTitledWindowMask
	set aDefer to current application's NSBackingStoreBuffered
	-- Window
	set aWin to current application's NSWindow's alloc()
	(aWin's initWithContentRect:aFrame styleMask:aBacking backing:aDefer defer:false screen:aScreen)
	aWin's setTitle:aTitle
	aWin's setDelegate:me
	aWin's setDisplaysWhenScreenProfileChanges:true
	aWin's setHasShadow:true
	aWin's setIgnoresMouseEvents:false
	aWin's setLevel:(current application's NSDockWindowLevel)
	aWin's setOpaque:false
	aWin's setReleasedWhenClosed:true
	aWin's |center|()
	aWin's makeKeyAndOrderFront:(me)
	aWin's setContentView:aView
	return aWin
end makeDockLevelWinWithView

--close win
on closeWin:aWindow
	repeat with n from 10 to 1 by -1
		(aWindow's setAlphaValue:n / 10)
		delay 0.02
	end repeat
	aWindow's |close|()
end closeWin:

--make progress indicator
on makeProgressIndicator(aMaxNum, aWidth)
	set aPBar to current application's NSProgressIndicator's alloc()'s initWithFrame:(current application's NSMakeRect(0, 40, aWidth, 40))
	aPBar's setMaxValue:aMaxNum
	aPBar's setMinValue:1
	aPBar's setIndeterminate:false
	aPBar's setControlSize:(current application's NSProgressIndicatorPreferredLargeThickness)
	aPBar's setDoubleValue:(1.0 as real)
	return aPBar
end makeProgressIndicator

Nice! Thank you. Works great!

The AS-ObjC may become indigestible for users with a little to no experience in AS-ObjC or lacking entirely thereof. Could you compile the command syntax as the standard sdef to make it readable in Script Editor dictionary viewer?

Once, Shane had such a great trial in his Myriad Helpers before OS X 10.10 era.

But sdef can not return NSObject values. I/O must be AppleScript native values or objects.
If sdef could pass through NSObjects, the operability might be more better.
Cocoa world is too large to wrap with sdef. And productivity might be lower by wrapping with sdef.

I made and use Script Editor’s context menu assistant including 570 scripts.
It is called Piyomaru Script Assistant.

It pastes various Cocoa-Scripting snipets inlcuded in script objects.

If there is some supporters to this product, I’ll translate the messages into English and support Script Debugger.

In some case you can work around this by returning script objects, and storing the Cocoa values as properties of the script object.

lol It is a big surprise. I’ll check it!

Actually, the demand may be already answered so there’s no need for the separate development of progress bars.

Per Apple documentation, since Yosemite AppleScript has got 4 new properties: progress total steps, progress completed steps, progress description and progress additional description.


I have been trying to insert a sub message into the progress bar without success above the bar. Could you suggest how I can do this in your above code?

Also in response to your question. I’m sure there would be supporters of this translated for script debugger!