Skip to content

How to use the EMFModelTreeView

chqu1012 edited this page Jun 10, 2019 · 6 revisions

Minimial configuration to use the EMFModelTreeView

  • Create a new plug-in project
  • Add several dependencies to created project
 de.dc.spring.bootstrap.blog.model,
 org.eclipse.emf.edit;bundle-version="2.14.0",
 de.dc.javafx.efxclipse.runtime;bundle-version="3.6.0",
 de.dc.javafx.xcore.workbench.event;bundle-version="1.0.0",
 de.dc.javafx.xcore.workbench.di;bundle-version="1.0.0",
 de.dc.javafx.xcore.workbench.ui;bundle-version="1.0.0",
 com.google.inject;bundle-version="3.0.0",
 de.dc.javafx.xcore.workbench.emf;bundle-version="1.0.0",
 de.dc.spring.bootstrap.blog.model.edit;bundle-version="1.0.0"

Further add the emf generated model and model.edit plug-ins

  • Created an ExtendendFactory and ExtendendFactoryImpl for the generated model ExtendedFactory Example
import org.eclipse.emf.ecore.EObject;

import de.dc.spring.bootstrap.blog.model.ModelFactory;

public interface ExtendedBlogFactory extends ModelFactory {

	ExtendedBlogFactory eINSTANCE = ExtendedBlogFactoryImpl.init();
	
	EObject create(int classifierId);
}
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;

import de.dc.spring.bootstrap.blog.model.ModelPackage;
import de.dc.spring.bootstrap.blog.model.impl.ModelFactoryImpl;

public class ExtendedBlogFactoryImpl extends ModelFactoryImpl implements ExtendedBlogFactory {

	public static ExtendedBlogFactory init() {
		try {
			ExtendedBlogFactory theResourceFactory = (ExtendedBlogFactory) EPackage.Registry.INSTANCE
					.getEFactory(ModelPackage.eNS_URI);
			if (theResourceFactory != null) {
				return theResourceFactory;
			}
		} catch (Exception exception) {
		}
		return new ExtendedBlogFactoryImpl();
	}

	// Todo: This Method is override from the base ModelFactoryImpl, because it doesn't support #create method for ids
	@Override
	public EObject create(int classifierId) {
		switch (classifierId) {
		case ModelPackage.BLOG:
			return createBlog();
		case ModelPackage.TILE_SMALL_SECTION:
			return createTileSmallSection();
		case ModelPackage.STORY_SECTION:
			return createStorySection();
		case ModelPackage.OVERIVEW_SECTION:
			return createOverivewSection();
		case ModelPackage.TITLE_BIG_SECTION:
			return createTitleBigSection();
		case ModelPackage.ABOUT_SECTION:
			return createAboutSection();
		case ModelPackage.WORKFLOW_SECTION:
			return createWorkflowSection();
		case ModelPackage.GALLERY_SECTION:
			return createGallerySection();
		case ModelPackage.GALLERY_MATERIAL_SECTION:
			return createGalleryMaterialSection();
		case ModelPackage.TILE:
			return createTile();
		default:
			throw new IllegalArgumentException("The class '" + classifierId + "' is not a valid classifier, please enhanced the class "+ExtendedBlogFactoryImpl.class.getSimpleName()+"#create(classifierId) in switch case!");
		}
	}
	
}
  • Create a manager to handle Undo/Redo and model resource
import org.eclipse.emf.ecore.change.util.ChangeRecorder;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory;
import org.eclipse.emf.edit.provider.resource.ResourceItemProviderAdapterFactory;

import de.dc.javafx.efxclipse.runtime.command.CommandStackImpl;
import de.dc.javafx.efxclipse.runtime.model.IEmfManager;
import de.dc.spring.bootstrap.blog.model.Blog;
import de.dc.spring.bootstrap.blog.model.impl.ModelFactoryImpl;

public class BlogEmfManager extends AbstractEmfManager<Blog> {
  	@Override
	protected AdapterFactory getModelItemProviderAdapterFactory() {
		return new ModelItemProviderAdapterFactory();
	}

	@Override
	protected Blog initModel() {
		return ModelFactory.eINSTANCE.createBlog();
	}

	@Override
	protected Blog createNewModelOnNullCheck() {
		return initModel();
	}
	@Override
	public EPackage getModelPackage() {
		return ModelPackage.eINSTANCE;
	}

	@Override
	public ExtendedFactory getExtendedModelFactory() {
		return ExtendedModelFactory.eINSTANCE;
	}
}
  • Create EMFModelTree
import de.dc.javafx.xcore.workbench.emf.IEmfManager;
import de.dc.javafx.xcore.workbench.ui.control.EmfTreeModelView;
import de.dc.spring.bootstrap.blog.model.Blog;
import de.dc.spring.bootstrap.blog.model.ModelPackage;
import de.dc.spring.bootstrap.blog.model.ui.manager.BlogModelManager;

public class BlogEmfTreeView extends EmfTreeModelView<Blog> {

	public BlogEmfTreeView() {
		// Set edit mode for several attributes
		addEditableFor(ModelPackage.eINSTANCE.getBlog_Title());
		addEditableFor(ModelPackage.eINSTANCE.getTile_Title());
	}

	@Override
	protected IEmfManager<Blog> getEmfManager() {
		return new BlogModelManager();
	}
}
  • Create a demo application
public class BlogEmfTreeViewDemo extends Application{

	public static void main(String[] args) {
		launch(args);
	}

	@Override
	public void start(Stage primaryStage) throws Exception {
                // Dependency Injection initialization, is required for the workbench ui, here for handle selection service and events
                DIPlatform.add(new WorkbenchModule());
		DIPlatform.init();
		primaryStage.setScene(new Scene(new BlogEmfTreeView(), 1200, 800));
		primaryStage.show();
	}

}

Handle EMFTreeView Selection or Doubleclick

In the BlogEmfTreeView class, a method was override to handle the double click event. It sends a open editor with the selection input to the EventBus (for more information about EventBus, look for Google Guava).

@Override
protected void onTreeViewMouseClicked(MouseEvent event) {
	if (treeView.isEditable()) {
		treeView.setEditable(false);
	}
	if (event.getClickCount() == 2) {
		TreeItem<Object> selection = treeView.getSelectionModel().getSelectedItem();
		eventBroker.post(new EventContext<>(EventTopic.OPEN_EDITOR, selection.getValue()));
	}
}

Listen to the selection or doubleclick event, the workbench (e.g. ExampleEmfWorkbench) has subscribe this method. In this method the EventBus is check by topic, it handles only open editor topic. After that the input of the given context is checked by type and opens the right editor. For this example it opens only empty tabs, this should be replaced by editor parts.

@Subscribe
public void openFile(EventContext<?> context) {
	Object input = context.getInput();
        if (context.getEventTopic() == EventTopic.OPEN_EDITOR) {
		if (input instanceof File) {
			File file = (File) input;
			editorArea.getTabs().add(new Tab(file.getName()));
		}else if(input instanceof Tile) {
			Tile tile = (Tile) input;
			editorArea.getTabs().add(new Tab(tile.getTitle()));
		}
	}
}