diff --git a/app/display/editor/src/main/java/org/csstudio/display/builder/editor/tracker/SelectedWidgetUITracker.java b/app/display/editor/src/main/java/org/csstudio/display/builder/editor/tracker/SelectedWidgetUITracker.java index 7010fa1682..4d95c72882 100644 --- a/app/display/editor/src/main/java/org/csstudio/display/builder/editor/tracker/SelectedWidgetUITracker.java +++ b/app/display/editor/src/main/java/org/csstudio/display/builder/editor/tracker/SelectedWidgetUITracker.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 @@ -14,6 +14,7 @@ import java.util.Objects; import java.util.Optional; import java.util.concurrent.RecursiveTask; +import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Level; import java.util.stream.Collectors; @@ -301,7 +302,8 @@ else if (widget instanceof GroupWidget) // Create text field, aligned with widget, but assert minimum size final MacroizedWidgetProperty property = (MacroizedWidgetProperty)check.get(); - inline_editor = new TextField(property.getSpecification()); + // Allow editing newlines as '\n' + inline_editor = new TextField(property.getSpecification().replace("\n", "\\n")); // 'Managed' text field would assume some default size, // but we set the exact size in here inline_editor.setManaged(false); @@ -316,21 +318,27 @@ else if (widget instanceof GroupWidget) PVAutocompleteMenu.INSTANCE.attachField(inline_editor); // On enter or lost focus, update the property. On Escape, just close. - final ChangeListener focused_listener = (prop, old, focused) -> + // Using atomic ref as holder so that focused_listener can remove itself + final AtomicReference> focused_listener = new AtomicReference<>(); + focused_listener.set((prop, old, focused) -> { if (! focused) { - if (!property.getSpecification().equals(inline_editor.getText())) - undo.execute(new SetMacroizedWidgetPropertyAction(property, inline_editor.getText())); + final String new_text = inline_editor.getText().replace("\\n", "\n"); + if (!property.getSpecification().equals(new_text)) + undo.execute(new SetMacroizedWidgetPropertyAction(property, new_text)); + inline_editor.focusedProperty().removeListener(focused_listener.get()); // Close when focus lost closeInlineEditor(); } - }; + }); inline_editor.setOnAction(event -> { - undo.execute(new SetMacroizedWidgetPropertyAction(property, inline_editor.getText())); - inline_editor.focusedProperty().removeListener(focused_listener); + final String new_text = inline_editor.getText().replace("\\n", "\n"); + if (!property.getSpecification().equals(new_text)) + undo.execute(new SetMacroizedWidgetPropertyAction(property, new_text)); + inline_editor.focusedProperty().removeListener(focused_listener.get()); closeInlineEditor(); }); @@ -340,13 +348,13 @@ else if (widget instanceof GroupWidget) { case ESCAPE: event.consume(); - inline_editor.focusedProperty().removeListener(focused_listener); + inline_editor.focusedProperty().removeListener(focused_listener.get()); closeInlineEditor(); default: } }); - inline_editor.focusedProperty().addListener(focused_listener); + inline_editor.focusedProperty().addListener(focused_listener.get()); inline_editor.selectAll(); inline_editor.requestFocus();