99
1010import java .util .ArrayList ;
1111import java .util .List ;
12- import java .util .concurrent . TimeUnit ;
12+ import java .util .Objects ;
1313
1414import org .phoebus .applications .alarm .model .TitleDetailDelay ;
1515import org .phoebus .applications .alarm .ui .AlarmUI ;
1616import org .phoebus .ui .dialog .DialogHelper ;
1717import org .phoebus .ui .dialog .MultiLineInputDialog ;
1818import org .phoebus .ui .javafx .ImageCache ;
19- import org .phoebus .ui .javafx .UpdateThrottle ;
2019
2120import javafx .application .Platform ;
2221import javafx .beans .InvalidationListener ;
3534import javafx .scene .control .TableView ;
3635import javafx .scene .control .Tooltip ;
3736import javafx .scene .control .cell .ComboBoxTableCell ;
38- import javafx .scene .control .cell .TextFieldTableCell ;
3937import javafx .scene .layout .BorderPane ;
4038import javafx .scene .layout .VBox ;
4139import javafx .util .converter .DefaultStringConverter ;
@@ -104,8 +102,49 @@ class DelayTableCell extends TableCell<TitleDetailDelay, Integer>
104102 public DelayTableCell ()
105103 {
106104 this .spinner = new Spinner <>(0 , 10000 , 1 );
107- spinner .setEditable (true );
108- this .spinner .valueProperty ().addListener ((observable , oldValue , newValue ) -> commitEdit (newValue ));
105+ this .spinner .setEditable (true );
106+
107+ // disable focus on buttons
108+ spinner .lookupAll (".increment-arrow-button, .decrement-arrow-button" )
109+ .forEach (node -> node .setFocusTraversable (false ));
110+
111+ this .spinner .valueProperty ().addListener ((obs , oldValue , newValue ) -> {
112+ if (isEditing ()) {
113+ commitEdit (newValue );
114+ }
115+ });
116+
117+ // validate when loosing focus
118+ spinner .focusedProperty ().addListener ((obs , wasFocused , isNowFocused ) -> {
119+ if (!isNowFocused ) {
120+ Integer currentValue = spinner .getValue ();
121+ Integer oldValue = getItem ();
122+
123+ if (Objects .equals (currentValue , oldValue )) {
124+ cancelEdit ();
125+ return ;
126+ }
127+
128+ // if not currently editing, force table to enter edit mode first
129+ if (!isEditing ()) {
130+ TableView <TitleDetailDelay > tv = getTableView ();
131+ if (tv != null ) {
132+ Platform .runLater (() -> {
133+ tv .getSelectionModel ().clearAndSelect (getIndex ());
134+ tv .edit (getIndex (), getTableColumn ());
135+ // commit after we've asked the table to start editing
136+ commitEdit (currentValue );
137+ });
138+ } else {
139+ // fallback: commit anyway
140+ commitEdit (currentValue );
141+ }
142+ } else {
143+ // normal case
144+ commitEdit (currentValue );
145+ }
146+ }
147+ });
109148 }
110149
111150 @ Override
@@ -135,6 +174,13 @@ public void updateItem(Integer item, boolean empty)
135174
136175 this .spinner .getValueFactory ().setValue (item );
137176 setGraphic (spinner );
177+ // force focus on the textedit not buttons
178+ Platform .runLater (() -> {
179+ if (isEditing ()) {
180+ spinner .getEditor ().requestFocus ();
181+ spinner .getEditor ().end ();
182+ }
183+ });
138184 }
139185 }
140186
@@ -147,20 +193,19 @@ private void createTable()
147193
148194 TableColumn <TitleDetailDelay , String > col = new TableColumn <>("Title" );
149195 col .setCellValueFactory (cell -> new SimpleStringProperty (cell .getValue ().title ));
150- col .setCellFactory (column -> new TextFieldTableCell <> (new DefaultStringConverter ()));
196+ col .setCellFactory (ValidatingTextFieldTableCell . forTableColumn (new DefaultStringConverter ()));
151197 col .setOnEditCommit (event ->
152198 {
153199 final int row = event .getTablePosition ().getRow ();
154200 items .set (row , new TitleDetailDelay (event .getNewValue (), items .get (row ).detail , items .get (row ).delay ));
155201
156202 // Trigger editing the detail
157- UpdateThrottle .TIMER .schedule (() ->
158- Platform .runLater (() ->
159- {
160- table .getSelectionModel ().clearAndSelect (row );
161- table .edit (row , table .getColumns ().get (1 ));
162- }),
163- 200 , TimeUnit .MILLISECONDS );
203+ Platform .runLater (() -> {
204+ TableColumn <TitleDetailDelay , ?> detailCol = table .getColumns ().get (1 );
205+ TableColumn <TitleDetailDelay , ?> optionCol = detailCol .getColumns ().get (0 );
206+ table .getSelectionModel ().clearAndSelect (row );
207+ table .edit (row , optionCol );
208+ });
164209 });
165210 col .setSortable (false );
166211 table .getColumns ().add (col );
@@ -182,18 +227,20 @@ private void createTable()
182227 items .set (row , newTitleDetailDelay );
183228 // Trigger editing the delay.
184229 if (newTitleDetailDelay .hasDelay ())
185- UpdateThrottle .TIMER .schedule (() -> Platform .runLater (() -> {
186- table .getSelectionModel ().clearAndSelect (row );
187- table .edit (row , table .getColumns ().get (2 ));
188- }), 200 , TimeUnit .MILLISECONDS );
230+ Platform .runLater (() -> {
231+ TableColumn <TitleDetailDelay , ?> detailCol = table .getColumns ().get (1 );
232+ TableColumn <TitleDetailDelay , ?> infoCol = detailCol .getColumns ().get (1 );
233+ table .getSelectionModel ().clearAndSelect (row );
234+ table .edit (row , infoCol );
235+ });
189236 });
190237 tmpOptionCol .setEditable (true );
191238 col .getColumns ().add (tmpOptionCol );
192239
193240 // Use a textfield to set info for detail
194241 TableColumn <TitleDetailDelay , String > infoCol = new TableColumn <>("Info" );
195242 infoCol .setCellValueFactory (cell -> new SimpleStringProperty (getInfoFromDetail (cell .getValue ())));
196- infoCol .setCellFactory (column -> new TextFieldTableCell <> (new DefaultStringConverter ()));
243+ infoCol .setCellFactory (ValidatingTextFieldTableCell . forTableColumn (new DefaultStringConverter ()));
197244 infoCol .setOnEditCommit (event -> {
198245 final int row = event .getTablePosition ().getRow ();
199246 TitleDetailDelay tmpT = items .get (row );
@@ -202,10 +249,10 @@ private void createTable()
202249 items .set (row , newTitleDetailDelay );
203250 // Trigger editing the delay.
204251 if (newTitleDetailDelay .hasDelay ())
205- UpdateThrottle . TIMER . schedule (() -> Platform .runLater (() -> {
206- table .getSelectionModel ().clearAndSelect (row );
207- table .edit (row , table .getColumns ().get (2 ));
208- }), 200 , TimeUnit . MILLISECONDS );
252+ Platform .runLater (() -> {
253+ table .getSelectionModel ().clearAndSelect (row );
254+ table .edit (row , table .getColumns ().get (2 ));
255+ } );
209256 });
210257 infoCol .setSortable (false );
211258 col .getColumns ().add (infoCol );
@@ -306,14 +353,12 @@ private void createButtons()
306353 items .add (new TitleDetailDelay ("" , "" , 0 ));
307354
308355 // Trigger editing the title of new item
309- UpdateThrottle .TIMER .schedule (() ->
310- Platform .runLater (() ->
311- {
312- final int row = items .size ()-1 ;
313- table .getSelectionModel ().clearAndSelect (row );
314- table .edit (row , table .getColumns ().get (0 ));
315- }),
316- 200 , TimeUnit .MILLISECONDS );
356+ Platform .runLater (() ->
357+ {
358+ final int row = items .size ()-1 ;
359+ table .getSelectionModel ().clearAndSelect (row );
360+ table .edit (row , table .getColumns ().get (0 ));
361+ });
317362 });
318363
319364 edit .setTooltip (new Tooltip ("Edit the detail field of table item." ));
0 commit comments