From 2af7dfe8e53506be212d9aee8bdbb0b785831723 Mon Sep 17 00:00:00 2001 From: Rebecca Williams Date: Tue, 14 Oct 2025 15:14:49 +0100 Subject: [PATCH 1/5] Add property to configure the 'not_enabled' css styling for widgets --- .../builder/representation/javafx/JFXPreferences.java | 2 ++ .../javafx/widgets/JFXBaseRepresentation.java | 10 ++++++++-- .../src/main/resources/jfx_repr_preferences.properties | 7 +++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/JFXPreferences.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/JFXPreferences.java index efce94633e..c0035ce6fa 100644 --- a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/JFXPreferences.java +++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/JFXPreferences.java @@ -24,6 +24,8 @@ public class JFXPreferences @Preference public static int tooltip_display_sec; /** make the transparent parts of symbols clickable */ @Preference public static boolean pick_on_bounds; + /** Override the default 'not_enabled' css style */ + @Preference public static String not_enabled_style; static { diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/JFXBaseRepresentation.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/JFXBaseRepresentation.java index cd9493c545..bd7e99fab7 100644 --- a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/JFXBaseRepresentation.java +++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/JFXBaseRepresentation.java @@ -27,6 +27,7 @@ import org.csstudio.display.builder.model.widgets.TabsWidget.TabItemProperty; import org.csstudio.display.builder.representation.WidgetRepresentation; import org.csstudio.display.builder.representation.javafx.Cursors; +import org.csstudio.display.builder.representation.javafx.JFXPreferences; import org.csstudio.display.builder.representation.javafx.JFXRepresentation; import javafx.collections.ObservableList; @@ -371,10 +372,15 @@ public void updateOrder() public void setDisabledLook(Boolean enabled, ObservableList children) { if (!toolkit.isEditMode()) { jfx_node.setCursor(enabled ? Cursor.DEFAULT : Cursors.NO_WRITE); - if (children != null) { + if (children != null && !enabled) { for (Node node : children) { - Styles.update(node, Styles.NOT_ENABLED, !enabled); + if (!JFXPreferences.not_enabled_style.equals("")) + // Apply users 'not enabled' style + node.setStyle(node.getStyle()+" "+JFXPreferences.not_enabled_style); + else + // Apply default 'not_enabled' style + Styles.update(node, Styles.NOT_ENABLED, !enabled); } } } diff --git a/app/display/representation-javafx/src/main/resources/jfx_repr_preferences.properties b/app/display/representation-javafx/src/main/resources/jfx_repr_preferences.properties index 11081928b7..e7349d7eec 100644 --- a/app/display/representation-javafx/src/main/resources/jfx_repr_preferences.properties +++ b/app/display/representation-javafx/src/main/resources/jfx_repr_preferences.properties @@ -22,3 +22,10 @@ tooltip_display_sec=30 # of the symbol widget. If false, interaction is # limited to the visible area of the element. pick_on_bounds=false + +# User can set the disabled/not_enabled css styling. Otherwise +# the default will be used which sets the opacity to 0.4. +# E.g. to not change the opacity set +# not_enabled_style=-fx-opacity: 1.0;-fx-background-insets: 0; +# -fx-color: -fx-base; -fx-focus-color: -fx-base; +not_enabled_style= \ No newline at end of file From 9d4979d09dd2d6c49c5beb3be80448766aa43471 Mon Sep 17 00:00:00 2001 From: Rebecca Williams Date: Wed, 15 Oct 2025 17:57:04 +0100 Subject: [PATCH 2/5] Remove 'not_enabled' custom styling when widget becomes enabled --- .../javafx/widgets/JFXBaseRepresentation.java | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/JFXBaseRepresentation.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/JFXBaseRepresentation.java index bd7e99fab7..2c77424da6 100644 --- a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/JFXBaseRepresentation.java +++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/JFXBaseRepresentation.java @@ -372,15 +372,31 @@ public void updateOrder() public void setDisabledLook(Boolean enabled, ObservableList children) { if (!toolkit.isEditMode()) { jfx_node.setCursor(enabled ? Cursor.DEFAULT : Cursors.NO_WRITE); - if (children != null && !enabled) { + if (children != null) { for (Node node : children) { - if (!JFXPreferences.not_enabled_style.equals("")) - // Apply users 'not enabled' style - node.setStyle(node.getStyle()+" "+JFXPreferences.not_enabled_style); - else - // Apply default 'not_enabled' style - Styles.update(node, Styles.NOT_ENABLED, !enabled); + // Apply default 'not_enabled' style + Styles.update(node, Styles.NOT_ENABLED, !enabled); + Boolean useCustomStyling = !JFXPreferences.not_enabled_style.equals(""); + if (useCustomStyling) + { + // Remove 'default' not_enabled styling + Styles.update(node, Styles.NOT_ENABLED, false); + String customCss = "/*CustomCSS START*/" + JFXPreferences.not_enabled_style + + "/*END*/"; + + if (!enabled) + { + // Apply users 'not enabled' style + node.setStyle(node.getStyle()+customCss); + } + else + { + // Remove the users disabled style from the current style + String removeDisabled = node.getStyle().replace(customCss, ""); + node.setStyle(removeDisabled); + } + } } } } From 933d2a2f270e0a89b8db591f6ea6a6e1139c7dc4 Mon Sep 17 00:00:00 2001 From: Rebecca Williams Date: Thu, 16 Oct 2025 14:52:32 +0100 Subject: [PATCH 3/5] Revert changes to override 'not_enabled' styling with custom css --- .../representation/javafx/JFXPreferences.java | 2 -- .../javafx/widgets/JFXBaseRepresentation.java | 22 ------------------- .../resources/jfx_repr_preferences.properties | 7 ------ 3 files changed, 31 deletions(-) diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/JFXPreferences.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/JFXPreferences.java index c0035ce6fa..efce94633e 100644 --- a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/JFXPreferences.java +++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/JFXPreferences.java @@ -24,8 +24,6 @@ public class JFXPreferences @Preference public static int tooltip_display_sec; /** make the transparent parts of symbols clickable */ @Preference public static boolean pick_on_bounds; - /** Override the default 'not_enabled' css style */ - @Preference public static String not_enabled_style; static { diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/JFXBaseRepresentation.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/JFXBaseRepresentation.java index 2c77424da6..cd9493c545 100644 --- a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/JFXBaseRepresentation.java +++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/JFXBaseRepresentation.java @@ -27,7 +27,6 @@ import org.csstudio.display.builder.model.widgets.TabsWidget.TabItemProperty; import org.csstudio.display.builder.representation.WidgetRepresentation; import org.csstudio.display.builder.representation.javafx.Cursors; -import org.csstudio.display.builder.representation.javafx.JFXPreferences; import org.csstudio.display.builder.representation.javafx.JFXRepresentation; import javafx.collections.ObservableList; @@ -375,28 +374,7 @@ public void setDisabledLook(Boolean enabled, ObservableList children) { if (children != null) { for (Node node : children) { - // Apply default 'not_enabled' style Styles.update(node, Styles.NOT_ENABLED, !enabled); - Boolean useCustomStyling = !JFXPreferences.not_enabled_style.equals(""); - if (useCustomStyling) - { - // Remove 'default' not_enabled styling - Styles.update(node, Styles.NOT_ENABLED, false); - String customCss = "/*CustomCSS START*/" + JFXPreferences.not_enabled_style - + "/*END*/"; - - if (!enabled) - { - // Apply users 'not enabled' style - node.setStyle(node.getStyle()+customCss); - } - else - { - // Remove the users disabled style from the current style - String removeDisabled = node.getStyle().replace(customCss, ""); - node.setStyle(removeDisabled); - } - } } } } diff --git a/app/display/representation-javafx/src/main/resources/jfx_repr_preferences.properties b/app/display/representation-javafx/src/main/resources/jfx_repr_preferences.properties index e7349d7eec..11081928b7 100644 --- a/app/display/representation-javafx/src/main/resources/jfx_repr_preferences.properties +++ b/app/display/representation-javafx/src/main/resources/jfx_repr_preferences.properties @@ -22,10 +22,3 @@ tooltip_display_sec=30 # of the symbol widget. If false, interaction is # limited to the visible area of the element. pick_on_bounds=false - -# User can set the disabled/not_enabled css styling. Otherwise -# the default will be used which sets the opacity to 0.4. -# E.g. to not change the opacity set -# not_enabled_style=-fx-opacity: 1.0;-fx-background-insets: 0; -# -fx-color: -fx-base; -fx-focus-color: -fx-base; -not_enabled_style= \ No newline at end of file From 26a710a3175206e9dbe8fc68604c5b136ebdfa86 Mon Sep 17 00:00:00 2001 From: Rebecca Williams Date: Thu, 16 Oct 2025 14:53:49 +0100 Subject: [PATCH 4/5] Allow users to define a custom CSS file that can override defaults Allows users to override the 'not_enabled' styling as well as others used by Phoebus. Introduces a new property that can be set to the path of the CSS file. --- core/ui/src/main/java/org/phoebus/ui/Preferences.java | 2 ++ core/ui/src/main/java/org/phoebus/ui/javafx/Styles.java | 6 ++++++ .../ui/src/main/resources/phoebus_ui_preferences.properties | 6 ++++++ 3 files changed, 14 insertions(+) diff --git a/core/ui/src/main/java/org/phoebus/ui/Preferences.java b/core/ui/src/main/java/org/phoebus/ui/Preferences.java index cb4b8d753a..bf97fb05e6 100644 --- a/core/ui/src/main/java/org/phoebus/ui/Preferences.java +++ b/core/ui/src/main/java/org/phoebus/ui/Preferences.java @@ -95,6 +95,8 @@ public class Preferences @Preference public static boolean save_credentials; /** documentation_location */ @Preference public static String documentation_location; + /** Custom stylings file */ + @Preference public static String custom_css_styling; static { diff --git a/core/ui/src/main/java/org/phoebus/ui/javafx/Styles.java b/core/ui/src/main/java/org/phoebus/ui/javafx/Styles.java index 18cce81cf3..d675319dd8 100644 --- a/core/ui/src/main/java/org/phoebus/ui/javafx/Styles.java +++ b/core/ui/src/main/java/org/phoebus/ui/javafx/Styles.java @@ -7,6 +7,8 @@ ******************************************************************************/ package org.phoebus.ui.javafx; +import org.phoebus.ui.Preferences; + import javafx.scene.Node; import javafx.scene.Scene; @@ -24,6 +26,10 @@ public static void setSceneStyle(final Scene scene) { final String css = Styles.class.getResource("csstudio.css").toExternalForm(); set(scene, css); + if (!Preferences.custom_css_styling.isEmpty()) + { + set(scene, Preferences.custom_css_styling); + } } /** Apply style sheet to scene (but only once) diff --git a/core/ui/src/main/resources/phoebus_ui_preferences.properties b/core/ui/src/main/resources/phoebus_ui_preferences.properties index 4020ae1580..fc85cf612e 100644 --- a/core/ui/src/main/resources/phoebus_ui_preferences.properties +++ b/core/ui/src/main/resources/phoebus_ui_preferences.properties @@ -179,3 +179,9 @@ save_credentials=false # Location of the Phoebus documentation documentation_location= + +# Custom stylings .css file allows users to override Phoebus and JavaFX +# default stylings.Set the full path to the .css file +# For a system file use syntax; 'file:' +# For a file served over http use syntax: 'http://' +custom_css_styling= From 7105d8286a5b44f5fb5fe8018855274ec2f35bcd Mon Sep 17 00:00:00 2001 From: Rebecca Williams Date: Thu, 16 Oct 2025 15:57:09 +0100 Subject: [PATCH 5/5] Add check that provided custom CSS file exists and can be read --- .../main/java/org/phoebus/ui/Preferences.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/core/ui/src/main/java/org/phoebus/ui/Preferences.java b/core/ui/src/main/java/org/phoebus/ui/Preferences.java index bf97fb05e6..1a5866fb0b 100644 --- a/core/ui/src/main/java/org/phoebus/ui/Preferences.java +++ b/core/ui/src/main/java/org/phoebus/ui/Preferences.java @@ -7,6 +7,10 @@ *******************************************************************************/ package org.phoebus.ui; +import java.net.URI; +import java.util.logging.Level; +import java.util.logging.Logger; + import org.phoebus.framework.preferences.AnnotatedPreferences; import org.phoebus.framework.preferences.Preference; @@ -17,6 +21,8 @@ public class Preferences { + public final static Logger logger = Logger.getLogger(Preferences.class.getPackageName()); + /** splash */ public static final String SPLASH = "splash"; /** default_apps */ @@ -106,5 +112,19 @@ public class Preferences // (PVASettings cannot use Preferences.max_array_formatting // since the PVA library may be used standalone) System.setProperty("EPICS_PVA_MAX_ARRAY_FORMATTING", Integer.toString(max_array_formatting)); + + // Check once if the custom style sheet is accessible + if (!custom_css_styling.isBlank()) + { + try + { + new URI(custom_css_styling).toURL().openStream().close(); + } + catch (Exception ex) + { + logger.log(Level.WARNING, custom_css_styling + " is inaccessible", ex); + custom_css_styling = ""; + } + } } }