Skip to content
Snippets Groups Projects
Commit c4723292 authored by Simon Barner's avatar Simon Barner
Browse files

Enable to edit EReferences by means of ComboViewer cells

Issue-Ref: 4092
Issue-Url: af3#4092



Signed-off-by: default avatarSimon Barner <barner@fortiss.org>
parent be7e5883
No related branches found
No related tags found
1 merge request!1474092: Implement a JFX controller for the creation and visualization of reference lists
This commit is part of merge request !147. Comments created here will be created in the context of that merge request.
AnnotationFxViewPart.java ca1548c49aa3842a9436262531464ba345b83688 GREEN
AnnotationTreeTableUIProvider.java 85dfcf003c79d45f82c901b0f3f6bb30db59effa GREEN
AnnotationViewFXController.java 4351373c216d0aa4539784c9742f4db8bbf161e6 GREEN
AnnotationViewFXController.java 7d62ea076e87b14c4916935d3466168503c83c6f YELLOW
AnnotationsFXUtils.java 754152735e037da59a4c40fa045602c3ed85a40f GREEN
ColumnHandle.java 7b0fe536d4eb9faa63c4d812f0c078cf83d0fd42 GREEN
FXAnnotationFilterContentProvider.java ca4587ef5dce1288ee4d7bf3bea5bd544ce6b89e GREEN
......@@ -15,9 +15,11 @@
+--------------------------------------------------------------------------*/
package org.fortiss.tooling.base.ui.annotation.view.fx;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.sort;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
import static org.fortiss.tooling.base.ui.annotation.view.fx.AnnotationsFXUtils.getValueLabel;
import static org.fortiss.tooling.base.ui.annotation.view.fx.FXAnnotationFilterContentProvider.HIERARCHY_LEVELS_ALL;
import static org.fortiss.tooling.base.ui.annotation.view.fx.FXAnnotationFilterContentProvider.HIERARCHY_LEVELS_CURRENT;
import static org.fortiss.tooling.base.ui.annotation.view.fx.FXAnnotationFilterContentProvider.HIERARCHY_LEVELS_SELECTED_SUBMODEL;
......@@ -34,7 +36,9 @@ import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EEnumLiteral;
......@@ -46,8 +50,8 @@ import org.fortiss.tooling.base.annotation.AnnotationEntry;
import org.fortiss.tooling.base.annotation.AnnotationValueService;
import org.fortiss.tooling.base.annotation.IAnnotationValueService;
import org.fortiss.tooling.base.annotation.valueprovider.EStructuralFeatureDescriptor;
import org.fortiss.tooling.base.annotation.valueprovider.EStructuralFeatureDescriptor.EReferenceScope;
import org.fortiss.tooling.base.annotation.valueprovider.IAnnotationValueProvider;
import org.fortiss.tooling.base.annotation.valueprovider.ValueProviderBase;
import org.fortiss.tooling.base.model.element.IAnnotatedSpecification;
import org.fortiss.tooling.base.model.element.IModelElement;
import org.fortiss.tooling.common.ui.javafx.control.treetableview.DynamicTreeTableUIProviderBase;
......@@ -57,6 +61,7 @@ import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
import org.fortiss.tooling.kernel.model.INamedCommentedElement;
import org.fortiss.tooling.kernel.model.IProjectRootElement;
import org.fortiss.tooling.kernel.service.IPersistencyService;
import org.fortiss.tooling.kernel.utils.HierarchicalNameComparator;
import com.sun.webkit.ThemeClient;
......@@ -396,8 +401,10 @@ public class AnnotationViewFXController extends CompositeFXControllerBase<SplitP
IAnnotationValueProvider<IAnnotatedSpecification> valueProvider =
entry.getAnnotationValueProvider(annotationType);
IAnnotatedSpecification specification = entry.getSpecification(annotationType);
EClassifier valueType =
valueProvider.getEStructuralFeatureDescriptor().getEType(specification);
EStructuralFeatureDescriptor featureDescriptor =
valueProvider.getEStructuralFeatureDescriptor();
EClassifier valueType = featureDescriptor.getEType(specification);
String columnName = valueProvider.getAnnotationName(specification);
......@@ -413,24 +420,12 @@ public class AnnotationViewFXController extends CompositeFXControllerBase<SplitP
return column;
}
if(valueType instanceof EEnum) {
// Add a combo column for enumerations.
if(valueType instanceof EEnum || valueType instanceof EClass) {
// Add a combo column for enumerations and references
column = annotationViewer.addComboColumn(columnName, 150, rowEntry -> {
ValueProviderBase<IAnnotatedSpecification> annotationValueProvider =
(ValueProviderBase<IAnnotatedSpecification>)rowEntry
.getAnnotationValueProvider(annotationType);
EStructuralFeatureDescriptor structuralFeature =
annotationValueProvider.getEStructuralFeatureDescriptor();
EClassifier type =
structuralFeature.getEType(rowEntry.getSpecification(annotationType));
// Get the enum literals again, as it might be different for each row.
if(type instanceof EEnum) {
EList<EEnumLiteral> allLiterals = ((EEnum)type).getELiterals();
return allLiterals.stream().map(l -> l.getLiteral()).collect(toList());
}
return emptyList();
Map<Object, String> comboValues = getComboValues(featureDescriptor, specification,
rowEntry.getModelElement());
return comboValues;
});
} else if(valueType.getInstanceClass().equals(Boolean.class)) {
// Use a checkbox column for booleans
......@@ -447,12 +442,49 @@ public class AnnotationViewFXController extends CompositeFXControllerBase<SplitP
return column;
}
/**
* Returns mapping of annotation values and their labels to be displayed in a combo box (for
* enums and references).
*/
private Map<Object, String> getComboValues(EStructuralFeatureDescriptor featureDescriptor,
IAnnotatedSpecification specification, IModelElement modelElement) {
EClassifier eType = featureDescriptor.getEType(specification);
if(eType instanceof EEnum) {
EList<EEnumLiteral> allLiterals = ((EEnum)eType).getELiterals();
return allLiterals.stream().collect(toMap(l -> l.getInstance(), l -> l.getLiteral()));
} else if(eType instanceof EClass) {
EObject root = featureDescriptor.getValueRootElement(modelElement);
if(root == null) {
return emptyMap();
}
EList<EObject> values = new BasicEList<EObject>();
if(featureDescriptor.getEReferenceScope() == EReferenceScope.SUB_MODEL) {
values.add(root);
}
Class<? extends EObject> clazz = (Class<? extends EObject>)eType.getInstanceClass();
for(EObject obj : getChildrenWithType(root, clazz)) {
if(featureDescriptor.isAvailableObject(obj, specification, modelElement)) {
values.add(obj);
}
}
sort(values, new HierarchicalNameComparator());
return values.stream().collect(toMap(v -> v, v -> getValueLabel(v, root)));
}
return emptyMap();
}
/**
* Local helper to set the given newValue for the given annotationEntry and
* specification.
*/
void setAnnotationEntryValue(IAnnotatedSpecification specification,
AnnotationEntry annotationEntry, String newValue) {
AnnotationEntry annotationEntry, Object newValue) {
ITopLevelElement tle =
IPersistencyService.getInstance().getTopLevelElementFor(curentRootElement);
......
......@@ -5,8 +5,8 @@ DynamicTextFieldTreeTableCell.java de24117e6f785b328f1ff62383626a0b4b54e8ff GREE
DynamicTreeContentProviderBase.java 91896b1fb5104d126544c44c1ff8c30f2a13a8d6 GREEN
DynamicTreeItem.java 7486071d20e896d6ca9a9101bf105caccf3656d0 GREEN
DynamicTreeItemBase.java d883066ecc181120302ca32f328538de7a45b093 GREEN
DynamicTreeTableUIProviderBase.java a091824351771293b8f68a53e658d712a2128878 GREEN
DynamicTreeTableViewer.java ead6f6671e9cb6b14632940bf440cba7e81fcd98 GREEN
DynamicTreeTableUIProviderBase.java 735766bf3b046dc696eb3324378754ae6db5f4d0 YELLOW
DynamicTreeTableViewer.java 9198fbd64af2c15829e63bafcab8095a173c6ff4 YELLOW
DynamicTreeUIProviderBase.java 82d3c051213f0147f4c67ad247a08696cee73110 GREEN
DynamicTreeViewer.java 545f1ca10b7b3cad171b294a4b447875da45c9ed GREEN
DynamicTreeViewerBase.java a2013538b62d86f6a09efdf2cd78babac2072484 GREEN
......
......@@ -13,10 +13,11 @@
*******************************************************************************/
package org.fortiss.tooling.common.ui.javafx.control.treetableview;
import static java.util.stream.Collectors.toMap;
import static javafx.collections.FXCollections.observableArrayList;
import static org.apache.commons.lang3.SystemUtils.IS_OS_LINUX;
import java.util.Collection;
import java.util.Map;
import java.util.function.Function;
import javafx.beans.property.SimpleBooleanProperty;
......@@ -268,10 +269,11 @@ public abstract class DynamicTreeTableUIProviderBase<T> {
* @param column
* The {@link TreeTableColumn} to be configured.
* @param comboValueFactory
* A {@link Function} that maps the cell elements to their respective combo values.
* A {@link Function} that maps cell elements to a combo value map (data model
* element -> label)
*/
/* package */ final void applyToComboColumn(int columnIndex, TreeTableColumn<T, String> column,
Function<T, Collection<String>> comboValueFactory) {
Function<T, Map<?, String>> comboValueFactory) {
column.setCellFactory(
createEditableComboCellFactory(columnIndex, column, comboValueFactory));
}
......@@ -345,7 +347,7 @@ public abstract class DynamicTreeTableUIProviderBase<T> {
/** Creates the cell factory for {@link ComboBox} editing. */
private Callback<TreeTableColumn<T, String>, TreeTableCell<T, String>>
createEditableComboCellFactory(int columnIndex, TreeTableColumn<T, String> column,
Function<T, Collection<String>> comboValueFactory) {
Function<T, Map<?, String>> comboValueFactory) {
// The list with the choices to be offered in the combo.
ObservableList<String> items = observableArrayList();
Callback<TreeTableColumn<T, String>, TreeTableCell<T, String>> comboCellFactory =
......@@ -374,14 +376,30 @@ public abstract class DynamicTreeTableUIProviderBase<T> {
// Changes the choices of the combo for every editing of every cell dynamically.
column.setOnEditStart(event -> {
TreeItem<T> treeItem = event.getRowValue();
T rowEntry = treeItem.getValue();
Collection<String> comboValues = comboValueFactory.apply(rowEntry);
T rowEntry = event.getRowValue().getValue();
Map<?, String> comboValueMap = comboValueFactory.apply(rowEntry);
items.clear();
items.addAll(comboValues);
items.addAll(comboValueMap.values());
});
column.setOnEditCommit(event -> {
// The column number needs to be retrieved from the viewer, as the the
// event.getTablePosition() does not take into account invisible columns for numbering.
TreeTableColumn<T, String> tableColumn = event.getTableColumn();
int colIndex = tableColumn.getTreeTableView().getColumns().indexOf(tableColumn);
// Convert displayed value label into underlying data model's value
String valueLabel = event.getNewValue();
T rowEntry = event.getRowValue().getValue();
Map<?, String> comboValueMap = comboValueFactory.apply(rowEntry);
Map<String, ?> valueMapInversed = comboValueMap.entrySet().stream()
.collect(toMap(Map.Entry::getValue, Map.Entry::getKey));
updateValue(rowEntry, colIndex, valueMapInversed.get(valueLabel));
column.getTreeTableView().refresh();
});
return comboCellFactory;
}
......
......@@ -19,6 +19,7 @@ import static java.lang.Integer.MAX_VALUE;
import static javafx.scene.control.cell.CheckBoxTreeTableCell.forTreeTableColumn;
import java.util.Collection;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;
......@@ -194,8 +195,7 @@ public final class DynamicTreeTableViewer<T> extends DynamicTreeViewerBase<T> {
/**
* Adds an editable column to the table part of the view. The labels, context menus and icons
* are shown as
* defined in the {@link DynamicTreeTableUIProviderBase}.
* are shown as defined in the {@link DynamicTreeTableUIProviderBase}.
*/
public TreeTableColumn<T, String> addTextColumn(String headerLabel, int prefWidth) {
int num = view.getColumns().size();
......@@ -232,17 +232,29 @@ public final class DynamicTreeTableViewer<T> extends DynamicTreeViewerBase<T> {
* @param prefWidth
* The preferred width of the new column in px.
* @param comboValueFactory
* A Function, that maps cell elements to choices for the combo box.
* A {@link Function} that maps cell elements to a combo value map (data model
* element -> label)
*
* @return The newly created an configured column.
*/
public TreeTableColumn<T, String> addComboColumn(String headerLabel, int prefWidth,
Function<T, Collection<String>> comboValueFactory) {
Function<T, Map<?, String>> comboValueFactory) {
int num = view.getColumns().size();
TreeTableColumn<T, String> column = addColumn(headerLabel, prefWidth);
TreeTableColumn<T, String> column = new TreeTableColumn<>(headerLabel);
column.setPrefWidth(prefWidth);
column.setCellValueFactory(param -> {
T data = param.getValue().getValue();
SimpleObjectProperty<String> cell =
new SimpleObjectProperty<String>(uiProvider.getLabel(data, num));
return cell;
});
uiProvider.applyToComboColumn(num, column, comboValueFactory);
view.getColumns().add(column);
return column;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment