Java tutorial
/****************************************************************************** * Copyright (c) 2015 Oracle and Liferay * 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: * Ling Hao - initial implementation and ongoing maintenance * Shenxue Zhou - Customized grid layer, grid state save and restore; DND fixes. * Shenxue Zhou - [365019] SapphireDiagramEditor does not work on non-workspace files * Gregory Amerson - [374022] SapphireGraphicalEditor init with SapphireEditor * Konstantin Komissarchik - [376245] Revert action in StructuredTextEditor does not revert diagram nodes and connections in SapphireDiagramEditor * Gregory Amerson - [346172] Support zoom, print and save as image actions in the diagram editor * Konstantin Komissarchik - [346172] Support zoom, print and save as image actions in the diagram editor * Konstantin Komissarchik - [381794] Cleanup needed in presentation code for diagram context menu * Konstantin Komissarchik - [382449] Support EL in EditorPageDef.PageHeaderText ******************************************************************************/ package org.eclipse.sapphire.ui.swt.gef; import static org.eclipse.sapphire.ui.forms.swt.SwtUtil.toImageDescriptor; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.draw2d.FigureCanvas; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.Point; import org.eclipse.gef.ContextMenuProvider; import org.eclipse.gef.DefaultEditDomain; import org.eclipse.gef.EditPart; import org.eclipse.gef.GraphicalEditPart; import org.eclipse.gef.GraphicalViewer; import org.eclipse.gef.KeyHandler; import org.eclipse.gef.RootEditPart; import org.eclipse.gef.SnapToGeometry; import org.eclipse.gef.SnapToGrid; import org.eclipse.gef.dnd.TemplateTransferDragSourceListener; import org.eclipse.gef.editparts.GridLayer; import org.eclipse.gef.editparts.ScalableFreeformRootEditPart; import org.eclipse.gef.editparts.ZoomManager; import org.eclipse.gef.palette.PaletteRoot; import org.eclipse.gef.ui.palette.FlyoutPaletteComposite.FlyoutPreferences; import org.eclipse.gef.ui.palette.PaletteViewer; import org.eclipse.gef.ui.palette.PaletteViewerProvider; import org.eclipse.gef.ui.parts.GraphicalEditorWithFlyoutPalette; import org.eclipse.gef.ui.parts.GraphicalViewerKeyHandler; import org.eclipse.jface.action.IAction; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.util.TransferDropTargetListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.sapphire.Element; import org.eclipse.sapphire.Event; import org.eclipse.sapphire.ImageData; import org.eclipse.sapphire.Listener; import org.eclipse.sapphire.LoggingService; import org.eclipse.sapphire.Sapphire; import org.eclipse.sapphire.modeling.CapitalizationType; import org.eclipse.sapphire.modeling.localization.LabelTransformer; import org.eclipse.sapphire.ui.Bounds; import org.eclipse.sapphire.ui.ISapphireEditorActionContributor; import org.eclipse.sapphire.ui.ISapphirePart; import org.eclipse.sapphire.ui.SapphireActionGroup; import org.eclipse.sapphire.ui.SapphireActionSystem; import org.eclipse.sapphire.ui.SapphireEditor; import org.eclipse.sapphire.ui.SapphireEditorPagePart.PageHeaderImageEvent; import org.eclipse.sapphire.ui.SapphireEditorPagePart.PageHeaderTextEvent; import org.eclipse.sapphire.ui.SapphireEditorPagePart.SelectionChangedEvent; import org.eclipse.sapphire.ui.SapphireHelpContext; import org.eclipse.sapphire.ui.SapphirePart; import org.eclipse.sapphire.ui.def.DefinitionLoader; import org.eclipse.sapphire.ui.def.EditorPageDef; import org.eclipse.sapphire.ui.diagram.ConnectionService; import org.eclipse.sapphire.ui.diagram.DiagramConnectionPart; import org.eclipse.sapphire.ui.diagram.def.DiagramEditorPageDef; import org.eclipse.sapphire.ui.diagram.editor.DiagramDirectEditPartEvent; import org.eclipse.sapphire.ui.diagram.editor.DiagramNodePart; import org.eclipse.sapphire.ui.diagram.editor.DiagramPageEvent; import org.eclipse.sapphire.ui.diagram.editor.SapphireDiagramEditorPagePart; import org.eclipse.sapphire.ui.diagram.editor.SapphireDiagramEditorPagePart.AutoLayoutEvent; import org.eclipse.sapphire.ui.diagram.editor.SapphireDiagramEditorPagePart.ZoomLevelEvent; import org.eclipse.sapphire.ui.diagram.editor.ShapePart; import org.eclipse.sapphire.ui.diagram.layout.DiagramLayoutPersistenceService; import org.eclipse.sapphire.ui.forms.swt.ActionBridge; import org.eclipse.sapphire.ui.forms.swt.ActionSystemPartBridge; import org.eclipse.sapphire.ui.forms.swt.EditorPagePresentation; import org.eclipse.sapphire.ui.forms.swt.HelpSystem; import org.eclipse.sapphire.ui.forms.swt.SapphireActionPresentationManager; import org.eclipse.sapphire.ui.forms.swt.SapphireToolBarManagerActionPresentation; import org.eclipse.sapphire.ui.swt.gef.contextbuttons.ContextButtonManager; import org.eclipse.sapphire.ui.swt.gef.dnd.ObjectsTransferDropTargetListener; import org.eclipse.sapphire.ui.swt.gef.dnd.SapphireTemplateTransferDropTargetListener; import org.eclipse.sapphire.ui.swt.gef.internal.DiagramEditorContextMenuProvider; import org.eclipse.sapphire.ui.swt.gef.layout.HorizontalGraphLayout; import org.eclipse.sapphire.ui.swt.gef.layout.VerticalGraphLayout; import org.eclipse.sapphire.ui.swt.gef.model.DiagramConnectionModel; import org.eclipse.sapphire.ui.swt.gef.model.DiagramModel; import org.eclipse.sapphire.ui.swt.gef.model.DiagramModelBase; import org.eclipse.sapphire.ui.swt.gef.model.DiagramNodeModel; import org.eclipse.sapphire.ui.swt.gef.model.DiagramResourceCache; import org.eclipse.sapphire.ui.swt.gef.model.ShapeModel; import org.eclipse.sapphire.ui.swt.gef.model.ShapeModelUtil; import org.eclipse.sapphire.ui.swt.gef.palette.DefaultFlyoutPalettePreferences; import org.eclipse.sapphire.ui.swt.gef.parts.DiagramConnectionEditPart; import org.eclipse.sapphire.ui.swt.gef.parts.DiagramNodeEditPart; import org.eclipse.sapphire.ui.swt.gef.parts.SapphireDiagramEditorEditPartFactory; import org.eclipse.sapphire.ui.swt.gef.presentation.DiagramPagePresentation; import org.eclipse.swt.SWT; import org.eclipse.swt.events.HelpEvent; import org.eclipse.swt.events.HelpListener; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseMoveListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Layout; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchPartConstants; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.ActionFactory; import org.eclipse.ui.forms.FormColors; import org.eclipse.ui.forms.IFormColors; import org.eclipse.ui.forms.editor.FormEditor; import org.eclipse.ui.forms.widgets.ILayoutExtension; import org.eclipse.ui.forms.widgets.SizeCache; import org.eclipse.ui.internal.forms.widgets.FormHeading; import org.eclipse.ui.internal.forms.widgets.FormUtil; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; /** * @author <a href="mailto:ling.hao@oracle.com">Ling Hao</a> * @author <a href="mailto:shenxue.zhou@oracle.com">Shenxue Zhou</a> * @author <a href="mailto:gregory.amerson@liferay.com">Gregory Amerson</a> * @author <a href="mailto:konstantin.komissarchik@oracle.com">Konstantin Komissarchik</a> */ public class SapphireDiagramEditor extends GraphicalEditorWithFlyoutPalette implements ISapphireEditorActionContributor, EditorPagePresentation { private final SapphireEditor editor; private Element element; private DefinitionLoader.Reference<EditorPageDef> definition; private SapphireDiagramEditorPagePart part; private DiagramLayoutPersistenceService layoutPersistenceService; private ConnectionService connectionService; private PaletteRoot root; private DiagramPagePresentation diagramPresentation; private DiagramModel diagramModel; private Listener layoutPersistenceServiceListener; private List<ISapphirePart> selectedParts = new ArrayList<ISapphirePart>(); private List<GraphicalEditPart> selectedEditParts = null; private boolean editorIsDirty = false; private Point mouseLocation; private DiagramConfigurationManager configManager; private GraphicalViewerKeyHandler graphicalViewerKeyHandler; private SapphireDiagramKeyHandler diagramKeyHandler; private ContextButtonManager contextButtonManager = null; private boolean directEditingActive = false; // Diagram header, borrowed from org.eclipse.ui.forms.widgets.Form class private FormHeading header; private Composite body; private SizeCache bodyCache = new SizeCache(); private SizeCache headCache = new SizeCache(); private FormColors formColors; private Listener diagramEditorPagePartListener; private Map<String, ActionBridge> globalActions; private SapphireDiagramOutline diagramOutline; private boolean isSelectionFromPagePart = false; public SapphireDiagramEditor(final SapphireEditor editor, final Element element, final DefinitionLoader.Reference<EditorPageDef> definition) { if (editor == null) { throw new IllegalArgumentException(); } if (element == null) { throw new IllegalArgumentException(); } if (definition == null) { throw new IllegalArgumentException(); } this.editor = editor; this.element = element; this.definition = definition; this.part = new SapphireDiagramEditorPagePart(); this.part.init(editor, this.element, this.definition.resolve(), Collections.<String, String>emptyMap()); this.part.initialize(); final String partName = this.definition.resolve().getPageName().localized(CapitalizationType.TITLE_STYLE, false); setPartName(partName); // Initialize connection service this.connectionService = SapphireDiagramEditorFactory.getConnectionService(this.part); // Initialize layout persistence service this.layoutPersistenceService = SapphireDiagramEditorFactory.getLayoutPersistenceService(this.part); this.configManager = new DiagramConfigurationManager(this); setEditDomain(new DefaultEditDomain(this)); this.part.attach(new Listener() { @Override public void handle(final Event event) { if (event instanceof SelectionChangedEvent) { isSelectionFromPagePart = true; selectParts(part.getSelections()); isSelectionFromPagePart = false; } else if (event instanceof DiagramPageEvent) { handleDiagramPageEvent((DiagramPageEvent) event); } else if (event instanceof DiagramDirectEditPartEvent) { selectAndDirectEditPart(((DiagramDirectEditPartEvent) event).part()); } } }); this.layoutPersistenceServiceListener = new Listener() { @Override public void handle(final Event event) { if (event instanceof DiagramLayoutPersistenceService.DirtyStateEvent) { final DiagramLayoutPersistenceService.DirtyStateEvent evt = (DiagramLayoutPersistenceService.DirtyStateEvent) event; if (evt.after() == true) { markEditorDirty(); } else { markEditorClean(); } } } }; this.layoutPersistenceService.attach(this.layoutPersistenceServiceListener); this.diagramEditorPagePartListener = new Listener() { @Override public void handle(final Event event) { if (event instanceof PageHeaderTextEvent) { refreshPageHeaderText(); } else if (event instanceof PageHeaderImageEvent) { refreshPageHeaderImage(); } else if (event instanceof ZoomLevelEvent) { refreshZoomLevel(); } else if (event instanceof AutoLayoutEvent) { autoLayout(((AutoLayoutEvent) event).horizontal()); } } }; this.part.attach(this.diagramEditorPagePartListener); } private void handleDiagramPageEvent(DiagramPageEvent event) { switch (event.getDiagramPageEventType()) { case GridStateChange: getGraphicalViewer().setProperty(SnapToGrid.PROPERTY_GRID_VISIBLE, part.isGridVisible()); getGraphicalViewer().setProperty(SnapToGrid.PROPERTY_GRID_ENABLED, part.isGridVisible()); getGraphicalViewer().setProperty(SnapToGrid.PROPERTY_GRID_SPACING, new Dimension(part.getGridUnit(), part.getVerticalGridUnit())); markEditorDirty(); break; case GuideStateChange: getGraphicalViewer().setProperty(SnapToGeometry.PROPERTY_SNAP_ENABLED, Boolean.valueOf(part.isShowGuides())); markEditorDirty(); break; case DiagramChange: refreshPalette(); break; case DiagramSave: // Noop break; case SelectAll: selectAll(); break; case SelectAllNodes: selectAllNodes(); break; default: break; } } public DiagramEditorPageDef getDiagramEditorPageDef() { return (DiagramEditorPageDef) this.definition.resolve(); } public final SapphireEditor getEditor() { return this.editor; } public SapphireDiagramEditorPagePart getPart() { return this.part; } public final Element getModelElement() { return this.part.getModelElement(); } public DiagramLayoutPersistenceService getLayoutPersistenceService() { return this.layoutPersistenceService; } public ConnectionService getConnectionService() { return this.connectionService; } @Override public boolean isDirty() { return this.editorIsDirty; } protected void markEditorDirty() { this.editorIsDirty = true; firePropertyChange(IWorkbenchPartConstants.PROP_DIRTY); } protected void markEditorClean() { this.editorIsDirty = false; firePropertyChange(IWorkbenchPartConstants.PROP_DIRTY); } @Override public DefaultEditDomain getEditDomain() { return super.getEditDomain(); } @Override public void selectionChanged(IWorkbenchPart part, ISelection selection) { // If not the active editor, ignore selection changed. boolean editorIsActive = getSite().getPage().isPartVisible(this); if (!editorIsActive) { // Check if we are a page of the active multipage editor IEditorPart activeEditor = getSite().getPage().getActiveEditor(); if (activeEditor != null) { // Check if the top level editor if it is active editorIsActive = getSite().getPage().isPartVisible(activeEditor); if (activeEditor instanceof FormEditor) { if (!(this.equals(((FormEditor) activeEditor).getActiveEditor()))) { editorIsActive = false; } } } } if (editorIsActive) { // Bug 339360 - MultiPage Editor's selectionProvider does not notify PropertySheet (edit) // bypass the selection provider if (selection instanceof StructuredSelection) { StructuredSelection structuredSelection = (StructuredSelection) selection; List<ISapphirePart> partList = new ArrayList<ISapphirePart>(); List<GraphicalEditPart> editPartList = new ArrayList<GraphicalEditPart>(); for (Iterator<?> iterator = structuredSelection.iterator(); iterator.hasNext();) { Object object = iterator.next(); EditPart editPart = null; if (object instanceof EditPart) { editPart = (EditPart) object; } else if (object instanceof IAdaptable) { editPart = (EditPart) ((IAdaptable) object).getAdapter(EditPart.class); } if (editPart != null && editPart.getModel() instanceof DiagramModelBase) { SapphirePart sp = ((DiagramModelBase) editPart.getModel()).getSapphirePart(); partList.add(sp); editPartList.add((GraphicalEditPart) editPart); } } // If the properties sheet has multiple tabs, switching tabs would trigger selection changed // event. But the selection would be empty. So we don't want to update the properties sheet or // the key handler in this case. if (!partList.isEmpty()) { this.selectedParts = partList; this.selectedEditParts = editPartList; if (!this.isSelectionFromPagePart) { getPart().setSelections(partList, false); } updateKeyHandler(); // // [Bug 380728] Floating toolbar appears on a node when multiple nodes are selected // if (partList.size() > 1 || !(partList.get(0) instanceof DiagramNodePart)) // { // this.contextButtonManager.hideContextButtonsInstantly(); // } this.contextButtonManager.refresh(); } } } } private void initActions() { this.globalActions = new HashMap<String, ActionBridge>(); final ActionBridge selectAllBridge = new ActionBridge(this.diagramPresentation, this.part.getAction("Sapphire.Diagram.SelectAll")); this.globalActions.put(ActionFactory.SELECT_ALL.getId(), selectAllBridge); final ActionBridge deleteBridge = new ActionBridge(this.diagramPresentation, this.part.getAction("Sapphire.Delete")); this.globalActions.put(ActionFactory.DELETE.getId(), deleteBridge); final ActionBridge printBridge = new ActionBridge(this.diagramPresentation, this.part.getAction("Sapphire.Diagram.Print")); this.globalActions.put(ActionFactory.PRINT.getId(), printBridge); } private void updateKeyHandler() { if (this.diagramKeyHandler != null) { this.diagramKeyHandler.dispose(); this.diagramKeyHandler = null; } List<ISapphirePart> selectedParts = this.getSelectedParts(); this.diagramKeyHandler = new SapphireDiagramKeyHandler(this, selectedParts); if (this.graphicalViewerKeyHandler == null) { graphicalViewerKeyHandler = new GraphicalViewerKeyHandler(getGraphicalViewer()); } KeyHandler parentKeyHandler = graphicalViewerKeyHandler.setParent(this.diagramKeyHandler); getGraphicalViewer().setKeyHandler(parentKeyHandler); } private void refreshPalette() { PaletteRoot pr = getPaletteRoot(); if (pr instanceof SapphirePaletteRoot) { SapphirePaletteRoot spr = (SapphirePaletteRoot) pr; spr.updatePaletteEntries(); } } @Override protected PaletteRoot getPaletteRoot() { if (root == null) root = new SapphirePaletteRoot(part); return root; } @Override public void doSave(IProgressMonitor monitor) { try { this.part.saveDiagram(); markEditorClean(); } catch (Exception e) { Sapphire.service(LoggingService.class).log(e); } } @Override protected void initializeGraphicalViewer() { super.initializeGraphicalViewer(); GraphicalViewer viewer = getGraphicalViewer(); viewer.getControl().addMouseMoveListener(new MouseMoveListener() { public void mouseMove(MouseEvent e) { setMouseLocation(e.x, e.y); } }); // set the contents of this editor viewer.setContents(diagramModel); // listen for dropped parts viewer.addDropTargetListener(new SapphireTemplateTransferDropTargetListener(this)); viewer.addDropTargetListener((TransferDropTargetListener) new ObjectsTransferDropTargetListener(viewer)); postInit(); } private void postInit() { // refresh node bounds for (DiagramNodeModel node : this.diagramModel.getNodes()) { node.handleMoveNode(); } //initRenderingContext(); initActions(); configureDiagramHeading(); // If the layout file doesn't exist or no layout is written to the layout file, apply auto layout if (hasNoExistingLayout()) { getGraphicalViewer().flush(); getPart().autoLayout(true); markEditorClean(); } } private void autoLayout(boolean horizontal) { if (horizontal) { new HorizontalGraphLayout().layout(this, true); } else { new VerticalGraphLayout().layout(this, true); } } private boolean hasNoExistingLayout() { if (this.layoutPersistenceService == null) { return true; } List<DiagramNodeModel> nodes = this.diagramModel.getNodes(); for (DiagramNodeModel node : nodes) { DiagramNodePart nodePart = node.getModelPart(); Bounds bounds = nodePart.getNodeBounds(); if (bounds.getX() == -1 || bounds.getY() == -1) { return true; } } return false; } public DiagramPagePresentation getDiagramPresentation() { return this.diagramPresentation; } public DiagramModel getDiagramModel() { return this.diagramModel; } public DiagramResourceCache getResourceCache() { return this.diagramPresentation.getResourceCache(); } public DiagramConfigurationManager getConfigurationManager() { return this.configManager; } public ContextButtonManager getContextButtonManager() { return contextButtonManager; } @Override public void createPartControl(Composite parent) { final Composite main = new Composite(parent, SWT.NONE); main.setLayout(new FormLayout()); this.header = new FormHeading(main, SWT.NULL); this.formColors = new FormColors(parent.getDisplay()); super.createPartControl(main); this.body = getGraphicalControl().getParent(); } @Override protected void configureGraphicalViewer() { super.configureGraphicalViewer(); GraphicalViewer viewer = getGraphicalViewer(); this.diagramPresentation = new DiagramPagePresentation(this.part, this.configManager, viewer.getControl().getShell()); this.diagramModel = new DiagramModel(this.diagramPresentation); viewer.setEditPartFactory(new SapphireDiagramEditorEditPartFactory(getConfigurationManager())); viewer.setRootEditPart(new ScalableFreeformRootEditPart() { @Override protected GridLayer createGridLayer() { return new SapphireDiagramGridLayer(diagramModel); } }); // configure the context menu provider ContextMenuProvider cmProvider = new DiagramEditorContextMenuProvider(this); viewer.setContextMenu(cmProvider); // Configure grid and guide properties boolean isGridVisibleInViewer = false; if (viewer.getProperty(SnapToGrid.PROPERTY_GRID_VISIBLE) != null) { isGridVisibleInViewer = (Boolean) viewer.getProperty(SnapToGrid.PROPERTY_GRID_VISIBLE); } if (this.part.isGridVisible() != isGridVisibleInViewer) { viewer.setProperty(SnapToGrid.PROPERTY_GRID_VISIBLE, this.part.isGridVisible()); viewer.setProperty(SnapToGrid.PROPERTY_GRID_ENABLED, this.part.isGridVisible()); viewer.setProperty(SnapToGrid.PROPERTY_GRID_SPACING, new Dimension(this.part.getGridUnit(), this.part.getVerticalGridUnit())); } boolean isShowGuidesInViewer = false; if (viewer.getProperty(SnapToGeometry.PROPERTY_SNAP_ENABLED) != null) { isShowGuidesInViewer = (Boolean) viewer.getProperty(SnapToGeometry.PROPERTY_SNAP_ENABLED); } if (this.part.isShowGuides() != isShowGuidesInViewer) { viewer.setProperty(SnapToGeometry.PROPERTY_SNAP_ENABLED, this.part.isShowGuides()); } // Support context help this.getGraphicalControl().addHelpListener(new HelpListener() { public void helpRequested(HelpEvent event) { if (getSelectedParts() != null && getSelectedParts().size() == 1) { ISapphirePart part = getSelectedParts().get(0); final SapphireHelpContext context = new SapphireHelpContext(part.getLocalModelElement(), null); if (context.getText() != null || (context.getRelatedTopics() != null && context.getRelatedTopics().length > 0)) { // determine a location in the upper right corner of the widget org.eclipse.swt.graphics.Point point = HelpSystem .computePopUpLocation(event.widget.getDisplay()); // display the help PlatformUI.getWorkbench().getHelpSystem().displayContext(context, point.x, point.y); } } } }); // context button manager contextButtonManager = new ContextButtonManager(this); final int zoomLevel = getPart().state().getZoomLevel().content(); final double zoom = (double) zoomLevel / 100; getZoomManager().setZoom(zoom); } @Override protected PaletteViewerProvider createPaletteViewerProvider() { return new PaletteViewerProvider(getEditDomain()) { @Override protected void configurePaletteViewer(PaletteViewer viewer) { super.configurePaletteViewer(viewer); viewer.addDragSourceListener(new TemplateTransferDragSourceListener(viewer)); } @Override public PaletteViewer createPaletteViewer(Composite parent) { PaletteViewer pViewer = new SapphirePaletteViewer(); pViewer.createControl(parent); configurePaletteViewer(pViewer); hookPaletteViewer(pViewer); return pViewer; } }; } @Override protected FlyoutPreferences getPalettePreferences() { return new DefaultFlyoutPalettePreferences(getPart().state()); } public IAction getAction(String actionId) { if (actionId.equals(ActionFactory.SELECT_ALL.getId())) { return this.globalActions.get(ActionFactory.SELECT_ALL.getId()); } else if (actionId.equals(ActionFactory.DELETE.getId())) { return this.globalActions.get(ActionFactory.DELETE.getId()); } else if (actionId.equals(ActionFactory.PRINT.getId())) { return this.globalActions.get(ActionFactory.PRINT.getId()); } return getActionRegistry().getAction(actionId); } @Override @SuppressWarnings("rawtypes") public Object getAdapter(Class type) { if (type == IContentOutlinePage.class) { return getDiagramOutline(); } return super.getAdapter(type); } @Override public GraphicalViewer getGraphicalViewer() { return super.getGraphicalViewer(); } public List<ISapphirePart> getSelectedParts() { return this.selectedParts; } public List<GraphicalEditPart> getSelectedEditParts() { return this.selectedEditParts; } public GraphicalEditPart getGraphicalEditPart(ISapphirePart sapphirePart) { if (sapphirePart instanceof DiagramNodePart || sapphirePart instanceof ShapePart || sapphirePart instanceof DiagramConnectionPart) { GraphicalViewer viewer = this.getGraphicalViewer(); Object editpartObj = null; DiagramNodePart nodePart = null; DiagramConnectionPart connPart = null; if (sapphirePart instanceof DiagramNodePart) { nodePart = (DiagramNodePart) sapphirePart; DiagramNodeModel nodeModel = this.getDiagramModel().getDiagramNodeModel(nodePart); editpartObj = viewer.getEditPartRegistry().get(nodeModel); } else if (sapphirePart instanceof ShapePart) { nodePart = sapphirePart.nearest(DiagramNodePart.class); DiagramNodeModel nodeModel = this.getDiagramModel().getDiagramNodeModel(nodePart); ShapeModel shapeModel = ShapeModelUtil.getChildShapeModel(nodeModel.getShapeModel(), (ShapePart) sapphirePart); editpartObj = viewer.getEditPartRegistry().get(shapeModel); } else if (sapphirePart instanceof DiagramConnectionPart) { connPart = (DiagramConnectionPart) sapphirePart; DiagramConnectionModel connModel = this.getDiagramModel().getDiagramConnectionModel(connPart); editpartObj = viewer.getEditPartRegistry().get(connModel); } return (GraphicalEditPart) editpartObj; } return null; } public void selectAndDirectEditPart(final ISapphirePart part) { if (part instanceof DiagramNodePart || part instanceof ShapePart || part instanceof DiagramConnectionPart) { GraphicalViewer viewer = getGraphicalViewer(); // Bug 370869 - DND from the tool palette would show an invalid cursor before placing the new node // in direct edit mode. TODO why? //viewer.getControl().forceFocus(); GraphicalEditPart editpart = getGraphicalEditPart(part); ISapphirePart parentPart = part.parent(); while ((editpart == null || !editpart.isSelectable()) && parentPart != null) { editpart = getGraphicalEditPart(parentPart); parentPart = parentPart.parent(); } if (editpart != null) { // Force a layout first. viewer.flush(); viewer.select(editpart); viewer.reveal(editpart); if (part instanceof DiagramNodePart) { getDiagramModel().handleDirectEditing((DiagramNodePart) part); } else if (part instanceof ShapePart) { getDiagramModel().handleDirectEditing((ShapePart) part); } else if (part instanceof DiagramConnectionPart) { getDiagramModel().handleDirectEditing((DiagramConnectionPart) part); } } } } public void selectAll() { GraphicalViewer viewer = this.getGraphicalViewer(); for (Object obj : viewer.getEditPartRegistry().values()) { if (obj instanceof DiagramConnectionEditPart || obj instanceof DiagramNodeEditPart) { viewer.appendSelection((EditPart) obj); } } } public void selectAllNodes() { GraphicalViewer viewer = this.getGraphicalViewer(); viewer.deselectAll(); for (Object obj : viewer.getEditPartRegistry().values()) { if (obj instanceof DiagramNodeEditPart) { viewer.appendSelection((DiagramNodeEditPart) obj); } } } public void selectParts(final List<ISapphirePart> selections) { boolean selectionChanged = false; if (this.selectedParts.size() != selections.size()) { selectionChanged = true; } else if (!this.selectedParts.containsAll(selections) || !selections.containsAll(this.selectedParts)) { selectionChanged = true; } if (selectionChanged) { GraphicalViewer viewer = this.getGraphicalViewer(); if (selections.isEmpty()) { viewer.flush(); viewer.deselectAll(); return; } boolean first = true; for (ISapphirePart sapphirePart : selections) { Object editpartObj = getGraphicalEditPart(sapphirePart); if (editpartObj != null) { if (first) { viewer.flush(); viewer.select((EditPart) editpartObj); first = false; } else { viewer.appendSelection((EditPart) editpartObj); } viewer.reveal((EditPart) editpartObj); } } } } public Point getMouseLocation() { if (mouseLocation == null) { mouseLocation = new Point(); } return mouseLocation; } private void setMouseLocation(int x, int y) { getMouseLocation().setLocation(x, y); Point realLocation = calculateRealMouseLocation(getMouseLocation()); this.part.setMouseLocation(realLocation.x, realLocation.y); } public FigureCanvas getFigureCanvas() { GraphicalViewer viewer = getGraphicalViewer(); return (FigureCanvas) viewer.getControl(); } public double getZoomLevel() { ZoomManager zoomManager = getZoomManager(); if (zoomManager == null) return 1; /* * avoid long running calculations for large diagrams and zoom factors * below 5% */ return Math.max(0.05D, zoomManager.getZoom()); } /** * Calculates the location in dependence from scrollbars and zoom factor. * * @param nativeLocation * the native location * @return the point */ public Point calculateRealMouseLocation(Point nativeLocation) { Point ret = new Point(nativeLocation); Point viewLocation; // view location depends on the current scroll bar position viewLocation = getFigureCanvas().getViewport().getViewLocation(); ret.x += viewLocation.x; ret.y += viewLocation.y; final ZoomManager zoomManager = getZoomManager(); if (zoomManager != null) { ret = ret.getScaled(1 / zoomManager.getZoom()); } return ret; } @Override public void dispose() { super.dispose(); diagramPresentation.dispose(); if (layoutPersistenceService != null) { // FIXME: KOSTA: This is very questionable. Only service context should be disposing services. layoutPersistenceService.detach(this.layoutPersistenceServiceListener); layoutPersistenceService.dispose(); } this.part.detach(this.diagramEditorPagePartListener); final Image image = this.header.getImage(); if (image != null) { image.dispose(); } for (ActionSystemPartBridge bridge : this.globalActions.values()) { bridge.dispose(); } this.element = null; this.part.dispose(); this.part = null; this.definition.dispose(); this.definition = null; } public boolean isDirectEditingActive() { return directEditingActive; } public void setDirectEditingActive(boolean directEditingActive) { this.directEditingActive = directEditingActive; getContextButtonManager().hideContextButtonsInstantly(); } private void configureDiagramHeading() { decorateHeading(); final SapphireActionGroup actions = this.part.getActions(SapphireActionSystem.CONTEXT_DIAGRAM_HEADER); if (actions != null && !actions.isEmpty()) { final SapphireActionPresentationManager actionPresentationManager = new SapphireActionPresentationManager( this.diagramPresentation, actions); final SapphireToolBarManagerActionPresentation actionPresentation = new SapphireToolBarManagerActionPresentation( actionPresentationManager); actionPresentation.setToolBarManager(this.header.getToolBarManager()); actionPresentation.render(); } refreshPageHeaderText(); refreshPageHeaderImage(); } /** * Takes advantage of the gradients and other capabilities to decorate the * form heading using colors computed based on the current skin and * operating system. * * @since 3.3 */ private void decorateHeading() { Color top = this.formColors.getColor(IFormColors.H_GRADIENT_END); Color bot = this.formColors.getColor(IFormColors.H_GRADIENT_START); this.header.setTextBackground(new Color[] { top, bot }, new int[] { 100 }, true); this.header.putColor(IFormColors.H_BOTTOM_KEYLINE1, this.formColors.getColor(IFormColors.H_BOTTOM_KEYLINE1)); this.header.putColor(IFormColors.H_BOTTOM_KEYLINE2, this.formColors.getColor(IFormColors.H_BOTTOM_KEYLINE2)); this.header.putColor(IFormColors.H_HOVER_LIGHT, this.formColors.getColor(IFormColors.H_HOVER_LIGHT)); this.header.putColor(IFormColors.H_HOVER_FULL, this.formColors.getColor(IFormColors.H_HOVER_FULL)); this.header.putColor(IFormColors.TB_TOGGLE, this.formColors.getColor(IFormColors.TB_TOGGLE)); this.header.putColor(IFormColors.TB_TOGGLE_HOVER, this.formColors.getColor(IFormColors.TB_TOGGLE_HOVER)); this.header.setSeparatorVisible(true); this.header.setFont(JFaceResources.getHeaderFont()); this.header.setForeground(this.formColors.getColor(IFormColors.TITLE)); } private void refreshPageHeaderText() { this.header.setText( LabelTransformer.transform(this.part.getPageHeaderText(), CapitalizationType.TITLE_STYLE, false)); this.header.layout(); } private void refreshPageHeaderImage() { final Image oldImage = this.header.getImage(); if (oldImage != null) { oldImage.dispose(); } final ImageData newImageData = this.part.getPageHeaderImage(); if (newImageData == null) { this.header.setImage(null); } else { this.header.setImage(toImageDescriptor(newImageData).createImage()); } } private void refreshZoomLevel() { final int zoomLevel = this.part.getZoomLevel(); final double zoom = (double) zoomLevel / 100; getZoomManager().setZoom(zoom); } private ZoomManager getZoomManager() { return (ZoomManager) getGraphicalViewer().getProperty(ZoomManager.class.toString()); } private SapphireDiagramOutline getDiagramOutline() { if (this.diagramOutline == null && getGraphicalViewer() != null) { RootEditPart rootEditPart = getGraphicalViewer().getRootEditPart(); if (rootEditPart instanceof ScalableFreeformRootEditPart) { this.diagramOutline = new SapphireDiagramOutline((ScalableFreeformRootEditPart) rootEditPart); } } return this.diagramOutline; } // ----------------------------------------------------------------------------------------------- // Inner classes //------------------------------------------------------------------------------------------------ private class FormLayout extends Layout implements ILayoutExtension { public int computeMinimumWidth(Composite composite, boolean flushCache) { return computeSize(composite, 5, SWT.DEFAULT, flushCache).x; } public int computeMaximumWidth(Composite composite, boolean flushCache) { return computeSize(composite, SWT.DEFAULT, SWT.DEFAULT, flushCache).x; } public org.eclipse.swt.graphics.Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) { if (flushCache) { bodyCache.flush(); headCache.flush(); } bodyCache.setControl(body); headCache.setControl(header); int width = 0; int height = 0; org.eclipse.swt.graphics.Point hsize = headCache.computeSize(FormUtil.getWidthHint(wHint, header), SWT.DEFAULT); width = Math.max(hsize.x, width); height = hsize.y; boolean ignoreBody = false; org.eclipse.swt.graphics.Point bsize; if (ignoreBody) bsize = new org.eclipse.swt.graphics.Point(0, 0); else bsize = bodyCache.computeSize(FormUtil.getWidthHint(wHint, body), SWT.DEFAULT); width = Math.max(bsize.x, width); height += bsize.y; return new org.eclipse.swt.graphics.Point(width, height); } protected void layout(Composite composite, boolean flushCache) { if (flushCache) { bodyCache.flush(); headCache.flush(); } bodyCache.setControl(body); headCache.setControl(header); Rectangle carea = composite.getClientArea(); org.eclipse.swt.graphics.Point hsize = headCache.computeSize(carea.width, SWT.DEFAULT); headCache.setBounds(0, 0, carea.width, hsize.y); bodyCache.setBounds(0, hsize.y, carea.width, carea.height - hsize.y); } } }