diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/TextEntryRepresentation.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/TextEntryRepresentation.java index 9829da1c64..e2d34d906b 100644 --- a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/TextEntryRepresentation.java +++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/TextEntryRepresentation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015-2018 Oak Ridge National Laboratory. + * Copyright (c) 2015-2024 Oak Ridge National Laboratory. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -9,6 +9,7 @@ import static org.csstudio.display.builder.representation.ToolkitRepresentation.logger; +import java.util.concurrent.TimeUnit; import java.util.logging.Level; import javafx.css.PseudoClass; @@ -20,6 +21,7 @@ import org.csstudio.display.builder.model.WidgetPropertyListener; import org.csstudio.display.builder.model.persist.NamedWidgetColors; import org.csstudio.display.builder.model.persist.WidgetColorService; +import org.csstudio.display.builder.model.properties.VerticalAlignment; import org.csstudio.display.builder.model.properties.WidgetColor; import org.csstudio.display.builder.model.widgets.PVWidget; import org.csstudio.display.builder.model.widgets.TextEntryWidget; @@ -423,7 +425,25 @@ else if(jfx_node instanceof TextArea){ if (! active) { if (dirty_content.checkAndClear()) + { + // For middle-aligned multi-line text, keep the scroll position + final TextArea area = jfx_node instanceof TextArea ? (TextArea) jfx_node : null; + final VerticalAlignment align = model_widget.propVerticalAlignment().getValue(); + double pos = 0; + if (area != null && align == VerticalAlignment.MIDDLE) + pos = area.getScrollTop(); + jfx_node.setText(value_text); + + if (area != null && pos != 0) + area.setScrollTop(pos); + // For bottom scroll detail, see comments in TextUpdateRepresentation + if (area != null && align == VerticalAlignment.BOTTOM) + { + area.selectRange(0, 1); + toolkit.schedule(() -> area.selectRange(value_text.length(), value_text.length()), 500, TimeUnit.MILLISECONDS); + } + } } // When not managed, trigger layout if (!jfx_node.isManaged()) diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/TextUpdateRepresentation.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/TextUpdateRepresentation.java index b6b010e24c..4287458de9 100644 --- a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/TextUpdateRepresentation.java +++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/widgets/TextUpdateRepresentation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015-2020 Oak Ridge National Laboratory. + * Copyright (c) 2015-2024 Oak Ridge National Laboratory. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -281,8 +281,18 @@ public void updateChanges() else { // Implies 'interactive' mode final TextArea area = (TextArea)jfx_node; + + // Before updating the text, get scroll position just in case we need it later + final double top = area.getScrollTop(); + area.setText(value_text); - if (model_widget.propVerticalAlignment().getValue() == VerticalAlignment.BOTTOM) + + final VerticalAlignment alignment = model_widget.propVerticalAlignment().getValue(); + if (alignment == VerticalAlignment.MIDDLE) + { // In 'middle' alignment mode, keep the scroll position. + area.setScrollTop(top); + } + else if (alignment == VerticalAlignment.BOTTOM) { // For bottom-aligned widget, scroll to bottom, // but area.setScrollTop(Double.MAX_VALUE) has no effect.