Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Firstly please note that I'm using simply Dynamic behavior to illustrate my question, I'm not asking how to move a Disk or make a Slider.

When defining custom functions that allow interactive changing of variables I have almost always gotten by with just setting the attribute HoldFirst and giving the variable as a first argument and wrapping Dynamic where appropriate in the code defining the controller for example:

 SetAttributes[mySlider, HoldAll]
  mySlider[var_, range_] := Slider[Dynamic[var], range]
  DynamicModule[{a = 0.4},
  {mySlider[a, {0, 1}], Dynamic[a]}
 ]

But I feel that this is somewhat clashing compared to the interfaces of the build-in controllers and would like to have a similar interface such as those, namely changing such a definition to:

 mySlider2[var_Dynamic, range_] := Slider[var, range]
 DynamicModule[{a = 0.4},
 {mySlider2[Dynamic[a, Temporary], {0, 1}], Dynamic[a]}]

Which in a sense allows the full specification of Dynamic to be used, here showing for example the use of a Temporary setter.

For this simple example the change is rather painless, however the problem arises in situations where the code doesn't just pass on variables but needs to split them out in some way, for instance this manual implementation of a movable disk:

 myMovableDisk[Dynamic[r_, {fstart_, f_, fend_}]] := 
  EventHandler[Dynamic@Disk[r, 1],{
   {"MouseDown", 1} :> fstart[MousePosition["Graphics"], r],
   {"MouseDragged", 1} :> f[MousePosition["Graphics"], r],
   {"MouseUp", 1} :> fend[MousePosition["Graphics"], r]
  }]

Now this matches the longest definition, but I would rather like not to have to provide multiple definitions for myMovableDisk[Dynamic[r_, { f_, fend_}]],myMovableDisk[Dynamic[r_, f_]] and such. So my way of doing this was to set HoldAll and just provide rewriting calls to other definitions:

 myMovableDisk[Dynamic[r_]] := myMovableDisk[Dynamic[r, {None, Automatic, None}]]
 myMovableDisk[Dynamic[r_, {f_}]] := myMovableDisk[Dynamic[r, {None, f, None}]]
 myMovableDisk[Dynamic[r_, f_]] := myMovableDisk[Dynamic[r, {None, f, None}]]
 myMovableDisk[Dynamic[r_, {f_, fend_}]] := myMovableDisk[Dynamic[r, {None, f, fend}]]
 myMovableDisk[Dynamic[r_, Temporary]] := myMovableDisk[Dynamic[r, {None, Temporary, Automatic}]]

To me this seems like a less elegant solution to allow normal dynamic interactivity, and I have yet to actually define how for instance a Temporary setter should work. I was wondering if there was an easier way to carry out such definitions, something akin to just accepting a _Dynamic argument and then query it to get the values of fstar,f and fend in the code actually defining myMovableDisk?

Additionally I wonder if there is a write up of something like an interface definition for Dynamic, in essence answering what a function accepting Dynamic[var] should live up to of expectations in order to mirror a build-in function, since I'm really just working against the help page.

share|improve this question
    
If you have to handle f, fend, Temporary, etc. in any way inside your function then I see no other way than writing different signatures for all cases, or combine them in one signature with Default and Optional. Or I did not understand the question. –  István Zachar Oct 26 '12 at 12:02
    
@IstvánZachar I don't think you misunderstood the question, yet I am hoping for a more elegant way. In essence I suppose i would have liked a function akin to AbsoluteCurrentArgument[dynvar,fstart], since I could very easily have implemented my wanted flexibility if fstart,fend and f where Options. As for the special treatment needed for Temporary that will of cause always be needed, however I think it's doable with a general pattern. –  jVincent Oct 26 '12 at 12:14
    
What's the need for HoldAll? (furthermore, you forgot "myMovableDisk` in your SetAttributes –  Rojo Oct 26 '12 at 14:41
    
Just edited the SetAttributes –  Rojo Oct 26 '12 at 14:54
    
@Rojo In the first case it's needed, I didn't remove it in the latter cases since I didn't notice that it was no longer needed since Dynamic does the holding. –  jVincent Oct 26 '12 at 15:03
show 1 more comment

1 Answer

up vote 1 down vote accepted

I am not sure I understood, but the function you seem to want is quite similar to the function you already created for the purposes of this question, right?

For example

getDynamic[r_Dynamic] := getDynamic[r, All];
getDynamic[Dynamic[r_], s_] := 
 getDynamic[Dynamic[r, {None, Automatic, None}], s]
getDynamic[Dynamic[r_, {f_}], s_] := 
 getDynamic[Dynamic[r, {None, f, None}], s]
getDynamic[Dynamic[r_, f_], s_] := 
 getDynamic[Dynamic[r, {None, f, None}], s]
getDynamic[Dynamic[r_, {f_, fend_}], s_] := 
 getDynamic[Dynamic[r, {None, f, fend}], s]
getDynamic[Dynamic[r_, Temporary], s_] := 
  getDynamic[Dynamic[r, {None, Temporary, Automatic}], s];
getDynamic[Dynamic[r_, {fstart_, f_, fend_}], "fstart"] := fstart;
getDynamic[Dynamic[r_, {fstart_, f_, fend_}], "f"] := f;
getDynamic[Dynamic[r_, {fstart_, f_, fend_}], "fend"] := fend;
getDynamic[Dynamic[r_, {fstart_, f_, fend_}], All] := {fstart, f, 
   fend};

You put that in some package, and from now on you can do

myMovableDisk[r : Dynamic[v_, ___]] := EventHandler[Graphics[
   Dynamic@Disk[v, 1], 
   PlotRange -> {{-5, 5}, {-5, 5}}], {{"MouseDown", 1} :> 
    getDynamic[r, "fstart"][MousePosition["Graphics"], 
     r], {"MouseDragged", 1} :> 
    getDynamic[r, "f"][MousePosition["Graphics"], r], {"MouseUp", 
     1} :> getDynamic[r, "fend"][MousePosition["Graphics"], r]}]

Perpahs you could summarize those getDynamic definitions by using defaults but the main point is that you don't need to do this coding more than once.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.