Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specify local Dynamic in Grid

I would like to update specific parts of a Grid dynamically in different ways. Consider the following toy example: I have two rows: one must be updated one-by-one (a, b, c), as these symbols depend on different triggers; the second row depends on one single trigger (show) that allows displaying/hiding some data.

Now I know that I can wrap the whole Grid structure into Dynamic, and even specify which symbols to track, thus this example does what I want:

Checkbox[Dynamic[show]]
test = {0, 0};
Dynamic[Grid[{{Dynamic@a, Dynamic@b, Dynamic@c}, 
   If[show, Prepend[test, "test:"], {}]}, Frame -> All],
 TrackedSymbols :> {show}]

Mathematica graphics

Though for certain reasons I would like to have a locally specified Dynamic, that is only applied to the second row of the Grid.

For those who are wondering what ungodly situation would it be, just imagine the followings: show is used in any of a, b or c, and these I do NOT want to update when show is changing, their changes depend on other triggers. Why not remove then show from the symbols of the first row? Imagine, I can't, as show is present in a function that is used in a, b or c, and this function I cannot access easily.

Of course wrapping the first argument of If into Dynamic won't help here, as the Grid itself or any of its cells won't become dynamic:

Grid[{
  {Dynamic@a, Dynamic@b, Dynamic@c},
  If[Dynamic@show, Prepend[test, "test:"], {}]
  }, Frame -> All]

Furthermore, wrapping a row into Dynamic makes the given row invalid, as it does not have head List anymore:

Grid[{
  {Dynamic@a, Dynamic@b, Dynamic@c},
  Dynamic@If[show, Prepend[test, "test:"], {}]
  }, Frame -> All]

Mapping Dynamic over the row does not work either because show is not updated dynamically:

Grid[{
  {Dynamic@a, Dynamic@b, Dynamic@c},
  Dynamic /@ If[show, Prepend[test, "test:"], {}]
  }, Frame -> All]

Also, wrapping Dynamic[If[...]] around list members work, but now I have to evaluate If 3 times instead of just 1.

Grid[{
  {Dynamic@a, Dynamic@b, Dynamic@c},
  Dynamic[If[show, #, ""]] & /@ Prepend[test, "test:"]
  }, Frame -> All]

Would like to know if there is any solution to overcome this particular problem by locally applying a Dynamic wrapper on a row.

like image 723
István Zachar Avatar asked Jan 10 '12 16:01

István Zachar


1 Answers

Here is a solution using the Experimental ValueFunction

show = True;
test = {0, 0};
Checkbox[Dynamic[show]]

Now write your own little Dynamic update function on the side

Needs["Experimental`"];
row = {};
updateRow[x_, v_] := row = If[v, Prepend[test, "test:"], {}];
ValueFunction[show] = updateRow;

Now make the Grid, and now can use Dynamic on EACH row, not around the whole Grid, which is what you wanted:

Grid[{
  {Dynamic@a, Dynamic@b, Dynamic@c},
  {Dynamic@row}
  },
 Frame -> All
 ]

enter image description here

ps. I just read a post here by telefunkenvf14 that mentions this package and this function, which I did not know about, and when I saw this function, I remembered this question, and I thought it should be possible to use that function to solve this problem.

ps. I need to work more on placing the grid row correctly....

update(1)

I can't figure how to splice the final row over the columns in the grid. Which is strange, as it has List head, yet it won't go across all the columns. It will only go in the first cell. Tried Sequence, SpanFromLeft, and such, but no luck. May be someone can figure this part out.

Here is my current trial:

Needs["Experimental`"];
row = {};
updateRow[x_, v_] := row = If[v, {"test:", 0, 0}, {}];
ValueFunction[show] = updateRow;
show = False;
Checkbox[Dynamic[show]]

f = Grid[{
   {Dynamic@a, Dynamic@b, Dynamic@c},
   List@Dynamic[row]
   },
  Frame -> All
  ]

It seems it should be doable. I do not see what is the problem now...

update(2)

As a temporary solution, I split the second row by force before hand. This made it possible to do what I want. Not sure if this meets the OP specifications or not (my guess is that it does not), but here it is:

Needs["Experimental`"];
ra = 0;
rb = 0;
rc = 0;
updateRow[x_, v_] := 
 row = If[v, ra = "test:"; rb = 0; rc = 0, ra = ""; rb = ""; rc = ""]
ValueFunction[show] = updateRow;
show = False;
Checkbox[Dynamic[show]]

f = Grid[{
   {Dynamic@a, Dynamic@b, Dynamic@c},
   {Dynamic@ra, Dynamic@rb, Dynamic@rc}
   },
  Frame -> All]

enter image description here

like image 162
Nasser Avatar answered Sep 29 '22 03:09

Nasser