/* * Copyright (c) 2006 Stiftung Deutsches Elektronen-Synchroton, * Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY. * * THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS. * WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND * NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE * IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR * CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. * NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. * DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, * OR MODIFICATIONS. * THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION, * USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS * PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY * AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM */ package org.csstudio.sds.ui.internal.editor; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.EventObject; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import org.csstudio.sds.SdsPlugin; import org.csstudio.sds.internal.model.LayerSupport; import org.csstudio.sds.internal.persistence.DisplayModelLoadAdapter; import org.csstudio.sds.internal.persistence.IDisplayModelLoadListener; import org.csstudio.sds.internal.persistence.PersistenceUtil; import org.csstudio.sds.internal.preferences.CategorizationType; import org.csstudio.sds.internal.preferences.PreferenceConstants; import org.csstudio.sds.model.AbstractWidgetModel; import org.csstudio.sds.model.DisplayModel; import org.csstudio.sds.model.IPropertyChangeListener; import org.csstudio.sds.model.PropertyChangeAdapter; import org.csstudio.sds.model.RulerModel; import org.csstudio.sds.model.WidgetModelFactoryService; import org.csstudio.sds.model.WidgetProperty; import org.csstudio.sds.model.commands.SetPropertyCommand; import org.csstudio.sds.ui.CheckedUiRunnable; import org.csstudio.sds.ui.SdsUiPlugin; import org.csstudio.sds.ui.editparts.AbstractBaseEditPart; import org.csstudio.sds.ui.editparts.ExecutionMode; import org.csstudio.sds.ui.internal.actions.ArrangeAction; import org.csstudio.sds.ui.internal.actions.CopyWidgetsAction; import org.csstudio.sds.ui.internal.actions.CreateGroupAction; import org.csstudio.sds.ui.internal.actions.CutWidgetsAction; import org.csstudio.sds.ui.internal.actions.DeleteWidgetsAction; import org.csstudio.sds.ui.internal.actions.MoveToBackAction; import org.csstudio.sds.ui.internal.actions.MoveToFrontAction; import org.csstudio.sds.ui.internal.actions.PasteWidgetsAction; import org.csstudio.sds.ui.internal.actions.RemoveGroupAction; import org.csstudio.sds.ui.internal.actions.StepBackAction; import org.csstudio.sds.ui.internal.actions.StepFrontAction; import org.csstudio.sds.ui.internal.commands.AssociableCommandListener; import org.csstudio.sds.ui.internal.editor.dnd.ProcessVariableAddressDropTargetListener; import org.csstudio.sds.ui.internal.editor.dnd.ProcessVariableDropTargetListener; import org.csstudio.sds.ui.internal.editor.dnd.ProcessVariablesDropTargetListener; import org.csstudio.sds.ui.internal.editor.dnd.TextTransferDropTargetListener; import org.csstudio.sds.ui.internal.editor.outline.ThumbnailViewOutlinePage; import org.csstudio.sds.ui.internal.editparts.WidgetEditPartFactory; import org.csstudio.sds.ui.internal.layers.ILayerManager; import org.csstudio.sds.ui.internal.properties.view.IPropertySheetPage; import org.csstudio.sds.ui.internal.properties.view.PropertySheetPage; import org.csstudio.sds.ui.internal.properties.view.UndoablePropertySheetEntry; import org.csstudio.sds.ui.internal.viewer.PatchedGraphicalViewer; import org.csstudio.sds.util.SaveAsDialog; import org.eclipse.core.filesystem.URIUtil; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.draw2d.ColorConstants; import org.eclipse.draw2d.PositionConstants; 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.GraphicalViewer; import org.eclipse.gef.MouseWheelHandler; import org.eclipse.gef.MouseWheelZoomHandler; import org.eclipse.gef.SnapToGeometry; import org.eclipse.gef.SnapToGrid; import org.eclipse.gef.commands.CommandStack; import org.eclipse.gef.editparts.ScalableFreeformRootEditPart; import org.eclipse.gef.editparts.ZoomListener; import org.eclipse.gef.editparts.ZoomManager; import org.eclipse.gef.palette.PaletteGroup; import org.eclipse.gef.palette.PaletteRoot; import org.eclipse.gef.palette.PanningSelectionToolEntry; import org.eclipse.gef.palette.ToolEntry; import org.eclipse.gef.rulers.RulerProvider; import org.eclipse.gef.ui.actions.ActionRegistry; import org.eclipse.gef.ui.actions.AlignmentAction; import org.eclipse.gef.ui.actions.CopyTemplateAction; import org.eclipse.gef.ui.actions.DirectEditAction; import org.eclipse.gef.ui.actions.GEFActionConstants; import org.eclipse.gef.ui.actions.MatchHeightAction; import org.eclipse.gef.ui.actions.MatchWidthAction; import org.eclipse.gef.ui.actions.ToggleGridAction; import org.eclipse.gef.ui.actions.ToggleRulerVisibilityAction; import org.eclipse.gef.ui.actions.ToggleSnapToGeometryAction; import org.eclipse.gef.ui.actions.ZoomInAction; import org.eclipse.gef.ui.actions.ZoomOutAction; import org.eclipse.gef.ui.parts.GraphicalEditorWithFlyoutPalette; import org.eclipse.gef.ui.parts.GraphicalViewerKeyHandler; import org.eclipse.gef.ui.parts.ScrollingGraphicalViewer; import org.eclipse.gef.ui.rulers.RulerComposite; import org.eclipse.jface.action.IAction; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IEditorReference; import org.eclipse.ui.IKeyBindingService; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.ActionFactory; import org.eclipse.ui.ide.FileStoreEditorInput; import org.eclipse.ui.internal.help.WorkbenchHelpSystem; import org.eclipse.ui.part.FileEditorInput; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; import org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor; import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * The editor for synoptic displays. * * @author Sven Wende & Alexander Will * @version $Revision: 1.120 $ * */ public final class DisplayEditor extends GraphicalEditorWithFlyoutPalette implements ITabbedPropertySheetPageContributor { private static final Logger LOG = LoggerFactory.getLogger(DisplayEditor.class); /** * The default value for the grid spacing property. */ public static final int GRID_SPACING = 12; /** * The file extension for SDS display files. */ public static final String SDS_FILE_EXTENSION = "css-sds"; /** */ private DisplayModel _displayModel = new DisplayModel(); private boolean isModelLoaded; private final List<IDisplayModelLoadListener> modelLoadedListeners; /** * A DisplayListener. */ private Map<String, IPropertyChangeListener> _propertyChangeListeners; /** * The preference page listener for the grid space. */ private org.eclipse.jface.util.IPropertyChangeListener _gridSpacingListener; /** * The palette root. */ private PaletteRoot _paletteRoot; private TabbedPropertySheetPage propertyPage; /** * The RulerComposite for the GraphicalViewer. */ private RulerComposite _rulerComposite; private IContentOutlinePage _outlinePage; private static KeyListenerAdapter keyAdapter = new KeyListenerAdapter(); /** * Constructor. */ public DisplayEditor() { setEditDomain(new DefaultEditDomain(this)); initPropertyChangeListeners(); initCommandStackListeners(); isModelLoaded = false; modelLoadedListeners = new ArrayList<IDisplayModelLoadListener>(); } /** * {@inheritDoc} */ @Override protected PaletteRoot getPaletteRoot() { // if (_paletteRoot == null) { _paletteRoot = new PaletteRoot(); // _paletteRoot.add(createControlGroup(_paletteRoot)); createControlGroup(_paletteRoot); // } return _paletteRoot; } /** * Returns the currently selected {@link AbstractBaseEditPart}s. * * @return a list of {@link AbstractBaseEditPart}s */ public List<AbstractBaseEditPart> getSelectedEditParts() { List<AbstractBaseEditPart> result = new ArrayList<AbstractBaseEditPart>(getGraphicalViewer() .getSelectedEditParts().size()); for (Object obj : getGraphicalViewer().getSelectedEditParts()) { if (obj instanceof AbstractBaseEditPart) { result.add((AbstractBaseEditPart) obj); } } return result; } /** * Installs standard tools in the specified palette root and returns a * palette container. * * @param root * the palette root * @return a palette container */ private static void createControlGroup(final PaletteRoot root) { PaletteGroup controlGroup = new PaletteGroup("controlGroup"); //$NON-NLS-1$ ToolEntry toolEntry = new PanningSelectionToolEntry(); controlGroup.add(toolEntry); root.add(controlGroup); WidgetModelFactoryService service = WidgetModelFactoryService.getInstance(); PaletteEntryCreator paletteEntryCreator = new PaletteEntryCreator(service, keyAdapter); String string = SdsPlugin.getDefault().getPluginPreferences() .getString(PreferenceConstants.PROP_WIDGET_CATEGORIZATION); CategorizationType categorization = CategorizationType.getTypeForId(string); paletteEntryCreator.createEntries(root, categorization); } /** * Initializes the ActionBars. */ protected void init() { ActionRegistry registry = getActionRegistry(); IActionBars bars = getEditorSite().getActionBars(); String id = ActionFactory.UNDO.getId(); bars.setGlobalActionHandler(id, registry.getAction(id)); id = ActionFactory.REDO.getId(); bars.setGlobalActionHandler(id, registry.getAction(id)); id = ActionFactory.DELETE.getId(); bars.setGlobalActionHandler(id, registry.getAction(id)); } /** * Returns the Point, which is the center of the Display. * * @return Point The Point, which is the center of the Display */ public Point getEditorCenterPosition() { ScalableFreeformRootEditPart root = (ScalableFreeformRootEditPart) getGraphicalViewer() .getRootEditPart(); ZoomManager zoomManager = root.getZoomManager(); Point center = zoomManager.getViewport().getBounds().getCenter(); center = translateCursorLocation(center); return center; } /** * Translates a point on the editor viewport to the actual point on the display. * * Doesn't manipulate <code>cursorLocation</code>, but returns a new translated point. * * @param cursorLocation The position on the editor viewport. * @return Point The point, on which the given location points on the display. */ public Point translateCursorLocation(Point cursorLocation) { ScalableFreeformRootEditPart root = (ScalableFreeformRootEditPart) getGraphicalViewer() .getRootEditPart(); ZoomManager zoomManager = root.getZoomManager(); Point viewportLocation = root.getZoomManager().getViewport().getViewLocation(); Point locationCopy = cursorLocation.getCopy(); locationCopy.translate(viewportLocation); zoomManager.getScalableFigure().translateFromParent(locationCopy); return locationCopy; } /** * {@inheritDoc} * * We overide the behaviour of the superclass totally. Don�t add a super * call in future!! */ @Override protected void createGraphicalViewer(final Composite parent) { _rulerComposite = new RulerComposite(parent, SWT.NONE); GraphicalViewer viewer = new PatchedGraphicalViewer(); viewer.createControl(_rulerComposite); setGraphicalViewer(viewer); configureGraphicalViewer(); hookGraphicalViewer(); initializeGraphicalViewer(); _rulerComposite.setGraphicalViewer((ScrollingGraphicalViewer) getGraphicalViewer()); WorkbenchHelpSystem.getInstance().setHelp(_rulerComposite, SdsUiPlugin.PLUGIN_ID + ".synoptic_display_studio"); viewer.getControl().addKeyListener(keyAdapter); } /** * Returns the main composite of the editor. * * @return the main composite of the editor */ public Composite getParentComposite() { return _rulerComposite; } /** * Adds a listener that is called when the model has been loaded. * The Listener is called once and automatically removed afterwards */ public void addModelLoadedListener(IDisplayModelLoadListener displayModelLoadListener) { assert displayModelLoadListener != null : "Precondition failed: displayModelLoadListener != null"; if(isModelLoaded) { // Fire listener directly if model is already loaded displayModelLoadListener.onDisplayModelLoaded(); } else { modelLoadedListeners.add(displayModelLoadListener); } } /** * Configure the properties for the rulers. */ private void configureRuler() { // Ruler properties RulerProvider hprovider = new SDSRulerProvider(new RulerModel(true)); RulerProvider vprovider = new SDSRulerProvider(new RulerModel(false)); getGraphicalViewer().setProperty(RulerProvider.PROPERTY_HORIZONTAL_RULER, hprovider); getGraphicalViewer().setProperty(RulerProvider.PROPERTY_VERTICAL_RULER, vprovider); getGraphicalViewer().setProperty(RulerProvider.PROPERTY_RULER_VISIBILITY, Boolean.FALSE); } /** * {@inheritDoc} */ @Override protected Control getGraphicalControl() { return _rulerComposite; } /** * Creates a new {@link DisplayModel} and adds listener to it. */ private void prepareModel() { _displayModel = new DisplayModel(); addModelListeners(); } /** * Adds a listener for the background color and one for the grid space. */ private void addModelListeners() { // register all property change listeners for (String propertyId : _propertyChangeListeners.keySet()) { WidgetProperty property = _displayModel.getPropertyInternal(propertyId); if (property != null) { property.addPropertyChangeListener(_propertyChangeListeners.get(propertyId)); } } // FIXME: 2008-07-24: Sven Wende: Entfernen, sobald Grid-Einstellungen // mit Model persistiert werden _gridSpacingListener = new GridSpacingListener(); SdsUiPlugin.getCorePreferenceStore().addPropertyChangeListener(_gridSpacingListener); } /** * Removes the listener for the model. */ private void removeModelListeners() { // remove all property change listeners // register all property change listeners for (String propertyId : _propertyChangeListeners.keySet()) { WidgetProperty property = _displayModel.getPropertyInternal(propertyId); if (property != null) { property.removePropertyChangeListener(_propertyChangeListeners.get(propertyId)); } } // FIXME: 2008-07-24: Sven Wende: Entfernen, sobald Grid-Einstellungen // mit Model persistiert werden SdsUiPlugin.getCorePreferenceStore().removePropertyChangeListener(_gridSpacingListener); } /** * Creates all property change listeners that should be registered to the * loaded display. */ private void initPropertyChangeListeners() { _propertyChangeListeners = new HashMap<String, IPropertyChangeListener>(); // ... background color IPropertyChangeListener listener = new PropertyChangeAdapter() { @Override public void propertyValueChanged(final Object oldValue, final Object newValue) { if (newValue instanceof String) { new CheckedUiRunnable() { @Override protected void doRunInUi() { getGraphicalViewer().getControl().setBackground(SdsUiPlugin .getDefault().getColorAndFontService() .getColor((String) newValue)); } }; } } }; _propertyChangeListeners.put(AbstractWidgetModel.PROP_COLOR_BACKGROUND, listener); // ... grid visibility listener = new PropertyChangeAdapter() { @Override public void propertyValueChanged(final Object oldValue, final Object newValue) { final boolean visible = (Boolean) newValue; new CheckedUiRunnable() { @Override protected void doRunInUi() { // update viewer settings getGraphicalViewer().setProperty(SnapToGrid.PROPERTY_GRID_ENABLED, visible); getGraphicalViewer().setProperty(SnapToGrid.PROPERTY_GRID_VISIBLE, visible); // update toolbar action state getActionRegistry().getAction(GEFActionConstants.TOGGLE_GRID_VISIBILITY) .setChecked(visible); } }; } }; _propertyChangeListeners.put(DisplayModel.PROP_GRID_ON, listener); // ... ruler visibility listener = new PropertyChangeAdapter() { @Override public void propertyValueChanged(final Object oldValue, final Object newValue) { final boolean visible = (Boolean) newValue; new CheckedUiRunnable() { @Override protected void doRunInUi() { // update viewer settings getGraphicalViewer().setProperty(RulerProvider.PROPERTY_RULER_VISIBILITY, visible); // update toolbar action state getActionRegistry().getAction(GEFActionConstants.TOGGLE_RULER_VISIBILITY) .setChecked(visible); } }; } }; _propertyChangeListeners.put(DisplayModel.PROP_RULER_ON, listener); // ... snap to geometry active listener = new PropertyChangeAdapter() { @Override public void propertyValueChanged(final Object oldValue, final Object newValue) { final boolean active = (Boolean) newValue; new CheckedUiRunnable() { @Override protected void doRunInUi() { // update viewer settings getGraphicalViewer().setProperty(SnapToGeometry.PROPERTY_SNAP_ENABLED, active); // update toolbar action state getActionRegistry().getAction(GEFActionConstants.TOGGLE_SNAP_TO_GEOMETRY) .setChecked(active); } }; } }; _propertyChangeListeners.put(DisplayModel.PROP_GEOMETRY_ON, listener); } /** * {@inheritDoc} */ @Override protected void initializeGraphicalViewer() { prepareModel(); final GraphicalViewer viewer = getGraphicalViewer(); // initialize context menu ContextMenuProvider cmProvider = new DisplayContextMenuProvider(viewer, getActionRegistry()); viewer.setContextMenu(cmProvider); getSite().registerContextMenu(cmProvider, viewer); // load the model loadModelAsynchroniously(); // initialize drop support (order matters!) viewer.addDropTargetListener(new ProcessVariablesDropTargetListener(viewer)); viewer.addDropTargetListener(new ProcessVariableDropTargetListener(viewer)); viewer.addDropTargetListener(new TextTransferDropTargetListener(viewer)); viewer.addDropTargetListener(new ProcessVariableAddressDropTargetListener(viewer)); viewer.addDropTargetListener(new LibraryElementDropTargetListener(viewer)); } private void initCommandStackListeners() { getCommandStack() .addCommandStackEventListener(new AssociableCommandListener(getCommandStack())); } /** * Loads the DisplayModel asynchronously. */ private void loadModelAsynchroniously() { getGraphicalViewer().setContents(_displayModel); final InputStream inputStream = getInputStream(); IDisplayModelLoadListener modelLoadListener = new DisplayModelLoadAdapter() { @Override public void onDisplayModelLoaded() { new CheckedUiRunnable() { @Override protected void doRunInUi() { GraphicalViewer viewer = getGraphicalViewer(); // setup grid and ruler states on the graphical editor viewer.setProperty(SnapToGrid.PROPERTY_GRID_ENABLED, _displayModel.getGridState()); viewer.setProperty(SnapToGrid.PROPERTY_GRID_VISIBLE, _displayModel.getGridState()); viewer.setProperty(RulerProvider.PROPERTY_RULER_VISIBILITY, _displayModel.getRulerState()); viewer.setProperty(SnapToGeometry.PROPERTY_SNAP_ENABLED, _displayModel.getGeometryState()); // refresh the checked state on the according editor // actions IAction action; action = getActionRegistry() .getAction(GEFActionConstants.TOGGLE_GRID_VISIBILITY); action.setChecked(action.isChecked()); action = getActionRegistry() .getAction(GEFActionConstants.TOGGLE_RULER_VISIBILITY); action.setChecked(action.isChecked()); action = getActionRegistry() .getAction(GEFActionConstants.TOGGLE_SNAP_TO_GEOMETRY); action.setChecked(action.isChecked()); isModelLoaded = true; for (IDisplayModelLoadListener modelLoadListener : modelLoadedListeners) { modelLoadListener.onDisplayModelLoaded(); } modelLoadedListeners.clear(); } }; } }; if (inputStream != null) { setPartName(getEditorInput().getName()); PersistenceUtil.asyncFillModel(_displayModel, inputStream, modelLoadListener); } } /** * {@inheritDoc} */ @Override protected void configureGraphicalViewer() { super.configureGraphicalViewer(); ScrollingGraphicalViewer viewer = (ScrollingGraphicalViewer) getGraphicalViewer(); viewer.setEditPartFactory(new WidgetEditPartFactory(ExecutionMode.EDIT_MODE)); viewer.getControl().setBackground(ColorConstants.listBackground); final SDSRootEditPart root = new SDSRootEditPart(); viewer.setRootEditPart(root); this.configureRuler(); // configure zoom actions configureZoomManager(root); // FIXME: 2008-07-24: Sven Wende: Entfernen, sobald Grid-Einstellungen // mit Model persistiert werden int spacing = SdsPlugin.getDefault().getPluginPreferences() .getInt(PreferenceConstants.PROP_GRID_SPACING); getGraphicalViewer().setProperty(SnapToGrid.PROPERTY_GRID_SPACING, new Dimension(spacing, spacing)); // Ruler Actions IAction showRulers = new ToggleRulerVisibilityAction(getGraphicalViewer()) { @Override public void run() { super.run(); DisplayModel displayModel = getDisplayModel(); SetPropertyCommand cmd = new SetPropertyCommand(displayModel, DisplayModel.PROP_RULER_ON, isChecked()); getCommandStack().execute(cmd); } }; getActionRegistry().registerAction(showRulers); // Grid Action IAction a = new ToggleGridAction(getGraphicalViewer()) { @Override public void run() { super.run(); DisplayModel displayModel = getDisplayModel(); SetPropertyCommand cmd = new SetPropertyCommand(displayModel, DisplayModel.PROP_GRID_ON, isChecked()); getCommandStack().execute(cmd); } }; getActionRegistry().registerAction(a); /* snap to geometry */ a = new ToggleSnapToGeometryAction(getGraphicalViewer()) { @Override public void run() { super.run(); DisplayModel displayModel = getDisplayModel(); SetPropertyCommand cmd = new SetPropertyCommand(displayModel, DisplayModel.PROP_GEOMETRY_ON, isChecked()); getCommandStack().execute(cmd); } }; getActionRegistry().registerAction(a); hookGraphicalViewer(); viewer.setKeyHandler(new GraphicalViewerKeyHandler(viewer)); } @SuppressWarnings("unchecked") private void configureZoomManager(final SDSRootEditPart rootEditPart) { SDSZoomManager zm = rootEditPart.getZoomManager(); List<String> zoomLevels = new ArrayList<String>(3); zoomLevels.add(ZoomManager.FIT_ALL); zoomLevels.add(ZoomManager.FIT_WIDTH); zoomLevels.add(ZoomManager.FIT_HEIGHT); zm.setZoomLevelContributions(zoomLevels); zm.setZoomLevels(createZoomLevels()); if (zm != null) { IAction zoomIn = new ZoomInAction(zm); getSelectionActions().add(zoomIn.getId()); getActionRegistry().registerAction(zoomIn); IAction zoomOut = new ZoomOutAction(zm); getActionRegistry().registerAction(zoomOut); } zm.addZoomFinishedListener(new ZoomListener() { @Override public void zoomChanged(double zoom) { List<AbstractBaseEditPart> selectedEditParts = getSelectedEditParts(); if (!selectedEditParts.isEmpty()) { getGraphicalViewer() .reveal(selectedEditParts.get(selectedEditParts.size() - 1)); } } }); /* scroll-wheel zoom */ getGraphicalViewer().setProperty(MouseWheelHandler.KeyGenerator.getKey(SWT.MOD1), MouseWheelZoomHandler.SINGLETON); } /** * Refreshes the GridLayer and sets the new spacing value. * * @param spacing * The new value for the spacing property from the GridLayer */ public void refreshGridLayer(final int spacing) { getGraphicalViewer().setProperty(SnapToGrid.PROPERTY_GRID_SPACING, new Dimension(spacing, spacing)); } /** * {@inheritDoc} */ @SuppressWarnings("unchecked") @Override protected void createActions() { super.createActions(); IKeyBindingService keyBindingService = getSite().getKeyBindingService(); ActionRegistry registry = getActionRegistry(); IAction action; action = new CreateGroupAction(this, getGraphicalViewer()); registry.registerAction(action); getSelectionActions().add(action.getId()); action = new RemoveGroupAction(this, getGraphicalViewer()); registry.registerAction(action); getSelectionActions().add(action.getId()); action = new DeleteWidgetsAction((IWorkbenchPart) this); registry.registerAction(action); getSelectionActions().add(action.getId()); action = new CopyTemplateAction(this); registry.registerAction(action); action = new MatchWidthAction(this); registry.registerAction(action); getSelectionActions().add(action.getId()); action = new MatchHeightAction(this); registry.registerAction(action); getSelectionActions().add(action.getId()); action = new DirectEditAction((IWorkbenchPart) this); registry.registerAction(action); getSelectionActions().add(action.getId()); action = new CopyWidgetsAction(this); registry.registerAction(action); getSelectionActions().add(action.getId()); keyBindingService.registerAction(action); action = new CutWidgetsAction(this); registry.registerAction(action); getSelectionActions().add(action.getId()); keyBindingService.registerAction(action); action = new PasteWidgetsAction(this); registry.registerAction(action); getSelectionActions().add(action.getId()); keyBindingService.registerAction(action); action = new MoveToFrontAction(this); registry.registerAction(action); getSelectionActions().add(action.getId()); action = new MoveToBackAction(this); registry.registerAction(action); getSelectionActions().add(action.getId()); action = new StepBackAction(this); registry.registerAction(action); getSelectionActions().add(action.getId()); action = new StepFrontAction(this); registry.registerAction(action); getSelectionActions().add(action.getId()); /* delete action (registered in superclass) */ String id = ActionFactory.DELETE.getId(); action = getActionRegistry().getAction(id); action.setActionDefinitionId("org.eclipse.ui.edit.delete"); //$NON-NLS-1$ keyBindingService.registerAction(action); id = ActionFactory.SELECT_ALL.getId(); action = getActionRegistry().getAction(id); action.setActionDefinitionId("org.eclipse.ui.edit.selectAll"); keyBindingService.registerAction(action); id = ActionFactory.UNDO.getId(); action = getActionRegistry().getAction(id); action.setActionDefinitionId("org.eclipse.ui.edit.undo"); keyBindingService.registerAction(action); id = ActionFactory.REDO.getId(); action = getActionRegistry().getAction(id); action.setActionDefinitionId("org.eclipse.ui.edit.redo"); keyBindingService.registerAction(action); action = new AlignmentAction((IWorkbenchPart) this, PositionConstants.LEFT); registry.registerAction(action); getSelectionActions().add(action.getId()); action = new AlignmentAction((IWorkbenchPart) this, PositionConstants.RIGHT); registry.registerAction(action); getSelectionActions().add(action.getId()); action = new AlignmentAction((IWorkbenchPart) this, PositionConstants.TOP); registry.registerAction(action); getSelectionActions().add(action.getId()); action = new AlignmentAction((IWorkbenchPart) this, PositionConstants.BOTTOM); registry.registerAction(action); getSelectionActions().add(action.getId()); action = new AlignmentAction((IWorkbenchPart) this, PositionConstants.CENTER); registry.registerAction(action); getSelectionActions().add(action.getId()); action = new AlignmentAction((IWorkbenchPart) this, PositionConstants.MIDDLE); registry.registerAction(action); getSelectionActions().add(action.getId()); action = new ArrangeAction(this, getGraphicalViewer(), getCommandStack(), Arrange.HORIZONTAL); registry.registerAction(action); getSelectionActions().add(action.getId()); action = new ArrangeAction(this, getGraphicalViewer(), getCommandStack(), Arrange.VERTICAL); registry.registerAction(action); getSelectionActions().add(action.getId()); } /** * {@inheritDoc} */ @SuppressWarnings("unchecked") @Override public void commandStackChanged(final EventObject event) { firePropertyChange(IEditorPart.PROP_DIRTY); if (propertyPage != null && !propertyPage.getControl().isDisposed()) { // .. update the property page (this is necessary to allow dynamic // visibility changes of properties) List<EditPart> selectedEditParts = getGraphicalViewer().getSelectedEditParts(); if (selectedEditParts.isEmpty()) { EditPart focusEditPart = getGraphicalViewer().getFocusEditPart(); selectedEditParts = new ArrayList<EditPart>(1); selectedEditParts.add(focusEditPart); } propertyPage.selectionChanged(this, new StructuredSelection(selectedEditParts) { @Override public boolean equals(Object o) { return false; } @Override public int hashCode() { return UUID.randomUUID().hashCode(); } }); } super.commandStackChanged(event); } /** * {@inheritDoc} */ @Override public void doSave(final IProgressMonitor monitor) { if (getEditorInput() instanceof FileEditorInput || getEditorInput() instanceof FileStoreEditorInput) { performSave(); } else { doSaveAs(); } } /** * {@inheritDoc} */ @Override public void doSaveAs() { SaveAsDialog saveAsDialog = new SaveAsDialog(getEditorSite().getShell()); saveAsDialog.setFileExtension(SDS_FILE_EXTENSION); //$NON-NLS-1$ int ret = saveAsDialog.open(); try { if (ret == Window.OK) { IPath targetPath = saveAsDialog.getResult(); IFile targetFile = ResourcesPlugin.getWorkspace().getRoot().getFile(targetPath); if (!targetFile.exists()) { targetFile.create(null, true, null); } FileEditorInput editorInput = new FileEditorInput(targetFile); setInput(editorInput); setPartName(targetFile.getName()); performSave(); } } catch (CoreException e) { MessageDialog.openError(getSite().getShell(), "IO Error", e.getMessage()); LOG.error(e.toString()); } } /** * {@inheritDoc} */ @Override public boolean isSaveAsAllowed() { return true; } /** * Save the edited model to the underlying <code>IFile</code> resource. */ private void performSave() { try { if (_displayModel.isLoading()) { MessageDialog .openInformation(getSite().getShell(), "Information", "The displayed model isn't completeley loaded, yet. It can not be saved until this operation is completed."); } else { // getInputStream().setContents(is, false, false, null); if (getEditorInput() instanceof FileEditorInput) { InputStream is = PersistenceUtil.createStream(_displayModel); ((FileEditorInput) getEditorInput()).getFile().setContents(is, false, false, null); } else if (getEditorInput() instanceof FileStoreEditorInput) { File file = URIUtil.toPath(((FileStoreEditorInput) getEditorInput()).getURI()) .toFile(); String content = PersistenceUtil.createString(_displayModel); try { FileWriter fileWriter = new FileWriter(file, false); BufferedWriter writer = new BufferedWriter(fileWriter); writer.write(content); writer.flush(); writer.close(); } catch (IOException e) { MessageDialog.openError(getSite().getShell(), "IO Error", e.getMessage()); LOG.error(e.toString()); } } getCommandStack().flush(); firePropertyChange(IEditorPart.PROP_DIRTY); } } catch (CoreException e) { MessageDialog.openError(getSite().getShell(), "IO Error", e.getMessage()); LOG.error(e.toString()); } } /** * Returns a stream which can be used to read this editors input data. * * @return a stream which can be used to read this editors input data */ private InputStream getInputStream() { InputStream result = null; IEditorInput editorInput = getEditorInput(); if (editorInput instanceof FileEditorInput) { try { result = ((FileEditorInput) editorInput).getFile().getContents(); } catch (CoreException e) { e.printStackTrace(); } } else if (editorInput instanceof FileStoreEditorInput) { IPath path = URIUtil.toPath(((FileStoreEditorInput) editorInput).getURI()); try { result = new FileInputStream(path.toFile()); } catch (FileNotFoundException e) { result = null; } } return result; } /** * Returns the path for this editor�s input data. * * @return the path for this editor�s input data */ public IPath getFilePath() { IPath result = null; IEditorInput editorInput = getEditorInput(); if (editorInput instanceof FileEditorInput) { result = ((FileEditorInput) editorInput).getFile().getFullPath(); } else if (editorInput instanceof FileStoreEditorInput) { result = URIUtil.toPath(((FileStoreEditorInput) editorInput).getURI()); } return result; } /** * Returns the name of the display. * * @return String The name */ public String getDisplayName() { return getEditorInput().getName(); } /** * {@inheritDoc} */ public DisplayModel getDisplayModel() { return _displayModel; } /** * {@inheritDoc} */ @Override public Object getAdapter(final Class adapter) { if (adapter == org.eclipse.ui.views.properties.IPropertySheetPage.class) { propertyPage = new TabbedPropertySheetPage(this); return propertyPage; } else if (adapter == IPropertySheetPage.class) { PropertySheetPage page = new PropertySheetPage(); page.setRootEntry(new UndoablePropertySheetEntry(getCommandStack())); return page; } else if (adapter == ZoomManager.class) { return ((ScalableFreeformRootEditPart) getGraphicalViewer().getRootEditPart()) .getZoomManager(); } else if (adapter == ILayerManager.class) { return new ILayerManager() { @Override public LayerSupport getLayerSupport() { return getDisplayModel().getLayerSupport(); } @Override public CommandStack getCommandStack() { return DisplayEditor.this.getCommandStack(); } }; } else if (adapter == IContentOutlinePage.class) { if (_outlinePage == null) { _outlinePage = new ThumbnailViewOutlinePage(getGraphicalViewer()); } return _outlinePage; } return super.getAdapter(adapter); } /** * Create a double array that contains the pre-defined zoom levels. * * @return A double array that contains the pre-defined zoom levels. */ private double[] createZoomLevels() { List<Double> zoomLevelList = new ArrayList<Double>(); double level = 0.1; while (level < 1.0) { zoomLevelList.add(level); level = level + 0.05; } zoomLevelList.add(1.0); zoomLevelList.add(1.5); zoomLevelList.add(2.0); zoomLevelList.add(2.5); zoomLevelList.add(3.0); zoomLevelList.add(3.5); zoomLevelList.add(4.0); zoomLevelList.add(4.5); zoomLevelList.add(5.0); double[] result = new double[zoomLevelList.size()]; for (int i = 0; i < zoomLevelList.size(); i++) { result[i] = zoomLevelList.get(i); } return result; } @Override public void dispose() { removeModelListeners(); _displayModel = null; super.dispose(); } final class GridSpacingListener implements org.eclipse.jface.util.IPropertyChangeListener { @Override public void propertyChange(final PropertyChangeEvent event) { if (event.getProperty().equals(PreferenceConstants.PROP_GRID_SPACING)) { IEditorReference[] references = PlatformUI.getWorkbench() .getActiveWorkbenchWindow().getActivePage().getEditorReferences(); for (IEditorReference ref : references) { IEditorPart editor = ref.getEditor(false); if (editor instanceof DisplayEditor) { Integer spacing; if (event.getNewValue() instanceof String) { spacing = new Integer((String) event.getNewValue()); } else { spacing = (Integer) event.getNewValue(); } if (spacing != null) { ((DisplayEditor) editor).refreshGridLayer(spacing); } } } } } } @Override public String getContributorId() { return getSite().getId(); } @Override public GraphicalViewer getGraphicalViewer() { return super.getGraphicalViewer(); } @Override public CommandStack getCommandStack() { return super.getCommandStack(); } }