1

What I'm trying to do is damn simple but it seems like Mathematica is extremely ill-designed for this ...

Here is a very simplified form of my code to show the basic idea. I have a variable number of tabs, depending on a dynamically set value, it already took me hours to find something that works :

Dynamic[TabView[ 
    Table[
        iTabIndex,
        {iTabIndex, iTabCount}
    ],
    Dynamic[iSelectedTab]
]]

where iTabCount is dynamically controlled by a slider in another part of the GUI. Now I want to have the content of each tab to contain dynamic controls (of course) over different parameters for each tab while sharing the same UI layout, but it just won't work ...

Dynamic[TabView[ 
    Table[
        Slider[ Dynamic[ someTable[[iTabIndex]] ], ... ],
        {iTabIndex, Count}
    ],
    Dynamic[iSelectedTab]
]]

===> Syntax error, iTabIndex is not connected anymore to the Table enumeration parameter when enclosed in Dynamic[] ... I NEED that Dynamic, otherwise controls nested in each tabs are pointless !

I tried working around by inserting a module (amongst other things) :

BuildTabUI[iTabIndex_] := (Dynamic)Module[
    {},
    Return[
        Slider[ Dynamic[ someTable[[iTabIndex]] ], ... ]
    ]
];

Dynamic[TabView[ 
    Table[
        BuildTabUI[iTabIndex],
        {iTabIndex, Count}
    ],
    Dynamic[iSelectedTab]
]]

Which does avoid the syntax error, but the slider is now unresponsive, despite the Dynamic enclosures inside BuildTabUI !

This would take seconds to code in C++ for any decent GUI engine ... how such a simple task can be so over-complicated ?

Can anyone please help me and give me a proper method to do this in a clean, efficient and generic way ? Thanks a lot in advance !

PS : Don't go easy on me with the technical details, I'm new to Mathematica but I'm an extremely experienced C++ programmer ... ;)

@JM, Test example :

param1 = param2 = param3 = 1;
iSelectedTab = 1;
iTabCount = 1;
someTable = { param1, param2, param3 };

Slider[ Dynamic[iTabCount], {1,3,1} ]

Dynamic[TabView[ 
    Table[
        Slider[ Dynamic[ someTable[[iTabIndex]] ], {1,5} ],
        {iTabIndex, iTabCount}
    ],
    Dynamic[iSelectedTab]
]]

I expect a tabview of 1-3 tabs, depending on first slider, each containing a nested slider controlling param1, param2, param3 ... Hope this is straightforward enough ... Thank you for your attention !

Shikifuyin
  • 11
  • 2

1 Answers1

4

Here's a quick mockup of what it sounds to me like you are attempting:

DynamicModule[{iTabCount, iSelectedTab, tabSlider, tabUI},
  iTabCount = 5;
  tabSlider[_] = 0;

  tabUI[i_] := 
    Column[{
      Slider[Dynamic @ tabSlider[i], {-1, 1}], 
      Dynamic @ Plot[Sin[x + tabSlider[i]], {x, -2 Pi, 2 Pi}]
    }];

  Column[{
    Dynamic @ TabView[Array[tabUI, iTabCount], Dynamic @ iSelectedTab],
    Slider[Dynamic @ iTabCount, {1, 10, 1}],
    Slider[Dynamic @ iSelectedTab, {1, Dynamic @ iTabCount, 1}]
  }]
]

enter image description here

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • Yeah ! That's exactly what I need ! However it is a bit tricky to translate your code sample in my own code, can you develop a bit on the details ? What's the difference between Dynamic[...] and Dynamic @ ... ? Is the global DynamicModule enclosing mandatory ? What is its precise role here ? What would take the place of tabSlider[i], in my code, is actually nested associative arrays I use to emulate C-like "struct" to have some object-oriented code support, but tabSlider seems to be a function in your code ? Thanks a lot for your answer, I'll adapt my code to this template if required ;) – Shikifuyin Jul 24 '16 at 16:45
  • The point is I'm trying to avoid mixing the model and the view as much as possible ... – Shikifuyin Jul 24 '16 at 16:52
  • @Shi, Dynamic[obj] and Dynamic @ obj are the same thing; the former is just the prefix application form. – J. M.'s missing motivation Jul 24 '16 at 16:55
  • Ok I see, thanks ;) – Shikifuyin Jul 24 '16 at 17:05
  • @Shikifuyin J. M. explained Dynamic @ obj but I shall add that I often use it because it makes clear that Dynamic is being used in the single parameter form, rather than having additional effects. DynamicModule is "good practice" and both scopes the dynamic variables reducing the chance of conflict, and keeps defined values through restarts. I am not a C coder so I have trouble understanding what you are asking with regard to that. (continued) – Mr.Wizard Jul 24 '16 at 17:16
  • 1
    In my code tabSlider is an "indexed object" and it allows me essentially to scope an arbitrary (dynamically generated) number of Symbols. Please reference: (6511), (13440) – Mr.Wizard Jul 24 '16 at 17:20
  • 1
    Alright I think I get it, the problem seems to be with the way I build my "objects" ... everything else is working fine now ... Those "indexed objects" seems to be exactly what I need in fact (scoping dynamically generated symbols), I didn't know about those ! I will setup things accordingly then. Thanks a lot again ! About DynamicModule, I was suspecting it to be doing some kind of implicit linkage in a context of dynamic symbols working together, but it seems its not the case and only deals with scoping, as expected from the documentation, again thanks a lot, you saved me a lot of time ! ;) – Shikifuyin Jul 24 '16 at 17:33
  • 3
    @MrWizard Use Dynamic@iselectedTab in the Dynamic@Tabview expression to get two way communication with the bottom most slider. – Jack LaVigne Jul 25 '16 at 01:52
  • @Jack Thanks, I overlooked that. I'll add it now. – Mr.Wizard Jul 25 '16 at 16:08