diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/annotation/view/fx/AnnotationViewFXController.java b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/annotation/view/fx/AnnotationViewFXController.java index 9a0366b6a22084f2f3dfc27df9f7b85fbc8b66db..2f58fff0927a0f7454753b819546a941167c937b 100644 --- a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/annotation/view/fx/AnnotationViewFXController.java +++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/annotation/view/fx/AnnotationViewFXController.java @@ -59,12 +59,18 @@ import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.scene.Node; import javafx.scene.control.SplitPane; +import javafx.scene.control.TextField; import javafx.scene.control.TreeItem; import javafx.scene.control.TreeTableCell; import javafx.scene.control.TreeTableColumn; +import javafx.scene.control.TreeTableRow; import javafx.scene.control.TreeTableView; import javafx.scene.control.cell.ComboBoxTreeTableCell; +import javafx.scene.control.cell.TextFieldTreeTableCell; +import javafx.scene.input.KeyCode; import javafx.util.Callback; +import javafx.util.StringConverter; +import javafx.util.converter.DefaultStringConverter; /** * @@ -189,49 +195,152 @@ public class AnnotationViewFXController extends CompositeFXControllerBase<SplitP IAnnotationValueProvider<IAnnotatedSpecification> valueProvider = entry .getAnnotationValueProvider(annotationClass); IAnnotatedSpecification specification = entry.getSpecification(annotationClass); + EClassifier valueType = valueProvider.getEStructuralFeatureDescriptor().getEType(specification); String columnName = valueProvider.getAnnotationName(specification); TreeTableColumn<AnnotationEntry, String> column = annotationTreeViewer.addColumn(columnName, 150); colIdxAnnotationMap.put(columnIdx, handle); - ObservableList<String> items = FXCollections.observableArrayList(); - Callback<TreeTableColumn<AnnotationEntry, String>, TreeTableCell<AnnotationEntry, String>> comboCellFactory = ComboBoxTreeTableCell - .forTreeTableColumn(items); - column.setCellFactory(comboCellFactory); + if (valueType == null) { + column.setEditable(false); + return; + } column.setEditable(true); - column.setOnEditStart(event -> { + + // Case distinction for the cell factory depending on the type to be edited. + if (valueType instanceof EEnum) { + ObservableList<String> items = FXCollections.observableArrayList(); + Callback<TreeTableColumn<AnnotationEntry, String>, TreeTableCell<AnnotationEntry, String>> comboCellFactory = ComboBoxTreeTableCell + .forTreeTableColumn(items); + column.setCellFactory(comboCellFactory); + + column.setOnEditStart(event -> { + // We need to get the type for every row individually, as it might be different + // Enums for every row. + TreeItem<AnnotationEntry> treeItem = event.getRowValue(); + AnnotationEntry rowEntry = treeItem.getValue(); + ValueProviderBase<IAnnotatedSpecification> annotationValueProvider = (ValueProviderBase<IAnnotatedSpecification>) rowEntry + .getAnnotationValueProvider(annotationClass); + EStructuralFeatureDescriptor structuralFeature = annotationValueProvider + .getEStructuralFeatureDescriptor(); + EClassifier type = structuralFeature.getEType(rowEntry.getSpecification(annotationClass)); + if (type instanceof EEnum) { + EList<EEnumLiteral> allLiterals = ((EEnum) type).getELiterals(); + + items.clear(); + items.addAll(allLiterals.stream().map(l -> l.getLiteral()).collect(toList())); + } + }); + } else if (valueType.getInstanceClass().equals(Boolean.class)) { + System.out.println(valueType); + } else { + // For all other types, there is text editing. + column.setCellFactory( + ttColumn -> new AnnotationTextFieldTreeTableCell(new DefaultStringConverter(), annotationClass)); + } + + column.setOnEditCommit(event -> { TreeItem<AnnotationEntry> treeItem = event.getRowValue(); AnnotationEntry rowEntry = treeItem.getValue(); - ValueProviderBase<IAnnotatedSpecification> annotationValueProvider = (ValueProviderBase<IAnnotatedSpecification>) rowEntry - .getAnnotationValueProvider(annotationClass); + String newValue = event.getNewValue(); + + setAnnotationEntryValue(specification, rowEntry, newValue); + }); - EStructuralFeatureDescriptor structuralFeature = annotationValueProvider.getEStructuralFeatureDescriptor(); + column.setOnEditCancel(event -> { + System.out.println(event); + }); + } - EClassifier type = structuralFeature.getEType(rowEntry.getSpecification(annotationClass)); - if (type instanceof EEnum) { - EList<EEnumLiteral> allLiterals = ((EEnum) type).getELiterals(); + private void setAnnotationEntryValue(IAnnotatedSpecification specification, AnnotationEntry annotationEntry, + String newValue) { + ITopLevelElement tle = IPersistencyService.getInstance().getTopLevelElementFor(selectedElement); - items.clear(); - items.addAll(allLiterals.stream().map(l -> l.getLiteral()).collect(toList())); + tle.runAsCommand(() -> { + try { + annotationEntry.setSpecificationValue(newValue, specification.getClass()); + } catch (Exception e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); } }); - column.setOnEditCommit(event -> { - TreeItem<AnnotationEntry> treeItem = event.getRowValue(); - AnnotationEntry rowEntry = treeItem.getValue(); + } + + private class AnnotationTextFieldTreeTableCell extends TextFieldTreeTableCell<AnnotationEntry, String> { + private final Class<IAnnotatedSpecification> annotationClass; + + private boolean escapePressed = false; + private AnnotationEntry currentlyEditedEntry; + private String currentInput = ""; + + private AnnotationTextFieldTreeTableCell(StringConverter<String> converter, + Class<IAnnotatedSpecification> annotationClass) { + super(converter); - ITopLevelElement tle = IPersistencyService.getInstance().getTopLevelElementFor(selectedElement); + this.annotationClass = annotationClass; - tle.runAsCommand(() -> { - try { - rowEntry.setSpecificationValue(event.getNewValue(), specification.getClass()); - } catch (Exception e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); + this.setOnKeyPressed(event -> { + if (event.getCode().equals(KeyCode.ESCAPE)) { + escapePressed = true; } }); - }); + } + + @Override + public void startEdit() { + TreeTableRow<AnnotationEntry> row = getTreeTableRow(); + AnnotationEntry currentEntry = row.getItem(); + + // We start editing only, if this cell is supposed to be editable. + IAnnotationValueProvider<IAnnotatedSpecification> annotationValueProvider = currentEntry + .getAnnotationValueProvider(annotationClass); + IAnnotatedSpecification currentSpecification = currentEntry.getSpecification(annotationClass); + if (annotationValueProvider != null && annotationValueProvider.canEdit(currentSpecification)) { + super.startEdit(); + + currentlyEditedEntry = currentEntry; + // Reset currentInput buffer for the new element. + currentInput = ""; + } else { + currentlyEditedEntry = null; + } + + // We keep the current input in the buffer variable currentInput to be able to + // use it during unintended cancel options. See cancelEdit(). + TextField textField = (TextField) getGraphic(); + if (textField != null) { + textField.setOnKeyReleased(event -> { + currentInput = textField.getText(); + }); + } + } + + @Override + public void cancelEdit() { + super.cancelEdit(); + + setText(currentInput); + + if (escapePressed) { + escapePressed = false; + currentlyEditedEntry = null; + } else { + if (currentlyEditedEntry != null) { + IAnnotatedSpecification specification = currentlyEditedEntry.getSpecification(annotationClass); + setAnnotationEntryValue(specification, currentlyEditedEntry, currentInput); + currentlyEditedEntry = null; + } + } + } + + @Override + public void commitEdit(String newValue) { + currentlyEditedEntry = null; + + super.commitEdit(newValue); + } } /**