Tuesday, September 26, 2017

#1 2017-02-25 03:24:48 pm

t.spoon
Member
From:: BFE, Massachusetts
Registered: 2013-01-13
Posts: 202

Change elements dynamically using Shane's Dialog Toolkit?

I've been messing around with it and am thinking the answer is probably "no," but I'm wondering if there's a way to have the selection in one UI element control the contents of another using Shane's Dialog Toolkit? (or any other way)

https://www.macosxautomation.com/apples … logToolkit

Here's a screenshot of what I'm trying to replicate:
https://www.dropbox.com/s/tupsftxoqfkl2 … g.png?dl=0

In that dialog, the second UI element, "Step 2," is blank when the dialog comes up, and the options are populated based on what was selected from the dropdown in Step 1.

I haven't been able to figure out a way to do anything like this in Applescript, but thought it wouldn't hurt to ask.

It also looks like an equivalent to AS's "Choose from list" isn't available in Dialog Toolkit, which is how "Step 2" in that screeshot functions. However, while it's unfortunate the required mouse targeting is more precise, it looks like I could just use "create labeled matrix" with the "with arranged vertically" argument to get pretty close. But I would have to have different sets of options for that and populate them based on the selection in the "Step 1" drop-down.

(BTW, I just found Dialog Toolkit and can't believe I didn't know about it earlier, I've done a lot of searches looking for anything like a modern replacement for Facespan, looking at X-Code & Smile, etc, and I even have Shane's book and still had somehow failed to come across this library until now. It's incredibly useful. So thanks again, Shane, if you're reading this.)


Hackintosh built February, 2012 |  Mac OS Sierra
GIGABYTE GA-Z68X-UD3H-B3 | Core i5 2500k | 16 GB DDR3 | GIGABYTE Geforce 1050 TI 4GB
250 GB Samsung 850 EVO | 4 TB RAID
Dell Ultrasharp U3011 | Dell Ultrasharp 2007FPb

Offline

 

#2 2017-02-25 08:50:03 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5136

Re: Change elements dynamically using Shane's Dialog Toolkit?

t.spoon wrote:

I'm wondering if there's a way to have the selection in one UI element control the contents of another using Shane's Dialog Toolkit? (or any other way)


Once you head down that road, moving to Xcode starts to make more sense. Nonetheless, you can do what you want in Dialog Toolkit. Let's say you keep the first popup, and make the second list another popup whose content changes when a selection is made from the first.

Each control is a subclass of NSResponder, which means they respond to user interaction. And the way they respond is defined by two things: the action, which is what you want to happen, and the target, which is the object that contains the code you want to be run.

So for your first popup you need to set the target:

Applescript:

thePopup's setTarget:me

And then the action. The action is the name of the method/handler to be called, and must take a single argument -- a reference to the control is passed as this argument. So something like:

Applescript:

thePopup's setAction:"rebuildList:"

Then you need to add the handler. You will also need to make sure the variable representing the second control is a property, so you can access it within the handler. You handler might be like this:

Applescript:

on rebuildList:sender -- sender is the popup
set theTitle to sender's titleOfSelectedItem() as text
my secondPopup's removeAllItems() -- secondPopup is a property
if theTitle = "Whatever" then
my secondPopup's addItemsWithTitles:{"One", "Two", "Three"}
else
my secondPopup's addItemsWithTitles:{"Four", "Five", "Six"}
...

If you look at Chapter 27 in my book, you can see something similar in the accessory view checkbox sample.


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#3 2017-02-25 09:26:19 pm

t.spoon
Member
From:: BFE, Massachusetts
Registered: 2013-01-13
Posts: 202

Re: Change elements dynamically using Shane's Dialog Toolkit?

Fantastic! I won't have a chance to mess with it again until Monday, but this looks very promising.

As always, thanks.

- Tom.


Hackintosh built February, 2012 |  Mac OS Sierra
GIGABYTE GA-Z68X-UD3H-B3 | Core i5 2500k | 16 GB DDR3 | GIGABYTE Geforce 1050 TI 4GB
250 GB Samsung 850 EVO | 4 TB RAID
Dell Ultrasharp U3011 | Dell Ultrasharp 2007FPb

Offline

 

#4 2017-03-13 04:06:06 pm

t.spoon
Member
From:: BFE, Massachusetts
Registered: 2013-01-13
Posts: 202

Re: Change elements dynamically using Shane's Dialog Toolkit?

I finally found time to dig into this again.

Changing the selection on the first popup is not changing the options on the matrix after it, which is what I'm going for.

When I click "OK," I get the error:

"Stopped: (Error: missing value doesn't understand the "title" message)
the AppleEvent was not handled by any handler (errAEEventNotHandled:-1708)"

Probably a simple stupid mistake on my end, but I'm a total noob with AS Obj C.

Any pointers on where I've gone wrong?

I'll have some other dialogs with variable data in the future, so can you point me toward the place to discover the syntax for things like "removeAllItems" and "addItemsWithTitles" ? Those are not things I would have known how to find.

Thanks,

Tom.

Applescript:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

use script "Dialog Toolkit" version "2.0"

property printAreaMatrix : {}

set theTop to -10

set theSavePath to "Fill This in Later"

set orderList to {"234567 - Bob Roberts - QTY: 6", "345678 - Bob Plant - QTY: 10,000", "456789 - Marshmellow Fiddlesticks - QTY: 1"}

set listOfTabLists to {{"Tab 1 - Front - Screen Print - Qty:1", "Tab 1 - Back - DTG - Qty:1"}, {"Tab 1 - Front - Screen Print - Qty:50", "Tab 1 - Back - DTG - Qty:50", "Tab 2 - Front - Screen Print - Qty:100", "Tab 2 - Back - Digital Vinyl - Qty:100", "Tab 3 - Front - Screen Print - Qty:1,000", "Tab 3 - Back - Screen Print - Qty:1,000"}}

set theProductionMethods to {"SP - Screen Printing", "DTG - Direct To Garment", "EMB - Embroidery", "DV - Digital Vinyl", "VIN - Regular Vinyl"}

set theLabelStrings to {"ORDER:", "PRINT AREA:", "OPTIONAL - Override Production Method:", "OPTIONAL - Edit Print Area Name:", "Your File Save Path Will Be:"}



set {thePath, theTop} to create label theSavePath left inset 0 bottom (theTop + 10) max width 400 aligns left without multiline

set {thePathLabel, theTop} to create label (item 5 of theLabelStrings) left inset 0 bottom (theTop + 10) max width 400 aligns left without multiline

set {fileNameField, fileNameLabel, theTop, fieldLeft} to create side labeled field "" placeholder text "Rt Sleeve" left inset 0 bottom (theTop + 10) total width 400 label text (item 4 of theLabelStrings) field left 0

set {printMethodPopup, printMethodLabel, theTop} to create labeled popup theProductionMethods left inset 0 bottom theTop + 10 popup width 200 max width 400 label text (item 3 of theLabelStrings) popup left 0

set {printAreaMatrix, printAreaMatrixLabel, theTop, matrixLeft} to create labeled matrix item 2 of listOfTabLists left inset 0 bottom theTop + 10 max width 400 matrix left 0 label text (item 2 of theLabelStrings) with arranged vertically

set {orderPopup, orderLabel, theTop} to create labeled popup orderList left inset 0 bottom theTop + 10 popup width 400 max width 400 label text (item 1 of theLabelStrings) popup left 0

orderPopup's setTarget:me
orderPopup's setAction:"setOrderList:"


set allControls to {orderPopup, orderLabel, printAreaMatrix, printAreaMatrixLabel, printMethodPopup, printMethodLabel, fileNameField, fileNameLabel, thePathLabel, thePath}

set {buttonName, suppressedState, controlsResults} to display enhanced alert "Send for output" message "" as informational alert buttons {"Cancel", "OK"} giving up after 120 acc view width 500 acc view height theTop acc view controls allControls without suppression

on setOrderList(sender, listOfTabLists)
   set currentSelection to sender's titleOfSelectedItem() as text
   my printAreaMatrix's removeAllItems()
   if currentSelection is "234567 - Bob Roberts - QTY: 6" then
       my (printAreaMatrix's addItemsWithTitles:(item 1 of listOfTabLists))
   else
       my (printAreaMatrix's addItemsWithTitles:(item 2 of listOfTabLists))
   end if
end setOrderList


Hackintosh built February, 2012 |  Mac OS Sierra
GIGABYTE GA-Z68X-UD3H-B3 | Core i5 2500k | 16 GB DDR3 | GIGABYTE Geforce 1050 TI 4GB
250 GB Samsung 850 EVO | 4 TB RAID
Dell Ultrasharp U3011 | Dell Ultrasharp 2007FPb

Offline

 

#5 2017-03-13 06:14:55 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5136

Re: Change elements dynamically using Shane's Dialog Toolkit?

You have a couple of problems.

First, action handlers have a fixed format: they can only take a single argument, which is the sender:

Applescript:

on setOrderList:sender

Second, matrixes don't support removeAllItems or addItemsWithTitles: -- they're for popups.  You will probably have to rename existing entries and add/remove extras. Changing the number of entries in a matrix is generally a bad move, because it's also likely to change the size of the whole dialog, which can appear disconcerting. I think you'd be better to have another popup instead.

It's also worth having Console running while you debug stuff with action handler. Then you see entries like this:

*** -[BAGenericObjectNoDeleteOSAID setOrderList:]: -[NSMatrix removeAllItems]: unrecognized selector sent to instance 0x7f88c0b93630 (error -10000)

I'll have some other dialogs with variable data in the future, so can you point me toward the place to discover the syntax for things like "removeAllItems" and "addItemsWithTitles" ? Those are not things I would have known how to find.


You need to search on the name of the class of the control -- they'll be listed among the control's methods (or its superclass's methods). If you use Script Debugger, its code-completion can also help by providing the correct options is some cases.


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#6 2017-03-15 06:06:19 pm

t.spoon
Member
From:: BFE, Massachusetts
Registered: 2013-01-13
Posts: 202

Re: Change elements dynamically using Shane's Dialog Toolkit?

Thanks so much Shane, I've got that working great now.

The other thing I need to update to get through this dialog is the last label in my dialog window, named "thePath."

I've been searching, I'm not finding commands for changing that beyond "setStringValue:"

I did Google up other people with issues changing that - saying it doesn't update just by changing the value, but their solutions immediately get waay over my head.

http://www.cocoabuilder.com/archive/coc … perly.html

It's my "on setThePath:sender" handler that's not doing anything.

Any help? Any other ASObjC users following along who wants to give Shane a break and give me a hint?

I apologize for having not found time to read Shane's book yet, perhaps I could spare you all from my questions.

Thanks,

Tom.

Applescript:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

use script "Dialog Toolkit" version "2.0"

property listOfTabLists : {}
property orderList : {}

set theTop to -10

set theSavePath to "Fill This in Later"

set orderList to {"234567 - Bob Roberts - QTY: 6", "345678 - Bob Plant - QTY: 10,000", "456789 - Marshmellow Fiddlesticks - QTY: 1"}

set listOfTabLists to {{"Tab 1 - Front - Screen Print - Qty:1", "Tab 1 - Back - DTG - Qty:1"}, {"Tab 1 - Front - Screen Print - Qty:50", "Tab 1 - Back - DTG - Qty:50", "Tab 2 - Front - Screen Print - Qty:100", "Tab 2 - Back - Digital Vinyl - Qty:100", "Tab 3 - Front - Screen Print - Qty:1,000", "Tab 3 - Back - Screen Print - Qty:1,000"}, {"Tab 1 - Front - Blank - Qty:1"}}

set theProductionMethods to {"SP - Screen Printing", "DTG - Direct To Garment", "EMB - Embroidery", "DV - Digital Vinyl", "VIN - Regular Vinyl"}

set theLabelStrings to {"ORDER:", "PRINT AREA:", "OPTIONAL - Override Production Method:", "OPTIONAL - Edit Print Area Name:", "Your File Save Path Will Be:"}



set {thePath, theTop} to create label theSavePath left inset 0 bottom (theTop + 10) max width 400 aligns left without multiline

set {thePathLabel, theTop} to create label (item 5 of theLabelStrings) left inset 0 bottom (theTop + 10) max width 400 aligns left without multiline

set {fileNameField, fileNameLabel, theTop, fieldLeft} to create side labeled field "" placeholder text "Rt Sleeve" left inset 0 bottom (theTop + 10) total width 400 label text (item 4 of theLabelStrings) field left 0

set {printMethodPopup, printMethodLabel, theTop} to create labeled popup theProductionMethods left inset 0 bottom theTop + 10 popup width 200 max width 400 label text (item 3 of theLabelStrings) popup left 0

set {printAreaPopop, printAreaPopupLabel, theTop, matrixLeft} to create labeled popup (item 1 of listOfTabLists) left inset 0 bottom theTop + 10 popup width 300 max width 400 label text (item 2 of theLabelStrings) popup left 0

set {orderPopup, orderLabel, theTop} to create labeled popup orderList left inset 0 bottom theTop + 10 popup width 400 max width 400 label text (item 1 of theLabelStrings) popup left 0

orderPopup's setTarget:me
orderPopup's setAction:"setOrderList:"
printAreaPopop's setTarget:me
printAreaPopop's setAction:"setThePath:"


set allControls to {orderPopup, orderLabel, printAreaPopop, printAreaPopupLabel, printMethodPopup, printMethodLabel, fileNameField, fileNameLabel, thePathLabel, thePath}

set {buttonName, suppressedState, controlsResults} to display enhanced alert "Send for output" message "" as informational alert buttons {"Cancel", "OK"} giving up after 120 acc view width 500 acc view height theTop acc view controls allControls without suppression

on setThePath:sender
   my thePath's setStringValue("Updated String")
end setThePath:

on setOrderList:sender
   set currentSelection to sender's titleOfSelectedItem() as text
   set orderChoosen to item 1 of my list_positions(orderList, currentSelection)
   my printAreaPopop's removeAllItems()
   my (printAreaPopop's addItemsWithTitles:(item orderChoosen of listOfTabLists))
end setOrderList:

on list_positions(this_list, this_item)
   set the offset_list to {}
   repeat with i from 1 to the count of this_list
       if item i of this_list is this_item then
           set the end of the offset_list to i
       end if
   end repeat
   return the offset_list
end list_positions


Hackintosh built February, 2012 |  Mac OS Sierra
GIGABYTE GA-Z68X-UD3H-B3 | Core i5 2500k | 16 GB DDR3 | GIGABYTE Geforce 1050 TI 4GB
250 GB Samsung 850 EVO | 4 TB RAID
Dell Ultrasharp U3011 | Dell Ultrasharp 2007FPb

Offline

 

#7 2017-03-15 06:18:37 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5136

Re: Change elements dynamically using Shane's Dialog Toolkit?

You have a couple of simple problems. First, you use "my thePath", implying thePath is a property, but you don't declare it as such. I think you need to, and add the "my" when you first use it. The second issue is syntax:

Applescript:

my thePath's setStringValue:"Updated String"


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#8 2017-03-15 07:39:15 pm

t.spoon
Member
From:: BFE, Massachusetts
Registered: 2013-01-13
Posts: 202

Re: Change elements dynamically using Shane's Dialog Toolkit?

Does the use of "my" imply it's a property? I thought it just allowed you to access top-level script objects from inside a handler.

Applescript:

set bob to "some text"
do_something()

on do_something()
   display dialog my bob
end do_something

works.

I had made printAreaPopop a property per your suggestion, but in modifying the script I had accidentally deleted the property declaration, and then later was surprised to see it still worked.

Simply changing the syntax to what you just provided:

my thePath's setStringValue:"Updated String"

made it work.

So thank you again, I certainly should have noticed that error.

I'm pretty sure I've got all the basic functionality I'm going to need now to make it all work,

- Tom.


Hackintosh built February, 2012 |  Mac OS Sierra
GIGABYTE GA-Z68X-UD3H-B3 | Core i5 2500k | 16 GB DDR3 | GIGABYTE Geforce 1050 TI 4GB
250 GB Samsung 850 EVO | 4 TB RAID
Dell Ultrasharp U3011 | Dell Ultrasharp 2007FPb

Offline

 

#9 2017-03-15 07:48:57 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5136

Re: Change elements dynamically using Shane's Dialog Toolkit?

t.spoon wrote:

Does the use of "my" imply it's a property? I thought it just allowed you to access top-level script objects from inside a handler.


Ignore that. I was mis-reading your code and thinking it was defined within a handler.

Simply changing the syntax to what you just provided:

my thePath's setStringValue:"Updated String"

made it work.


FWIW, if you had Console running with your eariler version, you would have seen entries like this:

Applescript:

-[NSTextField setStringValue]: unrecognized selector sent to instance 0x7f88c0bc6af0

That tells you there's something wrong with the method you're using.

I'm pretty sure I've got all the basic functionality I'm going to need now to make it all work


Great.


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#10 2017-03-15 08:28:24 pm

t.spoon
Member
From:: BFE, Massachusetts
Registered: 2013-01-13
Posts: 202

Re: Change elements dynamically using Shane's Dialog Toolkit?

I did have console running and saw the message. I'd used it's output to debug the 1st part. But I didn't know what to make out of that message in terms of knowing how to fix my code.

Thanks for the tip re: console,

- Tom.


Hackintosh built February, 2012 |  Mac OS Sierra
GIGABYTE GA-Z68X-UD3H-B3 | Core i5 2500k | 16 GB DDR3 | GIGABYTE Geforce 1050 TI 4GB
250 GB Samsung 850 EVO | 4 TB RAID
Dell Ultrasharp U3011 | Dell Ultrasharp 2007FPb

Offline

 

#11 2017-04-18 05:47:53 pm

t.spoon
Member
From:: BFE, Massachusetts
Registered: 2013-01-13
Posts: 202

Re: Change elements dynamically using Shane's Dialog Toolkit?

My dialog is huge and complicated now, and overwhelmingly working really well.

This is non-essential, it would be possible for me to compile an extensive list of what people might want to type in this situation, and use a pop-up instead of a text field.

But it would be nice if I could use the text-field...

At the bottom of my dialog I've got a non-editable, script-updated text field showing information on what's going to happen when the user clicks "OK" based on what they've input.

It's all working great except with one user-modifiable text-field. I can only get it to update the information at the bottom to include the contents of the text field iff the user changes a popup after changing the text field. This will be confusing to the user, that the information shown at the bottom will not reflect the text they've input unless they change [any unrelated UI element in the dialog] after filling in the text field.

Here's a simplified script showing the problem:

(the real script just has way too many dependencies to post / modify)

Applescript:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
use script "Dialog Toolkit" version "2.0"


property fileNameField : {}

set {aPopup, theTop} to create popup {"1st Item", "2nd Item"} left inset 0 bottom 0 popup width 200

set {thePathLabel, theTop} to create label "Modified Text" left inset 0 bottom (theTop + 10) max width 400 aligns left without multiline

set {fileNameField, fileNameLabel, theTop, fieldLeft} to create side labeled field "" placeholder text "Enter Text Here" left inset 0 bottom (theTop + 10) total width 400 label text "OPTIONAL - Edit Print Area Name:" field left 0

fileNameField's setTarget:me
fileNameField's setAction:"changePathText:"

aPopup's setTarget:me
aPopup's setAction:"changePathText:"

set {buttonName, suppressedState, controlsResults} to display enhanced alert "Test" message "" as informational alert buttons {"Cancel", "OK"} giving up after 120 acc view width 600 acc view height (theTop + 10) acc view controls {fileNameField, thePathLabel, aPopup} without suppression

on changePathText:sender
   set fileNameAddendum to fileNameField's stringValue()
   my (thePathLabel's setStringValue:fileNameAddendum)
end changePathText:

Inputting text into the text field does not change the value shown in the "thePathLabel" field. However, changing the popup after modifying the text field does change "thePathLabel." So it's reading and writing the values OK, it just appears  that the lines:

Applescript:

fileNameField's setTarget:me
fileNameField's setAction:"changePathText:"

Aren't sufficient to detect a change to the text field and trigger the handler.

I was looking at this:
http://stackoverflow.com/questions/7010 … ange-event
and this:
http://stackoverflow.com/questions/1738 … om-control

But was unable to figure out how to incorporate them into Applescript. Any help?

While I'm here:

When using my script, Console frequently logs:

This application is modifying the autolayout engine from a background thread after the engine was accessed from the main thread. This can lead to engine corruption and weird crashes.


Should I be worried about this / is there a way to fix it?

Also, I'm not quite done with the dialog yet, but so far in testing it works fine when run from Script Debugger or Script Editor, but if I put it on a FastScripts key command then FastScripts just crashes. I haven't done anything to investigate that myself yet, and if I can't solve it, I can address it in a separate post (or ask Daniel), but thought I'd throw it out here in case there's some easy thing "everybody knows" like "when running ASObjC from FastScripts, you have to do [x] to keep it from crashing."

Thanks,

Tom.

Last edited by t.spoon (2017-04-18 06:27:42 pm)


Hackintosh built February, 2012 |  Mac OS Sierra
GIGABYTE GA-Z68X-UD3H-B3 | Core i5 2500k | 16 GB DDR3 | GIGABYTE Geforce 1050 TI 4GB
250 GB Samsung 850 EVO | 4 TB RAID
Dell Ultrasharp U3011 | Dell Ultrasharp 2007FPb

Offline

 

#12 2017-04-18 08:19:32 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5136

Re: Change elements dynamically using Shane's Dialog Toolkit?

t.spoon wrote:

It's all working great except with one user-modifiable text-field. I can only get it to update the information at the bottom to include the contents of the text field iff the user changes a popup after changing the text field.


Actually, it's updated when the user leaves the text field -- the action is called when the user finishes editing.

To have it update each time the text changes, you can use a text field delegate method. So replace this:

Applescript:

fileNameField's setTarget:me
fileNameField's setAction:"changePathText:"

with this:

Applescript:

fileNameField's setDelegate:me

And then add this handler:

Applescript:

on controlTextDidChange:notif
   set fileNameAddendum to fileNameField's stringValue()
   my (thePathLabel's setStringValue:fileNameAddendum)
end controlTextDidChange:


Anything that refers to UI-prefixed classes instead of NS-prefixed classes is for iOS, not macOS. There are similarities, but also big differences.

When using my script, Console frequently logs:

This application is modifying the autolayout engine from a background thread after the engine was accessed from the main thread. This can lead to engine corruption and weird crashes.


Should I be worried about this / is there a way to fix it?


This should only happen when you're testing. Strictly speaking I'm playing a bit loose with threading, but it shouldn't matter. The solution makes things a lot more complicated.

if I put it on a FastScripts key command then FastScripts just crashes.


That shouldn't happen. Please email me the actual script and crash info.


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#13 2017-04-27 05:18:47 pm

t.spoon
Member
From:: BFE, Massachusetts
Registered: 2013-01-13
Posts: 202

Re: Change elements dynamically using Shane's Dialog Toolkit?

Thanks once again.

The text-updating is working brilliantly now. I rewrote a lot of what I had now that I've wrapped my head around Dialog Toolkit and the ASObjC components better.

Anybody:

On the script, it keeps getting much better, but I keep coming up with some additional case I have trouble solving.

This example shows it working great:

Applescript:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
use script "Dialog Toolkit" version "2.0"


property ordersNmethods : {}

set ordersNmethods to {theOrders:{"Please Make a Selection", "Order Number 1, Production Method 2", "Order Number 2, Production Method 5"}, theMethods:{missing value, 2, 5}}

set {methodPopup, methodPopupLabel, theTop, matrixLeft} to create labeled popup {"1 - Some Method", "2 - Another Method", "3 - Still More Methods", "4 - The Rhythm Method", "5 - Methodical"} left inset 0 bottom 0 popup width 200 max width 400 label text "Override Method" popup left 0

set {orderPopup, orderPopupLabel, theTop, matrixLeft} to create labeled popup (theOrders of ordersNmethods) left inset 0 bottom (theTop + 20) popup width 200 max width 400 label text "Choose an Order" popup left 0

orderPopup's setTarget:me
orderPopup's setAction:"setMethod:"

set {buttonName, suppressedState, controlsResults} to display enhanced alert "Test" message "" as informational alert buttons {"Cancel", "OK"} giving up after 120 acc view width 700 acc view height (theTop + 10) acc view controls {methodPopup, orderPopup} without suppression

on setMethod:sender
   set selectedOrderIndex to (my orderPopup's indexOfSelectedItem() as integer) + 1
   set orderMethod to item selectedOrderIndex of theMethods of ordersNmethods
   my (methodPopup's selectItemAtIndex:(orderMethod - 1))
end setMethod:

So in the dialog, the user needs to select which order they're working on. They occasionally need to override the default "production method" set in the system. I need the default production method field to populate with the default, and it's easy to do that when the user makes a selection for which order they're working on. So that's great.

The problem is that sometimes there's only one option for what order they could conceivably be working on. That happens a lot. In that case, I don't want the options on the top popup to start with "Please Make a Selection" like they do above, I just want that popup to be pre-selected with the only option so they don't have to waste time making a selection off a list with one option.

But I still need the production method field to update to the method of the single option showing in the first popup.

So when the data looks like this:

Applescript:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
use script "Dialog Toolkit" version "2.0"


property ordersNmethods : {}

set ordersNmethods to {theOrders:{"Order Number 1, Production Method 2"}, theMethods:{2}}

set {methodPopup, methodPopupLabel, theTop, matrixLeft} to create labeled popup {"1 - Some Method", "2 - Another Method", "3 - Still More Methods", "4 - The Rhythm Method", "5 - Methodical"} left inset 0 bottom 0 popup width 200 max width 400 label text "Override Method" popup left 0

set {orderPopup, orderPopupLabel, theTop, matrixLeft} to create labeled popup (theOrders of ordersNmethods) left inset 0 bottom (theTop + 20) popup width 200 max width 400 label text "Choose an Order" popup left 0

orderPopup's setTarget:me
orderPopup's setAction:"setMethod:"

set {buttonName, suppressedState, controlsResults} to display enhanced alert "Test" message "" as informational alert buttons {"Cancel", "OK"} giving up after 120 acc view width 700 acc view height (theTop + 10) acc view controls {methodPopup, orderPopup} without suppression

on setMethod:sender
   set selectedOrderIndex to (my orderPopup's indexOfSelectedItem() as integer) + 1
   set orderMethod to item selectedOrderIndex of theMethods of ordersNmethods
   my (methodPopup's selectItemAtIndex:(orderMethod - 1))
end setMethod:

I need the second popop ("Override Method") to come up with the method of the single, default order already selected.

The only way I could figure out how to do this is: when there's only a single order choice, then reorder the Production Method list so the correct choice is at the top of the list.

But this isn't a good option, because the users are used to these appearing in a certain order everywhere, and people are going to make incorrect selections when they're out-of-order.

I'm concerned that this possibility is excluded with Dialog Toolkit because it looks to me like a "selectItemAtIndex:" or "selectItemWithTitle:" would need to be called at the time of Dialog Toolkit's "display enhanced alert" call - Dialog Toolkit would need to accept a "default option" argument as a parameter of "create labeled popup." Applescript, of course, comes to a stop from when it calls "display enhanced alert" until the dialog is dismissed, unless an option is chosen in the dialog to trigger a handler.

I can possibly do something clunky like, before calling "display enhanced alert" call a "selectItemAtIndex:" inside a delay with an "ignoring application responses," but that sounds like it's asking for trouble. Especially since my real dialog retrieves information off the web to populate the dialog, introducing a large variation in the time for the dialog to load.

Any ideas?


Shane: I PM'd you a link to download the whole thing to take a look at the FastScripts issue.

I've had three modes of failure there:

At first, it was just crashing - nothing would happen, and if I clicked on the Fastscripts widget in the menu bar the menu would't come down, no Fastscripts scripts would run, and I'd have to force quit and relaunch it to get it to do anything.

Then it switched to opening a "Scripting Error" window that just says "Error Number: -1

Unknown error."

And at least once, it gave me an error that said something like ["Unable to use" or "Unable to load"] "framework "Foundation"" That's the only remotely helpful error I've received, although it still seems like an odd error to me.


Hackintosh built February, 2012 |  Mac OS Sierra
GIGABYTE GA-Z68X-UD3H-B3 | Core i5 2500k | 16 GB DDR3 | GIGABYTE Geforce 1050 TI 4GB
250 GB Samsung 850 EVO | 4 TB RAID
Dell Ultrasharp U3011 | Dell Ultrasharp 2007FPb

Offline

 

#14 2017-04-27 07:21:35 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5136

Re: Change elements dynamically using Shane's Dialog Toolkit?

t.spoon wrote:

Any ideas?


It sounds like you need to make a custom version of Dialog Toolkit that allows you to set the selected popup item.

Shane: I PM'd you a link to download the whole thing to take a look at the FastScripts issue.


It's behaving for me. One thing to keep in mind with FastScripts:

* It uses a single instance of AppleScript. This means that once it loads a lib, if you ever modify that lib, you need to restart FastScripts.


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#15 2017-04-27 08:11:20 pm

t.spoon
Member
From:: BFE, Massachusetts
Registered: 2013-01-13
Posts: 202

Re: Change elements dynamically using Shane's Dialog Toolkit?

Well that's fascinating.

I had restarted FastScripts plenty of times. I still get the crashes.

So... either it was a system difference, or it was the one change I made to send the script to  you - I commented out that handler that gets information on the open orders from our in-house CRM/ERP system in Chrome, and just made the function return dummy values.

So... it's that function. Fastscripts runs the version I sent you just fine. It crashes when I un-comment out that dialog and have it get the info from Chrome.

So clearly, it's not related to Dialog Toolkit.

Since it runs fine from Script Debugger and Script Editor, I'll bring it up with Daniel.

Is editing Dialog Toolkit to accept this as straight-forward as I'm thinking? Add a "default selection" term to the handler, and feed it to a "selectItemAtIndex:" argument?

If it's OK with you for me to dig into Dialog Toolkit and use a modified version, I'd be happy to give that a shot.

Thanks again,

- Tom.

Last edited by t.spoon (2017-04-27 08:11:50 pm)


Hackintosh built February, 2012 |  Mac OS Sierra
GIGABYTE GA-Z68X-UD3H-B3 | Core i5 2500k | 16 GB DDR3 | GIGABYTE Geforce 1050 TI 4GB
250 GB Samsung 850 EVO | 4 TB RAID
Dell Ultrasharp U3011 | Dell Ultrasharp 2007FPb

Offline

 

#16 2017-04-27 09:08:38 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5136

Re: Change elements dynamically using Shane's Dialog Toolkit?

t.spoon wrote:

If it's OK with you for me to dig into Dialog Toolkit and use a modified version, I'd be happy to give that a shot.


Of course! Probably the safest way is to add a whole new handler, thus keeping compatibility with any existing stuff. And if it's only for your use, you can make it a normal handler without terminology.


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#17 2017-05-01 03:32:41 pm

t.spoon
Member
From:: BFE, Massachusetts
Registered: 2013-01-13
Posts: 202

Re: Change elements dynamically using Shane's Dialog Toolkit?

FYI, Shane is on vacation, if anyone else wants to look this over.

Right off the bat my new handler seemed to be doing great. I went ahead and modified the dictionary to add terminology for it. (I'll show the original and my modified versions in each post here for comparison):

<command name="create popup" code="!ASuCrPo" description="Create a popup menu with a default item selected.">
            <direct-parameter description="A list of menu item names.">
                <type type="text" list="yes">
                </type>
            </direct-parameter>
            <parameter name="left inset" description="How much to inset the control from the left of the accessory view." code="!Lli" optional="NO">
                <type type="integer">
                </type>
            </parameter>
            <parameter description="The distance from the bottom of the accessory view to the bottom of the control." name="bottom" code="!BtM" optional="NO">
                <type type="integer">
                </type>
            </parameter>
            <parameter description="Width of the popup menu." name="popup width" code="!PuW" optional="NO">
                <type type="integer">
                </type>
            </parameter>
            <result description="A list containing the popup, and the distance from the top of the popup to the bottom of the accessory view.">
                <type type="any" list="yes">
                </type>
            </result>
        </command>
        <command name="create popup with default" code="!ASuCrPd" description="Create a popup menu.">
            <direct-parameter description="A list of menu item names.">
                <type type="text" list="yes">
                </type>
            </direct-parameter>
            <parameter name="left inset" description="How much to inset the control from the left of the accessory view." code="!Lli" optional="NO">
                <type type="integer">
                </type>
            </parameter>
            <parameter description="The distance from the bottom of the accessory view to the bottom of the control." name="bottom" code="!BtM" optional="NO">
                <type type="integer">
                </type>
            </parameter>
            <parameter description="Width of the popup menu." name="popup width" code="!PuW" optional="NO">
                <type type="integer">
                </type>
            </parameter>
            <parameter description="Default menu item selection by index" name="default selection" code="!DFW" optional="NO">
                <type type="integer">
                </type>
            </parameter>
            <result description="A list containing the popup, and the distance from the top of the popup to the bottom of the accessory view.">
                <type type="any" list="yes">
                </type>
            </result>
        </command>


Then I saved the dictionary and added the handler:

Applescript:

on create popup entryList left inset theLeft bottom theBottom popup width theWidth
   set thePopup to current application's NSPopUpButton's alloc()'s initWithFrame:(current application's NSMakeRect(theLeft, theBottom, theWidth, 26)) pullsDown:false
   thePopup's addItemsWithTitles:entryList
   return {thePopup, theBottom + 26}
end create popup


on create popup with default entryList left inset theLeft bottom theBottom popup width theWidth default selection defaultSelection
   set thePopup to current application's NSPopUpButton's alloc()'s initWithFrame:(current application's NSMakeRect(theLeft, theBottom, theWidth, 26)) pullsDown:false
   thePopup's addItemsWithTitles:entryList
   thePopup's selectItemAtIndex:defaultSelection
   return {thePopup, theBottom + 26}
end create popup with default

Gave it a try:

Applescript:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
use script "Dialog Toolkit ROT"


set designsForDisplay to {"1-option", "2-option", "3-option"}



set {_printAreaPopop, theTop} to create popup with default designsForDisplay left inset 0 bottom 0 popup width 300 default selection 2

display enhanced alert "Select Your Print Area" message "" as informational alert buttons {"Cancel", "OK"} giving up after 120 acc view width 700 acc view height theTop acc view controls {_printAreaPopop} without suppression

And success! Works perfectly.

So then I made a modified version of "create labeled popup" to add the default:

<command name="create labeled popup" code="!ASuCrPl" description="Create a popup menu with a label.">
            <direct-parameter description="A list of menu item names.">
                <type type="text" list="yes">
                </type>
            </direct-parameter>
            <parameter name="left inset" description="How much to inset the labeled control from the left of the accessory view." code="!Lli" optional="NO">
                <type type="integer">
                </type>
            </parameter>
            <parameter description="The distance from the bottom of the accessory view to the bottom of the control." name="bottom" code="!BtM" optional="NO">
                <type type="integer">
                </type>
            </parameter>
            <parameter description="Width of the popup menu." name="popup width" code="!PuW" optional="NO">
                <type type="integer">
                </type>
            </parameter>
            <parameter description="Maximum width of the label plus control." name="max width" code="!MxW" optional="NO">
                <type type="integer">
                </type>
            </parameter>
            <parameter description="Contents of the label." name="label text" code="!LtX" optional="NO">
                <type type="text">
                </type>
            </parameter>
            <parameter description="How much to inset the popup from the accessory view's left. If less than 'left inset' value, it will be ignored." name="popup left" code="!PuL" optional="NO">
                <type type="integer">
                </type>
            </parameter>
            <result description="A list containing the popup, the label, the distance from the top of the popup to the bottom of the accessory view, and the distance from the popup to the left of the accessory view.">
                <type type="any" list="yes">
                </type>
            </result>
        </command>
        <command name="create labeled popup with default" code="!ASuCrPe" description="Create a popup menu with a label and a default selection.">
            <direct-parameter description="A list of menu item names.">
                <type type="text" list="yes">
                </type>
            </direct-parameter>
            <parameter name="left inset" description="How much to inset the labeled control from the left of the accessory view." code="!Lli" optional="NO">
                <type type="integer">
                </type>
            </parameter>
            <parameter description="The distance from the bottom of the accessory view to the bottom of the control." name="bottom" code="!BtM" optional="NO">
                <type type="integer">
                </type>
            </parameter>
            <parameter description="Width of the popup menu." name="popup width" code="!PuW" optional="NO">
                <type type="integer">
                </type>
            </parameter>
            <parameter description="Maximum width of the label plus control." name="max width" code="!MxW" optional="NO">
                <type type="integer">
                </type>
            </parameter>
            <parameter description="Contents of the label." name="label text" code="!LtX" optional="NO">
                <type type="text">
                </type>
            </parameter>
            <parameter description="How much to inset the popup from the accessory view's left. If less than 'left inset' value, it will be ignored." name="popup left" code="!PuL" optional="NO">
                <type type="integer">
                </type>
            </parameter>
            <parameter description="Default menu item selection by index" name="default selection" code="!DFW" optional="NO">
                <type type="integer">
                </type>
            </parameter>
            <result description="A list containing the popup, the label, the distance from the top of the popup to the bottom of the accessory view, and the distance from the popup to the left of the accessory view.">
                <type type="any" list="yes">
                </type>
            </result>
        </command>


Added the handler:

Applescript:

on create labeled popup entryList left inset theLeft bottom theBottom popup width popupWidth max width theWidth label text theLabel popup left popupLeft
   if popupLeft ≤ theLeft then
       set {theLabel, theTop, newWidth} to create label theLabel left inset theLeft bottom (theBottom + 6) max width theWidth aligns "left" without multiline
       set popupLeft to (newWidth + 6)
       set {thePopup, theTop} to create popup entryList left inset popupLeft bottom theBottom popup width popupWidth
   else
       set {theLabel, theTop, newWidth} to create label theLabel left inset theLeft bottom (theBottom + 6) max width (popupLeft - theLeft - 6) aligns "right" without multiline
       set {thePopup, theTop} to create popup entryList left inset popupLeft bottom theBottom popup width popupWidth
   end if
   return {thePopup, theLabel, theTop, popupLeft}
end create labeled popup

on create labeled popup with default entryList left inset theLeft bottom theBottom popup width popupWidth max width theWidth label text theLabel popup left popupLeft default selection defaultSelection
   if popupLeft ≤ theLeft then
       set {theLabel, theTop, newWidth} to create label theLabel left inset theLeft bottom (theBottom + 6) max width theWidth aligns "left" without multiline
       set popupLeft to (newWidth + 6)
       set {thePopup, theTop} to create popup with default entryList left inset popupLeft bottom theBottom popup width popupWidth default selection defaultSelection
   else
       set {theLabel, theTop, newWidth} to create label theLabel left inset theLeft bottom (theBottom + 6) max width (popupLeft - theLeft - 6) aligns "right" without multiline
       set {thePopup, theTop} to create popup with default entryList left inset popupLeft bottom theBottom popup width popupWidth default selection defaultSelection
   end if
   return {thePopup, theLabel, theTop, popupLeft}
end create labeled popup with default

Call it:

Applescript:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
use script "Dialog Toolkit ROT"


set designsForDisplay to {"1-option", "2-option", "3-option"}



set {_printAreaPopop, printMethodLabel, theTop} to create labeled popup with default designsForDisplay left inset 0 bottom 0 popup width 200 max width 400 label text "OPTIONAL - Override Production Method:" popup left 0 default selection 2

display enhanced alert "Select Your Print Area" message "" as informational alert buttons {"Cancel", "OK"} giving up after 120 acc view width 700 acc view height theTop acc view controls {_printAreaPopop} without suppression

and... nothing.

I've been over it and over it and just can't find my error... I just don't see why calling "create popup with default" works when called directly, but "create labelled popup with default" doesn't work to set the default.

I've had Console open, but it doesn't log anything.

Any help?

If you want to download my modified version of Dialog Toolkit for testing so you don't have to paste in all my edits, I put it here:
https://www.dropbox.com/s/67mnhmlm9scyz … d.zip?dl=0

Since the first function works, I feel like I must have some very stupid mistake.

Thanks in advance,

- Tom.


Hackintosh built February, 2012 |  Mac OS Sierra
GIGABYTE GA-Z68X-UD3H-B3 | Core i5 2500k | 16 GB DDR3 | GIGABYTE Geforce 1050 TI 4GB
250 GB Samsung 850 EVO | 4 TB RAID
Dell Ultrasharp U3011 | Dell Ultrasharp 2007FPb

Offline

 

#18 2017-05-02 03:11:47 pm

t.spoon
Member
From:: BFE, Massachusetts
Registered: 2013-01-13
Posts: 202

Re: Change elements dynamically using Shane's Dialog Toolkit?

Shane messaged me to try putting the call to the handler straight into the library, and run it from Script Editor while holding down Control. I did that - and it worked - the correct choice was selected.

So I tried if from Script Editor as a separate script - and it worked. So I went back to Script debugger - and now it works there as well.

So it didn't work because ??? I haven't changed anything.

But now it's working, so at least that's the good news. Probably something just needed to be restarted to make it work, and now it's a new day, so whatever it was is restarted now. I wasn't running the script from Fastscripts, but from Script Debugger, which I didn't think cached libraries. But whatever it was, now everything's working without actually changing anything.

Thanks again for all the help, Shane.

- Tom.


Hackintosh built February, 2012 |  Mac OS Sierra
GIGABYTE GA-Z68X-UD3H-B3 | Core i5 2500k | 16 GB DDR3 | GIGABYTE Geforce 1050 TI 4GB
250 GB Samsung 850 EVO | 4 TB RAID
Dell Ultrasharp U3011 | Dell Ultrasharp 2007FPb

Offline

 

#19 2017-05-04 08:41:01 am

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5136

Re: Change elements dynamically using Shane's Dialog Toolkit?

Tom,

You're misunderstanding how library caching works. Libraries are cached per component instance of AppleScript. So an app like FastScripts uses a single instance for all scripts, which means you need to relaunch it if you modify a library.

Script Debugger (and Script Editor) uses a separate instance for each document, and each time you compile, it creates a new instance. But if you modify a library and then re-run a calling script without recompiling, the document's instance will still use the cached version.

Short version: when you modify a library, you should dirty and recompile any calling script to clear any caching.


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#20 2017-05-08 05:37:48 pm

t.spoon
Member
From:: BFE, Massachusetts
Registered: 2013-01-13
Posts: 202

Re: Change elements dynamically using Shane's Dialog Toolkit?

Good news: the FastScripts crash was tracked down to a bug that had cropped up on that individual script related to Script Debugger. Simply copying and pasting the code into a new Script Debugger document fixed the issue.

I'd like to find a way to disable clicking "OK" and only allow clicking "Cancel" until an acceptable set of choices have been made in the dialog.

I was hoping with a reference to the button I could just put handlers that do
[reference to button]  setEnabled:no
[reference to button]  setEnabled:yes

or is it setState:true ?

But I can't figure out how to reference the button.

Each UI element I make to go into the "display enhanced dialog" argument has a variable that's a reference to it:

Applescript:

set {aPopop, printAreaPopupLabel, theTop, matrixLeft} to create labeled popup ...

so I can send commands to this feature by addressing "aPopop's [whatever]"

But the buttons are created in the "display enhanced alert" argument, but no variable is set to represent the alert dialog itself.

Do I need to make a modified version of "display enhanced alert" that returns a fourth argument, "theAlert"?

So my Applescript would look like:

Applescript:


set {aPopop, printAreaPopupLabel, theTop, matrixLeft} to create labeled popup {"One", "Two", "Three"} left inset 0 bottom 0 popup width 300 max width 400 label text "Selection" popup left 0
aPopop's setTarget:me
aPopop's setAction:"setActive:"
set {buttonName, suppressedState, controlsResults, alertReference} to display enhanced alert "Title Text" message "" as informational alert buttons {"Cancel", "OK"} giving up after 120 acc view width 700 acc view height theTop acc view controls {aPopop} without suppression
on setActive:sender
   -- my (alertReference's [reference button by name?] setState:false
end setActive:

Please let me know if I'm on the right track at all here,

Thanks,

Tom.


Hackintosh built February, 2012 |  Mac OS Sierra
GIGABYTE GA-Z68X-UD3H-B3 | Core i5 2500k | 16 GB DDR3 | GIGABYTE Geforce 1050 TI 4GB
250 GB Samsung 850 EVO | 4 TB RAID
Dell Ultrasharp U3011 | Dell Ultrasharp 2007FPb

Offline

 

#21 2017-05-09 01:47:30 am

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5136

Re: Change elements dynamically using Shane's Dialog Toolkit?

Do I need to make a modified version of "display enhanced alert" that returns a fourth argument, "theAlert"?


probably. Then use something like:

Applescript:

(theAlert's |buttons|()'s objectAtIndex:0)'s setEnabled:false

And you must do that on the main thread.


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#22 2017-05-10 12:20:37 pm

t.spoon
Member
From:: BFE, Massachusetts
Registered: 2013-01-13
Posts: 202

Re: Change elements dynamically using Shane's Dialog Toolkit?

Thanks for helping out even when you're on vacation!

Here's what I've got:

Applescript:


use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
use script "Dialog Toolkit ROT"


set {aPopop, printAreaPopupLabel, theTop, matrixLeft} to create labeled popup {"One", "Two", "Three"} left inset 0 bottom 0 popup width 300 max width 400 label text "Selection" popup left 0

aPopop's setTarget:me
aPopop's setAction:"setActive:"


set {buttonName, suppressedState, controlsResults, theAlert} to display enhanced alert with return reference "The Title" message "" as informational alert buttons {"Cancel", "OK"} giving up after 120 acc view width 700 acc view height theTop acc view controls {aPopop} without suppression


on setActive:sender
   my ((theAlert's |buttons|()'s objectAtIndex:0)'s setEnabled:false)
end setActive:

And so far I've been running it on the main thread by running it from Script Editor with [control]. I figured I'd move it back to Script Debugger and figure out how to run it in the main thread there after I have it working.

Currently, it does not disable, and console logs:

*** -[BAGenericObjectNoDeleteOSAID setActive:]: {} doesn’t understand the “buttons” message. (error -1708)


I'm used to using UI Browser or Accessibility Inspector to browse UI's for Applescript UI scripting, but don't know how to figure out how to properly refer to UI elements in AS Obj C.

- Tom.


Hackintosh built February, 2012 |  Mac OS Sierra
GIGABYTE GA-Z68X-UD3H-B3 | Core i5 2500k | 16 GB DDR3 | GIGABYTE Geforce 1050 TI 4GB
250 GB Samsung 850 EVO | 4 TB RAID
Dell Ultrasharp U3011 | Dell Ultrasharp 2007FPb

Offline

 

#23 2017-05-10 01:19:50 pm

t.spoon
Member
From:: BFE, Massachusetts
Registered: 2013-01-13
Posts: 202

Re: Change elements dynamically using Shane's Dialog Toolkit?

So... I was thinking about this some more, and am wondering if there isn't a "catch 22" here...

Applescript:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
use script "Dialog Toolkit ROT"


set {aPopop, printAreaPopupLabel, theTop, matrixLeft} to create labeled popup {"One", "Two", "Three"} left inset 0 bottom 0 popup width 300 max width 400 label text "Selection" popup left 0

aPopop's setTarget:me
aPopop's setAction:"setActive:"


set {buttonName, suppressedState, controlsResults, theAlert} to display enhanced alert with return reference "The Title" message "" as informational alert buttons {"Cancel", "OK"} giving up after 120 acc view width 700 acc view height theTop acc view controls {aPopop} without suppression

set someVariable to (theAlert's |buttons|()'s objectAtIndex:0)

return someVariable

on setActive:sender
   my ((theAlert's |buttons|()'s objectAtIndex:0)'s setEnabled:false)
end setActive:

This still gets the same error, but here it returns

«class ocid» id «data optr00000000F0C0150080610000»


so that looks to me like it's finding "(theAlert's |buttons|()'s objectAtIndex:0)"

So I was thinking about my addition of returning a reference, and I'm thinking that this doesn't actually work with order-of-operations here...

All the variables set when the "display enhanced alert with return reference" command is called aren't going to be set until that handler in the dictionary completes and returns to executing the script, right? So "theAlert" isn't defined in my script until the user has clicked "OK." But the "setActive:" handler is being called and using the "theAlert" variable before that dialog is returned.

If that's correct, then I'm thinking that, rather than simply modifying "display enhanced alert" to be "display enhanced alert with return reference" and return the "theAlert" variable the handler used, I need to construct an alternate version of "display enhanced alert" that first just returns what's constructed as "theAlert," then I need to call that separately.

I'll take a look at doing that. I feel like this has to be the problem. I should have thought of this.


Hackintosh built February, 2012 |  Mac OS Sierra
GIGABYTE GA-Z68X-UD3H-B3 | Core i5 2500k | 16 GB DDR3 | GIGABYTE Geforce 1050 TI 4GB
250 GB Samsung 850 EVO | 4 TB RAID
Dell Ultrasharp U3011 | Dell Ultrasharp 2007FPb

Offline

 

#24 2017-05-10 03:36:52 pm

t.spoon
Member
From:: BFE, Massachusetts
Registered: 2013-01-13
Posts: 202

Re: Change elements dynamically using Shane's Dialog Toolkit?

Hooray!

It seems I correctly identified the problem and solution.

New functions in library:

Applescript:

on return enhanced alert mainText message theExplanation as styleType buttons buttonsList suppression showSuppression acc view width theWidth acc view height theHeight acc view controls controlsList
   if styleType = critical alert then
       set styleNum to 2
   else if styleType = warning alert then
       set styleNum to 0
   else
       set styleNum to 1
   end if
   set theError to current application's AEInteractWithUser(-1, missing value, missing value) -- -1 is kAEDefaultTimeout
   if theError is not 0 then
       error "User interaction disallowed" number theError
   end if
   -- make the accessory view
   set theAccessoryView to current application's NSView's alloc()'s initWithFrame:(current application's NSMakeRect(0, 0, theWidth, theHeight))
   theAccessoryView's setSubviews:controlsList
   -- reverse buttons because they get added in reverse order cf AS
   set buttonsList to reverse of buttonsList
   -- create an alert
   set theAlert to current application's NSAlert's alloc()'s init()
   -- set up alert
   tell theAlert
       its setAlertStyle:styleNum
       its setMessageText:mainText
       its setInformativeText:theExplanation
       repeat with anEntry in buttonsList
           (its addButtonWithTitle:anEntry)
       end repeat
       its setShowsSuppressionButton:showSuppression
       its setAccessoryView:theAccessoryView
       its (|window|()'s setAutorecalculatesKeyViewLoop:true)
   end tell
   set alertRecord to {theAlert:theAlert, controlsList:controlsList, buttonsList:buttonsList}
   return {alertRecord}
end return enhanced alert

on show returned alert alert reference alertRecord giving up after giveUp
   set theAlert to theAlert of alertRecord
   set controlsList to controlsList of alertRecord
   set buttonsList to buttonsList of alertRecord
   -- if giveUp value > 0, tell the app to abort any modal event loop after that time, and thus close the panel
   if giveUp > 0 then current application's NSApp's performSelector:"abortModal" withObject:(missing value) afterDelay:giveUp inModes:{current application's NSModalPanelRunLoopMode}
   -- show alert in modal loop on main thread
   my performSelectorOnMainThread:"showTheAlert:" withObject:theAlert waitUntilDone:true
   --    if a giveUp time was specified and the alert didn't timeout, cancel the pending abort request
   if giveUp > 0 and returnCode is not current application's NSModalResponseAbort then current application's NSObject's cancelPreviousPerformRequestsWithTarget:(current application's NSApp) selector:"abortModal" object:(missing value)
   -- get values after alert is closed
   set suppressedState to theAlert's suppressionButton()'s state() as boolean
   set buttonNumber to returnCode mod 1000 + 1 -- where 1 = right-most button
   if buttonNumber = 0 then
       set buttonName to "Gave Up"
   else
       set buttonName to item buttonNumber of buttonsList
   end if
   -- get values from controls
   set controlResults to {}
   repeat with aControl in controlsList
       if (aControl's isKindOfClass:(current application's NSTextField)) as boolean then
           set end of controlResults to aControl's stringValue() as text
       else if (aControl's isKindOfClass:(current application's NSPopUpButton)) as boolean then
           set end of controlResults to aControl's titleOfSelectedItem() as text
       else if (aControl's isKindOfClass:(current application's NSButton)) as boolean then
           set end of controlResults to aControl's state() as boolean
       else if (aControl's isKindOfClass:(current application's NSPathControl)) as boolean then
           set end of controlResults to aControl's |URL|()'s |path|() as text
       else if (aControl's isKindOfClass:(current application's NSMatrix)) as boolean then
           set end of controlResults to aControl's selectedCell()'s title() as text
       else -- NSBox
           set end of controlResults to missing value
       end if
   end repeat
   return {buttonName, suppressedState, controlResults}
end show returned alert

new test script:

Applescript:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
use script "Dialog Toolkit ROT"

property alertRecord : {}

set {aPopop, printAreaPopupLabel, theTop, matrixLeft} to create labeled popup {"One", "Two", "Three"} left inset 0 bottom 0 popup width 300 max width 400 label text "Selection" popup left 0

aPopop's setTarget:me
aPopop's setAction:"setActive:"



set {alertRecord} to return enhanced alert "The Title" message "" as informational alert buttons {"Cancel", "OK"} acc view width 700 acc view height theTop acc view controls {aPopop} without suppression

set {buttonName, suppressedState, controlsResults} to show returned alert alert reference alertRecord giving up after 120


on setActive:sender
   set theAlert to theAlert of alertRecord
   ((theAlert's |buttons|()'s objectAtIndex:0)'s setEnabled:false)
end setActive:

And it works!

However, I've been trying to get the syntax right for running it on the main thread in Script Debugger, and that's been an issue for me so far.

Oops! Nope, just thought of something else and tried that, and now I've got it working from Script Debugger like this:

Applescript:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
use script "Dialog Toolkit ROT"

property alertRecord : {}

set {aPopop, printAreaPopupLabel, theTop, matrixLeft} to create labeled popup {"One", "Two", "Three"} left inset 0 bottom 0 popup width 300 max width 400 label text "Selection" popup left 0

aPopop's setTarget:me
aPopop's setAction:"setActive:"


set {alertRecord} to return enhanced alert "The Title" message "" as informational alert buttons {"Cancel", "OK"} acc view width 700 acc view height theTop acc view controls {aPopop} without suppression

set {buttonName, suppressedState, controlsResults} to show returned alert alert reference alertRecord giving up after 120


on setActive:sender
   my performSelectorOnMainThread:"setActiveOnMain:" withObject:{missing value} waitUntilDone:true
end setActive:

on setActiveOnMain:sender
   set theAlert to theAlert of alertRecord
   ((theAlert's |buttons|()'s objectAtIndex:0)'s setEnabled:false)
end setActiveOnMain:

At first I was trying to get the syntax right to call the "setActive:" handler from "aPopop's setAction:" AND run it on the main thread as one call. Maybe that's possible, but I couldn't get it. Then it occurred to me to just nest the functions.

So thanks so much!

Feel free to tell me to take a hike if I'm driving you nuts here, but there's always something else that would make the UI better. I'd love to have a super obvious indicator when the UI was able to fully populate itself with default values, so the user should be able to just hit "return" unless they know they're doing something unusual and will have to modify the defaults. I was hoping to maybe set the entire background of the dialog to a pale green when everything's auto-filled, and a pale red when they have to pay attention. Or maybe change the icon to signify these things. What I've been able to Google up so far does not sound promising on the background color.

I can, of course, change a label, or even the dialog title, but I've found UI-wise that anything requiring someone to read text is much slower for users than something like the background color being as an indicator.


Hackintosh built February, 2012 |  Mac OS Sierra
GIGABYTE GA-Z68X-UD3H-B3 | Core i5 2500k | 16 GB DDR3 | GIGABYTE Geforce 1050 TI 4GB
250 GB Samsung 850 EVO | 4 TB RAID
Dell Ultrasharp U3011 | Dell Ultrasharp 2007FPb

Offline

 

#25 2017-05-11 04:47:27 pm

t.spoon
Member
From:: BFE, Massachusetts
Registered: 2013-01-13
Posts: 202

Re: Change elements dynamically using Shane's Dialog Toolkit?

*** EDIT AT END - Figured it out ***

Now I'm having the same issue I had with having a default selection on popup lists, but with deactivation of the "OK" button.

It's working fine to activate or deactivate the "OK" button based on any user interaction, but the intention was, until the a valid set of selections have been made, for the button to be deactivated.

This means that it must be deactivated when the dialog opens, and I'll use logic to activate it. The activation part looks good, but I can't get it to be deactivated on open.

I've been trying to modify Dialog Toolkit for this, but it seems to be back to the "chicken and the egg" problem that

(theAlert's |buttons|()'s objectAtIndex:0)'s setEnabled:false


does not work until the Alert window is open.

Adding:

thePopup's selectItemAtIndex:defaultSelection


inside Dialog Toolkit when the dialog was being constructed did work, but doing the same inside dialog toolkit for setting button activation does not, it can only be deactivated/activated once the dialog is shown.

Putting it inside the "showTheAlert" handler in Dialog Toolkit immediately after

set my returnCode to theAlert's runModal()


doesn't invoke it until the dialog has been dismissed.

I've been looking through the documentation for something like "defaultEnabled" under NSAlert and NSButton, but with no luck.

Man, I keep writing these and then figuring out something else to try when I'm basically done... then I think about just not posting, but I figure it's better to post the problem/solution in the thread in case anyone in the future Google's it up.

Functioning edit to Display Enhanced Alert making the buttons:

Applescript:

repeat with anEntry in buttonsList
           set aButton to (its addButtonWithTitle:anEntry)
           if buttonActive is false then
               if anEntry as text is "OK" then
                   (aButton's setEnabled:false)
               end if
           end if
       end repeat

Last edited by t.spoon (2017-05-11 04:58:09 pm)


Hackintosh built February, 2012 |  Mac OS Sierra
GIGABYTE GA-Z68X-UD3H-B3 | Core i5 2500k | 16 GB DDR3 | GIGABYTE Geforce 1050 TI 4GB
250 GB Samsung 850 EVO | 4 TB RAID
Dell Ultrasharp U3011 | Dell Ultrasharp 2007FPb

Offline

 

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)