From: Albert Retey on 25 Feb 2010 17:36 Hi, > suppose you wanna to display an alert to the user before to continue the > execution of your code when some conditions occur : probably you'll use > ChoiceDialog[], the useful function that "puts up a standard choice > dialog that displays expr together with OK and Cancel buttons, and > returns True if OK is clicked, and False if Cancel is clicked.". > > But if you use this function inside some Dynamic[] object, it hangs the > kernel. I've tried to find in the documentation some references to this > bad combination without any luck, so I don't understand if this is a bug > or there is something missing in the code. > > To better explain the problem here is a very basic example: > > (* just a silly example *) > Grid[{ > {"Choose a dividend: ", > PopupMenu[Dynamic[dividend], Table[i, {i, 0, 10}]]}, > {"Choose a divisor : ", PopupMenu[Dynamic[divisor], Table[i, {i, 0, 10}]]}, > {"Quotient: ", Dynamic[dividend / divisor]} > }, Frame -> All] > Dynamic[ > If[divisor == 0, > ChoiceDialog["Uh-oh, you are going to do a division by zero! Please select a different divisor.", {"Ok"}]; > ]]; It's a deficiency of how the modal dialogs behave. I have encountered this about a year ago or more and reported here, but have not yet received any answers. You have the same problem when you try to nest modal dialogs. In the meantime I just try to avoid modal dialogs where I can, which is often possible, but of course not always. > Instead, if you use the MessageDialog[] function to show a message window, all works well, but of course the execution will continue without waiting for the user action (that is not what I want). > > Same situation if you try to use ChoiceDialog[] inside a TabView, or other kind of Views: > > (* another silly example *) > TabView[{ > "Tab1" -> Button["Show ChoiceDialog", result = ChoiceDialog["This hangs.. :-(."];], > "Tab2" -> Button["Show MessageDialog", MessageDialog["This works!"];] > }] In some cases like your second example, where a modal dialog is started by a button, the Method->"Queued" trick helps: TabView[{ "Tab1" -> Button["Show ChoiceDialog", result = ChoiceDialog["This is ok:-)."], Method->"Queued" ], "Tab2" -> Button["Show MessageDialog", MessageDialog["This works!"]; ] }] hth, albert
From: Guido Tripaldi on 27 Feb 2010 03:12 mmh, I've said "problem solved" too soon in the previous message! So it is NOT possible to use ChoiceDialog inside a Manipulate or more in general inside a Dynamic object, or in nested modal dialogs: very bad! This certainly limits the grade of interactivity with the user that we can put in a program, think for example in cases where it's needed to stop and alert the user before a potentially destructive operations (i.e. deleting data, etc..). Hoping, as usual, in the next version... Anyway, thank you Adam and Albert for your hints! G Il giorno 25/feb/2010, alle ore 23.37, Albert Retey ha scritto: > Hi, > >> suppose you wanna to display an alert to the user before to continue the >> execution of your code when some conditions occur : probably you'll use >> ChoiceDialog[], the useful function that "puts up a standard choice >> dialog that displays expr together with OK and Cancel buttons, and >> returns True if OK is clicked, and False if Cancel is clicked.". >> >> But if you use this function inside some Dynamic[] object, it hangs the >> kernel. I've tried to find in the documentation some references to this >> bad combination without any luck, so I don't understand if this is a bug >> or there is something missing in the code. >> >> To better explain the problem here is a very basic example: >> >> (* just a silly example *) >> Grid[{ >> {"Choose a dividend: ", >> PopupMenu[Dynamic[dividend], Table[i, {i, 0, 10}]]}, >> {"Choose a divisor : ", PopupMenu[Dynamic[divisor], Table[i, {i, 0, 10}]]}, >> {"Quotient: ", Dynamic[dividend / divisor]} >> }, Frame -> All] >> Dynamic[ >> If[divisor == 0, >> ChoiceDialog["Uh-oh, you are going to do a division by zero! Please select a different divisor.", {"Ok"}]; >> ]]; > > It's a deficiency of how the modal dialogs behave. I have encountered > this about a year ago or more and reported here, but have not yet > received any answers. You have the same problem when you try to nest > modal dialogs. In the meantime I just try to avoid modal dialogs where I > can, which is often possible, but of course not always. > >> Instead, if you use the MessageDialog[] function to show a message window, all works well, but of course the execution will continue without waiting for the user action (that is not what I want). >> >> Same situation if you try to use ChoiceDialog[] inside a TabView, or other kind of Views: >> >> (* another silly example *) >> TabView[{ >> "Tab1" -> Button["Show ChoiceDialog", result = ChoiceDialog["This hangs.. :-(."];], >> "Tab2" -> Button["Show MessageDialog", MessageDialog["This works!"];] >> }] > > In some cases like your second example, where a modal dialog is started > by a button, the Method->"Queued" trick helps: > > TabView[{ > "Tab1" -> Button["Show ChoiceDialog", > result = ChoiceDialog["This is ok:-)."], > Method->"Queued" > ], > "Tab2" -> Button["Show MessageDialog", > MessageDialog["This works!"]; > ] > }] > > > hth, > > albert > --- Guido Tripaldi
From: Albert Retey on 28 Feb 2010 04:52 Hi, > Synchronous Dynamics (which is what you get by default) are stop-the-world sorts > of evaluations. When they're running, any ongoing kernel computation is > completely halted, and the Dynamic evaluation is completely uninterruptible. > Even another Dynamic evaluation cannot interrupt it. Likewise, the front end is > locked into a mode where it can only respond to a very limited number of events > while it awaits the resolution of the Dynamic. > > For this reason, all synchronous Dynamics are evaluated, by default, with a > TimeConstrained wrapper using a time derived from the EvaluationDynamicTimeout > option in the kernel. This option can be tailored on a per-Dynamic basis if you > like using the Style[] function to set the option. The goal is that absolutely > no Dynamic should be allowed to lock up the front end and kernel in such away > that they appear unresponsive to users. > > ChoiceDialog[], or any other function which awaits user input, causes the kernel > to wait for results, but doesn't stop the timer in TimeConstrained[] from > expiring. > > Any Dynamic which you expect to take a long time should be using > SynchronousDynamic->False. This causes the Dynamic to be put into the same > queue as Shift+Enter evaluations, and it can take as long as you want. So it's > not evaluated urgently, but there will be no need for it to evaluate urgently, > either. > > Incidentally, the same thing applies with Method->{"Queued"} (as opposed to > "Preemptive") in Button and ActionMenu. I hear your words, but probably don't understand.... While my experience shows that Method->"Queued" in Buttons and ActionMenus fixes any problems with kernel blocking dialogs, using SynchronosUpdating->False (I guess that's what you meant) does not help, at least with my version 7 on Windows XP this also hangs: DynamicModule[{planets, x, habitantq}, planets = {"Mercury", "Venus", "Earth"}; x = First[planets]; Column[{ PopupMenu[Dynamic[x, {x = #; If[StringMatchQ[x, "Earth"], habitantq = ChoiceDialog[Column[{"Do you live on earth?"}], {"Yes" -> True, "No" -> False}]]} &, SynchronousUpdating -> False], planets], Dynamic[x], Dynamic[habitantq] }]] and so does this: DynamicModule[{planets, x, habitantq}, planets = {"Mercury", "Venus", "Earth"}; x = First[planets]; Column[{ PopupMenu[Dynamic[x, {x = #; If[StringMatchQ[x, "Earth"], habitantq = ChoiceDialog[Column[{"Do you live on earth?"}], {"Yes" -> True, "No" -> False}]]} &, SynchronousUpdating -> False], planets], Dynamic[x, SynchronousUpdating -> False], Dynamic[habitantq, SynchronousUpdating -> False] }]] is there any known way to get something like this working? regards, albert
From: John Fultz on 1 Mar 2010 04:43 On Sun, 28 Feb 2010 04:53:10 -0500 (EST), Albert Retey wrote: > Hi, > >> Synchronous Dynamics (which is what you get by default) are stop-the- >> world sorts >> of evaluations. When they're running, any ongoing kernel computation is >> completely halted, and the Dynamic evaluation is completely >> uninterruptible. >> Even another Dynamic evaluation cannot interrupt it. Likewise, the >> front end is >> locked into a mode where it can only respond to a very limited number >> of events >> while it awaits the resolution of the Dynamic. >> >> For this reason, all synchronous Dynamics are evaluated, by default, >> with a >> TimeConstrained wrapper using a time derived from the >> EvaluationDynamicTimeout >> option in the kernel. This option can be tailored on a per-Dynamic >> basis if you >> like using the Style[] function to set the option. The goal is that >> absolutely >> no Dynamic should be allowed to lock up the front end and kernel in >> such away >> that they appear unresponsive to users. >> >> ChoiceDialog[], or any other function which awaits user input, causes >> the kernel >> to wait for results, but doesn't stop the timer in TimeConstrained[] >> from >> expiring. >> >> Any Dynamic which you expect to take a long time should be using >> SynchronousDynamic->False. This causes the Dynamic to be put into the >> same >> queue as Shift+Enter evaluations, and it can take as long as you want. >> So it's >> not evaluated urgently, but there will be no need for it to evaluate >> urgently, >> either. >> >> Incidentally, the same thing applies with Method->{"Queued"} (as >> opposed to >> "Preemptive") in Button and ActionMenu. >> > I hear your words, but probably don't understand.... > > While my experience shows that Method->"Queued" in Buttons and > ActionMenus fixes any problems with kernel blocking dialogs, using > SynchronosUpdating->False (I guess that's what you meant) does not help, > at least with my version 7 on Windows XP this also hangs: > > DynamicModule[{planets, x, habitantq}, > planets = {"Mercury", "Venus", "Earth"}; > x = First[planets]; > Column[{ > PopupMenu[Dynamic[x, {x = #; > If[StringMatchQ[x, "Earth"], > habitantq = ChoiceDialog[Column[{"Do you live on earth?"}], > {"Yes" -> True, "No" -> False}]]} &, > SynchronousUpdating -> False], planets], > Dynamic[x], > Dynamic[habitantq] > }]] > > and so does this: > > DynamicModule[{planets, x, habitantq}, > planets = {"Mercury", "Venus", "Earth"}; > x = First[planets]; > Column[{ > PopupMenu[Dynamic[x, {x = #; > If[StringMatchQ[x, "Earth"], > habitantq = ChoiceDialog[Column[{"Do you live on earth?"}], > {"Yes" -> True, "No" -> False}]]} &, > SynchronousUpdating -> False], planets], > Dynamic[x, SynchronousUpdating -> False], > Dynamic[habitantq, SynchronousUpdating -> False] > }]] > > is there any known way to get something like this working? > > regards, > > albert Sorry...yes, of course I meant SynchronousUpdating. You raise an important issue which I've never taken the opportunity to completely clarify on this group (although I think I touched on it briefly a couple of months ago). The issue is that there are really two different kinds of Dynamics. They share so many properties that many people really don't need to understand the difference, but there are a small number of ways in which they are distinctly different. We don't have official names for these things really, so I'll make up some names which you may or may not like, but probably shouldn't consider official Wolfram lingo. I'll refer to "instancing" Dynamics and "controller" Dynamics. An instancing Dynamic is one which creates an area on the screen containing some contents. MakeBoxes, when run on such a Dynamic, turns it into a DynamicBox. If such a Dynamic were unable to resolve, you'd see a gray box on the screen representing the area it would have taken (with a few exceptions...a Dynamic inside of a graphic might not show the gray box). You can think of an instancing Dynamic as an output-only zone. You can't somehow click on an instancing Dynamic and directly affect its properties...not without some mechanism of causing additional evaluations. Therefore, the second argument of Dynamic is meaningless to an instancing Dynamic. A controller Dynamic is one which does not represent an area on the screen, but merely sets the value of another thing which displays on the screen. For example, the Dynamic argument of Slider, Checkbox and Locator. Any coordinates of a graphics primitive specified with Dynamic are using a controller Dynamic. Dynamics on the right-hand side of front end options are also controller Dynamics. MakeBoxes of such a Dynamic returns Dynamic, not DynamicBox. It doesn't return DynamicBox because what's important is the *value* of the Dynamic result, not its appearance. The appearance of a Slider is always as a slider; the Dynamic argument merely controls the value the slider appears to be set to. In nearly all cases (excepting the rhs of FE options), a controller Dynamic represents a two-way interface. It controls the display of its value, but also accepts the setting of new values through some interactive means, which makes the second argument of Dynamic a very meaningful concept here. As I said, most of the functionality of Dynamic is shared between both types. But here's a list of things (well, the things I could think of...might not be complete) which you can only meaningfully use within one of the types... * Second argument of Dynamic - controller Dynamic * ShrinkingDelay option of Dynamic - instancing Dynamic * SynchronousUpdating option of Dynamic - instancing Dynamic The first two limitations are conceptual and really quite necessary. If an instancing Dynamic allowed you to change it, it would be an InputField (with Appearance->None). There are many times when that's really not what you want, and if it is, you should simply use InputField instead. ShrinkingDelay just isn't meaningful for an object which has no concept of size, such as a controller Dynamic. SynchronousUpdating is a bit trickier. There are extra difficulties with implementing an asynchronous version of controller Dynamic (particularly, having a control which is in an "unknown" state for a possibly long period of time). And that extra difficulty is exactly why it's not implemented in controller Dynamics for now. But one can imagine that this as a meaningful concept, and so this might change for future versions. But for now, SynchronousUpdating only works for instancing Dynamics. Which means that controller Dynamics are generally locked into what I referred to before as "stop-the-world" evaluations. Note that it's generally not necessary to implement things this way, though. You can make an controller Dynamic which sets immediately, and then triggers an instancing Dynamic that operates asynchronously. Or, perhaps a controller Dynamic isn't necessary at all...but instead some sort of Button or ActionMenu item. Here's an interesting concept I worked up for someone recently which you might find interesting...an ActionMenu which works like a PopupMenu by virtue of containing an instancing Dynamic for the appearance. The simplest case... DynamicModule[{x = 1}, ActionMenu[Dynamic[x], {1 :> (x = 1), 2 :> (x = 2), 3 :> (x = 3)}]] which is equivalent to DynamicModule[{x = 1}, PopupMenu[Dynamic[x], {1, 2, 3}]] except that it guarantees the evaluation of the "x =" statements every time you choose the menu, rather than only when 'x' would change. Your example could very easily be reformulated using such a mechanism. Then setting Method->"Queued" would allow you to put things such as ChoiceDialog[] in the actions. Sincerely, John Fultz jfultz(a)wolfram.com User Interface Group Wolfram Research, Inc.
From: John Fultz on 4 Mar 2010 05:29
The Button ought to work. This looks to me like a bug, and one which appears to have already been fixed in the version of Mathematica presently under development. Sincerely, John Fultz jfultz(a)wolfram.com User Interface Group Wolfram Research, Inc. On Wed, 3 Mar 2010 13:00:11 +0100, Guido Tripaldi wrote: > consider this example: > > (* define a function that ask the user for choosing values *) > chooseItems[itemsList_, defaultItems_] := Module[ > {selectedItems}, > selectedItems = defaultItems; > ChoiceDialog[ > CheckboxBar[Dynamic[selectedItems], itemsList] > ]; > Return[selectedItems] > ] > > (* some defaults inits *) > myItemsList = {1 -> "A", 2 -> "B", 3 -> "C"}; > myDefaultItems = {2}; > mySelectedItems = {}; > > (* call the function from a Button *) > Button["choose", mySelectedItems = chooseItems[myItemsList, > myDefaultItems], Method -> "Queued"] > > (* display result *) > Dynamic[mySelectedItems] > > > if you call (evaluate) the chooseItems[itemsList_, defaultItems_] > function directly, it works as expected, but if you call it as a Button > action, the CheckBoxBar view isn't updated according to the box clicked > (but the returned value will be set correctly). > > Now, in the function definition, making global instead of local the > "selectedItems" var, all will works as wanted : > > chooseItems[itemsList_, defaultItems_] := Module[ > {}, (* moved to global *) > selectedItems = defaultItems; > ChoiceDialog[ > CheckboxBar[Dynamic[selectedItems], itemsList] > ]; > Return[selectedItems] > ] > > myItemsList = {1 -> "A", 2 -> "B", 3 -> "C"}; > myDefaultItems = {2}; > mySelectedItems = {}; > selectedItems = {}; (* global *) > > Button["choose", > mySelectedItems = chooseItems[myItemsList, myDefaultItems], > Method -> "Queued"] > > of course, this workaround isn't very desirable as "When you write a > program in Mathematica, you should always try to set it up so that its > parts are as independent as possible". Even after reading the really > interesting answer by John I don't find a different way around, nor I > understand if this undesirable side effect of Dynamics is somewhat > predictable by an average Mathematica user (like myself) or to understand > (and to be able to resolve) it, requires a deeper study of the insides of > Mathematica.. > > thanks in advance, > Guido > > Il giorno 01/mar/2010, alle ore 10.42, John Fultz ha scritto: > >> On Sun, 28 Feb 2010 04:53:10 -0500 (EST), Albert Retey wrote: >>> Hi, >>> >>>> Synchronous Dynamics (which is what you get by default) are stop- >>>> the- >>>> world sorts >>>> of evaluations. When they're running, any ongoing kernel >>>> computation is >>>> completely halted, and the Dynamic evaluation is completely >>>> uninterruptible. >>>> Even another Dynamic evaluation cannot interrupt it. Likewise, the >>>> front end is >>>> locked into a mode where it can only respond to a very limited >>>> number >>>> of events >>>> while it awaits the resolution of the Dynamic. >>>> >>>> For this reason, all synchronous Dynamics are evaluated, by default, >>>> with a >>>> TimeConstrained wrapper using a time derived from the >>>> EvaluationDynamicTimeout >>>> option in the kernel. This option can be tailored on a per-Dynamic >>>> basis if you >>>> like using the Style[] function to set the option. The goal is that >>>> absolutely >>>> no Dynamic should be allowed to lock up the front end and kernel in >>>> such away >>>> that they appear unresponsive to users. >>>> >>>> ChoiceDialog[], or any other function which awaits user input, >>>> causes >>>> the kernel >>>> to wait for results, but doesn't stop the timer in TimeConstrained[] >>>> from >>>> expiring. >>>> >>>> Any Dynamic which you expect to take a long time should be using >>>> SynchronousDynamic->False. This causes the Dynamic to be put into >>>> the >>>> same >>>> queue as Shift+Enter evaluations, and it can take as long as you >>>> want. >>>> So it's >>>> not evaluated urgently, but there will be no need for it to evaluate >>>> urgently, >>>> either. >>>> >>>> Incidentally, the same thing applies with Method->{"Queued"} (as >>>> opposed to >>>> "Preemptive") in Button and ActionMenu. >>>> >>> I hear your words, but probably don't understand.... >>> >>> While my experience shows that Method->"Queued" in Buttons and >>> ActionMenus fixes any problems with kernel blocking dialogs, using >>> SynchronosUpdating->False (I guess that's what you meant) does not >>> help, >>> at least with my version 7 on Windows XP this also hangs: >>> >>> DynamicModule[{planets, x, habitantq}, >>> planets = {"Mercury", "Venus", "Earth"}; >>> x = First[planets]; >>> Column[{ >>> PopupMenu[Dynamic[x, {x = #; >>> If[StringMatchQ[x, "Earth"], >>> habitantq = ChoiceDialog[Column[{"Do you live on earth?"}], >>> {"Yes" -> True, "No" -> False}]]} &, >>> SynchronousUpdating -> False], planets], >>> Dynamic[x], >>> Dynamic[habitantq] >>> }]] >>> >>> and so does this: >>> >>> DynamicModule[{planets, x, habitantq}, >>> planets = {"Mercury", "Venus", "Earth"}; >>> x = First[planets]; >>> Column[{ >>> PopupMenu[Dynamic[x, {x = #; >>> If[StringMatchQ[x, "Earth"], >>> habitantq = ChoiceDialog[Column[{"Do you live on earth?"}], >>> {"Yes" -> True, "No" -> False}]]} &, >>> SynchronousUpdating -> False], planets], >>> Dynamic[x, SynchronousUpdating -> False], >>> Dynamic[habitantq, SynchronousUpdating -> False] >>> }]] >>> >>> is there any known way to get something like this working? >>> >>> regards, >>> >>> albert >>> >> Sorry...yes, of course I meant SynchronousUpdating. >> >> You raise an important issue which I've never taken the opportunity to >> completely clarify on this group (although I think I touched on it >> briefly a >> couple of months ago). The issue is that there are really two >> different kinds >> of Dynamics. They share so many properties that many people really >> don't need >> to understand the difference, but there are a small number of ways in >> which they >> are distinctly different. >> >> We don't have official names for these things really, so I'll make up >> some names >> which you may or may not like, but probably shouldn't consider official >> Wolfram >> lingo. I'll refer to "instancing" Dynamics and "controller" Dynamics. >> >> An instancing Dynamic is one which creates an area on the screen >> containing some >> contents. MakeBoxes, when run on such a Dynamic, turns it into a >> DynamicBox. >> If such a Dynamic were unable to resolve, you'd see a gray box on the >> screen >> representing the area it would have taken (with a few exceptions...a >> Dynamic >> inside of a graphic might not show the gray box). You can think of an >> instancing Dynamic as an output-only zone. You can't somehow click on >> an >> instancing Dynamic and directly affect its properties...not without some >> mechanism of causing additional evaluations. Therefore, the second >> argument of >> Dynamic is meaningless to an instancing Dynamic. >> >> A controller Dynamic is one which does not represent an area on the >> screen, but >> merely sets the value of another thing which displays on the screen. >> For >> example, the Dynamic argument of Slider, Checkbox and Locator. Any >> coordinates >> of a graphics primitive specified with Dynamic are using a controller >> Dynamic. >> Dynamics on the right-hand side of front end options are also controller >> Dynamics. MakeBoxes of such a Dynamic returns Dynamic, not DynamicBox. >> It >> doesn't return DynamicBox because what's important is the *value* of >> the Dynamic >> result, not its appearance. The appearance of a Slider is always as a >> slider; >> the Dynamic argument merely controls the value the slider appears to be >> set to. >> In nearly all cases (excepting the rhs of FE options), a controller >> Dynamic >> represents a two-way interface. It controls the display of its value, >> but also >> accepts the setting of new values through some interactive means, which >> makes >> the second argument of Dynamic a very meaningful concept here. >> >> As I said, most of the functionality of Dynamic is shared between both >> types. >> But here's a list of things (well, the things I could think of...might >> not be >> complete) which you can only meaningfully use within one of the types... >> >> * Second argument of Dynamic - controller Dynamic >> * ShrinkingDelay option of Dynamic - instancing Dynamic >> * SynchronousUpdating option of Dynamic - instancing Dynamic >> >> The first two limitations are conceptual and really quite necessary. >> If an >> instancing Dynamic allowed you to change it, it would be an InputField >> (with >> Appearance->None). There are many times when that's really not what >> you want, >> and if it is, you should simply use InputField instead. ShrinkingDelay >> just >> isn't meaningful for an object which has no concept of size, such as a >> controller Dynamic. >> >> SynchronousUpdating is a bit trickier. There are extra difficulties >> with >> implementing an asynchronous version of controller Dynamic >> (particularly, having >> a control which is in an "unknown" state for a possibly long period of >> time). >> And that extra difficulty is exactly why it's not implemented in >> controller >> Dynamics for now. But one can imagine that this as a meaningful >> concept, and so >> this might change for future versions. >> >> But for now, SynchronousUpdating only works for instancing Dynamics. >> Which >> means that controller Dynamics are generally locked into what I >> referred to >> before as "stop-the-world" evaluations. >> >> Note that it's generally not necessary to implement things this way, >> though. >> You can make an controller Dynamic which sets immediately, and then >> triggers an >> instancing Dynamic that operates asynchronously. Or, perhaps a >> controller >> Dynamic isn't necessary at all...but instead some sort of Button or >> ActionMenu >> item. >> >> Here's an interesting concept I worked up for someone recently which >> you might >> find interesting...an ActionMenu which works like a PopupMenu by virtue >> of >> containing an instancing Dynamic for the appearance. The simplest >> case... >> >> DynamicModule[{x = 1}, >> ActionMenu[Dynamic[x], {1 :> (x = 1), 2 :> (x = 2), 3 :> (x = 3)}]] >> >> which is equivalent to >> >> DynamicModule[{x = 1}, PopupMenu[Dynamic[x], {1, 2, 3}]] >> >> except that it guarantees the evaluation of the "x =" statements every >> time you >> choose the menu, rather than only when 'x' would change. Your example >> could >> very easily be reformulated using such a mechanism. Then setting >> Method->"Queued" would allow you to put things such as ChoiceDialog[] >> in the >> actions. >> >> Sincerely, >> >> John Fultz >> jfultz(a)wolfram.com >> User Interface Group >> Wolfram Research, Inc. >> > > --- > Guido Tripaldi > imho.gtripaldi.it |