From 251ed4accda8411914c7d7741f5adf6866be04f1 Mon Sep 17 00:00:00 2001 From: Gabriel Desmarchelier Date: Fri, 19 Dec 2025 11:15:29 +0100 Subject: [PATCH 01/10] create individual color properties for each tab --- .../model/widgets/NavigationTabsWidget.java | 25 ++++++++-- .../javafx/widgets/NavigationTabs.java | 48 ++++++++++++++----- .../widgets/NavigationTabsRepresentation.java | 28 ++++++++--- 3 files changed, 78 insertions(+), 23 deletions(-) diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/NavigationTabsWidget.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/NavigationTabsWidget.java index de21dfdcf0..b774bf25ed 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/NavigationTabsWidget.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/NavigationTabsWidget.java @@ -26,6 +26,7 @@ import org.csstudio.display.builder.model.ArrayWidgetProperty; import org.csstudio.display.builder.model.DisplayModel; import org.csstudio.display.builder.model.MacroizedWidgetProperty; +import org.csstudio.display.builder.model.Messages; import org.csstudio.display.builder.model.StructuredWidgetProperty; import org.csstudio.display.builder.model.Widget; import org.csstudio.display.builder.model.WidgetCategory; @@ -47,6 +48,8 @@ */ public class NavigationTabsWidget extends VisibleWidget { + private static final WidgetColor DEFAULT_SELECT_COLOR = new WidgetColor(236, 236, 236); + private static final WidgetColor DEFAULT_DESELECT_COLOR = new WidgetColor(200, 200, 200); /** Widget descriptor */ public static final WidgetDescriptor WIDGET_DESCRIPTOR = new WidgetDescriptor("navtabs", WidgetCategory.STRUCTURE, @@ -61,10 +64,17 @@ public Widget createWidget() } }; - // 'state' structure that describes one state + // 'tab' structure that describes one tab private static final StructuredWidgetProperty.Descriptor propTab = new StructuredWidgetProperty.Descriptor(WidgetPropertyCategory.BEHAVIOR, "tab", "Tab"); + // Elements of the 'tab' structure + private static final WidgetPropertyDescriptor propIndividualSelectedColor = + CommonWidgetProperties.newColorPropertyDescriptor(WidgetPropertyCategory.DISPLAY, "selected_color", "Selected Color"); + + private static final WidgetPropertyDescriptor propIndividualDeselectedColor = + CommonWidgetProperties.newColorPropertyDescriptor(WidgetPropertyCategory.DISPLAY, "deselected_color", "Deselected Color"); + /** Structure for one tab item and its embedded display */ public static class TabProperty extends StructuredWidgetProperty { @@ -77,7 +87,9 @@ public TabProperty(final Widget widget, final int index) Arrays.asList(propName.createProperty(widget, "Tab " + (index + 1)), propFile.createProperty(widget, ""), propMacros.createProperty(widget, new Macros()), - propGroupName.createProperty(widget, "") + propGroupName.createProperty(widget, ""), + propIndividualSelectedColor.createProperty(widget, DEFAULT_SELECT_COLOR), + propIndividualDeselectedColor.createProperty(widget, DEFAULT_DESELECT_COLOR) )); } /** @return Tab name */ @@ -88,6 +100,11 @@ public TabProperty(final Widget widget, final int index) public WidgetProperty macros() { return getElement(2); } /** @return Optional sub-group of file */ public WidgetProperty group() { return getElement(3); } + /** @return Tab color when selected */ + public WidgetProperty individual_selected_color() { return getElement(4); } + /** @return Tab color when not selected */ + public WidgetProperty individual_deselected_color() { return getElement(5); } + } // 'tabs' array @@ -134,8 +151,8 @@ protected void defineProperties(final List> properties) properties.add(tab_width = propTabWidth.createProperty(this, ActionButtonWidget.DEFAULT_WIDTH)); properties.add(tab_height = propTabHeight.createProperty(this, ActionButtonWidget.DEFAULT_HEIGHT)); properties.add(tab_spacing = propTabSpacing.createProperty(this, 2)); - properties.add(selected_color = propSelectedColor.createProperty(this, new WidgetColor(236, 236, 236))); - properties.add(deselected_color = propDeselectedColor.createProperty(this, new WidgetColor(200, 200, 200))); + properties.add(selected_color = propSelectedColor.createProperty(this, DEFAULT_SELECT_COLOR)); + properties.add(deselected_color = propDeselectedColor.createProperty(this, DEFAULT_DESELECT_COLOR)); properties.add(font = propFont.createProperty(this, WidgetFontService.get(NamedWidgetFonts.DEFAULT))); properties.add(active = propActiveTab.createProperty(this, 0)); properties.add(embedded_model = runtimeModel.createProperty(this, null)); diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabs.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabs.java index 7af2b89f6d..e8e26b2e71 100644 --- a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabs.java +++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabs.java @@ -12,7 +12,9 @@ import java.util.concurrent.CopyOnWriteArrayList; import org.csstudio.display.builder.model.properties.Direction; +import org.csstudio.display.builder.model.properties.WidgetColor; import org.csstudio.display.builder.representation.javafx.JFXUtil; +import org.phoebus.ui.javafx.NonCachingScrollPane; import javafx.collections.ObservableList; import javafx.css.PseudoClass; @@ -26,7 +28,6 @@ import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.scene.text.Font; -import org.phoebus.ui.javafx.NonCachingScrollPane; /** Navigation Tabs * @@ -72,8 +73,15 @@ public static interface Listener private final Pane body = new Pane(); /** Labels for the tabs */ - private final List tabs = new CopyOnWriteArrayList<>(); + private final List tab_names = new CopyOnWriteArrayList<>(); + + /** Selected colors for the tabs */ + private final List tab_selected_colors = new CopyOnWriteArrayList<>(); + + /** Deselected colors for the tabs */ + private final List tab_deselected_colors = new CopyOnWriteArrayList<>(); + /** Size and spacing for the tabs */ private int tab_width = 100, tab_height = 50, tab_spacing = 2; /** Direction of tabs */ @@ -84,6 +92,7 @@ public static interface Listener deselected = Color.rgb(200, 200, 200); private Font font = null; + private int selected_tab = -1; /** Listener to selected tab * @@ -123,21 +132,33 @@ public void removeListener(final Listener listener) } /** @param tabs Tab labels */ - public void setTabs(final List tabs) + public void setTabNames(final List tab_names) + { + this.tab_names.clear(); + this.tab_names.addAll(tab_names); + updateTabs(); + } + + /** @param tabs Selected colors */ + public void setTabSelectedColors(final List tab_selected_colors) { - this.tabs.clear(); - this.tabs.addAll(tabs); + this.tab_selected_colors.clear(); + this.tab_selected_colors.addAll(tab_selected_colors); + updateTabs(); + } + + /** @param tabs Deselected colors */ + public void setTabDeselectedColors(final List tab_deselected_colors) + { + this.tab_deselected_colors.clear(); + this.tab_deselected_colors.addAll(tab_deselected_colors); updateTabs(); } /** @return Index of the selected tab. -1 if there are no buttons or nothing selected */ public int getSelectedTab() { - final ObservableList siblings = buttons.getChildren(); - for (int i=0; i siblings = buttons.getChildren(); + int i = 0; + selected_tab = -1; int i = 0, selected_tab = -1; for (Node sibling : siblings) { diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabsRepresentation.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabsRepresentation.java index 6f42f09f06..fd89598c3b 100644 --- a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabsRepresentation.java +++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabsRepresentation.java @@ -24,6 +24,7 @@ import org.csstudio.display.builder.model.Widget; import org.csstudio.display.builder.model.WidgetProperty; import org.csstudio.display.builder.model.WidgetPropertyListener; +import org.csstudio.display.builder.model.properties.WidgetColor; import org.csstudio.display.builder.model.widgets.NavigationTabsWidget; import org.csstudio.display.builder.model.widgets.NavigationTabsWidget.TabProperty; import org.csstudio.display.builder.representation.EmbeddedDisplayRepresentationUtil.DisplayAndGroup; @@ -98,7 +99,7 @@ private static class SelectedNavigationTabs */ private final AtomicReference active_content_model = new AtomicReference<>(); - private final WidgetPropertyListener tab_name_listener = (property, old_value, new_value) -> + private final UntypedWidgetPropertyListener tabs_listener = (property, old_value, new_value) -> { dirty_tabs.mark(); toolkit.scheduleUpdate(this); @@ -348,10 +349,12 @@ private void removeTabs(final List removed) { for (TabProperty tab : removed) { - tab.name().removePropertyListener(tab_name_listener); + tab.name().removePropertyListener(tabs_listener); tab.file().removePropertyListener(tab_display_listener); tab.macros().removePropertyListener(tab_display_listener); tab.group().removePropertyListener(tab_display_listener); + tab.individual_selected_color().removePropertyListener(tabs_listener); + tab.individual_deselected_color().removePropertyListener(tabs_listener); } } @@ -359,10 +362,12 @@ private void addTabs(final List added) { for (TabProperty tab : added) { + tab.individual_selected_color().addUntypedPropertyListener(tabs_listener); + tab.individual_deselected_color().addUntypedPropertyListener(tabs_listener); tab.group().addUntypedPropertyListener(tab_display_listener); tab.macros().addUntypedPropertyListener(tab_display_listener); tab.file().addUntypedPropertyListener(tab_display_listener); - tab.name().addPropertyListener(tab_name_listener); + tab.name().addUntypedPropertyListener(tabs_listener); } } @@ -388,9 +393,20 @@ public void updateChanges() } if (dirty_tabs.checkAndClear()) { - final List tabs = new ArrayList<>(); - model_widget.propTabs().getValue().forEach(tab -> tabs.add(tab.name().getValue())); - jfx_node.setTabs(tabs); + final List tab_names = new ArrayList<>(); + final List tab_selected_colors = new ArrayList<>(); + final List tab_deselected_colors = new ArrayList<>(); + + List tabList = model_widget.propTabs().getValue(); + tabList.forEach(tab -> { + tab_names.add(tab.name().getValue()); + tab_selected_colors.add(tab.individual_selected_color().getValue()); + tab_deselected_colors.add(tab.individual_deselected_color().getValue()); + }); + + jfx_node.setTabNames(tab_names); + jfx_node.setTabSelectedColors(tab_selected_colors); + jfx_node.setTabDeselectedColors(tab_deselected_colors); } if (dirty_active_tab.checkAndClear()) jfx_node.selectTab(model_widget.propActiveTab().getValue()); From c0bef377a7321c737b38bb29e60bfe9477ac326d Mon Sep 17 00:00:00 2001 From: Gabriel Desmarchelier Date: Fri, 19 Dec 2025 11:40:28 +0100 Subject: [PATCH 02/10] create enable_individual_colors propert for navtabs and manage the widget accordingly --- .../model/widgets/NavigationTabsWidget.java | 19 ++++-- .../javafx/widgets/NavigationTabs.java | 65 +++++++++++++++++-- .../widgets/NavigationTabsRepresentation.java | 3 + 3 files changed, 79 insertions(+), 8 deletions(-) diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/NavigationTabsWidget.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/NavigationTabsWidget.java index b774bf25ed..65ae853686 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/NavigationTabsWidget.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/NavigationTabsWidget.java @@ -8,6 +8,7 @@ package org.csstudio.display.builder.model.widgets; import static org.csstudio.display.builder.model.ModelPlugin.logger; +import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.newBooleanPropertyDescriptor; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propDirection; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propFile; import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propFont; @@ -50,7 +51,7 @@ public class NavigationTabsWidget extends VisibleWidget { private static final WidgetColor DEFAULT_SELECT_COLOR = new WidgetColor(236, 236, 236); private static final WidgetColor DEFAULT_DESELECT_COLOR = new WidgetColor(200, 200, 200); - /** Widget descriptor */ + /** Widget descriptor */ public static final WidgetDescriptor WIDGET_DESCRIPTOR = new WidgetDescriptor("navtabs", WidgetCategory.STRUCTURE, "Navigation Tabs", @@ -118,15 +119,18 @@ public TabProperty(final Widget widget, final int index) private static final WidgetPropertyDescriptor propTabSpacing = CommonWidgetProperties.newIntegerPropertyDescriptor(WidgetPropertyCategory.DISPLAY, "tab_spacing", "Tab Spacing"); - private static final WidgetPropertyDescriptor propDeselectedColor = - CommonWidgetProperties.newColorPropertyDescriptor(WidgetPropertyCategory.DISPLAY, "deselected_color", "Deselected Color"); - + private static final WidgetPropertyDescriptor propEnablePerTabColors = + CommonWidgetProperties.newBooleanPropertyDescriptor(WidgetPropertyCategory.DISPLAY, "enable_per_tab_colors", "Per Tab Colors"); + private static final WidgetPropertyDescriptor propDeselectedColor = + CommonWidgetProperties.newColorPropertyDescriptor(WidgetPropertyCategory.DISPLAY, "deselected_color", "Deselected Color"); + private volatile ArrayWidgetProperty tabs; private volatile WidgetProperty direction; private volatile WidgetProperty tab_width; private volatile WidgetProperty tab_height; private volatile WidgetProperty tab_spacing; + private volatile WidgetProperty enable_per_tab_colors; private volatile WidgetProperty selected_color; private volatile WidgetProperty deselected_color; private volatile WidgetProperty font; @@ -151,6 +155,7 @@ protected void defineProperties(final List> properties) properties.add(tab_width = propTabWidth.createProperty(this, ActionButtonWidget.DEFAULT_WIDTH)); properties.add(tab_height = propTabHeight.createProperty(this, ActionButtonWidget.DEFAULT_HEIGHT)); properties.add(tab_spacing = propTabSpacing.createProperty(this, 2)); + properties.add(enable_per_tab_colors = propEnablePerTabColors.createProperty(this, false)); properties.add(selected_color = propSelectedColor.createProperty(this, DEFAULT_SELECT_COLOR)); properties.add(deselected_color = propDeselectedColor.createProperty(this, DEFAULT_DESELECT_COLOR)); properties.add(font = propFont.createProperty(this, WidgetFontService.get(NamedWidgetFonts.DEFAULT))); @@ -188,6 +193,12 @@ public WidgetProperty propTabSpacing() return tab_spacing; } + /** @return 'enable_per_tab_colors' property */ + public WidgetProperty propEnablePerTabColors() + { + return enable_per_tab_colors; + } + /** @return 'selected_color' property */ public WidgetProperty propSelectedColor() { diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabs.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabs.java index e8e26b2e71..3ecbd7aab6 100644 --- a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabs.java +++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabs.java @@ -84,6 +84,9 @@ public static interface Listener /** Size and spacing for the tabs */ private int tab_width = 100, tab_height = 50, tab_spacing = 2; + /** Enable per tab colors */ + private boolean enable_per_tab_colors = false; + /** Direction of tabs */ private Direction direction = Direction.VERTICAL; @@ -223,6 +226,15 @@ public void setTabSpacing(final int spacing) updateTabs(); } + /** @param enable per tab colors */ + public void setEnablePerTabColors(final boolean enabled) + { + if (enable_per_tab_colors == enabled) + return; + enable_per_tab_colors = enabled; + updateTabs(); + } + /** @param color Color for selected tab */ public void setSelectedColor(final Color color) { @@ -271,6 +283,9 @@ private void updateTabs() buttons.getStyleClass().add("navtab_tabregion"); // Create button for each tab + Color tmpColor = deselected; + WidgetColor tmpWidgetColor = null; + for (int i = 0; i < tab_names.size(); ++i) { final ToggleButton button = new ToggleButton(tab_names.get(i)); // Buttons without text vanish, creating a gap in the tab lineup. @@ -279,8 +294,31 @@ private void updateTabs() if (direction == Direction.HORIZONTAL) button.pseudoClassStateChanged(HORIZONTAL, true); + if (getSelectedTab() == i) { + button.setSelected(true); + // Set color to global "selected" color value + tmpColor = selected; + // If the per-tab colors are enabled, the color to apply is to be found in the tab_selected_colors list + if (enable_per_tab_colors == true) { + if (i < tab_selected_colors.size()) { + tmpWidgetColor = tab_selected_colors.get(i); + tmpColor = JFXUtil.convert(tmpWidgetColor); + } + } + } else { + // Set color to global "deselected" color value + tmpColor = deselected; + // If the per-tab colors are enabled, the color to apply is to be found in the tab_deselected_colors list + if (enable_per_tab_colors == true) { + if (i < tab_deselected_colors.size()) { + tmpWidgetColor = tab_deselected_colors.get(i); + tmpColor = JFXUtil.convert(tmpWidgetColor); + } + } + } + // base color, '-fx-color', is either selected or deselected - button.setStyle("-fx-color: " + JFXUtil.webRGB(deselected)); + button.setStyle("-fx-color: " + JFXUtil.webRGB(tmpColor)); button.getStyleClass().add("navtab_button"); button.setMinSize(ButtonBase.USE_PREF_SIZE, ButtonBase.USE_PREF_SIZE); button.setPrefSize(tab_width, tab_height); @@ -299,12 +337,15 @@ private void handleTabSelection(final ToggleButton pressed, final boolean notify final ObservableList siblings = buttons.getChildren(); int i = 0; selected_tab = -1; - int i = 0, selected_tab = -1; + Color tmpColor = deselected; + WidgetColor tmpWidgetColor = null; for (Node sibling : siblings) { final ToggleButton button = (ToggleButton) sibling; if (button == pressed) { + // Set color to global "selected" color value + tmpColor = selected; // If user clicked a button that was already selected, // it would now be de-selected, leaving nothing selected. if (! pressed.isSelected()) @@ -312,14 +353,30 @@ private void handleTabSelection(final ToggleButton pressed, final boolean notify pressed.setSelected(true); } // Highlight active tab by setting it to the 'selected' color - pressed.setStyle("-fx-color: " + JFXUtil.webRGB(selected)); + // If the per-tab colors are enabled, the color to apply is to be found in the tab_selected_colors list + if (enable_per_tab_colors == true) { + if(i < tab_selected_colors.size()) { + tmpWidgetColor = tab_selected_colors.get(i); + tmpColor = JFXUtil.convert(tmpWidgetColor); + } + } + pressed.setStyle("-fx-color: " + JFXUtil.webRGB(tmpColor)); selected_tab = i; } else if (button.isSelected()) { // Radio-button behavior: De-select other tabs button.setSelected(false); - button.setStyle("-fx-color: " + JFXUtil.webRGB(deselected)); + // Set color to global "deselected" color value + tmpColor = deselected; + // If the per-tab colors are enabled, the color to apply is to be found in the tab_deselected_colors list + if (enable_per_tab_colors == true) { + if(i < tab_deselected_colors.size()) { + tmpWidgetColor = tab_deselected_colors.get(i); + tmpColor = JFXUtil.convert(tmpWidgetColor); + } + } + button.setStyle("-fx-color: " + JFXUtil.webRGB(tmpColor)); } ++i; } diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabsRepresentation.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabsRepresentation.java index fd89598c3b..d550bb265b 100644 --- a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabsRepresentation.java +++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabsRepresentation.java @@ -165,6 +165,7 @@ protected void registerListeners() model_widget.propTabWidth().addUntypedPropertyListener(tabLookChangedListener); model_widget.propTabHeight().addUntypedPropertyListener(tabLookChangedListener); model_widget.propTabSpacing().addUntypedPropertyListener(tabLookChangedListener); + model_widget.propEnablePerTabColors().addUntypedPropertyListener(tabLookChangedListener); model_widget.propSelectedColor().addUntypedPropertyListener(tabLookChangedListener); model_widget.propDeselectedColor().addUntypedPropertyListener(tabLookChangedListener); model_widget.propFont().addUntypedPropertyListener(tabLookChangedListener); @@ -188,6 +189,7 @@ protected void unregisterListeners() model_widget.propTabWidth().removePropertyListener(tabLookChangedListener); model_widget.propTabHeight().removePropertyListener(tabLookChangedListener); model_widget.propTabSpacing().removePropertyListener(tabLookChangedListener); + model_widget.propEnablePerTabColors().removePropertyListener(tabLookChangedListener); model_widget.propSelectedColor().removePropertyListener(tabLookChangedListener); model_widget.propDeselectedColor().removePropertyListener(tabLookChangedListener); model_widget.propFont().removePropertyListener(tabLookChangedListener); @@ -387,6 +389,7 @@ public void updateChanges() jfx_node.setTabSize(model_widget.propTabWidth().getValue(), model_widget.propTabHeight().getValue()); jfx_node.setTabSpacing(model_widget.propTabSpacing().getValue()); + jfx_node.setEnablePerTabColors(model_widget.propEnablePerTabColors().getValue()); jfx_node.setSelectedColor(JFXUtil.convert(model_widget.propSelectedColor().getValue())); jfx_node.setDeselectedColor(JFXUtil.convert(model_widget.propDeselectedColor().getValue())); jfx_node.setFont(JFXUtil.convert(model_widget.propFont().getValue())); From e96f8d67625235e85ad24f170babb4bbef774f29 Mon Sep 17 00:00:00 2001 From: Gabriel Desmarchelier Date: Fri, 19 Dec 2025 13:12:55 +0100 Subject: [PATCH 03/10] fix call to setTabNames in NavigationTabsDemo.java --- .../representation/javafx/sandbox/NavigationTabsDemo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/display/representation-javafx/src/test/java/org/csstudio/display/builder/representation/javafx/sandbox/NavigationTabsDemo.java b/app/display/representation-javafx/src/test/java/org/csstudio/display/builder/representation/javafx/sandbox/NavigationTabsDemo.java index b68cb16986..251b10cffc 100644 --- a/app/display/representation-javafx/src/test/java/org/csstudio/display/builder/representation/javafx/sandbox/NavigationTabsDemo.java +++ b/app/display/representation-javafx/src/test/java/org/csstudio/display/builder/representation/javafx/sandbox/NavigationTabsDemo.java @@ -35,7 +35,7 @@ public void start(final Stage stage) final NavigationTabs nav_tabs = new NavigationTabs(); final List tabs = IntStream.range(1, 10).mapToObj(i -> "Step" + i).collect(Collectors.toList()); - nav_tabs.setTabs(tabs); + nav_tabs.setTabNames(tabs); nav_tabs.setTabSize(80, 40); nav_tabs.setTabSpacing(5); nav_tabs.getBodyPane().getChildren().setAll(new Label(" Go on, select something!")); From 400445a925a7fed596a2b10c80f00c9978e2af0d Mon Sep 17 00:00:00 2001 From: Gabriel Desmarchelier Date: Wed, 7 Jan 2026 16:45:52 +0100 Subject: [PATCH 04/10] NavigationTabs : fix minor typo issues --- .../javafx/widgets/NavigationTabs.java | 12 ++++++------ .../javafx/widgets/NavigationTabsRepresentation.java | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabs.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabs.java index 3ecbd7aab6..7c3644fbaa 100644 --- a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabs.java +++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabs.java @@ -299,7 +299,7 @@ private void updateTabs() // Set color to global "selected" color value tmpColor = selected; // If the per-tab colors are enabled, the color to apply is to be found in the tab_selected_colors list - if (enable_per_tab_colors == true) { + if (enable_per_tab_colors) { if (i < tab_selected_colors.size()) { tmpWidgetColor = tab_selected_colors.get(i); tmpColor = JFXUtil.convert(tmpWidgetColor); @@ -309,7 +309,7 @@ private void updateTabs() // Set color to global "deselected" color value tmpColor = deselected; // If the per-tab colors are enabled, the color to apply is to be found in the tab_deselected_colors list - if (enable_per_tab_colors == true) { + if (enable_per_tab_colors) { if (i < tab_deselected_colors.size()) { tmpWidgetColor = tab_deselected_colors.get(i); tmpColor = JFXUtil.convert(tmpWidgetColor); @@ -354,8 +354,8 @@ private void handleTabSelection(final ToggleButton pressed, final boolean notify } // Highlight active tab by setting it to the 'selected' color // If the per-tab colors are enabled, the color to apply is to be found in the tab_selected_colors list - if (enable_per_tab_colors == true) { - if(i < tab_selected_colors.size()) { + if (enable_per_tab_colors) { + if (i < tab_selected_colors.size()) { tmpWidgetColor = tab_selected_colors.get(i); tmpColor = JFXUtil.convert(tmpWidgetColor); } @@ -370,8 +370,8 @@ else if (button.isSelected()) // Set color to global "deselected" color value tmpColor = deselected; // If the per-tab colors are enabled, the color to apply is to be found in the tab_deselected_colors list - if (enable_per_tab_colors == true) { - if(i < tab_deselected_colors.size()) { + if (enable_per_tab_colors) { + if (i < tab_deselected_colors.size()) { tmpWidgetColor = tab_deselected_colors.get(i); tmpColor = JFXUtil.convert(tmpWidgetColor); } diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabsRepresentation.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabsRepresentation.java index d550bb265b..46f7dd9545 100644 --- a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabsRepresentation.java +++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabsRepresentation.java @@ -397,9 +397,9 @@ public void updateChanges() if (dirty_tabs.checkAndClear()) { final List tab_names = new ArrayList<>(); - final List tab_selected_colors = new ArrayList<>(); - final List tab_deselected_colors = new ArrayList<>(); - + final List tab_selected_colors = new ArrayList<>(); + final List tab_deselected_colors = new ArrayList<>(); + List tabList = model_widget.propTabs().getValue(); tabList.forEach(tab -> { tab_names.add(tab.name().getValue()); From e4041387cad59b3a66389a93aa8df91fa766b75c Mon Sep 17 00:00:00 2001 From: Gabriel Desmarchelier Date: Wed, 7 Jan 2026 16:50:18 +0100 Subject: [PATCH 05/10] NavigationTabs : indentation is consistent in using 4 spaces --- .../model/widgets/NavigationTabsWidget.java | 6 +- .../javafx/widgets/NavigationTabs.java | 74 +++++++++---------- .../widgets/NavigationTabsRepresentation.java | 2 +- 3 files changed, 41 insertions(+), 41 deletions(-) diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/NavigationTabsWidget.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/NavigationTabsWidget.java index 65ae853686..ec723afa38 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/NavigationTabsWidget.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/NavigationTabsWidget.java @@ -49,9 +49,9 @@ */ public class NavigationTabsWidget extends VisibleWidget { - private static final WidgetColor DEFAULT_SELECT_COLOR = new WidgetColor(236, 236, 236); - private static final WidgetColor DEFAULT_DESELECT_COLOR = new WidgetColor(200, 200, 200); - /** Widget descriptor */ + private static final WidgetColor DEFAULT_SELECT_COLOR = new WidgetColor(236, 236, 236); + private static final WidgetColor DEFAULT_DESELECT_COLOR = new WidgetColor(200, 200, 200); + /** Widget descriptor */ public static final WidgetDescriptor WIDGET_DESCRIPTOR = new WidgetDescriptor("navtabs", WidgetCategory.STRUCTURE, "Navigation Tabs", diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabs.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabs.java index 7c3644fbaa..4553c841bc 100644 --- a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabs.java +++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabs.java @@ -286,36 +286,36 @@ private void updateTabs() Color tmpColor = deselected; WidgetColor tmpWidgetColor = null; - for (int i = 0; i < tab_names.size(); ++i) { - final ToggleButton button = new ToggleButton(tab_names.get(i)); + for (int i = 0; i < tab_names.size(); ++i) { + final ToggleButton button = new ToggleButton(tab_names.get(i)); // Buttons without text vanish, creating a gap in the tab lineup. if (button.getText().isEmpty()) button.setVisible(false); if (direction == Direction.HORIZONTAL) button.pseudoClassStateChanged(HORIZONTAL, true); - if (getSelectedTab() == i) { - button.setSelected(true); - // Set color to global "selected" color value - tmpColor = selected; - // If the per-tab colors are enabled, the color to apply is to be found in the tab_selected_colors list - if (enable_per_tab_colors) { - if (i < tab_selected_colors.size()) { - tmpWidgetColor = tab_selected_colors.get(i); - tmpColor = JFXUtil.convert(tmpWidgetColor); - } - } - } else { - // Set color to global "deselected" color value - tmpColor = deselected; - // If the per-tab colors are enabled, the color to apply is to be found in the tab_deselected_colors list - if (enable_per_tab_colors) { - if (i < tab_deselected_colors.size()) { - tmpWidgetColor = tab_deselected_colors.get(i); - tmpColor = JFXUtil.convert(tmpWidgetColor); - } - } - } + if (getSelectedTab() == i) { + button.setSelected(true); + // Set color to global "selected" color value + tmpColor = selected; + // If the per-tab colors are enabled, the color to apply is to be found in the tab_selected_colors list + if (enable_per_tab_colors) { + if (i < tab_selected_colors.size()) { + tmpWidgetColor = tab_selected_colors.get(i); + tmpColor = JFXUtil.convert(tmpWidgetColor); + } + } + } else { + // Set color to global "deselected" color value + tmpColor = deselected; + // If the per-tab colors are enabled, the color to apply is to be found in the tab_deselected_colors list + if (enable_per_tab_colors) { + if (i < tab_deselected_colors.size()) { + tmpWidgetColor = tab_deselected_colors.get(i); + tmpColor = JFXUtil.convert(tmpWidgetColor); + } + } + } // base color, '-fx-color', is either selected or deselected button.setStyle("-fx-color: " + JFXUtil.webRGB(tmpColor)); @@ -344,8 +344,8 @@ private void handleTabSelection(final ToggleButton pressed, final boolean notify final ToggleButton button = (ToggleButton) sibling; if (button == pressed) { - // Set color to global "selected" color value - tmpColor = selected; + // Set color to global "selected" color value + tmpColor = selected; // If user clicked a button that was already selected, // it would now be de-selected, leaving nothing selected. if (! pressed.isSelected()) @@ -355,10 +355,10 @@ private void handleTabSelection(final ToggleButton pressed, final boolean notify // Highlight active tab by setting it to the 'selected' color // If the per-tab colors are enabled, the color to apply is to be found in the tab_selected_colors list if (enable_per_tab_colors) { - if (i < tab_selected_colors.size()) { - tmpWidgetColor = tab_selected_colors.get(i); - tmpColor = JFXUtil.convert(tmpWidgetColor); - } + if (i < tab_selected_colors.size()) { + tmpWidgetColor = tab_selected_colors.get(i); + tmpColor = JFXUtil.convert(tmpWidgetColor); + } } pressed.setStyle("-fx-color: " + JFXUtil.webRGB(tmpColor)); selected_tab = i; @@ -367,14 +367,14 @@ else if (button.isSelected()) { // Radio-button behavior: De-select other tabs button.setSelected(false); - // Set color to global "deselected" color value - tmpColor = deselected; - // If the per-tab colors are enabled, the color to apply is to be found in the tab_deselected_colors list + // Set color to global "deselected" color value + tmpColor = deselected; + // If the per-tab colors are enabled, the color to apply is to be found in the tab_deselected_colors list if (enable_per_tab_colors) { - if (i < tab_deselected_colors.size()) { - tmpWidgetColor = tab_deselected_colors.get(i); - tmpColor = JFXUtil.convert(tmpWidgetColor); - } + if (i < tab_deselected_colors.size()) { + tmpWidgetColor = tab_deselected_colors.get(i); + tmpColor = JFXUtil.convert(tmpWidgetColor); + } } button.setStyle("-fx-color: " + JFXUtil.webRGB(tmpColor)); } diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabsRepresentation.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabsRepresentation.java index 46f7dd9545..81eb2346e9 100644 --- a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabsRepresentation.java +++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabsRepresentation.java @@ -351,7 +351,7 @@ private void removeTabs(final List removed) { for (TabProperty tab : removed) { - tab.name().removePropertyListener(tabs_listener); + tab.name().removePropertyListener(tabs_listener); tab.file().removePropertyListener(tab_display_listener); tab.macros().removePropertyListener(tab_display_listener); tab.group().removePropertyListener(tab_display_listener); From f425702e5b39459cfd2cc981566bf706446a9def Mon Sep 17 00:00:00 2001 From: Gabriel Desmarchelier Date: Wed, 7 Jan 2026 17:28:39 +0100 Subject: [PATCH 06/10] NavigationTabs : using a single setTabs method to update Tabs --- .../javafx/widgets/NavigationTabs.java | 16 ++-------------- .../widgets/NavigationTabsRepresentation.java | 4 +--- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabs.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabs.java index 4553c841bc..d8cf6774fd 100644 --- a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabs.java +++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabs.java @@ -134,25 +134,13 @@ public void removeListener(final Listener listener) this.listener = null; } - /** @param tabs Tab labels */ - public void setTabNames(final List tab_names) + /** @param tabs Tabs */ + public void setTabs(final List tab_names, final List tab_selected_colors, final List tab_deselected_colors) { this.tab_names.clear(); this.tab_names.addAll(tab_names); - updateTabs(); - } - - /** @param tabs Selected colors */ - public void setTabSelectedColors(final List tab_selected_colors) - { this.tab_selected_colors.clear(); this.tab_selected_colors.addAll(tab_selected_colors); - updateTabs(); - } - - /** @param tabs Deselected colors */ - public void setTabDeselectedColors(final List tab_deselected_colors) - { this.tab_deselected_colors.clear(); this.tab_deselected_colors.addAll(tab_deselected_colors); updateTabs(); diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabsRepresentation.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabsRepresentation.java index 81eb2346e9..bb1965770f 100644 --- a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabsRepresentation.java +++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabsRepresentation.java @@ -407,9 +407,7 @@ public void updateChanges() tab_deselected_colors.add(tab.individual_deselected_color().getValue()); }); - jfx_node.setTabNames(tab_names); - jfx_node.setTabSelectedColors(tab_selected_colors); - jfx_node.setTabDeselectedColors(tab_deselected_colors); + jfx_node.setTabs(tab_names, tab_selected_colors, tab_deselected_colors); } if (dirty_active_tab.checkAndClear()) jfx_node.selectTab(model_widget.propActiveTab().getValue()); From 6e6247c5588b768c95f95e4e016c58b895f201ee Mon Sep 17 00:00:00 2001 From: Gabriel Desmarchelier Date: Wed, 7 Jan 2026 17:34:45 +0100 Subject: [PATCH 07/10] NavigatonTabs : fix minor typo issues --- .../display/builder/model/widgets/NavigationTabsWidget.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/NavigationTabsWidget.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/NavigationTabsWidget.java index ec723afa38..945e318e78 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/NavigationTabsWidget.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/NavigationTabsWidget.java @@ -91,7 +91,7 @@ public TabProperty(final Widget widget, final int index) propGroupName.createProperty(widget, ""), propIndividualSelectedColor.createProperty(widget, DEFAULT_SELECT_COLOR), propIndividualDeselectedColor.createProperty(widget, DEFAULT_DESELECT_COLOR) - )); + )); } /** @return Tab name */ public WidgetProperty name() { return getElement(0); } @@ -105,7 +105,6 @@ public TabProperty(final Widget widget, final int index) public WidgetProperty individual_selected_color() { return getElement(4); } /** @return Tab color when not selected */ public WidgetProperty individual_deselected_color() { return getElement(5); } - } // 'tabs' array @@ -274,4 +273,4 @@ public Macros getEffectiveMacros() } return base; } -} +} \ No newline at end of file From 272a54073fe15451d7767128e070901d671d0b74 Mon Sep 17 00:00:00 2001 From: Gabriel Desmarchelier Date: Wed, 7 Jan 2026 17:36:06 +0100 Subject: [PATCH 08/10] remove Messages import --- .../display/builder/model/widgets/NavigationTabsWidget.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/NavigationTabsWidget.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/NavigationTabsWidget.java index 945e318e78..0caa566aba 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/NavigationTabsWidget.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/NavigationTabsWidget.java @@ -27,7 +27,6 @@ import org.csstudio.display.builder.model.ArrayWidgetProperty; import org.csstudio.display.builder.model.DisplayModel; import org.csstudio.display.builder.model.MacroizedWidgetProperty; -import org.csstudio.display.builder.model.Messages; import org.csstudio.display.builder.model.StructuredWidgetProperty; import org.csstudio.display.builder.model.Widget; import org.csstudio.display.builder.model.WidgetCategory; From 7f4f7261c676e7ee48e5ec33a47aea4912db47b3 Mon Sep 17 00:00:00 2001 From: Gabriel Desmarchelier Date: Wed, 7 Jan 2026 17:39:52 +0100 Subject: [PATCH 09/10] NavigatonTabs : fix minor typo issues --- .../display/builder/model/widgets/NavigationTabsWidget.java | 2 +- .../builder/representation/javafx/widgets/NavigationTabs.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/NavigationTabsWidget.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/NavigationTabsWidget.java index 0caa566aba..cd2370a5e5 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/NavigationTabsWidget.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/widgets/NavigationTabsWidget.java @@ -272,4 +272,4 @@ public Macros getEffectiveMacros() } return base; } -} \ No newline at end of file +} diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabs.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabs.java index d8cf6774fd..84d8e1f5de 100644 --- a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabs.java +++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/NavigationTabs.java @@ -273,7 +273,7 @@ private void updateTabs() // Create button for each tab Color tmpColor = deselected; WidgetColor tmpWidgetColor = null; - + for (int i = 0; i < tab_names.size(); ++i) { final ToggleButton button = new ToggleButton(tab_names.get(i)); // Buttons without text vanish, creating a gap in the tab lineup. @@ -373,4 +373,4 @@ else if (button.isSelected()) if (selected_tab >= 0 && notify && safe_copy != null) safe_copy.tabSelected(selected_tab); } -} \ No newline at end of file +} From 666a19e7361c271e789846afaad138766ca670db Mon Sep 17 00:00:00 2001 From: Gabriel Desmarchelier Date: Wed, 7 Jan 2026 17:51:15 +0100 Subject: [PATCH 10/10] NavigationTabs : fix NavigationTabsDemo.java --- .../representation/javafx/sandbox/NavigationTabsDemo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/display/representation-javafx/src/test/java/org/csstudio/display/builder/representation/javafx/sandbox/NavigationTabsDemo.java b/app/display/representation-javafx/src/test/java/org/csstudio/display/builder/representation/javafx/sandbox/NavigationTabsDemo.java index 251b10cffc..b68cb16986 100644 --- a/app/display/representation-javafx/src/test/java/org/csstudio/display/builder/representation/javafx/sandbox/NavigationTabsDemo.java +++ b/app/display/representation-javafx/src/test/java/org/csstudio/display/builder/representation/javafx/sandbox/NavigationTabsDemo.java @@ -35,7 +35,7 @@ public void start(final Stage stage) final NavigationTabs nav_tabs = new NavigationTabs(); final List tabs = IntStream.range(1, 10).mapToObj(i -> "Step" + i).collect(Collectors.toList()); - nav_tabs.setTabNames(tabs); + nav_tabs.setTabs(tabs); nav_tabs.setTabSize(80, 40); nav_tabs.setTabSpacing(5); nav_tabs.getBodyPane().getChildren().setAll(new Label(" Go on, select something!"));