TabbedComponent and/or TabbedButtonBar Listeners?

There’s currently no way to be informed when the state of a TabbedComponent or TabbedButtonBar is changed. My model depends on knowing what the current tab is, and when tabs are added, removed, or reordered via addTab, moveTab, etc.

I find it very odd that there’s no Listener subclass for these classes like there are for nearly every single other Component type. TabbedButtonBar is a ChangeBroadcaster, but that barely helps since the user is left to deduce how the current tab arrangement changed since the last broadcast message. Having tabDidMove(int fromIndex, int toIndex), tabWasAdded(int atIndex) and the like would be really nice.

I’d have thought that if you need a model class to closely follow the behaviour of a tabbed component, then maybe your whole thing is the wrong way round…? The change broadcasting is really just there so that things like other components can repaint themselves or do other simple responses to something changing, but if you have a model class involved, maybe the model should be in charge, and the tabbed bar should be responding to changes in the model rather than the other way round?

For some additional context, what I’m building is essentially a linear AudioProcessorGraph fronted by a TabbedComponent. Each tab represents a processor in the chain from left to right, with the tab’s component being the editor.

I’ve implemented tab reordering via dragging as the method by which the user can rearrange the graph by reordering the tabs (all the connection breaking/re-forming is handled internally). The tab re-ordering should trigger the graph to update in a “the user made something happen” fashion so it can update the stored properties in the graph (currently just the linear index used for the node’s “order” in the linear graph).

Since the rearrangeable tabs employ things like animation, snapping, and other visual aesthetics I was trying to shortcut controlling the entire visual behavior of the tabs in a manner similar to the plugin host where a full User -> View -> Update Model -> Update View happens, instead doing User -> View -> Update View + Model since any tab arrangement will never be invalid. I feel like the Tab* classes are very resistant to adding direct interactive editing capabilities, so neither approach is easy to do.

I totally see what you mean by the Tab* component family being oriented around reacting to a model change rather than triggering a model change through user interaction just from looking at the API, but in my case it’s the opposite from the way the Tab* classes were designed I guess. If you have any suggestions on how to restructure things I’d love to hear them.

2 Likes