1818 */
1919package org .phoebus .applications .saveandrestore .ui .configuration ;
2020
21+ import javafx .application .Platform ;
22+ import javafx .beans .binding .Bindings ;
2123import javafx .beans .property .SimpleBooleanProperty ;
2224import javafx .beans .property .SimpleIntegerProperty ;
2325import javafx .beans .property .SimpleObjectProperty ;
5557
5658import java .net .URL ;
5759import java .text .NumberFormat ;
58- import java .time .Instant ;
59- import java .time .ZoneId ;
60- import java .time .format .DateTimeFormatter ;
6160import java .util .ArrayList ;
6261import java .util .List ;
6362import java .util .Map ;
6463import java .util .Optional ;
6564import java .util .ResourceBundle ;
65+ import java .util .logging .Level ;
6666import java .util .logging .Logger ;
6767
6868/**
@@ -84,8 +84,6 @@ private static class TableRowEntry {
8484 private ConfigPv pv ;
8585 }
8686
87- private static final DateTimeFormatter configurationTimeFormat = DateTimeFormatter .ofPattern ("yyyy-MM-dd HH:mm:ss" ).withZone (ZoneId .systemDefault ());
88-
8987 private final List <String > nodeListInFolder = new ArrayList <>();
9088
9189 @ FXML
@@ -95,10 +93,10 @@ private static class TableRowEntry {
9593 private Button browseButton ;
9694
9795 @ FXML
98- private TextField configurationName ;
96+ private TextField configurationNameField ;
9997
10098 @ FXML
101- private TextArea description ;
99+ private TextArea descriptionTextArea ;
102100
103101 @ FXML
104102 private Label numSelectedLabel ;
@@ -137,6 +135,14 @@ public void disableConfigurationSelectionInBrowsing() {
137135
138136 private SimpleObjectProperty <Node > createdConfiguration = null ;
139137
138+ private final SimpleStringProperty configurationName = new SimpleStringProperty ();
139+
140+ private final SimpleStringProperty description = new SimpleStringProperty ();
141+
142+ private final SimpleStringProperty locationProperty = new SimpleStringProperty ();
143+
144+ private final SimpleBooleanProperty updateOfExistingConfiguration = new SimpleBooleanProperty ();
145+
140146
141147 public void setCreatedConfigurationProperty (SimpleObjectProperty <Node > createdConfiguration ) {
142148 this .createdConfiguration = createdConfiguration ;
@@ -147,43 +153,30 @@ public void initialize(URL location, ResourceBundle resources) {
147153 targetNode .addListener ((observableValue , node , newNode ) -> {
148154 if (newNode != null ) {
149155 try {
156+ nodeListInFolder .clear ();
157+ configurationNameField .promptTextProperty ().set (null );
150158 if (newNode .getNodeType () == NodeType .CONFIGURATION ) {
151- configurationName .setText (newNode .getName ());
152- description .setText (newNode .getDescription ());
153-
154- configurationName .setEditable (false );
155- description .setEditable (true );
156-
159+ configurationName .set (newNode .getName ());
160+ description .set (newNode .getDescription ());
157161 Node parentNode = saveAndRestoreService .getParentNode (newNode .getUniqueId ());
158- locationTextField .setText (DirectoryUtilities .CreateLocationString (parentNode , false ));
159-
160- nodeListInFolder .clear ();
162+ locationProperty .set (DirectoryUtilities .CreateLocationString (parentNode , false ));
161163 saveAndRestoreService .getChildNodes (parentNode ).forEach (item -> nodeListInFolder .add (item .getName ()));
162-
163- saveButton .setDisable (false );
164-
164+ updateOfExistingConfiguration .set (true );
165165 } else {
166- configurationName .setText ("" );
167- description .setText ("" );
168-
169- configurationName .setEditable (true );
170- description .setEditable (true );
171-
172- locationTextField .setText (DirectoryUtilities .CreateLocationString (newNode , false ));
173-
174- nodeListInFolder .clear ();
166+ configurationName .set (null );
167+ description .set (null );
168+ locationProperty .set (DirectoryUtilities .CreateLocationString (newNode , false ));
175169 saveAndRestoreService .getChildNodes (newNode ).forEach (item -> nodeListInFolder .add (item .getName ()));
176-
170+ updateOfExistingConfiguration . set ( false );
177171 }
178- configurationName .getStyleClass ().remove ("input-error" );
179- configurationName .setTooltip (null );
172+ configurationNameField .getStyleClass ().remove ("input-error" );
180173 } catch (Exception e ) {
181- e . printStackTrace ( );
174+ LOGGER . log ( Level . WARNING , "Failed to handle selection of target node" , e );
182175 }
183176 }
184177 });
185178
186- targetNode . set ( saveAndRestoreService . getChildNodes ( saveAndRestoreService . getRootNode ()). get ( 0 ) );
179+ locationTextField . textProperty (). bind ( locationProperty );
187180
188181 browseButton .setOnAction (action -> {
189182 try {
@@ -208,25 +201,22 @@ public void initialize(URL location, ResourceBundle resources) {
208201 targetNode .set (selectedNode );
209202 }
210203 } catch (Exception e ) {
211- e . printStackTrace ( );
204+ LOGGER . log ( Level . WARNING , "Unable to launch UI" , e );
212205 }
213206 });
214207
215- configurationName .setPromptText (configurationTimeFormat .format (Instant .now ()));
216- configurationName .getStylesheets ().add (getClass ().getResource ("/style.css" ).toExternalForm ());
217- configurationName .textProperty ().addListener ((observableValue , oldName , newName ) -> {
218- saveButton .setDisable (nodeListInFolder .contains (newName ));
219-
220- if (saveButton .isDisabled ()) {
221- configurationName .getStyleClass ().add ("input-error" );
222- configurationName .setTooltip (new Tooltip (Messages .toolTipConfigurationExists + (!isDisabledConfigurationSelectionInBrowsing ? System .lineSeparator () + Messages .toolTipConfigurationExistsOption : "" )));
208+ configurationNameField .getStylesheets ().add (getClass ().getResource ("/style.css" ).toExternalForm ());
209+ configurationNameField .textProperty ().addListener ((observableValue , oldName , newName ) -> {
210+ if (nodeListInFolder .contains (newName )) {
211+ configurationNameField .getStyleClass ().add ("input-error" );
212+ configurationNameField .setTooltip (new Tooltip (Messages .toolTipConfigurationExists + (!isDisabledConfigurationSelectionInBrowsing ? System .lineSeparator () + Messages .toolTipConfigurationExistsOption : "" )));
223213 } else {
224- configurationName .getStyleClass ().remove ("input-error" );
225- configurationName .setTooltip (null );
214+ configurationNameField .getStyleClass ().remove ("input-error" );
215+ configurationNameField .setTooltip (null );
226216 }
227217 });
228218
229- description . setPromptText ( "Configuration created at " + configurationTimeFormat . format ( Instant . now ()) );
219+ configurationNameField . textProperty (). bindBidirectional ( configurationName );
230220
231221 selectColumn .setReorderable (false );
232222 selectColumn .setCellFactory (CheckBoxTableCell .forTableColumn (selectColumn ));
@@ -275,6 +265,28 @@ public void initialize(URL location, ResourceBundle resources) {
275265 });
276266
277267 numSelected .addListener ((observableValue , number , newValue ) -> numSelectedLabel .setText (NumberFormat .getIntegerInstance ().format (newValue )));
268+
269+ // Cannot save until location, config name and description are set.
270+ saveButton .disableProperty ().bind (Bindings .createBooleanBinding (() -> targetNode .get () == null ||
271+ configurationName .get () == null || configurationName .get ().isEmpty () ||
272+ description .get () == null || description .get ().isEmpty (),
273+ targetNode , configurationName , description ));
274+
275+ // Make config name field non-editable if location is not set, or if user is updating existing configuration
276+ configurationNameField .editableProperty ().bind (Bindings .createBooleanBinding (() -> targetNode .get () != null
277+ && updateOfExistingConfiguration .not ().get (),
278+ targetNode ,
279+ updateOfExistingConfiguration ));
280+
281+
282+ // Make description text area non-editable if location is not set, or if user is updating existing configuration
283+ descriptionTextArea .editableProperty ().bind (Bindings .createBooleanBinding (() -> targetNode .get () != null
284+ && updateOfExistingConfiguration .not ().get (),
285+ targetNode ,
286+ updateOfExistingConfiguration ));
287+ descriptionTextArea .textProperty ().bindBidirectional (description );
288+
289+ Platform .runLater (() -> browseButton .requestFocus ());
278290 }
279291
280292 public void setSelection (List <ProcessVariable > pvList ) {
@@ -298,8 +310,10 @@ public void setData(Node targetNode, String name, String description, List<Map<S
298310 this .targetNode .set (targetNode );
299311 }
300312
301- this .configurationName .setText (name );
302- this .description .setText (description );
313+ //this.configurationNameField.setText(name);
314+ //this.descriptionTextArea.setText(description);
315+ this .configurationName .set (name );
316+ this .description .set (description );
303317
304318 for (Map <String , String > entry : entries ) {
305319 final TableRowEntry rowEntry = new TableRowEntry ();
@@ -338,7 +352,7 @@ private void save(ActionEvent ae) {
338352 if (selectedNode .getNodeType () == NodeType .FOLDER ) {
339353 Node newConfigurationBuild = Node .builder ()
340354 .nodeType (NodeType .CONFIGURATION )
341- .name (configurationName .getText ().trim ().isEmpty () ? configurationName .getPromptText () : configurationName .getText ().trim ())
355+ .name (configurationNameField .getText ().trim ().isEmpty () ? configurationNameField .getPromptText () : configurationNameField .getText ().trim ())
342356 .build ();
343357
344358 try {
@@ -347,7 +361,7 @@ private void save(ActionEvent ae) {
347361 configurationData .setPvList (pvs );
348362
349363 Configuration configuration = new Configuration ();
350- newConfigurationBuild .setDescription (description .getText ().trim ().isEmpty () ? description .getPromptText () : description .getText ().trim ());
364+ newConfigurationBuild .setDescription (descriptionTextArea .getText ().trim ().isEmpty () ? descriptionTextArea .getPromptText () : descriptionTextArea .getText ().trim ());
351365 configuration .setConfigurationNode (newConfigurationBuild );
352366 configuration .setConfigurationData (configurationData );
353367
0 commit comments