|
18 | 18 | import java.util.concurrent.atomic.AtomicReference; |
19 | 19 | import java.util.logging.Level; |
20 | 20 |
|
21 | | -import javafx.util.Pair; |
22 | | -import org.apache.commons.lang3.tuple.MutablePair; |
23 | 21 | import org.csstudio.display.builder.model.DirtyFlag; |
24 | 22 | import org.csstudio.display.builder.model.DisplayModel; |
25 | 23 | import org.csstudio.display.builder.model.UntypedWidgetPropertyListener; |
@@ -61,10 +59,22 @@ public class NavigationTabsRepresentation extends RegionBaseRepresentation<Navig |
61 | 59 | // Track the "active tab" of navigation tabs _inside_ this one. |
62 | 60 | // As user toggles between tabs, this will allow restoring the active tab |
63 | 61 | // of nested instances, which would otherwise start over at their default tab |
64 | | - private class SelectedNavigationTabs extends MutablePair<Integer, HashMap<Pair<Integer, String>, HashMap<String, SelectedNavigationTabs>>> { |
65 | | - public SelectedNavigationTabs(int activeTab) { |
66 | | - left = activeTab; |
67 | | - right = new HashMap<>(); // 'right' is a mapping of the form: Tab Number & Tab Name (Integer, String) -> Name of Navigator Tab Widget (String) -> Opened Tab and Sub-Tabs (SelectedNavigationTabs) |
| 62 | + |
| 63 | + // Tab index and name as unique identifier for a tab |
| 64 | + private static record UniqueTabID(int index, String name) {} |
| 65 | + |
| 66 | + private static class SelectedNavigationTabs |
| 67 | + { |
| 68 | + // Index of active tab in this nav tabs widget |
| 69 | + int active_tab; |
| 70 | + |
| 71 | + // Map from UniqueTabID -> ( Map from Name of child Navigator Tab Widget -> Opened Tab and Sub-Tabs ) |
| 72 | + final HashMap<UniqueTabID, |
| 73 | + HashMap<String, SelectedNavigationTabs>> child_navtab_selections = new HashMap<>(); |
| 74 | + |
| 75 | + SelectedNavigationTabs(int activeTab) |
| 76 | + { |
| 77 | + active_tab = activeTab; |
68 | 78 | } |
69 | 79 | }; |
70 | 80 | protected SelectedNavigationTabs selectedNavigationTabs = new SelectedNavigationTabs(0); |
@@ -190,7 +200,7 @@ private void activeTabChanged(final WidgetProperty<Integer> property, final Inte |
190 | 200 | dirty_active_tab.mark(); |
191 | 201 | toolkit.scheduleUpdate(this); |
192 | 202 | tab_display_listener.propertyChanged(null, null, null); |
193 | | - selectedNavigationTabs.left = tab_index; |
| 203 | + selectedNavigationTabs.active_tab = tab_index; |
194 | 204 | } |
195 | 205 |
|
196 | 206 | /** Update to the next pending display |
@@ -250,35 +260,33 @@ private synchronized void updatePendingDisplay(final JobMonitor monitor) |
250 | 260 | final List<TabProperty> tabs = model_widget.propTabs().getValue(); |
251 | 261 | final int tabNumber = Math.min(model_widget.propActiveTab().getValue(), tabs.size()-1); |
252 | 262 | final String tabName = tabs.get(tabNumber).name().getValue(); |
253 | | - final Pair<Integer, String> tabNumberAndTabName = new Pair<>(tabNumber, tabName); |
| 263 | + final UniqueTabID tab_id = new UniqueTabID(tabNumber, tabName); |
254 | 264 |
|
255 | | - if (!selectedNavigationTabs.right.containsKey(tabNumberAndTabName)) { |
256 | | - selectedNavigationTabs.right.put(tabNumberAndTabName, new HashMap<>()); |
257 | | - } |
258 | | - HashMap<String, SelectedNavigationTabs> selectedNavigationTabsHashMapForCurrentTab = selectedNavigationTabs.right.get(tabNumberAndTabName); |
259 | | - |
260 | | - new_model.getChildren() |
261 | | - .stream() |
262 | | - .filter(widget -> widget instanceof NavigationTabsWidget) |
263 | | - .forEach(widget -> { |
264 | | - NavigationTabsWidget nestedNavigationTabsWidget = (NavigationTabsWidget) widget; |
265 | | - NavigationTabsRepresentation nestedNavigationTabsRepresentation = (NavigationTabsRepresentation) nestedNavigationTabsWidget.getUserData(Widget.USER_DATA_REPRESENTATION); |
266 | | - if (nestedNavigationTabsRepresentation != null) { |
267 | | - SelectedNavigationTabs nestedNavigationTabsRepresentation_selectedNavigationTabs; |
268 | | - |
269 | | - if (!selectedNavigationTabsHashMapForCurrentTab.containsKey(nestedNavigationTabsWidget.getName())) { |
270 | | - nestedNavigationTabsRepresentation_selectedNavigationTabs = new SelectedNavigationTabs(nestedNavigationTabsWidget.propActiveTab().getValue()); |
271 | | - selectedNavigationTabsHashMapForCurrentTab.put(nestedNavigationTabsWidget.getName(), nestedNavigationTabsRepresentation_selectedNavigationTabs); |
272 | | - } |
273 | | - else { |
274 | | - nestedNavigationTabsRepresentation_selectedNavigationTabs = selectedNavigationTabsHashMapForCurrentTab.get(nestedNavigationTabsWidget.getName()); |
275 | | - if (nestedNavigationTabsWidget.propTabs().size() > nestedNavigationTabsRepresentation_selectedNavigationTabs.left) { |
276 | | - nestedNavigationTabsWidget.propActiveTab().setValue(nestedNavigationTabsRepresentation_selectedNavigationTabs.left); |
277 | | - } |
278 | | - } |
279 | | - nestedNavigationTabsRepresentation.selectedNavigationTabs = nestedNavigationTabsRepresentation_selectedNavigationTabs; |
280 | | - } |
281 | | - }); |
| 265 | + // For this tab_id, create or update map of NavTabs children to their selected tab index and sub-navtabs |
| 266 | + final HashMap<String, SelectedNavigationTabs> selectedNavTabsMapForCurrentTab = selectedNavigationTabs.child_navtab_selections.computeIfAbsent(tab_id, tid -> new HashMap<>()); |
| 267 | + |
| 268 | + for (Widget w : new_model.getChildren()) |
| 269 | + if (w instanceof NavigationTabsWidget childNavTab) |
| 270 | + { |
| 271 | + final NavigationTabsRepresentation childRepr = childNavTab.getUserData(Widget.USER_DATA_REPRESENTATION); |
| 272 | + if (childRepr != null) |
| 273 | + { |
| 274 | + SelectedNavigationTabs childRepr_selectedNavigationTabs = selectedNavTabsMapForCurrentTab.get(childNavTab.getName()); |
| 275 | + if (childRepr_selectedNavigationTabs == null) |
| 276 | + { // See childNavTab for the first time? Create its SelectedNavigationTabs with its propActiveTab as start value |
| 277 | + childRepr_selectedNavigationTabs = new SelectedNavigationTabs(childNavTab.propActiveTab().getValue()); |
| 278 | + selectedNavTabsMapForCurrentTab.put(childNavTab.getName(), childRepr_selectedNavigationTabs); |
| 279 | + } |
| 280 | + // Known childNavTab? Re-select its last active tab (if valid index) |
| 281 | + else if (childRepr_selectedNavigationTabs.active_tab < childNavTab.propTabs().size()) |
| 282 | + childNavTab.propActiveTab().setValue(childRepr_selectedNavigationTabs.active_tab); |
| 283 | + |
| 284 | + // childRepr.selectedNavigationTabs was set when the childNavTabRepr got constructed, |
| 285 | + // but it's empty and its reference will be lost when we switch tabs. |
| 286 | + // Replace it with the one that's tracked by the parent navtab (this one) |
| 287 | + childRepr.selectedNavigationTabs = childRepr_selectedNavigationTabs; |
| 288 | + } |
| 289 | + } |
282 | 290 |
|
283 | 291 | model_widget.runtimePropEmbeddedModel().setValue(new_model); |
284 | 292 | } |
|
0 commit comments