I want to build my own dialog box, with my own button style, etc.
So I made a template for the box in the IB.
That makes, I can not use AS’s "set theAnswer to display dialog … " and “if button returned of theAnswer is …”
In my case I need a response of a button click in the dialog. In the documents I found only the ‘setAction’ instance for buttons. But it is not realy helpfull, because it let me not come back to the script for a further script flow.
Here is my attempt:
on myHandler()
-- Dialog for 2 or 3 buttons:
set theText to "Soll diese Namenliste auch in die Datenbank eingesetzt werden?"
set theIcon to "AlertCautionIcon"
set theWindowTitle to ""
set theFont to "Lucida Grande"
set theSize to 14
set theButton1Title to ""
set theButton2Title to "Nein"
set theButton3Title to "Einsetzen"
set theButton1setHidden to true
displayMyDialog(theText,theIcon,theWindowTitle,theFont,theSize,theButton1Title,theButton2Title,theButton3Title,theButton1setHidden)
(* There is no return for script flow !! It's a mouse trap.*)
end myHandler
on displayMyDialog(aText,anIcon,aWindowTitle,aFont,aSize,aButton1Title,aButton2Title,aButton3Title,button1setHidden)
dialogTextView's setStringValue_(aText)
dialogTextView's setFont_(current application's NSFont's fontWithName_size_(aFont, aSize))
dialogIcon's setImage_(current application's (NSImage's imageNamed_(anIcon)))
dialogWindow's setTitle_(aWindowTitle)
dialogButton1's setHidden_(button1setHidden)
dialogButton1's setTitle_(aButton1Title)
dialogButton2's setTitle_(aButton2Title)
dialogButton3's setTitle_(aButton3Title)
set dummy1 to dialogButton1's setAction_("button1")
set dummy2 to dialogButton2's setAction_("button2")
set dummy3 to dialogButton3's setAction_("button3")
dialogWindow's makeKeyAndOrderFront_(me)
end displayMyDialog
on button1()
--set buttonReturned to dialogButton1's title()
--log buttonReturned -- for testing
-- do nothing else
dialogWindow's orderOut_(me) -- close dialog
end button1
on button2()
--set buttonReturned to dialogButton2's title()
--log buttonReturned -- for testing
-- do nothing else
dialogWindow's orderOut_(me) -- close dialog
end button2
on button3()
set buttonReturned to dialogButton3's title()
--log "aButton3Title: " & buttonReturned -- for testing
dialogWindow's orderOut_(me) -- close dialog
-- do stuff:
listenWindow's makeKeyAndOrderFront_(me) -- call a window
oeffnenKursTitel() -- do stuff with it
namenWindow's makeKeyAndOrderFront_(me) -- call a 2. window
handleNamenListeEinfuegen2(theContents, theCount) -- do stuff with it
end button3
I see several problems in your code, but I don’t know what changes you made already – you should repost your updated code, and report what is wrong. Does clicking the buttons do what you expect?
One thing wrong are these lines:
setAction: has a return type of void so you shouldn’t be setting anything to them – should just be dialogButton1’s setAction_(“button1:”). But usually, you just connect the action method to the button in IB, rather than doing it in code.
When you say the it is not coming back to allow further script flow, where do you mean? Does it come back to myHandler or not (did you try a log statement at the end of myHandler to see if it is executed)?
To make it a bit more clearly, myHandler is not a handler of it’s own. It is just a part of a longer handler.
I tried up to now this:
-- Dialog for 2 or 3 buttons:
set theText to "Soll diese Namenliste auch in die Datenbank eingesetzt werden?"
set theIcon to "myAlertCaution"
set theWindowTitle to ""
set theFont to "Lucida Grande"
set theSize to 14
set theButton1Title to ""
set theButton2Title to "Nein"
set theButton3Title to "Einsetzen"
set theButton1setHidden to true
displayMyDialog(theText,theIcon,theWindowTitle,theFont,theSize,theButton1Title,theButton2Title,theButton3Title,theButton1setHidden)
(* There is no return for script flow !! It's a mouse trap.*)
log buttonReturned -- (null) but buttonReturned is set as a global property: missing value !
if buttonReturned is "Einfügen" then -- title of button 3
tell current application to beep
dialogWindow's orderOut_(me) -- close dialog
end if
on displayMyDialog(aText,anIcon,aWindowTitle,aFont,aSize,aButton1Title,aButton2Title,aButton3Title,button1setHidden)
--settings
dialogTextView's setStringValue_(aText)
dialogTextView's setFont_(current application's NSFont's fontWithName_size_(aFont, aSize))
dialogIcon's setImage_(current application's (NSImage's imageNamed_(anIcon)))
dialogWindow's setTitle_(aWindowTitle)
dialogButton1's setHidden_(button1setHidden)
dialogButton1's setTitle_(aButton1Title)
dialogButton2's setTitle_(aButton2Title)
dialogButton3's setTitle_(aButton3Title)
-- to get which button is clicked and send back
--set dummy1 to dialogButton1's setAction_("button1")
--set dummy2 to dialogButton2's setAction_("button2")
dialogWindow's makeKeyAndOrderFront_(me)
dialogButton1's setAction_("button1")
dialogButton2's setAction_("button2")
dialogButton3's setAction_("button3")
end displayMyDialog
-- for button 3 only:
on button3()
set buttonReturned to dialogButton3's title() -- buttonReturned is set as a property!
log "aButton3Title: " & buttonReturned -- mess.: "aButton3Title: Einsetzen" -- it's OK
-- return buttonReturned -- this doesn't work too
dialogWindow's orderOut_(me) -- dialog will not close
end button3
Meanwhile I’m not sure if the setAction instance is the correct one to solve that problem.
The setAction is fine, I think that you have a misunderstanding of how dialogs work. The standard display alert or display dialog commands, cause the code to stop executing until you press a button to dismiss the alert, so that the execution picks up with the next line. Your dialog box doesn’t do this – I’m not sure if there is an easy way to make the code pause until you dismiss your dialog. So, the way your code is right now, the “log buttonReturned” will get executed right after the call to displayMyDialog – it doesn’t wait until you push a button which is why it logs NULL.
One way to get around this is to put the code you want to start running after you press a button in a dialog in another handler that you call from a buttonPressed_(sender) handler. Notice that I have the same action set for all three buttons, and that the name buttonPressed: has a colon on the end So something like:
on applicationWillFinishLaunching_(aNotification)
set theText to "Soll diese Namenliste auch in die Datenbank eingesetzt werden?"
set theIcon to "myAlertCaution"
set theWindowTitle to ""
set theFont to "Lucida Grande"
set theSize to 14
set theButton1Title to ""
set theButton2Title to "Nein"
set theButton3Title to "Einsetzen"
set theButton1setHidden to true
displayMyDialog(theText, theIcon, theWindowTitle, theFont, theSize, theButton1Title, theButton2Title, theButton3Title, theButton1setHidden)
end applicationWillFinishLaunching_
on displayMyDialog(aText, anIcon, aWindowTitle, aFont, aSize, aButton1Title, aButton2Title, aButton3Title, button1setHidden)
dialogTextView's setStringValue_(aText)
dialogTextView's setFont_(current application's NSFont's fontWithName_size_(aFont, aSize))
dialogIcon's setImage_(current application's (NSImage's imageNamed_(anIcon)))
dialogWindow's setTitle_(aWindowTitle)
dialogButton1's setHidden_(button1setHidden)
dialogButton1's setTitle_(aButton1Title)
dialogButton2's setTitle_(aButton2Title)
dialogButton3's setTitle_(aButton3Title)
dialogWindow's makeKeyAndOrderFront_(me)
dialogButton1's setAction_("buttonPressed:")
dialogButton2's setAction_("buttonPressed:")
dialogButton3's setAction_("buttonPressed:")
end displayMyDialog
on buttonPressed_(sender) -- sender will be the button pressed
log sender's |title|()
dialogWindow's orderOut_(me)
resumeRestOfProgram_(sender's |title|())
end buttonPressed_
on resumeRestOfProgram_(buttonTitle)
if buttonTitle as string is "Einfügen" then
log "pressed button3"
--do what ever you want to happen next
else if buttonTitle as string is "Nein" then
log "pressed button2"
--do something else
end if
end resumeRestOfProgram_
That’s it!
Ric, your setAction-handler buttonPressed_(sender) is very fine. But the resumeRestOfProgram_(buttonTitle) handler doesn’t solve the problem realy, it is the next mouse trap.
The AS’s set display dialog to … is something like a function which gets one or more value(s) returned.
But how?
I think I should better go back to the pre-defined AS’s dialogs (at least now).
That’s right – it’s runModalForWindow:, after which only code triggered by the window or its buttons will run, until one of them sends stopModal or abortModal.
I’m not sure that running windows in modal mode will do what Heiner wants, although it could be used to make his dialog behave just like an applescript display dialog – because I’m not sure what he wants. What do you mean by " resumeRestOfProgram_(buttonTitle) is the next mouse trap". The code that I posted does return a value, the title of the button you pressed, and allows you to go on with the program based on that value. This is the same thing that an applescript display dialog does.
Running windows in modal mode prevent users from interacting with your main window until they do something in your dialog, but it sounds like your problem is not preventing the user from doing something, but with something not happening – your “mouse trap”. Perhaps you could describe how you want the program to flow after the user interacts with your dialog.
Well modal window starts a new event loop while the main event loop pauses. This also means that the command who started the new event loop (runModalForWindow) isn’t finished before the new event loop stops so it looks like the command is paused until stopModal command is given. This way dialogs can presented to the screen. If you have a popup button in your modal window you can simply connect that value with a property so even if the modal run is stopped you still can get the values.
so first you tell
on showDialog()
set theCode to runModalForWindow_(theWindow)
if theCode is 0 then
--button1 is pressed
return button1's |title|()
else if theCode is 1 then
--button2 is pressed
return button2's |title|()
else if theCode is 2 then
--button3 is pressed
return button3's |title|()
end if
end
on button1()
stopModalWithCode_(0) --for OK for instance
end
on button2()
stopModalWithCode_(1) --for cancel for instance
end
on button3()
stopModalWithCode_(2) --for other button for instance
end
p.s. there can be typos – behind a computer without xcode at the moment
Now the theCode is set above and then with some if statements you’ll now how the modal window has stopped.
It means I have lost some values set in the script above. Of course they can be set as global properties and then your idea will work properly. But DJ Bazzie Wazzie’s idea needs a global too (I think).
I did that:
...
-- Dialog for 2 or 3 buttons:
set theText to "Soll diese Namenliste auch in die Datenbank eingesetzt werden?"
set theIcon to "myAlertCaution"
set theWindowTitle to ""
set theFont to "Lucida Grande"
set theSize to 14
set theButton1Title to ""
set theButton2Title to "Nein"
set theButton3Title to "Einsetzen"
set theButton1setHidden to true
displayMyDialog(theText,theIcon,theWindowTitle,theFont,theSize,theButton1Title,theButton2Title,theButton3Title,theButton1setHidden)
if buttonReturned is "Einsetzen" then -- buttonReturned is a global property
listenWindow's makeKeyAndOrderFront_(sender)
oeffnenKursTitel()
namenWindow's makeKeyAndOrderFront_(sender)
handleNamenListeEinfuegen2(theContents, theCount)
else
-- do nothing; button "Nein"
end if
...
and later:
on displayMyDialog(aText,anIcon,aWindowTitle,aFont,aSize,aButton1Title,aButton2Title,aButton3Title,button1setHidden)
--settings
dialogTextView's setStringValue_(aText)
dialogTextView's setFont_(current application's NSFont's fontWithName_size_(aFont, aSize))
dialogIcon's setImage_(current application's (NSImage's imageNamed_(anIcon)))
dialogWindow's setTitle_(aWindowTitle)
dialogButton1's setHidden_(button1setHidden)
dialogButton1's setTitle_(aButton1Title)
dialogButton2's setTitle_(aButton2Title)
dialogButton3's setTitle_(aButton3Title)
set theCode to current application's NSApp's runModalForWindow_(dialogWindow)
if theCode is 1 then
-- button 1 is pressed
set buttonReturned to dialogButton1's |title|() as text
-- buttonReturned is a global for work flow above
else if theCode is 2 then
set buttonReturned to dialogButton2's |title|() as text
else if theCode is 3 then
set buttonReturned to dialogButton3's |title|() as text
end if
end displayMyDialog
on dialogButton1_(sender)
current application's NSApp's stopModalWithCode_(1)
dialogWindow's orderOut_(me)
end dialogButton1_
on dialogButton2_(sender)
current application's NSApp's stopModalWithCode_(2)
dialogWindow's orderOut_(me)
end dialogButton2_
on dialogButton3_(sender)
current application's NSApp's stopModalWithCode_(3)
dialogWindow's orderOut_(me)
end dialogButton3_