24
24
import com .github .nianna .karedi .util .NumericNodeUtils ;
25
25
import com .github .nianna .karedi .util .TableViewUtils ;
26
26
import com .github .nianna .karedi .util .ValidationUtils ;
27
+ import javafx .beans .InvalidationListener ;
27
28
import javafx .beans .binding .Bindings ;
29
+ import javafx .beans .binding .BooleanBinding ;
28
30
import javafx .beans .property .ReadOnlyStringProperty ;
29
31
import javafx .beans .property .SimpleStringProperty ;
30
32
import javafx .event .EventHandler ;
35
37
import javafx .scene .control .TableCell ;
36
38
import javafx .scene .control .TableColumn ;
37
39
import javafx .scene .control .TableColumn .CellEditEvent ;
40
+ import javafx .scene .control .TablePosition ;
38
41
import javafx .scene .control .TableRow ;
39
42
import javafx .scene .control .TableView ;
40
- import javafx .scene .control .TablePosition ;
41
43
import javafx .scene .input .KeyCode ;
42
44
import javafx .scene .input .KeyEvent ;
43
45
import javafx .scene .input .MouseEvent ;
52
54
53
55
import java .util .Collections ;
54
56
import java .util .List ;
57
+ import java .util .Optional ;
55
58
import java .util .function .Function ;
56
59
57
60
public class TagsTableController implements Controller {
@@ -170,20 +173,8 @@ private void onKeyPressed(KeyEvent event) {
170
173
private Callback <TableView <Tag >, TableRow <Tag >> getRowFactory () {
171
174
return (tv -> {
172
175
TableRow <Tag > row = new TableRow <Tag >();
173
-
174
176
row .contextMenuProperty ().bind (Bindings .when (row .emptyProperty ()).then (baseContextMenu )
175
177
.otherwise (getContextMenuForRow (row )));
176
-
177
- row .itemProperty ().addListener ((obs , oldItem , newItem ) -> {
178
- row .setOnScroll (null );
179
- if (newItem != null ) {
180
- TagKey .optionalValueOf (newItem .getKey ()).ifPresent (tagKey -> {
181
- row .setOnScroll (
182
- getScrollHandlerForRow (row , tagKey , newItem .valueProperty ()));
183
- });
184
- }
185
- });
186
-
187
178
return row ;
188
179
});
189
180
}
@@ -198,34 +189,6 @@ private ContextMenu getContextMenuForRow(TableRow<Tag> row) {
198
189
return result ;
199
190
}
200
191
201
- private EventHandler <ScrollEvent > getScrollHandlerForRow (TableRow <Tag > row , TagKey key ,
202
- ReadOnlyStringProperty value ) {
203
- EventHandler <ScrollEvent > handler = null ;
204
- if (TagKey .expectsAnInteger (key )) {
205
- handler = NumericNodeUtils .createUpdateIntValueOnScrollHandler (
206
- () -> Converter .toInteger (value .get ()), newValue -> changeTagValueIfValid (key ,
207
- Converter .toString (newValue .intValue ())));
208
- }
209
- if (TagKey .expectsADouble (key )) {
210
- handler = NumericNodeUtils .createUpdateDoubleValueOnScrollHandler (
211
- () -> Converter .toDouble (value .get ()), newValue -> changeTagValueIfValid (key ,
212
- Converter .toString (MathUtils .roundTo (newValue .doubleValue (), 3 ))));
213
- }
214
- return adaptScrollHandlerForRow (row , handler );
215
- }
216
-
217
- private EventHandler <ScrollEvent > adaptScrollHandlerForRow (TableRow <Tag > row ,
218
- EventHandler <ScrollEvent > handler ) {
219
- if (handler != null ) {
220
- return (event -> {
221
- if (row .isSelected () && !row .isEditing ()) {
222
- handler .handle (event );
223
- }
224
- });
225
- }
226
- return null ;
227
- }
228
-
229
192
@ FXML
230
193
private void handleAdd () {
231
194
actionContext .execute (KarediActions .ADD_TAG );
@@ -289,13 +252,19 @@ public void handleEvent(ControllerEvent controllerEvent) {
289
252
}
290
253
291
254
private class TagValueTableCell extends TableCell <Tag , String > {
255
+
256
+ private static final String SCROLL_EDIT_ACTIVE_STYLE_CLASS = "scroll-edit-active" ;
257
+
292
258
private final RestrictedTextField textField = new RestrictedTextField ("" );
293
259
private Function <Tag , Validator <String >> validatorSupplier ;
294
260
private Validator <String > validator ;
295
261
private ValidationDecoration validationDecoration = new GraphicValidationDecoration ();
296
262
private Tag lastTag ;
297
263
private AutoCompletionBinding <?> valueSuggestions ;
298
264
265
+ private BooleanBinding isScrollEditAllowed ;
266
+ private InvalidationListener isScrollEditAllowedInvalidationListener = obs -> refreshScrollEditEffect ();
267
+
299
268
private ValidationResult applyValidator () {
300
269
return validator .apply (textField , textField .getText ());
301
270
}
@@ -325,6 +294,71 @@ private ValidationResult applyValidator() {
325
294
cancelEdit ();
326
295
}
327
296
});
297
+ addListenerUpdatingEditViaScrollAvailability ();
298
+ }
299
+
300
+ private void addListenerUpdatingEditViaScrollAvailability () {
301
+ itemProperty ().addListener (obs -> Optional .ofNullable (getTableRow ().getItem ())
302
+ .map (Tag ::getKey )
303
+ .flatMap (TagKey ::optionalValueOf )
304
+ .flatMap (tagKey -> scrollHandlerForCell (tagKey , getTableRow ().getItem ().valueProperty ()))
305
+ .ifPresentOrElse (handler -> {
306
+ isScrollEditAllowed = getTableRow ().selectedProperty ().and (editingProperty ().not ());
307
+ setOnScroll (handler );
308
+ setOnMouseEntered (event -> {
309
+ isScrollEditAllowed .addListener (isScrollEditAllowedInvalidationListener );
310
+ isScrollEditAllowed .invalidate ();
311
+ });
312
+ setOnMouseExited (event -> {
313
+ isScrollEditAllowed .removeListener (isScrollEditAllowedInvalidationListener );
314
+ removeScrollEditEffect ();
315
+ });
316
+ }, () -> {
317
+ setOnScroll (null );
318
+ setOnMouseEntered (null );
319
+ setOnMouseExited (null );
320
+ removeScrollEditEffect ();
321
+ }));
322
+ }
323
+
324
+ private void refreshScrollEditEffect () {
325
+ if (isScrollEditAllowed .get ()) {
326
+ if (!getStyleClass ().contains (SCROLL_EDIT_ACTIVE_STYLE_CLASS )) {
327
+ getStyleClass ().add (SCROLL_EDIT_ACTIVE_STYLE_CLASS );
328
+ }
329
+ } else {
330
+ removeScrollEditEffect ();
331
+ }
332
+ }
333
+
334
+ private void removeScrollEditEffect () {
335
+ getStyleClass ().remove (SCROLL_EDIT_ACTIVE_STYLE_CLASS );
336
+ }
337
+
338
+ private Optional <EventHandler <ScrollEvent >> scrollHandlerForCell (TagKey key , ReadOnlyStringProperty value ) {
339
+ EventHandler <ScrollEvent > handler = null ;
340
+ if (TagKey .expectsAnInteger (key )) {
341
+ handler = NumericNodeUtils .createUpdateIntValueOnScrollHandler (
342
+ () -> Converter .toInteger (value .get ()), newValue -> changeTagValueIfValid (key ,
343
+ Converter .toString (newValue .intValue ())));
344
+ }
345
+ if (TagKey .expectsADouble (key )) {
346
+ handler = NumericNodeUtils .createUpdateDoubleValueOnScrollHandler (
347
+ () -> Converter .toDouble (value .get ()), newValue -> changeTagValueIfValid (key ,
348
+ Converter .toString (MathUtils .roundTo (newValue .doubleValue (), 3 ))));
349
+ }
350
+ return Optional .ofNullable (adaptScrollHandlerForCell (handler ));
351
+ }
352
+
353
+ private EventHandler <ScrollEvent > adaptScrollHandlerForCell (EventHandler <ScrollEvent > handler ) {
354
+ if (handler != null ) {
355
+ return (event -> {
356
+ if (isScrollEditAllowed .get ()) {
357
+ handler .handle (event );
358
+ }
359
+ });
360
+ }
361
+ return null ;
328
362
}
329
363
330
364
@ Override
@@ -346,6 +380,7 @@ public void startEdit() {
346
380
textField .selectAll ();
347
381
348
382
textField .requestFocus ();
383
+ removeScrollEditEffect ();
349
384
}
350
385
351
386
private void resetValueSuggestions (Tag tag ) {
0 commit comments