1212import javafx .event .ActionEvent ;
1313import javafx .event .EventHandler ;
1414import javafx .geometry .Pos ;
15+ import javafx .scene .control .Alert ;
1516import javafx .scene .control .Button ;
1617import javafx .scene .control .ButtonType ;
1718import javafx .scene .control .CheckBox ;
2223import javafx .scene .control .ScrollPane ;
2324import javafx .scene .control .Spinner ;
2425import javafx .scene .control .TextField ;
26+ import javafx .scene .control .TextFormatter ;
2527import javafx .scene .control .Tooltip ;
28+ import javafx .scene .input .KeyCode ;
29+ import javafx .scene .input .KeyEvent ;
2630import javafx .scene .layout .ColumnConstraints ;
2731import javafx .scene .layout .GridPane ;
2832import javafx .scene .layout .HBox ;
2933import javafx .scene .layout .Priority ;
3034import javafx .stage .Modality ;
3135import javafx .util .Duration ;
36+ import javafx .util .StringConverter ;
3237import org .phoebus .applications .alarm .AlarmSystem ;
3338import org .phoebus .applications .alarm .client .AlarmClient ;
3439import org .phoebus .applications .alarm .client .AlarmClientLeaf ;
3540import org .phoebus .applications .alarm .client .AlarmClientNode ;
3641import org .phoebus .applications .alarm .model .AlarmTreeItem ;
3742import org .phoebus .applications .alarm .ui .tree .datetimepicker .DateTimePicker ;
43+ import org .phoebus .ui .dialog .DialogHelper ;
3844import org .phoebus .ui .dialog .ExceptionDetailsErrorDialog ;
3945import org .phoebus .util .time .SecondsParser ;
4046import org .phoebus .util .time .TimeParser ;
4147
4248import java .time .LocalDate ;
4349import java .time .LocalDateTime ;
50+ import java .time .format .DateTimeParseException ;
4451import java .time .temporal .TemporalAmount ;
4552
4653
@@ -120,7 +127,6 @@ public ItemConfigDialog(final AlarmClient model, final AlarmTreeItem<?> item) {
120127 }
121128 });
122129
123-
124130 latching = new CheckBox ("Latch" );
125131 latching .setTooltip (new Tooltip ("Latch alarm until acknowledged?" ));
126132 latching .setSelected (leaf .isLatching ());
@@ -141,6 +147,27 @@ public ItemConfigDialog(final AlarmClient model, final AlarmTreeItem<?> item) {
141147 enabled_date_picker .setDisable (!leaf .isEnabled ());
142148 enabled_date_picker .disableProperty ().bind (itemEnabled .not ());
143149
150+
151+ enabled_date_picker .addEventHandler (KeyEvent .KEY_PRESSED , keyEvent -> {
152+ if (keyEvent .getCode () == KeyCode .ENTER ) {
153+ try {
154+ // Test that the input is well-formed (if the input
155+ // isn't well-formed, valueConverter.fromString()
156+ // throws a DateTimeParseException):
157+ TextFormatter <?> textFormatter = enabled_date_picker .getEditor ().getTextFormatter ();
158+ StringConverter valueConverter = textFormatter .getValueConverter ();
159+ LocalDate dateTime = (LocalDate ) valueConverter .fromString (enabled_date_picker .getEditor ().getText ());
160+
161+ enabled_date_picker .getEditor ().commitValue ();
162+ }
163+ catch (DateTimeParseException dateTimeParseException ) {
164+ // The input was not well-formed. Prevent further
165+ // processing by consuming the key-event:
166+ keyEvent .consume ();
167+ }
168+ }
169+ });
170+
144171 relative_date = new ComboBox <>();
145172 relative_date .setTooltip (new Tooltip ("Select a predefined duration for disabling the alarm" ));
146173 relative_date .getItems ().addAll (AlarmSystem .shelving_options );
@@ -169,6 +196,15 @@ public ItemConfigDialog(final AlarmClient model, final AlarmTreeItem<?> item) {
169196 }
170197 });
171198
199+ // Configure date picker to disable selection of all dates in the past.
200+ enabled_date_picker .setDayCellFactory (picker -> new DateCell () {
201+ public void updateItem (LocalDate date , boolean empty ) {
202+ super .updateItem (date , empty );
203+ LocalDate today = LocalDate .now ();
204+ setDisable (empty || date .isBefore (today ));
205+ }
206+ });
207+
172208 final HBox until_box = new HBox (10 , enabled_date_picker , relative_date );
173209 until_box .setAlignment (Pos .CENTER );
174210 HBox .setHgrow (relative_date , Priority .ALWAYS );
@@ -264,15 +300,6 @@ public ItemConfigDialog(final AlarmClient model, final AlarmTreeItem<?> item) {
264300 validateAndStore (model , item , event ));
265301
266302 setResultConverter (button -> button == ButtonType .OK );
267-
268- // Configure date picker to disable selection of all dates in the past.
269- enabled_date_picker .setDayCellFactory (picker -> new DateCell () {
270- public void updateItem (LocalDate date , boolean empty ) {
271- super .updateItem (date , empty );
272- LocalDate today = LocalDate .now ();
273- setDisable (empty || date .isBefore (today ));
274- }
275- });
276303 }
277304
278305 /**
@@ -287,29 +314,44 @@ private void validateAndStore(final AlarmClient model, final AlarmTreeItem<?> it
287314
288315 if (item instanceof AlarmClientLeaf ) {
289316 final AlarmClientLeaf pv = new AlarmClientLeaf (null , item .getName ());
317+
318+ boolean validEnableDate ;
319+ {
320+ final LocalDateTime selected_enable_date = enabled_date_picker .getDateTimeValue ();
321+ final String relative_enable_date = relative_date .getValue ();
322+
323+ if ((selected_enable_date != null )) {
324+ validEnableDate = pv .setEnabledDate (selected_enable_date );
325+ } else if (relative_enable_date != null ) {
326+ final TemporalAmount amount = TimeParser .parseTemporalAmount (relative_enable_date );
327+ final LocalDateTime update_date = LocalDateTime .now ().plus (amount );
328+ validEnableDate = pv .setEnabledDate (update_date );
329+ } else {
330+ pv .setEnabled (itemEnabled .get ());
331+ validEnableDate = true ;
332+ }
333+ }
334+
335+ if (!validEnableDate ) {
336+ Alert prompt = new Alert (Alert .AlertType .INFORMATION );
337+ prompt .setTitle ("'Disable until' is set to a point in time in the past" );
338+ prompt .setHeaderText ("'Disable until' is set to a point in time in the past" );
339+ prompt .setContentText ("The option 'disable until' must be set to a point in time in the future." );
340+ DialogHelper .positionDialog (prompt , enabled_date_picker , 0 , 0 );
341+ prompt .showAndWait ();
342+
343+ event .consume ();
344+ return ;
345+ }
346+
290347 pv .setDescription (description .getText ().trim ());
291- pv .setEnabled (enabled .isSelected ());
292348 pv .setLatching (latching .isSelected ());
293349 pv .setAnnunciating (annunciating .isSelected ());
294350 pv .setDelay (delay .getValue ());
295351 pv .setCount (count .getValue ());
296352 // TODO Check filter expression
297353 pv .setFilter (filter .getText ().trim ());
298354
299-
300- final LocalDateTime selected_enable_date = enabled_date_picker .getDateTimeValue ();
301- final String relative_enable_date = relative_date .getValue ();
302-
303- if ((selected_enable_date != null )) {
304- pv .setEnabledDate (selected_enable_date );
305- } else if (relative_enable_date != null ) {
306- final TemporalAmount amount = TimeParser .parseTemporalAmount (relative_enable_date );
307- final LocalDateTime update_date = LocalDateTime .now ().plus (amount );
308- pv .setEnabledDate (update_date );
309- } else {
310- pv .setEnabled (itemEnabled .get ());
311- }
312-
313355 config = pv ;
314356 } else
315357 config = new AlarmClientNode (null , item .getName ());
0 commit comments