MathGroup Archive 2010

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Re: Problems with ChoiceDialog inside a Dynamic: Bug or not (well)

  • To: mathgroup at smc.vnet.net
  • Subject: [mg107976] Re: [mg107855] Re: Problems with ChoiceDialog inside a Dynamic: Bug or not (well)
  • From: John Fultz <jfultz at wolfram.com>
  • Date: Thu, 4 Mar 2010 05:28:57 -0500 (EST)
  • Reply-to: jfultz at wolfram.com

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 at 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 at wolfram.com
>> User Interface Group
>> Wolfram Research, Inc.
>>
>
> ---
> Guido Tripaldi
> imho.gtripaldi.it




  • Prev by Date: Communication over Mathlink with C/C++
  • Next by Date: Re: Re: Problems with ChoiceDialog inside a Dynamic: Bug or not (well)
  • Previous by thread: Re: Re: Problems with ChoiceDialog inside a Dynamic: Bug or not (well)
  • Next by thread: Background color or alike for Panel && Manipulate