| /******************************************************************************* |
| * Copyright (c) 2000, 2010 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.gef.ui.parts; |
| |
| import java.util.ArrayList; |
| import java.util.EventObject; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.swt.widgets.Composite; |
| |
| import org.eclipse.jface.action.IAction; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.ui.IEditorInput; |
| import org.eclipse.ui.IEditorSite; |
| import org.eclipse.ui.ISelectionListener; |
| import org.eclipse.ui.ISelectionService; |
| import org.eclipse.ui.IWorkbenchPart; |
| import org.eclipse.ui.PartInitException; |
| import org.eclipse.ui.part.EditorPart; |
| import org.eclipse.ui.views.properties.PropertySheetPage; |
| |
| import org.eclipse.draw2d.ColorConstants; |
| import org.eclipse.draw2d.IFigure; |
| |
| 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.commands.CommandStack; |
| import org.eclipse.gef.commands.CommandStackListener; |
| import org.eclipse.gef.ui.actions.ActionBarContributor; |
| import org.eclipse.gef.ui.actions.ActionRegistry; |
| import org.eclipse.gef.ui.actions.DeleteAction; |
| import org.eclipse.gef.ui.actions.PrintAction; |
| import org.eclipse.gef.ui.actions.RedoAction; |
| import org.eclipse.gef.ui.actions.SaveAction; |
| import org.eclipse.gef.ui.actions.SelectAllAction; |
| import org.eclipse.gef.ui.actions.UndoAction; |
| import org.eclipse.gef.ui.actions.UpdateAction; |
| import org.eclipse.gef.ui.properties.UndoablePropertySheetEntry; |
| |
| /** |
| * This class serves as a quick starting point for clients who are new to GEF. |
| * It will create an Editor containing a single GraphicalViewer as its control. |
| * <P> |
| * <EM>IMPORTANT</EM>This class should only be used as a reference for creating |
| * your own EditorPart implementation. This class will not suit everyone's |
| * needs, and may change in the future. Clients may copy the implementation. |
| * |
| * @author hudsonr |
| */ |
| public abstract class GraphicalEditor extends EditorPart implements |
| CommandStackListener, ISelectionListener { |
| |
| private static class ActionIDList extends ArrayList { |
| public boolean add(Object o) { |
| if (o instanceof IAction) { |
| try { |
| IAction action = (IAction) o; |
| o = action.getId(); |
| throw new IllegalArgumentException( |
| "Action IDs should be added to lists, not the action: " + action); //$NON-NLS-1$ |
| } catch (IllegalArgumentException exc) { |
| exc.printStackTrace(); |
| } |
| } |
| return super.add(o); |
| } |
| } |
| |
| private DefaultEditDomain editDomain; |
| private GraphicalViewer graphicalViewer; |
| private ActionRegistry actionRegistry; |
| private SelectionSynchronizer synchronizer; |
| private List selectionActions = new ActionIDList(); |
| private List stackActions = new ActionIDList(); |
| private List propertyActions = new ActionIDList(); |
| |
| /** |
| * Constructs the editor part |
| */ |
| public GraphicalEditor() { |
| } |
| |
| /** |
| * When the command stack changes, the actions interested in the command |
| * stack are updated. |
| * |
| * @param event |
| * the change event |
| */ |
| public void commandStackChanged(EventObject event) { |
| updateActions(stackActions); |
| } |
| |
| /** |
| * Called to configure the graphical viewer before it receives its contents. |
| * This is where the root editpart should be configured. Subclasses should |
| * extend or override this method as needed. |
| */ |
| protected void configureGraphicalViewer() { |
| getGraphicalViewer().getControl().setBackground( |
| ColorConstants.listBackground); |
| } |
| |
| /** |
| * Creates actions for this editor. Subclasses should override this method |
| * to create and register actions with the {@link ActionRegistry}. |
| */ |
| protected void createActions() { |
| ActionRegistry registry = getActionRegistry(); |
| IAction action; |
| |
| action = new UndoAction(this); |
| registry.registerAction(action); |
| getStackActions().add(action.getId()); |
| |
| action = new RedoAction(this); |
| registry.registerAction(action); |
| getStackActions().add(action.getId()); |
| |
| action = new SelectAllAction(this); |
| registry.registerAction(action); |
| |
| action = new DeleteAction((IWorkbenchPart) this); |
| registry.registerAction(action); |
| getSelectionActions().add(action.getId()); |
| |
| action = new SaveAction(this); |
| registry.registerAction(action); |
| getPropertyActions().add(action.getId()); |
| |
| registry.registerAction(new PrintAction(this)); |
| } |
| |
| /** |
| * Creates the GraphicalViewer on the specified <code>Composite</code>. |
| * |
| * @param parent |
| * the parent composite |
| */ |
| protected void createGraphicalViewer(Composite parent) { |
| GraphicalViewer viewer = new ScrollingGraphicalViewer(); |
| viewer.createControl(parent); |
| setGraphicalViewer(viewer); |
| configureGraphicalViewer(); |
| hookGraphicalViewer(); |
| initializeGraphicalViewer(); |
| } |
| |
| /** |
| * Realizes the Editor by creating it's Control. |
| * <P> |
| * WARNING: This method may or may not be called by the workbench prior to |
| * {@link #dispose()}. |
| * |
| * @param parent |
| * the parent composite |
| */ |
| public void createPartControl(Composite parent) { |
| createGraphicalViewer(parent); |
| } |
| |
| /** |
| * @see org.eclipse.ui.IWorkbenchPart#dispose() |
| */ |
| public void dispose() { |
| getCommandStack().removeCommandStackListener(this); |
| getSite().getWorkbenchWindow().getSelectionService() |
| .removeSelectionListener(this); |
| getEditDomain().setActiveTool(null); |
| getActionRegistry().dispose(); |
| super.dispose(); |
| } |
| |
| /** |
| * Does nothing be default. This method should be overridden if |
| * {@link #isSaveAsAllowed()} has been overridden to return |
| * <code>true</code>. |
| * |
| * @see org.eclipse.ui.ISaveablePart#doSaveAs() |
| */ |
| public void doSaveAs() { |
| throw new RuntimeException("doSaveAs must be overridden"); //$NON-NLS-1$ |
| } |
| |
| /** |
| * @see org.eclipse.ui.part.WorkbenchPart#firePropertyChange(int) |
| */ |
| protected void firePropertyChange(int property) { |
| super.firePropertyChange(property); |
| updateActions(propertyActions); |
| } |
| |
| /** |
| * Lazily creates and returns the action registry. |
| * |
| * @return the action registry |
| */ |
| protected ActionRegistry getActionRegistry() { |
| if (actionRegistry == null) |
| actionRegistry = new ActionRegistry(); |
| return actionRegistry; |
| } |
| |
| /** |
| * Returns the adapter for the specified key. |
| * |
| * <P> |
| * <EM>IMPORTANT</EM> certain requests, such as the property sheet, may be |
| * made before or after {@link #createPartControl(Composite)} is called. The |
| * order is unspecified by the Workbench. |
| * |
| * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) |
| */ |
| public Object getAdapter(Class type) { |
| if (type == org.eclipse.ui.views.properties.IPropertySheetPage.class) { |
| PropertySheetPage page = new PropertySheetPage(); |
| page.setRootEntry(new UndoablePropertySheetEntry(getCommandStack())); |
| return page; |
| } |
| if (type == GraphicalViewer.class) |
| return getGraphicalViewer(); |
| if (type == CommandStack.class) |
| return getCommandStack(); |
| if (type == ActionRegistry.class) |
| return getActionRegistry(); |
| if (type == EditPart.class && getGraphicalViewer() != null) |
| return getGraphicalViewer().getRootEditPart(); |
| if (type == IFigure.class && getGraphicalViewer() != null) |
| return ((GraphicalEditPart) getGraphicalViewer().getRootEditPart()) |
| .getFigure(); |
| return super.getAdapter(type); |
| } |
| |
| /** |
| * Returns the command stack. |
| * |
| * @return the command stack |
| */ |
| protected CommandStack getCommandStack() { |
| return getEditDomain().getCommandStack(); |
| } |
| |
| /** |
| * Returns the edit domain. |
| * |
| * @return the edit domain |
| */ |
| protected DefaultEditDomain getEditDomain() { |
| return editDomain; |
| } |
| |
| /** |
| * Returns the graphical viewer. |
| * |
| * @return the graphical viewer |
| */ |
| protected GraphicalViewer getGraphicalViewer() { |
| return graphicalViewer; |
| } |
| |
| /** |
| * Returns the list of {@link IAction IActions} dependant on property |
| * changes in the Editor. These actions should implement the |
| * {@link UpdateAction} interface so that they can be updated in response to |
| * property changes. An example is the "Save" action. |
| * |
| * @return the list of property-dependant actions |
| */ |
| protected List getPropertyActions() { |
| return propertyActions; |
| } |
| |
| /** |
| * Returns the list of <em>IDs</em> of Actions that are dependant on changes |
| * in the workbench's {@link ISelectionService}. The associated Actions can |
| * be found in the action registry. Such actions should implement the |
| * {@link UpdateAction} interface so that they can be updated in response to |
| * selection changes. |
| * |
| * @see #updateActions(List) |
| * @return the list of selection-dependant action IDs |
| */ |
| protected List getSelectionActions() { |
| return selectionActions; |
| } |
| |
| /** |
| * Returns the selection syncronizer object. The synchronizer can be used to |
| * sync the selection of 2 or more EditPartViewers. |
| * |
| * @return the syncrhonizer |
| */ |
| protected SelectionSynchronizer getSelectionSynchronizer() { |
| if (synchronizer == null) |
| synchronizer = new SelectionSynchronizer(); |
| return synchronizer; |
| } |
| |
| /** |
| * Returns the list of <em>IDs</em> of Actions that are dependant on the |
| * CommmandStack's state. The associated Actions can be found in the action |
| * registry. These actions should implement the {@link UpdateAction} |
| * interface so that they can be updated in response to command stack |
| * changes. An example is the "undo" action. |
| * |
| * @return the list of stack-dependant action IDs |
| */ |
| protected List getStackActions() { |
| return stackActions; |
| } |
| |
| /** |
| * Hooks the GraphicalViewer to the rest of the Editor. By default, the |
| * viewer is added to the SelectionSynchronizer, which can be used to keep 2 |
| * or more EditPartViewers in sync. The viewer is also registered as the |
| * ISelectionProvider for the Editor's PartSite. |
| */ |
| protected void hookGraphicalViewer() { |
| getSelectionSynchronizer().addViewer(getGraphicalViewer()); |
| getSite().setSelectionProvider(getGraphicalViewer()); |
| } |
| |
| /** |
| * Sets the site and input for this editor then creates and initializes the |
| * actions. Subclasses may extend this method, but should always call |
| * <code>super.init(site, input) |
| * </code>. |
| * |
| * @see org.eclipse.ui.IEditorPart#init(IEditorSite, IEditorInput) |
| */ |
| public void init(IEditorSite site, IEditorInput input) |
| throws PartInitException { |
| setSite(site); |
| setInput(input); |
| getCommandStack().addCommandStackListener(this); |
| getSite().getWorkbenchWindow().getSelectionService() |
| .addSelectionListener(this); |
| initializeActionRegistry(); |
| } |
| |
| /** |
| * Initializes the ActionRegistry. This registry may be used by |
| * {@link ActionBarContributor ActionBarContributors} and/or |
| * {@link ContextMenuProvider ContextMenuProviders}. |
| * <P> |
| * This method may be called on Editor creation, or lazily the first time |
| * {@link #getActionRegistry()} is called. |
| */ |
| protected void initializeActionRegistry() { |
| createActions(); |
| updateActions(propertyActions); |
| updateActions(stackActions); |
| } |
| |
| /** |
| * Override to set the contents of the GraphicalViewer after it has been |
| * created. |
| * |
| * @see #createGraphicalViewer(Composite) |
| */ |
| protected abstract void initializeGraphicalViewer(); |
| |
| /** |
| * Returns <code>true</code> if the command stack is dirty |
| * |
| * @see org.eclipse.ui.ISaveablePart#isDirty() |
| */ |
| public boolean isDirty() { |
| return getCommandStack().isDirty(); |
| } |
| |
| /** |
| * Returns <code>false</code> by default. Subclasses must return |
| * <code>true</code> to allow {@link #doSaveAs()} to be called. |
| * |
| * @see org.eclipse.ui.ISaveablePart#isSaveAsAllowed() |
| */ |
| public boolean isSaveAsAllowed() { |
| return false; |
| } |
| |
| /** |
| * @see org.eclipse.ui.ISelectionListener#selectionChanged(IWorkbenchPart, |
| * ISelection) |
| */ |
| public void selectionChanged(IWorkbenchPart part, ISelection selection) { |
| // If not the active editor, ignore selection changed. |
| if (this.equals(getSite().getPage().getActiveEditor())) |
| updateActions(selectionActions); |
| } |
| |
| /** |
| * Sets the ActionRegistry for this EditorPart. |
| * |
| * @param registry |
| * the registry |
| */ |
| protected void setActionRegistry(ActionRegistry registry) { |
| actionRegistry = registry; |
| } |
| |
| /** |
| * Sets the EditDomain for this EditorPart. |
| * |
| * @param ed |
| * the domain |
| */ |
| protected void setEditDomain(DefaultEditDomain ed) { |
| this.editDomain = ed; |
| } |
| |
| /** |
| * @see org.eclipse.ui.IWorkbenchPart#setFocus() |
| */ |
| public void setFocus() { |
| getGraphicalViewer().getControl().setFocus(); |
| } |
| |
| /** |
| * Sets the graphicalViewer for this EditorPart. |
| * |
| * @param viewer |
| * the graphical viewer |
| */ |
| protected void setGraphicalViewer(GraphicalViewer viewer) { |
| getEditDomain().addViewer(viewer); |
| this.graphicalViewer = viewer; |
| } |
| |
| /** |
| * A convenience method for updating a set of actions defined by the given |
| * List of action IDs. The actions are found by looking up the ID in the |
| * {@link #getActionRegistry() action registry}. If the corresponding action |
| * is an {@link UpdateAction}, it will have its <code>update()</code> method |
| * called. |
| * |
| * @param actionIds |
| * the list of IDs to update |
| */ |
| protected void updateActions(List actionIds) { |
| ActionRegistry registry = getActionRegistry(); |
| Iterator iter = actionIds.iterator(); |
| while (iter.hasNext()) { |
| IAction action = registry.getAction(iter.next()); |
| if (action instanceof UpdateAction) |
| ((UpdateAction) action).update(); |
| } |
| } |
| |
| } |