Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Schindl2013-04-17 20:45:23 +0000
committerTom Schindl2013-04-17 20:45:23 +0000
commitfdd4019e045000d9d478b962a6066c3eb1fbb170 (patch)
tree700cf46fb004873a49673e8188c43e960f74e9de
parent8182f8673e1b8faa0e346467b5dd15070ce974e3 (diff)
downloadorg.eclipse.efxclipse-fdd4019e045000d9d478b962a6066c3eb1fbb170.tar.gz
org.eclipse.efxclipse-fdd4019e045000d9d478b962a6066c3eb1fbb170.tar.xz
org.eclipse.efxclipse-fdd4019e045000d9d478b962a6066c3eb1fbb170.zip
initial checkin
-rwxr-xr-xbundles/runtime/org.eclipse.fx.emf.edit.ui/.classpath7
-rwxr-xr-xbundles/runtime/org.eclipse.fx.emf.edit.ui/.gitignore2
-rwxr-xr-xbundles/runtime/org.eclipse.fx.emf.edit.ui/.project28
-rw-r--r--bundles/runtime/org.eclipse.fx.emf.edit.ui/.settings/org.eclipse.jdt.core.prefs7
-rwxr-xr-xbundles/runtime/org.eclipse.fx.emf.edit.ui/META-INF/MANIFEST.MF40
-rwxr-xr-xbundles/runtime/org.eclipse.fx.emf.edit.ui/build.properties4
-rwxr-xr-xbundles/runtime/org.eclipse.fx.emf.edit.ui/pom.xml34
-rwxr-xr-xbundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/AdapterFactoryCellFactory.java305
-rwxr-xr-xbundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/AdapterFactoryListCellFactory.java124
-rwxr-xr-xbundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/AdapterFactoryObservableList.java251
-rwxr-xr-xbundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/AdapterFactoryTableCellFactory.java173
-rwxr-xr-xbundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/AdapterFactoryTreeCellFactory.java126
-rwxr-xr-xbundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/AdapterFactoryTreeItem.java141
-rwxr-xr-xbundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/EAttributeCellEditHandler.java67
-rwxr-xr-xbundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/ProxyCellValueFactory.java41
-rwxr-xr-xbundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/dnd/CellDragAdapter.java82
-rwxr-xr-xbundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/dnd/EditingDomainCellDropAdapter.java185
-rwxr-xr-xbundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/dnd/LocalTransfer.java35
18 files changed, 1652 insertions, 0 deletions
diff --git a/bundles/runtime/org.eclipse.fx.emf.edit.ui/.classpath b/bundles/runtime/org.eclipse.fx.emf.edit.ui/.classpath
new file mode 100755
index 000000000..098194ca4
--- /dev/null
+++ b/bundles/runtime/org.eclipse.fx.emf.edit.ui/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/runtime/org.eclipse.fx.emf.edit.ui/.gitignore b/bundles/runtime/org.eclipse.fx.emf.edit.ui/.gitignore
new file mode 100755
index 000000000..4dc009173
--- /dev/null
+++ b/bundles/runtime/org.eclipse.fx.emf.edit.ui/.gitignore
@@ -0,0 +1,2 @@
+/target
+/bin
diff --git a/bundles/runtime/org.eclipse.fx.emf.edit.ui/.project b/bundles/runtime/org.eclipse.fx.emf.edit.ui/.project
new file mode 100755
index 000000000..07f363d57
--- /dev/null
+++ b/bundles/runtime/org.eclipse.fx.emf.edit.ui/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.fx.emf.edit.ui</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/bundles/runtime/org.eclipse.fx.emf.edit.ui/.settings/org.eclipse.jdt.core.prefs b/bundles/runtime/org.eclipse.fx.emf.edit.ui/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 000000000..f42de363a
--- /dev/null
+++ b/bundles/runtime/org.eclipse.fx.emf.edit.ui/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.7
diff --git a/bundles/runtime/org.eclipse.fx.emf.edit.ui/META-INF/MANIFEST.MF b/bundles/runtime/org.eclipse.fx.emf.edit.ui/META-INF/MANIFEST.MF
new file mode 100755
index 000000000..d8346512b
--- /dev/null
+++ b/bundles/runtime/org.eclipse.fx.emf.edit.ui/META-INF/MANIFEST.MF
@@ -0,0 +1,40 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: EMF Edit UI for JavaFX
+Bundle-SymbolicName: org.eclipse.fx.emf.edit.ui
+Bundle-Version: 0.8.1.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Import-Package: javafx.animation;version="2.2.0",
+ javafx.application;version="2.2.0",
+ javafx.beans;version="2.2.0",
+ javafx.beans.binding;version="2.2.0",
+ javafx.beans.property;version="2.2.0",
+ javafx.beans.property.adapter;version="2.2.0",
+ javafx.beans.value;version="2.2.0",
+ javafx.collections;version="2.2.0",
+ javafx.concurrent;version="2.2.0",
+ javafx.embed.swing;version="2.2.0",
+ javafx.embed.swt;version="2.2.0",
+ javafx.event;version="2.2.0",
+ javafx.fxml;version="2.2.0",
+ javafx.geometry;version="2.2.0",
+ javafx.scene;version="2.2.0",
+ javafx.scene.chart;version="2.2.0",
+ javafx.scene.control;version="2.2.0",
+ javafx.scene.control.cell;version="2.2.0",
+ javafx.scene.effect;version="2.2.0",
+ javafx.scene.image;version="2.2.0",
+ javafx.scene.input;version="2.2.0",
+ javafx.scene.layout;version="2.2.0",
+ javafx.scene.media;version="2.2.0",
+ javafx.scene.paint;version="2.2.0",
+ javafx.scene.shape;version="2.2.0",
+ javafx.scene.text;version="2.2.0",
+ javafx.scene.transform;version="2.2.0",
+ javafx.scene.web;version="2.2.0",
+ javafx.stage;version="2.2.0",
+ javafx.util;version="2.2.0",
+ javafx.util.converter;version="2.2.0"
+Require-Bundle: org.eclipse.emf.edit;bundle-version="2.7.0"
+Export-Package: org.eclipse.fx.emf.edit.ui,
+ org.eclipse.fx.emf.edit.ui.dnd
diff --git a/bundles/runtime/org.eclipse.fx.emf.edit.ui/build.properties b/bundles/runtime/org.eclipse.fx.emf.edit.ui/build.properties
new file mode 100755
index 000000000..34d2e4d2d
--- /dev/null
+++ b/bundles/runtime/org.eclipse.fx.emf.edit.ui/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
diff --git a/bundles/runtime/org.eclipse.fx.emf.edit.ui/pom.xml b/bundles/runtime/org.eclipse.fx.emf.edit.ui/pom.xml
new file mode 100755
index 000000000..350fca939
--- /dev/null
+++ b/bundles/runtime/org.eclipse.fx.emf.edit.ui/pom.xml
@@ -0,0 +1,34 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <name>e(fx)clipse - Runtime - EMF UI Edit Support</name>
+ <groupId>org.eclipse.fx</groupId>
+ <artifactId>org.eclipse.fx.emf.edit.ui</artifactId>
+ <packaging>eclipse-plugin</packaging>
+
+ <parent>
+ <groupId>org.eclipse.fx</groupId>
+ <artifactId>releng</artifactId>
+ <relativePath>../../../releng/org.eclipse.fx.releng/pom.xml</relativePath>
+ <version>0.8.1-SNAPSHOT</version>
+ </parent>
+
+ <build>
+ <resources>
+ <!-- to ensure that the feature lookup of the ui test works -->
+ <resource>
+ <directory>.</directory>
+ <includes>
+ <include>META-INF/</include>
+ </includes>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.eclipse.tycho</groupId>
+ <artifactId>tycho-source-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project> \ No newline at end of file
diff --git a/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/AdapterFactoryCellFactory.java b/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/AdapterFactoryCellFactory.java
new file mode 100755
index 000000000..7d0512130
--- /dev/null
+++ b/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/AdapterFactoryCellFactory.java
@@ -0,0 +1,305 @@
+/*******************************************************************************
+ * Copyright (c) 2012 TESIS DYNAware GmbH and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Torsten Sommer <torsten.sommer@tesis.de> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.fx.emf.edit.ui;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import javafx.scene.Node;
+import javafx.scene.control.Cell;
+import javafx.scene.image.ImageView;
+import javafx.scene.layout.Pane;
+import javafx.scene.paint.Color;
+import javafx.scene.text.Font;
+import javafx.scene.text.FontPosture;
+import javafx.scene.text.FontWeight;
+
+import org.eclipse.emf.common.notify.AdapterFactory;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.edit.provider.ComposedImage;
+import org.eclipse.emf.edit.provider.IItemColorProvider;
+import org.eclipse.emf.edit.provider.IItemFontProvider;
+import org.eclipse.emf.edit.provider.IItemLabelProvider;
+
+/**
+ * Base class for the AdapterFactoryCellFactories
+ */
+public abstract class AdapterFactoryCellFactory {
+
+ /**
+ * A listener interface for callbacks that process newly created
+ * {@link Cell}s
+ */
+ public interface ICellCreationListener {
+
+ /**
+ * @param cell the newly created {@link Cell}
+ */
+ void cellCreated(Cell<?> cell);
+
+ }
+
+ /**
+ * A listener interface for callbacks that process {@link Cell}s being
+ * updated during {@link Cell#updateItem}.
+ */
+ public interface ICellUpdateListener {
+
+ /**
+ * @param cell the {@link Cell} being updated
+ * @param item as defined in {@link Cell#updateItem}
+ * @param empty as defined in {@link Cell#updateItem}
+ */
+ void updateItem(Cell<?> cell, Object item, boolean empty);
+
+ }
+
+ /**
+ * An interface for providers that handle cell editing. The {@link Cell}s
+ * created by the factory will delegate calls to their editing methods to
+ * the first handler in {@link AdapterFactoryCellFactory#cellEditHandlers}
+ * that returns <code>true</code> for {@link ICellEditHandler#canEdit(Cell)}
+ * .
+ */
+ public interface ICellEditHandler {
+
+ /**
+ * Whether editing treeCell can be handled
+ */
+ boolean canEdit(Cell<?> treeCell);
+
+ /**
+ * Delegate for {@link Cell#startEdit()}
+ */
+ void startEdit(Cell<?> treeCell);
+
+ /**
+ * Delegate for {@link Cell#commitEdit(Object)}
+ */
+ void commitEdit(Cell<?> treeCell, Object newValue);
+
+ /**
+ * Delegate for {@link Cell#cancelEdit()}
+ */
+ void cancelEdit(Cell<?> treeCell);
+
+ }
+
+ final protected AdapterFactory adapterFactory;
+ final List<ICellCreationListener> cellCreationListeners = new ArrayList<>();
+ final List<ICellUpdateListener> cellUpdateListeners = new ArrayList<>();
+ final List<ICellEditHandler> cellEditHandlers = new ArrayList<>();
+
+ public AdapterFactoryCellFactory(AdapterFactory adapterFactory) {
+ super();
+
+ if (adapterFactory == null)
+ throw new IllegalArgumentException("AdapterFactory must not be null.");
+
+ this.adapterFactory = adapterFactory;
+ }
+
+ public AdapterFactory getAdapterFactory() {
+ return adapterFactory;
+ }
+
+ public void addCellCreationListener(ICellCreationListener listener) {
+ cellCreationListeners.add(listener);
+ }
+
+ public void removeCellCreationListener(ICellCreationListener listener) {
+ cellCreationListeners.remove(listener);
+ }
+
+ public void addCellUpdateListener(ICellUpdateListener listener) {
+ cellUpdateListeners.add(listener);
+ }
+
+ public void removeCellUpdateListener(ICellUpdateListener listener) {
+ cellUpdateListeners.remove(listener);
+ }
+
+ public void addCellEditHandler(ICellEditHandler cellEditHandler) {
+ cellEditHandlers.add(cellEditHandler);
+ }
+
+ public void remvoveCellEditHandler(ICellEditHandler cellEditHandler) {
+ cellEditHandlers.remove(cellEditHandler);
+ }
+
+ ICellEditHandler getCellEditHandler(Cell<?> cell) {
+ for (ICellEditHandler cellEditHandler : cellEditHandlers) {
+ if (cellEditHandler.canEdit(cell))
+ return cellEditHandler;
+ }
+ return null;
+ }
+
+ void applyItemProviderStyle(Object item, Cell<?> cell, AdapterFactory adapterFactory) {
+ applyItemProviderLabel(item, cell, adapterFactory);
+ applyItemProviderColor(item, cell, adapterFactory);
+ applyItemProviderFont(item, cell, adapterFactory);
+ }
+
+ void applyItemProviderFont(Object item, Cell<?> cell, AdapterFactory adapterFactory) {
+ IItemFontProvider fontProvider = (IItemFontProvider) adapterFactory.adapt(item, IItemFontProvider.class);
+ if (fontProvider != null) {
+ Font font = fontFromObject(fontProvider.getFont(item));
+ if (font != null)
+ cell.setFont(font);
+ }
+ }
+
+ Font fontFromObject(Object object) {
+
+ if (object instanceof URI) {
+ URI fontURI = (URI) object;
+ if (!"font".equals(fontURI.scheme()))
+ throw new IllegalArgumentException("Only 'font' scheme is recognized" + fontURI);
+
+ if (fontURI.segmentCount() != 2)
+ throw new IllegalArgumentException("The URI must have an authority and two segments");
+
+ // font name
+ String fontNameSpecification = fontURI.authority();
+ if ("".equals(fontNameSpecification))
+ fontNameSpecification = null;
+
+ // font height
+ String heightSpecification = fontURI.segment(0);
+ boolean delta;
+ int height;
+ if (heightSpecification.startsWith("+")) {
+ delta = true;
+ height = Integer.parseInt(heightSpecification.substring(1));
+ } else if ("".equals(heightSpecification)) {
+ delta = true;
+ height = 0;
+ } else {
+ height = Integer.parseInt(heightSpecification);
+ delta = height < 0;
+ }
+
+ // font style
+ String styleSpecification = fontURI.segment(1);
+ boolean italic = false;
+ boolean bold = false;
+ if ("bold".equals(styleSpecification))
+ bold = true;
+ else if ("italic".equals(styleSpecification))
+ italic = true;
+ else if ("italic+bold".equals(styleSpecification) || "bold+italic".equals(styleSpecification))
+ bold = italic = true;
+
+ double size = delta ? Font.getDefault().getSize() + height : height;
+
+ return Font.font(fontNameSpecification, bold ? FontWeight.BOLD : FontWeight.NORMAL, italic ? FontPosture.ITALIC
+ : FontPosture.REGULAR, size);
+ }
+
+ return null;
+ }
+
+ void applyItemProviderLabel(Object item, Cell<?> cell, AdapterFactory adapterFactory) {
+ IItemLabelProvider labelProvider = (IItemLabelProvider) adapterFactory.adapt(item, IItemLabelProvider.class);
+
+ if (labelProvider != null) {
+ cell.setText(labelProvider.getText(item));
+
+ if (item != null) {
+ Node image = graphicFromObject(labelProvider.getImage(item));
+ if (image != null)
+ cell.setGraphic(image);
+ }
+ }
+ }
+
+ Node graphicFromObject(Object object) {
+ if (object instanceof Node) {
+ return (Node) object;
+ } else if (object instanceof URL) {
+ return new ImageView(((URL) object).toExternalForm());
+ } else if (object instanceof ComposedImage) {
+ Pane pane = new Pane();
+
+ for (Object image : ((ComposedImage) object).getImages()) {
+ if (image instanceof URL) {
+ ImageView imageView = new ImageView(((URL) image).toExternalForm());
+ pane.getChildren().add(imageView);
+ }
+ }
+
+ return pane;
+ }
+
+ return null;
+ }
+
+ void applyItemProviderColor(Object item, Cell<?> cell, AdapterFactory adapterFactory) {
+ IItemColorProvider colorProvider = (IItemColorProvider) adapterFactory.adapt(item, IItemColorProvider.class);
+ if (colorProvider != null) {
+ Color foreground = colorFromObject(colorProvider.getForeground(item));
+ if (foreground != null)
+ cell.setTextFill(foreground);
+
+ String background = cssColorFromObject(colorProvider.getBackground(item));
+ if (background != null)
+ cell.setStyle("-fx-background-color: " + background);
+ }
+ }
+
+ Color colorFromObject(Object object) {
+ URI colorURI = toColorURI(object);
+
+ if (colorURI != null) {
+ try {
+ int red = Integer.parseInt(colorURI.segment(0));
+ int green = Integer.parseInt(colorURI.segment(1));
+ int blue = Integer.parseInt(colorURI.segment(2));
+ return Color.rgb(red, green, blue);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Cannot parse color values " + colorURI + ". " + e.getMessage());
+ }
+ }
+
+ return null;
+ }
+
+ String cssColorFromObject(Object object) {
+ URI colorURI = toColorURI(object);
+
+ if (colorURI != null)
+ return "rgb(" + colorURI.segment(0) + ", " + colorURI.segment(1) + ", " + colorURI.segment(2) + ")";
+
+ return null;
+ }
+
+ URI toColorURI(Object object) {
+ if (object instanceof URI) {
+ URI colorURI = (URI) object;
+
+ if (!"color".equals(colorURI.scheme()))
+ throw new IllegalArgumentException("Only 'color' scheme is recognized " + colorURI);
+
+ if (!"rgb".equals(colorURI.authority()))
+ throw new IllegalArgumentException("Only 'rgb' authority is recognized " + colorURI);
+
+ if (colorURI.segmentCount() != 3)
+ throw new IllegalArgumentException("Color must have 3 segments (r, g, b) " + colorURI);
+
+ return colorURI;
+ }
+
+ return null;
+ }
+
+}
diff --git a/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/AdapterFactoryListCellFactory.java b/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/AdapterFactoryListCellFactory.java
new file mode 100755
index 000000000..d032169c2
--- /dev/null
+++ b/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/AdapterFactoryListCellFactory.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (c) 2012 TESIS DYNAware GmbH and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Torsten Sommer <torsten.sommer@tesis.de> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.fx.emf.edit.ui;
+
+import javafx.scene.Node;
+import javafx.scene.control.Cell;
+import javafx.scene.control.ListCell;
+import javafx.scene.control.ListView;
+import javafx.util.Callback;
+
+import org.eclipse.emf.common.notify.AdapterFactory;
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.common.notify.Notifier;
+import org.eclipse.emf.common.notify.impl.AdapterImpl;
+import org.eclipse.emf.edit.provider.IItemColorProvider;
+import org.eclipse.emf.edit.provider.IItemFontProvider;
+import org.eclipse.emf.edit.provider.IItemLabelProvider;
+
+/**
+ * This list cell factory wraps an {@link AdapterFactory} and delegates calls to
+ * its {@link ListCell}s to the corresponding adapter-implemented item provider
+ * interfaces.
+ *
+ * <ul>
+ * <li>{@link Cell#setText(String)} and {@link Cell#setGraphic(Node)} are
+ * delegated to {@link IItemLabelProvider}</li>
+ * <li>{@link Cell#setTextFill(javafx.scene.paint.Paint)} and the CSS property
+ * <code>-fx-background-color</code> are delegated to {@link IItemColorProvider}
+ * </li>
+ * <li>{@link Cell#setFont(javafx.scene.text.Font)} is delegated to
+ * {@link IItemFontProvider}</li>
+ * </ul>
+ */
+public class AdapterFactoryListCellFactory extends AdapterFactoryCellFactory implements Callback<ListView<Object>, ListCell<Object>> {
+
+ public AdapterFactoryListCellFactory(AdapterFactory adapterFactory) {
+ super(adapterFactory);
+ }
+
+ @Override
+ public ListCell<Object> call(ListView<Object> param) {
+
+ final ListCell<Object> listCell = new ListCell<Object>() {
+
+ Object currentItem = null;
+ ICellEditHandler cellEditHandler;
+
+ AdapterImpl adapter = new AdapterImpl() {
+ @Override
+ public void notifyChanged(Notification msg) {
+ update(msg.getNotifier());
+ }
+ };
+
+ @Override
+ protected void updateItem(Object item, boolean empty) {
+ super.updateItem(item, empty);
+
+ // check if the item changed
+ if (item != currentItem) {
+
+ // remove the adapter if attached
+ if (currentItem instanceof Notifier)
+ ((Notifier) currentItem).eAdapters().remove(adapter);
+
+ // update the current item
+ currentItem = item;
+
+ // attach the adapter to the new item
+ if (currentItem instanceof Notifier)
+ ((Notifier) currentItem).eAdapters().add(adapter);
+ }
+
+ // notify the listeners
+ for (ICellUpdateListener cellUpdateListener : cellUpdateListeners)
+ cellUpdateListener.updateItem(this, item, empty);
+
+ update(item);
+ }
+
+ @Override
+ public void startEdit() {
+ super.startEdit();
+ cellEditHandler = getCellEditHandler(this);
+ if (cellEditHandler != null)
+ cellEditHandler.startEdit(this);
+ }
+
+ @Override
+ public void commitEdit(Object newValue) {
+ super.commitEdit(newValue);
+ if (cellEditHandler != null)
+ cellEditHandler.commitEdit(this, newValue);
+ }
+
+ @Override
+ public void cancelEdit() {
+ super.cancelEdit();
+ if (cellEditHandler != null)
+ cellEditHandler.cancelEdit(this);
+ update(getItem());
+ }
+
+ private void update(Object item) {
+ applyItemProviderStyle(item, this, adapterFactory);
+ }
+
+ };
+
+ for (ICellCreationListener cellCreationListener : cellCreationListeners)
+ cellCreationListener.cellCreated(listCell);
+
+ return listCell;
+ }
+
+}
diff --git a/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/AdapterFactoryObservableList.java b/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/AdapterFactoryObservableList.java
new file mode 100755
index 000000000..a4da3dfa6
--- /dev/null
+++ b/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/AdapterFactoryObservableList.java
@@ -0,0 +1,251 @@
+/*******************************************************************************
+ * Copyright (c) 2012 TESIS DYNAware GmbH and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Torsten Sommer <torsten.sommer@tesis.de> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.fx.emf.edit.ui;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+import javafx.beans.InvalidationListener;
+import javafx.collections.FXCollections;
+import javafx.collections.ListChangeListener;
+import javafx.collections.ObservableList;
+
+import org.eclipse.emf.common.notify.AdapterFactory;
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.common.notify.Notifier;
+import org.eclipse.emf.common.notify.impl.AdapterImpl;
+import org.eclipse.emf.edit.provider.IChangeNotifier;
+import org.eclipse.emf.edit.provider.INotifyChangedListener;
+import org.eclipse.emf.edit.provider.IStructuredItemContentProvider;
+
+/**
+ * This {@link ObservableList} wraps an {@link AdapterFactory} and retrieves its elements from the
+ * adapter-implemented {@link IStructuredItemContentProvider} interface. The content of the list can only be
+ * modified through changes to the underlying model.
+ */
+public class AdapterFactoryObservableList<T> implements ObservableList<T> {
+
+ private static final String CHANGES_THROUGH_MODEL = "An AdapterFactoryObservableList cannot be manipulated directly. Changes must be made via the model.";
+ protected AdapterFactory adapterFactory;
+ protected Object root;
+ protected IStructuredItemContentProvider provider;
+ /* package */ObservableList<T> elements = FXCollections.observableArrayList();
+
+ @SuppressWarnings("unchecked")
+ public AdapterFactoryObservableList(AdapterFactory adapterFactory, final Object root) {
+ super();
+
+ if (adapterFactory == null)
+ throw new IllegalArgumentException("AdapterFactory must not be null.");
+
+ this.adapterFactory = adapterFactory;
+ this.root = root;
+ Object contentProvider = adapterFactory.adapt(root, IStructuredItemContentProvider.class);
+
+ if(contentProvider instanceof IStructuredItemContentProvider)
+ provider = (IStructuredItemContentProvider) contentProvider;
+ else
+ throw new IllegalArgumentException("Provided root object cannot be adapted.");
+
+ elements.addAll((Collection<? extends T>) provider.getElements(root));
+
+ if (root instanceof Notifier) {
+ AdapterImpl adapter = new AdapterImpl() {
+
+ @Override
+ public void notifyChanged(Notification msg) {
+ elements.setAll((Collection<? extends T>) provider.getElements(root));
+ }
+
+ };
+
+ ((Notifier) root).eAdapters().add(adapter);
+ } else if (root instanceof IChangeNotifier) {
+ ((IChangeNotifier) root).addListener(new INotifyChangedListener() {
+
+ @Override
+ public void notifyChanged(Notification notification) {
+ elements.setAll((Collection<? extends T>) provider.getElements(root));
+ }
+
+ });
+ }
+
+ }
+
+ @Override
+ public boolean add(Object e) {
+ throw new UnsupportedOperationException(CHANGES_THROUGH_MODEL);
+ }
+
+ @Override
+ public void add(int index, Object element) {
+ throw new UnsupportedOperationException(CHANGES_THROUGH_MODEL);
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends T> c) {
+ throw new UnsupportedOperationException(CHANGES_THROUGH_MODEL);
+ }
+
+ @Override
+ public boolean addAll(int index, Collection<? extends T> c) {
+ throw new UnsupportedOperationException(CHANGES_THROUGH_MODEL);
+ }
+
+ @Override
+ public void clear() {
+ throw new UnsupportedOperationException(CHANGES_THROUGH_MODEL);
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return elements.contains(o);
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ return elements.containsAll(c);
+ }
+
+ @Override
+ public T get(int index) {
+ return elements.get(index);
+ }
+
+ @Override
+ public int indexOf(Object o) {
+ return elements.indexOf(o);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return elements.isEmpty();
+ }
+
+ @Override
+ public Iterator<T> iterator() {
+ return elements.iterator();
+ }
+
+ @Override
+ public int lastIndexOf(Object o) {
+ return elements.lastIndexOf(o);
+ }
+
+ @Override
+ public ListIterator<T> listIterator() {
+ return elements.listIterator();
+ }
+
+ @Override
+ public ListIterator<T> listIterator(int index) {
+ return elements.listIterator(index);
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ throw new UnsupportedOperationException(CHANGES_THROUGH_MODEL);
+ }
+
+ @Override
+ public T remove(int index) {
+ throw new UnsupportedOperationException(CHANGES_THROUGH_MODEL);
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ throw new UnsupportedOperationException(CHANGES_THROUGH_MODEL);
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ throw new UnsupportedOperationException(CHANGES_THROUGH_MODEL);
+ }
+
+ @Override
+ public T set(int index, Object element) {
+ throw new UnsupportedOperationException(CHANGES_THROUGH_MODEL);
+ }
+
+ @Override
+ public int size() {
+ return elements.size();
+ }
+
+ @Override
+ public List<T> subList(int fromIndex, int toIndex) {
+ return elements.subList(fromIndex, toIndex);
+ }
+
+ @Override
+ public Object[] toArray() {
+ return elements.toArray();
+ }
+
+ @Override
+ public <A> A[] toArray(A[] a) {
+ return elements.toArray(a);
+ }
+
+ @Override
+ public void addListener(InvalidationListener listener) {
+ elements.addListener(listener);
+ }
+
+ @Override
+ public void removeListener(InvalidationListener listener) {
+ elements.removeListener(listener);
+ }
+
+ @Override
+ public boolean addAll(Object... arg0) {
+ throw new UnsupportedOperationException(CHANGES_THROUGH_MODEL);
+ }
+
+ @Override
+ public void addListener(ListChangeListener<? super T> listener) {
+ elements.addListener(listener);
+ }
+
+ @Override
+ public void remove(int arg0, int arg1) {
+ throw new UnsupportedOperationException(CHANGES_THROUGH_MODEL);
+ }
+
+ @Override
+ public boolean removeAll(Object... arg0) {
+ throw new UnsupportedOperationException(CHANGES_THROUGH_MODEL);
+ }
+
+ @Override
+ public void removeListener(ListChangeListener<? super T> listener) {
+ elements.removeListener(listener);
+ }
+
+ @Override
+ public boolean retainAll(Object... arg0) {
+ throw new UnsupportedOperationException(CHANGES_THROUGH_MODEL);
+ }
+
+ @Override
+ public boolean setAll(Object... arg0) {
+ throw new UnsupportedOperationException(CHANGES_THROUGH_MODEL);
+ }
+
+ @Override
+ public boolean setAll(Collection<? extends T> arg0) {
+ throw new UnsupportedOperationException(CHANGES_THROUGH_MODEL);
+ }
+
+}
diff --git a/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/AdapterFactoryTableCellFactory.java b/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/AdapterFactoryTableCellFactory.java
new file mode 100755
index 000000000..281afff6c
--- /dev/null
+++ b/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/AdapterFactoryTableCellFactory.java
@@ -0,0 +1,173 @@
+/*******************************************************************************
+ * Copyright (c) 2012 TESIS DYNAware GmbH and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Torsten Sommer <torsten.sommer@tesis.de> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.fx.emf.edit.ui;
+
+import java.net.URL;
+
+import javafx.scene.Node;
+import javafx.scene.control.Cell;
+import javafx.scene.control.TableCell;
+import javafx.scene.control.TableColumn;
+import javafx.scene.image.ImageView;
+import javafx.scene.paint.Color;
+import javafx.scene.text.Font;
+import javafx.util.Callback;
+
+import org.eclipse.emf.common.notify.AdapterFactory;
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.common.notify.Notifier;
+import org.eclipse.emf.common.notify.impl.AdapterImpl;
+import org.eclipse.emf.edit.provider.ITableItemColorProvider;
+import org.eclipse.emf.edit.provider.ITableItemFontProvider;
+import org.eclipse.emf.edit.provider.ITableItemLabelProvider;
+
+/**
+ * This list cell factory wraps an {@link AdapterFactory} and delegates calls to
+ * its {@link TableCell}s to the corresponding adapter-implemented item provider
+ * interfaces.
+ *
+ * <ul>
+ * <li>{@link Cell#setText(String)} and {@link Cell#setGraphic(Node)} are
+ * delegated to {@link ITableItemLabelProvider}</li>
+ * <li>{@link Cell#setTextFill(javafx.scene.paint.Paint)} and the CSS property
+ * <code>-fx-background-color</code> are delegated to
+ * {@link ITableItemColorProvider}</li>
+ * <li>{@link Cell#setFont(javafx.scene.text.Font)} is delegated to
+ * {@link ITableItemFontProvider}</li>
+ * </ul>
+ */
+public class AdapterFactoryTableCellFactory<S, T> extends AdapterFactoryCellFactory implements
+ Callback<TableColumn<S,T>, TableCell<S, T>> {
+
+ protected int columnIndex;
+
+ public AdapterFactoryTableCellFactory(AdapterFactory adapterFactory, int columnIndex) {
+ super(adapterFactory);
+ this.columnIndex = columnIndex;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public TableCell<S, T> call(TableColumn<S, T> arg0) {
+
+ final TableCell<Object, Object> tableCell = new TableCell<Object, Object>() {
+
+ Object currentItem = null;
+ ICellEditHandler cellEditHandler;
+
+ AdapterImpl adapter = new AdapterImpl() {
+ @Override
+ public void notifyChanged(Notification msg) {
+ update(msg.getNotifier());
+ }
+ };
+
+ @Override
+ protected void updateItem(Object item, boolean empty) {
+ super.updateItem(item, empty);
+
+ // check if the item changed
+ if (item != currentItem) {
+
+ // remove the adapter if attached
+ if (currentItem instanceof Notifier)
+ ((Notifier) currentItem).eAdapters().remove(adapter);
+
+ // update the current item
+ currentItem = item;
+
+ // attach the adapter to the new item
+ if (currentItem instanceof Notifier)
+ ((Notifier) currentItem).eAdapters().add(adapter);
+ }
+
+ // notify the listeners
+ for (ICellUpdateListener cellUpdateListener : cellUpdateListeners)
+ cellUpdateListener.updateItem(this, item, empty);
+
+ update(item);
+ }
+
+ @Override
+ public void startEdit() {
+ super.startEdit();
+ cellEditHandler = getCellEditHandler(this);
+ if(cellEditHandler != null)
+ cellEditHandler.startEdit(this);
+ }
+
+ @Override
+ public void commitEdit(Object newValue) {
+ super.commitEdit(newValue);
+ if(cellEditHandler != null)
+ cellEditHandler.commitEdit(this, newValue);
+ }
+
+ @Override
+ public void cancelEdit() {
+ super.cancelEdit();
+ if(cellEditHandler != null)
+ cellEditHandler.cancelEdit(this);
+ update(getItem());
+ }
+
+ private void update(Object item) {
+ applyTableItemProviderStyle(item, columnIndex, this, adapterFactory);
+ }
+
+ };
+
+ for (ICellCreationListener cellCreationListener : cellCreationListeners)
+ cellCreationListener.cellCreated(tableCell);
+
+ return (TableCell<S, T>) tableCell;
+ }
+
+ void applyTableItemProviderStyle(Object item, int columnIndex, Cell<?> cell, AdapterFactory adapterFactory) {
+
+ applyTableItemProviderLabel(item, columnIndex, cell, adapterFactory);
+ applyTableItemProviderColor(item, columnIndex, cell, adapterFactory);
+ applyTableItemProviderFont(item, columnIndex, cell, adapterFactory);
+ }
+
+ void applyTableItemProviderLabel(Object item, int columnIndex, Cell<?> cell, AdapterFactory adapterFactory) {
+ ITableItemLabelProvider labelProvider = (ITableItemLabelProvider) adapterFactory.adapt(item, ITableItemLabelProvider.class);
+ if (labelProvider != null) {
+ cell.setText(labelProvider.getColumnText(item, columnIndex));
+ Object columnImage = labelProvider.getColumnImage(item, columnIndex);
+ Node graphic = graphicFromObject(columnImage);
+ cell.setGraphic(graphic);
+ }
+ }
+
+ void applyTableItemProviderColor(Object item, int columnIndex, Cell<?> cell, AdapterFactory adapterFactory) {
+ ITableItemColorProvider colorProvider = (ITableItemColorProvider) adapterFactory.adapt(item, ITableItemColorProvider.class);
+ if (colorProvider != null) {
+ Color foreground = colorFromObject(colorProvider.getForeground(item, columnIndex));
+ if (foreground != null)
+ cell.setTextFill(foreground);
+
+ String background = cssColorFromObject(colorProvider.getBackground(item, columnIndex));
+ if (background != null)
+ cell.setStyle("-fx-background-color: " + background);
+ }
+ }
+
+ void applyTableItemProviderFont(Object item, int columnIndex, Cell<?> cell, AdapterFactory adapterFactory) {
+ ITableItemFontProvider fontProvider = (ITableItemFontProvider) adapterFactory.adapt(item, ITableItemFontProvider.class);
+ if (fontProvider != null) {
+ Font font = fontFromObject(fontProvider.getFont(item, columnIndex));
+ if (font != null)
+ cell.setFont(font);
+ }
+ }
+
+}
diff --git a/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/AdapterFactoryTreeCellFactory.java b/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/AdapterFactoryTreeCellFactory.java
new file mode 100755
index 000000000..28ea214f9
--- /dev/null
+++ b/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/AdapterFactoryTreeCellFactory.java
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ * Copyright (c) 2012 TESIS DYNAware GmbH and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Torsten Sommer <torsten.sommer@tesis.de> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.fx.emf.edit.ui;
+
+import javafx.scene.Node;
+import javafx.scene.control.Cell;
+import javafx.scene.control.TreeCell;
+import javafx.scene.control.TreeView;
+import javafx.util.Callback;
+
+import org.eclipse.emf.common.notify.AdapterFactory;
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.common.notify.Notifier;
+import org.eclipse.emf.common.notify.impl.AdapterImpl;
+import org.eclipse.emf.edit.provider.IItemColorProvider;
+import org.eclipse.emf.edit.provider.IItemFontProvider;
+import org.eclipse.emf.edit.provider.IItemLabelProvider;
+
+/**
+ * This {@link TreeCell} factory wraps an {@link AdapterFactory} and delegates
+ * calls to its {@link TreeCell}s to the corresponding adapter-implemented item
+ * provider interfaces.
+ *
+ * <ul>
+ * <li>{@link Cell#setText(String)} and {@link Cell#setGraphic(Node)} are
+ * delegated to {@link IItemLabelProvider}</li>
+ * <li>{@link Cell#setTextFill(javafx.scene.paint.Paint)} and the CSS property
+ * <code>-fx-background-color</code> are delegated to {@link IItemColorProvider}
+ * </li>
+ * <li>{@link Cell#setFont(javafx.scene.text.Font)} is delegated to
+ * {@link IItemFontProvider}</li>
+ * </ul>
+ */
+public class AdapterFactoryTreeCellFactory extends AdapterFactoryCellFactory implements Callback<TreeView<Object>, TreeCell<Object>> {
+
+ public AdapterFactoryTreeCellFactory(AdapterFactory adapterFactory) {
+ super(adapterFactory);
+ }
+
+ @Override
+ public TreeCell<Object> call(TreeView<Object> param) {
+
+ final TreeCell<Object> treeCell = new TreeCell<Object>() {
+
+ Object currentItem = null;
+ ICellEditHandler cellEditHandler;
+
+ AdapterImpl adapter = new AdapterImpl() {
+ @Override
+ public void notifyChanged(Notification msg) {
+ update(msg.getNotifier());
+ }
+ };
+
+
+ @Override
+ public void startEdit() {
+ super.startEdit();
+ cellEditHandler = getCellEditHandler(this);
+ if(cellEditHandler != null)
+ cellEditHandler.startEdit(this);
+ }
+
+ @Override
+ public void commitEdit(Object newValue) {
+ super.commitEdit(newValue);
+ if(cellEditHandler != null)
+ cellEditHandler.commitEdit(this, newValue);
+ }
+
+ @Override
+ public void cancelEdit() {
+ super.cancelEdit();
+ if(cellEditHandler != null)
+ cellEditHandler.cancelEdit(this);
+ update(getItem());
+ }
+
+ @Override
+ protected void updateItem(Object item, boolean empty) {
+ super.updateItem(item, empty);
+
+ // check if the item changed
+ if (item != currentItem) {
+
+ // remove the adapter if attached
+ if (currentItem instanceof Notifier)
+ ((Notifier) currentItem).eAdapters().remove(adapter);
+
+ // update the current item
+ currentItem = item;
+
+ // attach the adapter to the new item
+ if (currentItem instanceof Notifier)
+ ((Notifier) currentItem).eAdapters().add(adapter);
+ }
+
+ // notify the listeners
+ for (ICellUpdateListener cellUpdateListener : cellUpdateListeners)
+ cellUpdateListener.updateItem(this, item, empty);
+
+ update(item);
+ }
+
+ private void update(Object item) {
+ // setText(item == null ? "null" : item.toString());
+ applyItemProviderStyle(item, this, adapterFactory);
+ }
+
+ };
+
+ for (ICellCreationListener cellCreationListener : cellCreationListeners)
+ cellCreationListener.cellCreated(treeCell);
+
+ return treeCell;
+ }
+
+}
diff --git a/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/AdapterFactoryTreeItem.java b/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/AdapterFactoryTreeItem.java
new file mode 100755
index 000000000..801914e7f
--- /dev/null
+++ b/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/AdapterFactoryTreeItem.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2012 TESIS DYNAware GmbH and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Torsten Sommer <torsten.sommer@tesis.de> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.fx.emf.edit.ui;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import javafx.scene.control.MultipleSelectionModel;
+import javafx.scene.control.TreeItem;
+import javafx.scene.control.TreeView;
+
+import org.eclipse.emf.common.notify.AdapterFactory;
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.common.notify.Notifier;
+import org.eclipse.emf.common.notify.impl.AdapterImpl;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.edit.provider.ITreeItemContentProvider;
+
+/**
+ * A {@link TreeItem} that wraps an {@link AdapterFactory} and retrieves its
+ * children from the adapter-implemented {@link ITreeItemContentProvider}
+ * interface.
+ */
+public class AdapterFactoryTreeItem extends TreeItem<Object> {
+
+ final AdapterFactory adapterFactory;
+ final TreeView<?> treeView;
+ final ObservableList<TreeItem<Object>> children;
+ final ITreeItemContentProvider provider;
+
+ public AdapterFactoryTreeItem(Object object, TreeView<?> treeView, AdapterFactory adapterFactory) {
+ super(object);
+ this.treeView = treeView;
+ this.adapterFactory = adapterFactory;
+ children = FXCollections.unmodifiableObservableList(super.getChildren());
+
+ Object adapter = adapterFactory.adapt(object, ITreeItemContentProvider.class);
+ provider = (adapter instanceof ITreeItemContentProvider) ? (ITreeItemContentProvider) adapter : null;
+
+ if (object instanceof Notifier) {
+ ((Notifier) object).eAdapters().add(new AdapterImpl() {
+ @Override
+ public void notifyChanged(Notification msg) {
+ if (msg.getFeature() instanceof EReference)
+ updateChildren();
+ }
+
+ });
+ }
+
+ updateChildren();
+ }
+
+ /**
+ * This method overrides {@link TreeItem#getChildren()} and returns an
+ * unmodifiable {@link ObservableList} as the children may only be changed
+ * via the underlying model.
+ */
+ @Override
+ public ObservableList<TreeItem<Object>> getChildren() {
+ return children;
+ }
+
+ /**
+ * Recreates the child tree items using the {@link ITreeItemContentProvider}
+ * and restores the selection and expanded state of the tree items.
+ */
+ void updateChildren() {
+ ObservableList<TreeItem<Object>> childTreeItems = super.getChildren();
+ MultipleSelectionModel<?> selectionModel = treeView.getSelectionModel();
+ List<?> selection = selectionModel.getSelectedItems();
+ ArrayList<Object> selectedItems = new ArrayList<>();
+ ArrayList<TreeItem<?>> selectedTreeItems = new ArrayList<>();
+ ArrayList<Object> expandedItems = new ArrayList<>();
+
+ // remember the expanded items
+ for (TreeItem<Object> childTreeItem : childTreeItems) {
+ if (childTreeItem.isExpanded())
+ expandedItems.add(childTreeItem.getValue());
+ }
+
+ // remember the selected items
+ for (Object selectedTreeItem : selection) {
+ for (TreeItem<Object> childTreeItem : childTreeItems) {
+ if (selectedTreeItem == childTreeItem) {
+ selectedTreeItems.add(childTreeItem);
+ selectedItems.add(childTreeItem.getValue());
+ }
+ }
+ }
+
+ // clear the selection
+ for (TreeItem<?> selectedTreeItem : selectedTreeItems) {
+ int treeItemIndex = selectionModel.getSelectedItems().indexOf(selectedTreeItem);
+ int selectionIndex = selectionModel.getSelectedIndices().get(treeItemIndex);
+ selectionModel.clearSelection(selectionIndex);
+ }
+
+ // remove the old tree items
+ childTreeItems.clear();
+
+ if (provider == null)
+ return;
+
+ // add the new tree items
+ for (Object child : provider.getChildren(getValue())) {
+ AdapterFactoryTreeItem treeItem = new AdapterFactoryTreeItem(child, treeView, adapterFactory);
+
+ childTreeItems.add(treeItem);
+
+ // expand the new tree items
+ if (expandedItems.contains(child))
+ treeItem.setExpanded(true);
+
+ // restore the selection
+ if (selectedItems.contains(child)
+ && "javafx.scene.control.TreeView$TreeViewBitSetSelectionModel".equals(selectionModel.getClass().getName())) {
+ try {
+ Method m = selectionModel.getClass().getDeclaredMethod("select", new Class[] { TreeItem.class });
+ m.setAccessible(true);
+ m.invoke(selectionModel, treeItem);
+ } catch (Exception e) {
+ // do nothing
+ }
+ }
+ }
+
+ }
+
+}
diff --git a/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/EAttributeCellEditHandler.java b/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/EAttributeCellEditHandler.java
new file mode 100755
index 000000000..887f7b96b
--- /dev/null
+++ b/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/EAttributeCellEditHandler.java
@@ -0,0 +1,67 @@
+package org.eclipse.fx.emf.edit.ui;
+
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.scene.control.Cell;
+import javafx.scene.control.TextField;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.edit.command.SetCommand;
+import org.eclipse.emf.edit.domain.EditingDomain;
+import org.eclipse.fx.emf.edit.ui.AdapterFactoryCellFactory.ICellEditHandler;
+
+
+public class EAttributeCellEditHandler implements ICellEditHandler {
+
+ EAttribute attribute;
+ EditingDomain editingDomain;
+ TextField textField;
+
+ public EAttributeCellEditHandler(EAttribute attribute, EditingDomain editingDomain) {
+ this.attribute = attribute;
+ this.editingDomain = editingDomain;
+ }
+
+ @Override
+ public boolean canEdit(Cell<?> treeCell) {
+ Object item = treeCell.getItem();
+ return item instanceof EObject && ((EObject) item).eClass().getEAllAttributes().contains(attribute);
+ }
+
+ @Override
+ public void startEdit(final Cell<?> cell) {
+ EObject item = (EObject) cell.getItem();
+ String string = EcoreUtil.convertToString(attribute.getEAttributeType(), item.eGet(attribute));
+ textField = new TextField();
+ textField.focusedProperty().addListener(new ChangeListener<Boolean>() {
+
+ @Override
+ public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
+ if (!newValue)
+ commitEdit(cell, textField.getText());
+ }
+
+ });
+ textField.setText(string);
+ cell.setText(null);
+ cell.setGraphic(textField);
+ textField.selectAll();
+ }
+
+ @Override
+ public void cancelEdit(Cell<?> treeCell) {
+ // do nothing
+ }
+
+ @Override
+ public void commitEdit(Cell<?> treeCell, Object newValue) {
+ Object item = treeCell.getItem();
+ Object value = EcoreUtil.createFromString(attribute.getEAttributeType(), (String) newValue);
+ Command command = SetCommand.create(editingDomain, item, attribute, value);
+ if (command.canExecute())
+ editingDomain.getCommandStack().execute(command);
+ }
+
+} \ No newline at end of file
diff --git a/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/ProxyCellValueFactory.java b/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/ProxyCellValueFactory.java
new file mode 100755
index 000000000..e9bf107a2
--- /dev/null
+++ b/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/ProxyCellValueFactory.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2012 TESIS DYNAware GmbH and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Torsten Sommer <torsten.sommer@tesis.de> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.fx.emf.edit.ui;
+
+import javafx.beans.value.ObservableValue;
+import javafx.beans.value.ObservableValueBase;
+import javafx.scene.control.TableColumn;
+import javafx.scene.control.TableColumn.CellDataFeatures;
+import javafx.util.Callback;
+
+/**
+ * A cell value factory that simply forwards {@link CellDataFeatures#getValue()} as an {@link ObservableValue}.
+ */
+public class ProxyCellValueFactory<S, T> implements Callback<TableColumn.CellDataFeatures<S, T>, ObservableValue<T>> {
+
+ @Override
+ public ObservableValue<T> call(final CellDataFeatures<S, T> features) {
+
+ //TODO add notifications on update
+
+ return new ObservableValueBase<T>() {
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public T getValue() {
+ return (T) features.getValue();
+ }
+
+ };
+
+ }
+
+} \ No newline at end of file
diff --git a/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/dnd/CellDragAdapter.java b/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/dnd/CellDragAdapter.java
new file mode 100755
index 000000000..0a7bca923
--- /dev/null
+++ b/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/dnd/CellDragAdapter.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2012 TESIS DYNAware GmbH and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Torsten Sommer <torsten.sommer@tesis.de> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.fx.emf.edit.ui.dnd;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.fx.emf.edit.ui.AdapterFactoryCellFactory;
+import org.eclipse.fx.emf.edit.ui.AdapterFactoryCellFactory.ICellCreationListener;
+
+
+import javafx.collections.ObservableList;
+import javafx.event.EventHandler;
+import javafx.scene.control.Cell;
+import javafx.scene.control.ListCell;
+import javafx.scene.control.MultipleSelectionModel;
+import javafx.scene.control.TableCell;
+import javafx.scene.control.TreeCell;
+import javafx.scene.control.TreeItem;
+import javafx.scene.input.ClipboardContent;
+import javafx.scene.input.Dragboard;
+import javafx.scene.input.MouseEvent;
+import javafx.scene.input.TransferMode;
+
+/**
+ * Allows to drag items from viewers backed by an {@link AdapterFactoryCellFactory} using a {@link LocalTransfer}.
+ */
+public class CellDragAdapter implements ICellCreationListener {
+
+ @Override
+ public void cellCreated(final Cell<?> treeCell) {
+
+ treeCell.setOnDragDetected(new EventHandler<MouseEvent>() {
+ public void handle(MouseEvent event) {
+ /* allow any transfer mode */
+ Dragboard db = treeCell.startDragAndDrop(TransferMode.ANY);
+
+ /* put a string on dummy content dragboard */
+ ClipboardContent content = new ClipboardContent();
+ content.putString("dummy content");
+ db.setContent(content);
+
+ MultipleSelectionModel<?> selectionModel = getSelectionModel(treeCell);
+ ObservableList<?> selectedItems = selectionModel.getSelectedItems();
+
+ List<Object> items = new ArrayList<>(selectedItems.size());
+
+ for (Object item : selectedItems) {
+ if (item instanceof TreeItem)
+ items.add(((TreeItem<?>) item).getValue());
+ else
+ items.add(item);
+ }
+
+ LocalTransfer.INSTANCE.setObject(items);
+
+ event.consume();
+ }
+ });
+
+ }
+
+ private MultipleSelectionModel<?> getSelectionModel(Cell<?> cell) {
+ if (cell instanceof TreeCell)
+ return ((TreeCell<?>) cell).getTreeView().getSelectionModel();
+ else if (cell instanceof ListCell)
+ return ((ListCell<?>) cell).getListView().getSelectionModel();
+ else if (cell instanceof TableCell)
+ return ((TableCell<?, ?>) cell).getTableView().getSelectionModel();
+
+ throw new IllegalArgumentException("Unsupported Cell type");
+ }
+
+}
diff --git a/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/dnd/EditingDomainCellDropAdapter.java b/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/dnd/EditingDomainCellDropAdapter.java
new file mode 100755
index 000000000..331d949e6
--- /dev/null
+++ b/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/dnd/EditingDomainCellDropAdapter.java
@@ -0,0 +1,185 @@
+/*******************************************************************************
+ * Copyright (c) 2012 TESIS DYNAware GmbH and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Torsten Sommer <torsten.sommer@tesis.de> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.fx.emf.edit.ui.dnd;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import javafx.event.EventHandler;
+import javafx.scene.control.Cell;
+import javafx.scene.control.TableCell;
+import javafx.scene.input.DragEvent;
+import javafx.scene.input.TransferMode;
+
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.edit.command.DragAndDropCommand;
+import org.eclipse.emf.edit.command.DragAndDropFeedback;
+import org.eclipse.emf.edit.domain.EditingDomain;
+import org.eclipse.fx.emf.edit.ui.AdapterFactoryCellFactory;
+import org.eclipse.fx.emf.edit.ui.AdapterFactoryCellFactory.ICellCreationListener;
+
+
+/**
+ * Allows to drop items into viewers backed by an
+ * {@link AdapterFactoryCellFactory} using a {@link LocalTransfer}.
+ */
+public class EditingDomainCellDropAdapter implements ICellCreationListener {
+
+ /**
+ * Handles the feedback to Drag & Drop events by styling or otherwise
+ * modifying the affected {@link Cell}
+ */
+ public interface IDnDFeedbackHandler {
+
+ void onFeedbackInsertBefore(Cell<?> cell);
+
+ void onFeedbackInsertAfter(Cell<?> cell);
+
+ void onFeedbackSelect(Cell<?> cell);
+
+ void onFeedbackNone(Cell<?> cell);
+
+ }
+
+ final EditingDomain editingDomain;
+ Command dndCommand;
+ IDnDFeedbackHandler feedbackHandler = new DefaultFeedbackHandler();
+
+ public EditingDomainCellDropAdapter(EditingDomain editingDomain) {
+ this.editingDomain = editingDomain;
+ }
+
+ public IDnDFeedbackHandler getFeedbackHandler() {
+ return feedbackHandler;
+ }
+
+ public void setFeedbackHandler(IDnDFeedbackHandler feedbackHandler) {
+ if (feedbackHandler == null)
+ throw new IllegalArgumentException("The feeback handler cannot be null");
+
+ this.feedbackHandler = feedbackHandler;
+ }
+
+ @Override
+ public void cellCreated(final Cell<?> cell) {
+
+ cell.setOnDragOver(new EventHandler<DragEvent>() {
+
+ @Override
+ public void handle(DragEvent event) {
+ Object item = cell.getItem();
+
+ Cell<?> node = getRowNode(cell);
+
+ double y = event.getY();
+ double height = cell.getLayoutBounds().getHeight();
+
+ float position = (float) (y / height);
+
+ Object object = LocalTransfer.INSTANCE.getObject();
+
+ Command command = DragAndDropCommand.create(editingDomain, item, position, DragAndDropFeedback.DROP_MOVE
+ | DragAndDropFeedback.DROP_LINK, DragAndDropFeedback.DROP_MOVE, (Collection<?>) object);
+
+ if (command.canExecute()) {
+ dndCommand = command;
+
+ if (command instanceof DragAndDropFeedback) {
+ DragAndDropFeedback dndFeedback = (DragAndDropFeedback) command;
+ int feedback = dndFeedback.getFeedback();
+
+ if ((feedback & DragAndDropFeedback.FEEDBACK_INSERT_BEFORE) != 0)
+ feedbackHandler.onFeedbackInsertBefore(node);
+ else if ((feedback & DragAndDropFeedback.FEEDBACK_INSERT_AFTER) != 0)
+ feedbackHandler.onFeedbackInsertAfter(node);
+ else if ((feedback & DragAndDropFeedback.FEEDBACK_SELECT) != 0)
+ feedbackHandler.onFeedbackSelect(node);
+ else
+ feedbackHandler.onFeedbackNone(node);
+
+ if (System.getProperties().getProperty("os.name").toLowerCase().contains("mac")) {
+ event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
+ } else {
+ ArrayList<TransferMode> modes = new ArrayList<>();
+
+ if ((feedback & DragAndDropFeedback.DROP_COPY) != 0)
+ modes.add(TransferMode.COPY);
+ if ((feedback & DragAndDropFeedback.DROP_LINK) != 0)
+ modes.add(TransferMode.LINK);
+ if ((feedback & DragAndDropFeedback.DROP_MOVE) != 0)
+ modes.add(TransferMode.MOVE);
+
+ event.acceptTransferModes(modes.toArray(new TransferMode[modes.size()]));
+ }
+ }
+
+ } else {
+ dndCommand = null;
+ feedbackHandler.onFeedbackNone(node);
+ }
+
+ }
+
+ });
+
+ cell.setOnDragExited(new EventHandler<DragEvent>() {
+
+ @Override
+ public void handle(DragEvent event) {
+ feedbackHandler.onFeedbackNone(getRowNode(cell));
+ }
+
+ });
+
+ cell.setOnDragDropped(new EventHandler<DragEvent>() {
+ public void handle(DragEvent event) {
+ if (dndCommand != null)
+ editingDomain.getCommandStack().execute(dndCommand);
+
+ event.setDropCompleted(true);
+ event.consume();
+ }
+ });
+ }
+
+ Cell<?> getRowNode(final Cell<?> cell) {
+ return cell instanceof TableCell ? ((TableCell<?, ?>) cell).getTableRow() : cell;
+ }
+
+ /**
+ * This default implementation of {@link IDnDFeedbackHandler} adds a red
+ * line where the dragged {@link Cell} can be dropped.
+ */
+ public static class DefaultFeedbackHandler implements IDnDFeedbackHandler {
+
+ @Override
+ public void onFeedbackInsertBefore(Cell<?> cell) {
+ cell.setStyle("-fx-border-color: red transparent transparent transparent;");
+ }
+
+ @Override
+ public void onFeedbackInsertAfter(Cell<?> cell) {
+ cell.setStyle("-fx-border-color: transparent transparent red transparent;");
+ }
+
+ @Override
+ public void onFeedbackSelect(Cell<?> cell) {
+ cell.setStyle("-fx-border-color: transparent;");
+ }
+
+ @Override
+ public void onFeedbackNone(Cell<?> cell) {
+ cell.setStyle("-fx-border-color: transparent;");
+ }
+
+ }
+
+}
diff --git a/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/dnd/LocalTransfer.java b/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/dnd/LocalTransfer.java
new file mode 100755
index 000000000..c1ed9b317
--- /dev/null
+++ b/bundles/runtime/org.eclipse.fx.emf.edit.ui/src/org/eclipse/fx/emf/edit/ui/dnd/LocalTransfer.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2012 TESIS DYNAware GmbH and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Torsten Sommer <torsten.sommer@tesis.de> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.fx.emf.edit.ui.dnd;
+
+import javafx.scene.input.Dragboard;
+
+/**
+ * Replacement for the {@link Dragboard} that transfers the content without serializing it.
+ */
+public class LocalTransfer {
+
+ public static LocalTransfer INSTANCE = new LocalTransfer();
+
+ /**
+ * The object being transfered
+ */
+ private Object object;
+
+ public void setObject(Object object) {
+ this.object = object;
+ }
+
+ public Object getObject() {
+ return object;
+ }
+
+}

Back to the top