Warning: Declaration of action_plugin_indexmenu::register(&$controller) should be compatible with DokuWiki_Action_Plugin::register($controller) in /homepages/24/d93998614/htdocs/doc.hammurapi.com/dokuwiki/lib/plugins/indexmenu/action.php on line 18

Warning: Declaration of action_plugin_jcapture::register(&$controller) should be compatible with DokuWiki_Action_Plugin::register($controller) in /homepages/24/d93998614/htdocs/doc.hammurapi.com/dokuwiki/lib/plugins/jcapture/action.php on line 30

Warning: Declaration of action_plugin_modalpopup::register(&$controller) should be compatible with DokuWiki_Action_Plugin::register($controller) in /homepages/24/d93998614/htdocs/doc.hammurapi.com/dokuwiki/lib/plugins/modalpopup/action.php on line 34

Warning: Declaration of action_plugin_popularity::register(&$controller) should be compatible with DokuWiki_Action_Plugin::register($controller) in /homepages/24/d93998614/htdocs/doc.hammurapi.com/dokuwiki/lib/plugins/popularity/action.php on line 21

Warning: Declaration of action_plugin_safefnrecode::register(Doku_Event_Handler &$controller) should be compatible with DokuWiki_Action_Plugin::register($controller) in /homepages/24/d93998614/htdocs/doc.hammurapi.com/dokuwiki/lib/plugins/safefnrecode/action.php on line 16

Warning: Declaration of action_plugin_tag::register(&$contr) should be compatible with DokuWiki_Action_Plugin::register($controller) in /homepages/24/d93998614/htdocs/doc.hammurapi.com/dokuwiki/lib/plugins/tag/action.php on line 22

Warning: Cannot modify header information - headers already sent by (output started at /homepages/24/d93998614/htdocs/doc.hammurapi.com/dokuwiki/lib/plugins/indexmenu/action.php:11) in /homepages/24/d93998614/htdocs/doc.hammurapi.com/dokuwiki/inc/auth.php on line 377

Warning: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead in /homepages/24/d93998614/htdocs/doc.hammurapi.com/dokuwiki/inc/auth.php on line 656

Warning: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead in /homepages/24/d93998614/htdocs/doc.hammurapi.com/dokuwiki/inc/auth.php on line 656

Warning: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead in /homepages/24/d93998614/htdocs/doc.hammurapi.com/dokuwiki/inc/auth.php on line 656

Warning: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead in /homepages/24/d93998614/htdocs/doc.hammurapi.com/dokuwiki/inc/auth.php on line 656

Warning: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead in /homepages/24/d93998614/htdocs/doc.hammurapi.com/dokuwiki/inc/auth.php on line 656

Warning: Cannot modify header information - headers already sent by (output started at /homepages/24/d93998614/htdocs/doc.hammurapi.com/dokuwiki/lib/plugins/indexmenu/action.php:11) in /homepages/24/d93998614/htdocs/doc.hammurapi.com/dokuwiki/inc/actions.php on line 187
gmf_cheat_sheet [Hammurapi Group Documentation Wiki]

User Tools

Site Tools


Sidebar

{{indexmenu>..#1|js navbar nocookie context}}

gmf_cheat_sheet

====== GMF Cheat Sheet ====== This page is a very short list of things to be done to create a diagram editor with EMF and GMF. * Create either empty EMF project or Java projects. It is recommended to name project after plug-in ID, e.g. com.hammurapi.modeler. This obviates editing of plug-in names and dependencies. * Create ECore model. * Create ECore diagram. * Create domain model. * Document the model. Include specification on how elements shall be represented graphically. * Generate model documentation with ECoreDoc. * Generate EMF genmodel file. * Adjust the genmodel file - how different features shall be displayed, base package name. * Generate code - model first. * Adjust model plug-in - name, id, dependencies. * Generate .edit code. * Adjust edit plugin name if needed. * Adjust .edit code as necessary to limit feature selection lists, presentation, icons. * Backup customized icons to a different directory to prevent accidental overwriting during re-generation. * Open GMF dashboard (Open view). * Derive .gmfgraph. * Adjust appearance of model elements - backgrounds, shapes, ... * Derive .gmftool * Group tools into tool groups. Adjust tool groups appearance. * Combine .gmfmap. Be careful with element models which are rendered as edges - check their attributes in the wizard. * Adjust .gmfmap - the current version of GMF is buggy and messes up creation tools. * Transform .gmfmap to .gmfgen. * Add context menus and do other adjustments in .gmfgen. Important - it is not necessary to re-generate .gmfmap after editing .gmftool and .gmfgraph. However it is necessary to re-generate .gmfgen. Therefore, it is better to note changes made in the .gmfgen file somewhere. Another option is to version-control the file and use text diff - visual diff is a bit tricky. * Implement context menu actions. The code snippet below shows how to open a dialog. * Implement runtime behavior in the model. Create build-runtime.xml to build runtime libraries. * Implement model validation. * Create feature project. Add plug-ins to the feature project. * Add the feature to the update site project. <code java> Shell parent = HandlerUtil.getActiveShellChecked(event); NewDialog dialog = new NewDialog(parent, SWT.DIALOG_TRIM); dialog.open(); </code> Dialog centering <code java> Point parentSize = getParent().getSize(); Point mySize = dialogShell.getSize(); dialogShell.setLocation(getParent().toDisplay((parentSize.x-mySize.x)/2, (parentSize.y-mySize.y)/2)); </code> ===== Custom property editors ===== To provide a custom property editor (e.g. rich text editor for description property) modify XxxPropertySection generated class in the .diagram plugin. In the ''getPropertySource()'' method override inline createPropertyDescriptor() method of PropertySource as shown below: <code java> public IPropertySource getPropertySource(Object object) { if (object instanceof IPropertySource) { return (IPropertySource) object; } AdapterFactory af = getAdapterFactory(object); if (af != null) { IItemPropertySource ips = (IItemPropertySource) af.adapt(object, IItemPropertySource.class); if (ips != null) { return new PropertySource(object, ips) { @Override protected IPropertyDescriptor createPropertyDescriptor(IItemPropertyDescriptor itemPropertyDescriptor) { System.out.println("Got it! - "+itemPropertyDescriptor.getDisplayName(object)); return super.createPropertyDescriptor(itemPropertyDescriptor); } }; } } if (object instanceof IAdaptable) { return (IPropertySource) ((IAdaptable) object) .getAdapter(IPropertySource.class); } return null; } To pass custom dialog - mix-in some interface into IItemPropertyDescriptor and pass dialog through that interface. Tweak PropertyDescriptor as well - override createPropertyEditor() - check if itemPropertyDescriptor implements interface to create custom property dialogs. If it does - use the dialog, otherwise call super(); </code> Replace property descriptor creation as necessary. Use ''org.eclipse.emf.edit.ui.provider.PropertyDescriptor'' as a reference - it contains logic of creating different kinds of cell editors. To provide custom dialog editor use org.eclipse.emf.common.ui.celleditor.ExtendedDialogCellEditor or org.eclipse.jface.viewers.DialogCellEditor and override openDialogBox() method. <code java 1|h createEDataTypeCellEditor()> protected CellEditor createEDataTypeCellEditor(final EDataType eDataType, Composite composite) { if (itemPropertyDescriptor.isMultiLine(object)) { return new ExtendedDialogCellEditor(composite, getEditLabelProvider()) { protected EDataTypeValueHandler valueHandler = new EDataTypeValueHandler(eDataType); @Override protected Object openDialogBox(Control cellEditorWindow) { InputDialog dialog = new MultiLineInputDialog (cellEditorWindow.getShell(), EMFEditUIPlugin.INSTANCE.getString ("_UI_FeatureEditorDialog_title", new Object [] { getDisplayName(), getEditLabelProvider().getText(object) }), EMFEditUIPlugin.INSTANCE.getString("_UI_MultiLineInputDialog_message"), valueHandler.toString(getValue()), valueHandler); return dialog.open() == Window.OK ? valueHandler.toValue(dialog.getValue()) : null; } }; } return new EDataTypeCellEditor(eDataType, composite); } </code> In the code snippet above insert code at the beginning that checks if itemPropertyDescriptor implements interface which creates a custom edit dialog. If it does - create ExtendedDialogCellEditor with custom dialog. Use MultiLineInputDialog from org.eclipse.emf.edit.ui.provider.PropertyDescriptor or org.eclipse.emf.edit.ui.provider.InputDialog as an example of creating an input dialog. Or simply extend org.eclipse.jface.dialogs.Dialog. ===== Embedding AWT into SWT ===== In order to use EKit as HTML WYSIWYG editor for descriptions and human activity pages, AWT/Swing component shall be inserted into SWT. This is how it can be done: <code java> Composite awtPort = new Composite(this, SWT.EMBEDDED); Frame embeddedFrame = SWT_AWT.new_Frame(awtPort); Panel contentPanel = new Panel(); embeddedFrame.add(contentPanel); </code> If EKit root component is a panel, then it is not necessary to create additional panel. The panel in the example above is needed to hold lightweight components because frame created by SWT has a problem with handling mouse events. ===== Custom property editors in EMF ===== To replace the built-in property editor in EMF modify the generated editor class as shown below. Provide custom property source at the ''System.out.println()'' line. The custom property source can extend ''PropertySource'' and override ''createPropertyDescriptor()'' class. The reason why PropertySource shall be replaced instead of replacement of ''PropertyDescriptor'' is because it might be necessary to use different editors for field X depending on value in field Y. E.g. field X can contain source code and field Y the name of source code language (Java, XML, ...). Depending on the Y value different syntax highlighting editors might be instantiated. <code java> /** * This accesses a cached version of the property sheet. * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ public IPropertySheetPage getPropertySheetPage() { if (propertySheetPage == null) { propertySheetPage = new ExtendedPropertySheetPage(editingDomain) { @Override public void setSelectionToViewer(List<?> selection) { MytestEditor.this.setSelectionToViewer(selection); MytestEditor.this.setFocus(); } @Override public void setActionBars(IActionBars actionBars) { super.setActionBars(actionBars); getActionBarContributor().shareGlobalActions(this, actionBars); } }; propertySheetPage.setPropertySourceProvider(new AdapterFactoryContentProvider(adapterFactory) { @Override protected IPropertySource createPropertySource(Object object, IItemPropertySource itemPropertySource) { System.out.println(object+" "+itemPropertySource); return super.createPropertySource(object, itemPropertySource); } }); } return propertySheetPage; } </code> In order to have a unified extensible approach to property editors replacement two approaches can be used: * Eclipse extension points approach. * Java 6 ServiceLoader - define PropertySourceFactory interface. Add implementations to the plug-in classpath and they will be discovered. Service interface: <code java> public interface PropertySourceFactory { IPropertySource createPropertySource(Object object, IItemPropertySource itemPropertySource); } </code> ===== Diagram image rendering ===== Take a look at ''org.eclipse.gmf.runtime.diagram.ui.render.actions.CopyToImageAction'' or use ''CopyToImageUtil''. Rendering from context menu action: <code java> public Object execute(ExecutionEvent event) throws ExecutionException { MyDiagramEditor diagramEditor = (MyDiagramEditor) HandlerUtil.getActiveEditorChecked(event); System.out.println(diagramEditor); ISelection selection = HandlerUtil.getCurrentSelectionChecked(event); IWorkbenchWindow ww = HandlerUtil.getActiveWorkbenchWindow(event); // FIXME implement required behavior CopyToImageUtil ctiu = new CopyToImageUtil(); IPath destination = new Path("C:/test.gif"); ImageFileFormat format = ImageFileFormat.GIF; ProgressMonitorDialog progressMonitorDialog = new ProgressMonitorDialog(ww.getShell()); progressMonitorDialog.open(); IProgressMonitor monitor = progressMonitorDialog.getProgressMonitor(); try { ctiu.copyToImage(diagramEditor.getDiagram(), destination, format, monitor, PreferencesHint.USE_DEFAULTS); return null; } catch (CoreException e) { e.printStackTrace(); throw new ExecutionException(e.toString()); } finally { progressMonitorDialog.close(); } } </code> ===== Compartments ===== http://gmfsamples.tuxfamily.org/wiki/doku.php?id=gmf_tutorial7 Important thing - to make shapes freely positionable in compartments change Compartment/List layout property to false in .gmfgen/Gen Diagram .../Gen Compartment ... ===== Polymorphic icons ===== ==== EMF editor ==== Item provider <code java> /** * This returns SystemActivity.gif. * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ @Override public Object getImage(Object object) { if ("Pasha".equals(((SystemActivity) object).getName())) { System.out.println("Alternative image"); return overlayImage(object, getResourceLocator().getImage("full/obj16/TypeReference")); } return overlayImage(object, getResourceLocator().getImage("full/obj16/SystemActivity")); } </code> ==== Diagram editor ==== Node edit part <code java> /** * @generated */ protected Image getLabelIcon() { EObject parserElement = getParserElement(); if (parserElement == null) { return null; } if ("Pasha".equals(getLabelText())) { return ModelerElementTypes.getImage(ModelerPackage.eINSTANCE.getTypeReference()); } return ModelerElementTypes.getImage(parserElement.eClass()); } </code> Edge edit part <code java> @Override public IFigure getFigure() { IFigure ret = super.getFigure(); EObject semEl = resolveSemanticElement(); if ("Pasha".equals(((ErrorTransition) semEl).getName())) { ((ErrorTransitionFigure) ret).setLineStyle(org.eclipse.swt.SWT.LINE_DASH); } else { ((ErrorTransitionFigure) ret).setLineStyle(org.eclipse.swt.SWT.LINE_SOLID); } return ret; } </code> {{:gmf_cheat_sheet-edge_visual_polymorphism.gif|}} ===== Grouping properties below categories ===== The trick is to have a property which value is a IItemPropertySource. This trick can be used to mount properties of child objects to the property set of the parent object or to group properties of the object below categories level. The code below shows how to to do the trick: <code java> /** * This adds a property descriptor for the Source Path feature. * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated NOT */ protected void addSourcePathPropertyDescriptor(final Object theObject) { final IItemPropertySource ips = new IItemPropertySource() { @Override public Object getEditableValue(Object object) { return this; } @Override public IItemPropertyDescriptor getPropertyDescriptor(Object object, Object propertyID) { for (IItemPropertyDescriptor ipd: getPropertyDescriptors(object)) { if (propertyID.equals(ipd.getId(object))) { return ipd; } } return null; } @Override public List<IItemPropertyDescriptor> getPropertyDescriptors(Object object) { List<IItemPropertyDescriptor> ret = new ArrayList<IItemPropertyDescriptor>(); ret.add(new ItemPropertyDescriptorDecorator(theObject, createItemPropertyDescriptor (((ComposeableAdapterFactory)adapterFactory).getRootAdapterFactory(), getResourceLocator(), getString("_UI_FlowCodeImplementationType_classPath_feature"), getString("_UI_PropertyDescriptor_description", "_UI_FlowCodeImplementationType_classPath_feature", "_UI_FlowCodeImplementationType_type"), CorePackage.Literals.FLOW_CODE_IMPLEMENTATION_TYPE__CLASS_PATH, true, false, false, ItemPropertyDescriptor.GENERIC_VALUE_IMAGE, getString("_UI_ImplementationPropertyCategory"), null))); return ret; } @Override public String toString() { return "My complex property"; } }; ItemPropertyDescriptor pd = new ItemPropertyDescriptor( ((ComposeableAdapterFactory)adapterFactory).getRootAdapterFactory(), getResourceLocator(), getString("_UI_FlowCodeImplementationType_sourcePath_feature"), getString("_UI_PropertyDescriptor_description", "_UI_FlowCodeImplementationType_sourcePath_feature", "_UI_FlowCodeImplementationType_type"), CorePackage.Literals.FLOW_CODE_IMPLEMENTATION_TYPE__SOURCE_PATH, false, false, false, ItemPropertyDescriptor.GENERIC_VALUE_IMAGE, getString("_UI_ImplementationPropertyCategory"), null) { @Override public Object getPropertyValue(Object object) { return ips; } }; itemPropertyDescriptors.add(pd); } </code> ===== Centering labels withing shape ===== Maybe it is possible to do declaratively. Programmatically: <code java> /** * @generated */ private void createContents() { Ellipse circle0 = new Ellipse(); circle0.setLineWidth(1); circle0.setBackgroundColor(ColorConstants.lightBlue); this.add(circle0); fFigureNodeNameFigure = new WrappingLabel(); fFigureNodeNameFigure.setAlignment(PositionConstants.CENTER | PositionConstants.MIDDLE); fFigureNodeNameFigure.setTextJustification(PositionConstants.CENTER); fFigureNodeNameFigure.setTextWrap(true); fFigureNodeNameFigure.setText("<...>"); this.add(fFigureNodeNameFigure); } </code> ===== Resolving semantic elements ===== <code java|h Resolving semantic elements and diagram element> public void buildContextMenu(final IMenuManager menu) { getViewer().flush(); try { DiagramImpl model = (DiagramImpl) getViewer().getContents().getModel(); for (Object ep: getViewer().getSelectedEditParts()) { GraphicalEditPart nep = (GraphicalEditPart) ep; Object se = nep.resolveSemanticElement(); System.out.println(se); } System.out.println(model.getElement()); ... </code> ===== Adding target decorations ===== Add to connection figure constructor (or other code): <code java> setTargetDecoration(createTargetDecoration()); </code> Example of create target decoration - arrow: <code java> private RotatableDecoration createTargetDecoration() { PolylineDecoration df = new PolylineDecoration(); return df; } </code> ===== Rounded rectange ===== Change figure extends from RectangleFigure to RoundedRectangle. add to constructor <code java> this.setCornerDimensions(new Dimension(getMapMode().DPtoLP(8), getMapMode().DPtoLP(8))); </code> ===== Insets ===== <code java> this.setBorder(new MarginBorder(getMapMode().DPtoLP(5), getMapMode().DPtoLP(5), getMapMode().DPtoLP(5), getMapMode().DPtoLP(5))); </code> ===== Partitioning (sub-diagrams) ===== In the model - set related diagrams in gmfmap/misc, re-generate gmfgen and diagram code. ===== Dynamic EMF ===== Example <code java|h Dynamic EMF> EcoreFactory theFactory = EcoreFactory.eINSTANCE; EPackage dynamicPackage = theFactory.createEPackage(); dynamicPackage.setName("myDynamicPackage"); EClass dynamicClass = theFactory.createEClass(); dynamicClass.setName("MyDynamicClass"); dynamicPackage.getEClassifiers().add(dynamicClass); EOperation dynamicOperation = theFactory.createEOperation(); dynamicOperation.setName("myDynamicOperation"); InvocationDelegate id = new InvocationDelegate() { @Override public Object dynamicInvoke(InternalEObject target, EList<?> arguments) throws InvocationTargetException { System.out.println(target+", "+arguments); return null; } }; ((EOperation.Internal) dynamicOperation).setInvocationDelegate(id); dynamicClass.getEOperations().add(dynamicOperation); EFactory factory = dynamicPackage.getEFactoryInstance(); EObject dynamicObject = factory.create(dynamicClass); dynamicObject.eInvoke(dynamicOperation, new BasicEList<Object>()); </code> Article: http://www.ibm.com/developerworks/library/os-eclipse-dynamicemf/ ===== Notifications ===== Example: <code java|h Notifications> SystemOfRecord sr = TranslatorFactory.eINSTANCE.createSystemOfRecord(); sr.eAdapters().add(new Adapter() { @Override public void notifyChanged(Notification notification) { // TODO Auto-generated method stub System.out.println(notification.getNotifier()); } @Override public Notifier getTarget() { // TODO Auto-generated method stub return null; } @Override public void setTarget(Notifier newTarget) { // TODO Auto-generated method stub } @Override public boolean isAdapterForType(Object type) { // TODO Auto-generated method stub return false; } }); SimpleElement sl = TranslatorFactory.eINSTANCE.createSimpleElement(); sl.setContainer(sr); </code> Diagram elements shall be notification routers between facets and implementation types. Only active facets/implementation type shall receive notifications. Routed notification shall be wrapped and notifier shall be changed to the most recent source. Use NotificationWrapper for that. Maybe subclass to analyze notification chain and prevent notification loops. Connections shall notify sources and targets, sources and targets shall notify connections. Connections shall propagate notifications from source to target and vice versa, but not more than one hop. Maybe subclass NotificationWrapper and track not only notifiers stack but also number of hops. Connections are not considered hops. It is not clear right now how notifications can be used. Also extensive notifications may interfere with EMF/GMF editors. But maybe this is the idea - e.g. connection changes and it affects visual appearance of its target. <code java|h listening for all changes in a list> public class TotalObserver { private IPersonList persons; public TotalObserver() { ModelFactory factory = ModelFactory.eINSTANCE; persons = factory.createIPersonList(); EContentAdapter adapter = new EContentAdapter() { public void notifyChanged(Notification notification) { super.notifyChanged(notification); System.out .println("Notfication received from the data model. Data model has changed!!!"); } }; persons.eAdapters().add(adapter); } public void doStuff() { ModelFactory factory = ModelFactory.eINSTANCE; IPerson person = factory.createIPerson(); person.setFirstName("Lars"); System.out.println("I'm adding a person."); persons.getPersons().add(person); System.out.println("I'm changing a entry"); IPerson person2 = persons.getPersons().get(0); person2.setFirstName("Lars2"); } } </code> ===== References ===== * [[http://www.eclipse.org/articles/Article-Debugger/how-to.html]] * http://wiki.eclipse.org/GMF_Tutorial_Part_2#Compartments * http://gmfsamples.tuxfamily.org/wiki/doku.php?id=gmf_tutorial7 * http://wiki.eclipse.org/GMF_Newsgroup_Q_and_A#How_can_I_vertically_center_a_label.3F * http://www.vogella.de/articles/EclipseExtensionPoint/article.html * http://www.eclipse.org/articles/Article-Tabbed-Properties/tabbed_properties_view.html * http://tomsondev.bestsolution.at/2009/06/07/galileo-emf-databinding-part-2/ * http://wiki.eclipse.org/GMF_Tips * http://wiki.eclipse.org/index.php/GMF_Tips#Sharing_single_EditingDomain_instance_across_several_diagrams * http://www.jevon.org/wiki/GMF * http://wiki.eclipse.org/Diagram_Partitioning * http://www.moskitt.org/fileadmin/conselleria/documentacion/Presentaciones/MOSKitt-MultipleDiagramsInSingleResource.pdf * http://www.youtube.com/watch?v=fD5QLuPo-uE * http://wiki.eclipse.org/GMF_Tutorial_BPMN#Custom_Figures * http://dev.eclipse.org/newslists/news.eclipse.tools.gef/msg15294.html * http://dev.eclipse.org/newslists/news.eclipse.tools.gef/msg19667.html * http://wiki.eclipse.org/GMF_Documentation_Index * http://dev.eclipse.org/newslists/news.eclipse.tools.emf/msg03998.html


Warning: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead in /homepages/24/d93998614/htdocs/doc.hammurapi.com/dokuwiki/inc/auth.php on line 656
gmf_cheat_sheet.txt · Last modified: 2011/03/14 16:58 (external edit)