/******************************************************************************* * Copyright (c) 2004, 2005 Sybase, Inc. 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: * Sybase, Inc. - initial API and implementation *******************************************************************************/ package org.eclipse.jst.jsf.facesconfig.ui.pageflow; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IResourceDeltaVisitor; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.draw2d.PositionConstants; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.gef.ContextMenuProvider; import org.eclipse.gef.DefaultEditDomain; import org.eclipse.gef.EditPart; import org.eclipse.gef.EditPartViewer; import org.eclipse.gef.GraphicalEditPart; import org.eclipse.gef.GraphicalViewer; import org.eclipse.gef.KeyHandler; import org.eclipse.gef.KeyStroke; import org.eclipse.gef.RootEditPart; import org.eclipse.gef.commands.CommandStack; import org.eclipse.gef.commands.CommandStackEvent; import org.eclipse.gef.commands.CommandStackEventListener; import org.eclipse.gef.editparts.ScalableFreeformRootEditPart; import org.eclipse.gef.editparts.ScalableRootEditPart; import org.eclipse.gef.editparts.ZoomManager; import org.eclipse.gef.palette.PaletteRoot; import org.eclipse.gef.requests.CreationFactory; import org.eclipse.gef.ui.actions.ActionRegistry; import org.eclipse.gef.ui.actions.DeleteAction; import org.eclipse.gef.ui.actions.GEFActionConstants; import org.eclipse.gef.ui.actions.RedoAction; import org.eclipse.gef.ui.actions.SelectionAction; import org.eclipse.gef.ui.actions.StackAction; import org.eclipse.gef.ui.actions.UndoAction; import org.eclipse.gef.ui.actions.UpdateAction; 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.parts.SelectionSynchronizer; import org.eclipse.jface.action.IAction; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.PreferenceConverter; import org.eclipse.jface.resource.FontRegistry; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.util.TransferDropTargetListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jst.jsf.common.ui.internal.logging.Logger; import org.eclipse.jst.jsf.facesconfig.ui.EditorPlugin; import org.eclipse.jst.jsf.facesconfig.ui.pageflow.action.AlignmentAction; import org.eclipse.jst.jsf.facesconfig.ui.pageflow.action.OpenEditorAction; import org.eclipse.jst.jsf.facesconfig.ui.pageflow.action.ShowPropertyViewAction; import org.eclipse.jst.jsf.facesconfig.ui.pageflow.command.PreExecuteCommandStack; import org.eclipse.jst.jsf.facesconfig.ui.pageflow.editpart.ConfigurableRootEditPart; import org.eclipse.jst.jsf.facesconfig.ui.pageflow.editpart.IConnectionPreference; import org.eclipse.jst.jsf.facesconfig.ui.pageflow.editpart.IFigurePreference; import org.eclipse.jst.jsf.facesconfig.ui.pageflow.editpart.ILayerPanePreference; import org.eclipse.jst.jsf.facesconfig.ui.pageflow.editpart.INodePreference; import org.eclipse.jst.jsf.facesconfig.ui.pageflow.editpart.PageflowEditPartsFactory; import org.eclipse.jst.jsf.facesconfig.ui.pageflow.editpart.PageflowNodeEditPart; import org.eclipse.jst.jsf.facesconfig.ui.pageflow.model.Pageflow; import org.eclipse.jst.jsf.facesconfig.ui.pageflow.model.PageflowPage; import org.eclipse.jst.jsf.facesconfig.ui.pageflow.synchronization.FC2PFTransformer; import org.eclipse.jst.jsf.facesconfig.ui.pageflow.util.EditPartMarkerUtil; import org.eclipse.jst.jsf.facesconfig.ui.pageflow.util.PageflowAnnotationUtil; import org.eclipse.jst.jsf.facesconfig.ui.pageflow.util.PageflowModelManager; import org.eclipse.jst.jsf.facesconfig.ui.pageflow.util.PageflowResourceFactory; import org.eclipse.jst.jsf.facesconfig.ui.preference.GEMPreferences; import org.eclipse.jst.jsf.facesconfig.ui.util.WebrootUtil; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PartInitException; import org.eclipse.ui.actions.ActionFactory; import org.eclipse.ui.ide.IGotoMarker; import org.eclipse.ui.part.FileEditorInput; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; import org.eclipse.ui.views.properties.IPropertySheetPage; import org.eclipse.ui.views.properties.PropertySheetPage; /** * This the the main editor page for modifying a complete pageflow. */ public class PageflowEditor extends GraphicalEditorWithFlyoutPalette implements IAdaptable, IPropertyChangeListener, IGotoMarker { /** log instance */ private static final Logger log = EditorPlugin .getLogger(PageflowEditor.class); /** pageflow context menu registration ID */ private static final String PAGEFLOW_CONTEXTMENU_REG_ID = ".pageflow.editor.contextmenu"; //$NON-NLS-1$ /** the edit domain */ private final DefaultEditDomain domain; /** the palette root */ private PaletteRoot paletteRoot = null; /** the parent multi-page editor */ private IEditorPart parentEditor = null; /** the graphical viewer */ private GraphicalViewer viewer = null; /** the undoable <code>IPropertySheetPage</code> */ private PropertySheetPage undoablePropertySheetPage = null; /** the editor's action registry */ private ActionRegistry actionRegistry = null; /** * The id of the editor page */ public static final String PAGE_ID = "org.eclipse.jst.jsf.facesconfig.ui.pageflow.PageflowEditor"; //$NON-NLS-1$ /** the list of action ids that are to EditPart actions */ private List editPartActionIDs = new ArrayList(); /** the selection listener */ private ISelectionListener selectionListener = new ISelectionListener() { public void selectionChanged(IWorkbenchPart part, ISelection selection) { updateActions(); } }; /** the selection synchronizer for the edit part viewer */ private SelectionSynchronizer synchronizer = null; /** the shared key handler */ private KeyHandler sharedKeyHandler = null; /** pageflow model manager */ private PageflowModelManager pageflowManager; /** the dirty status of this page */ private boolean isDirty = false; /** the command stack of this page */ private CommandStack commandStack; private FC2PFTransformer modelsTransform; List stackActions = new ArrayList(); /** * @return the faces-config to pageflow model */ public FC2PFTransformer getModelsTransform() { if (modelsTransform == null) { modelsTransform = new FC2PFTransformer(); } return modelsTransform; } /** * update the editor actions */ public void updateActions() { updateActions(stackActions); updateActions(editPartActionIDs); } /** * This class listens for command stack changes of the page and decides if * the editor is dirty or not. * */ private class PageCommandStackListener implements CommandStackEventListener { public void stackChanged(CommandStackEvent event) { if (((CommandStack) event.getSource()).isDirty()) { // at least one command stack is dirty, // so the multi page editor is dirty too setDirty(true); } updateActions(); } } /** * This class listens to changes to the file system in the workspace, and * validate the current pageflow based on web files' status. */ private class ResourceTracker implements IResourceChangeListener, IResourceDeltaVisitor { /* * (non-Javadoc) * * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent) */ public void resourceChanged(IResourceChangeEvent event) { IResourceDelta delta = event.getDelta(); try { if (delta != null) { delta.accept(this); } } catch (CoreException exception) { // Pageflow.PageflowEditor.Error.ResourceChange = Failed in the // resource change. log.error("Pageflow.PageflowEditor.Error.ResourceChange", //$NON-NLS-1$ exception); } } /* * (non-Javadoc) * * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta) */ public boolean visit(IResourceDelta delta) { // if the delta is not a file instance, just return true if (!(delta.getResource() instanceof IFile)) { return true; } // web file is changed. if (WebrootUtil.isValidWebFile(((IFile) delta.getResource()) .getFullPath())) { webPageChanged(((IFile) delta.getResource()).getFullPath()); return false; } return false; } } /** the resource tracker instance */ private ResourceTracker resourceTracker = null; /** * Returns the resource tracker instance * * @return - Returns the resource tracker instance */ private ResourceTracker getResourceTracker() { if (null == resourceTracker) { resourceTracker = new ResourceTracker(); } return resourceTracker; } /** * Changes the dirty state. * * @param dirty - * dirty state */ protected void setDirty(boolean dirty) { if (isDirty != dirty) { isDirty = dirty; } } /** * Updates the specified actions. * * @param actionIds - * the list of ids of actions to update */ protected void updateActions(List actionIds) { for (Iterator ids = actionIds.iterator(); ids.hasNext();) { IAction action = getActionRegistry().getAction(ids.next()); if (null != action && action instanceof UpdateAction) { ((UpdateAction) action).update(); } } } /** * Creates a new PageflowPage instance. * <p> * By design this page uses its own <code>EditDomain</code>. The main * goal of this approach is that this page has its own undo/redo command * stack. * * @param parent - * the parent multi page editor */ public PageflowEditor(IEditorPart parent) { domain = new DefaultEditDomain(parent); domain.setCommandStack(getCommandStack()); this.setEditDomain(domain); parentEditor = parent; } /** * Adds an <code>CommandStack</code> action to this editor. * <p> * <code>CommandStack</code> actions are actions that depend and work on * the <code>CommandStack</code>. * * @param action - * the <code>CommandStack</code> action */ protected void addStackAction(StackAction action) { getActionRegistry().registerAction(action); stackActions.add(action.getId()); } /** * Creates different kinds of actions and registers them to the * ActionRegistry. */ protected void createActions() { // register delete action addEditPartAction(new DeleteAction((IWorkbenchPart) this)); // register undo/redo action addStackAction(new UndoAction(this)); addStackAction(new RedoAction(this)); // Allows opening of JSP files from the pageflow addEditPartAction(new OpenEditorAction(this)); // Allows showing property view for the pageflow SelectionAction action = new ShowPropertyViewAction(this); action .setImageDescriptor(getImageDescriptorForView("org.eclipse.ui.views.PropertySheet")); //$NON-NLS-1$ addEditPartAction(action); // Allows showing property view for the pageflow // addEditPartAction(new ShowPaletteViewAction((IWorkbenchPart) this)); // register alignment actions addEditPartAction(new AlignmentAction((IWorkbenchPart) this, PositionConstants.LEFT)); addEditPartAction(new AlignmentAction((IWorkbenchPart) this, PositionConstants.RIGHT)); addEditPartAction(new AlignmentAction((IWorkbenchPart) this, PositionConstants.TOP)); addEditPartAction(new AlignmentAction((IWorkbenchPart) this, PositionConstants.BOTTOM)); addEditPartAction(new AlignmentAction((IWorkbenchPart) this, PositionConstants.CENTER)); addEditPartAction(new AlignmentAction((IWorkbenchPart) this, PositionConstants.MIDDLE)); // register zoom in/out action IAction zoomIn = new ZoomInAction(getZoomManager(getGraphicalViewer())); IAction zoomOut = new ZoomOutAction( getZoomManager(getGraphicalViewer())); addAction(zoomIn); addAction(zoomOut); // getSite().getKeyBindingService().registerAction(zoomIn); // getSite().getKeyBindingService().registerAction(zoomOut); } /** * Returns the zoom manager of the specified viewer. * * @param viewer_ - * the viewer to get the zoom manager from * @return - the zoom manager */ private ZoomManager getZoomManager(GraphicalViewer viewer_) { // get zoom manager from root edit part RootEditPart rootEditPart = viewer_.getRootEditPart(); ZoomManager zoomManager = null; if (rootEditPart instanceof ScalableFreeformRootEditPart) { zoomManager = ((ScalableFreeformRootEditPart) rootEditPart) .getZoomManager(); } else if (rootEditPart instanceof ScalableRootEditPart) { zoomManager = ((ScalableRootEditPart) rootEditPart) .getZoomManager(); } return zoomManager; } /** * Adds an action to this editor's <code>ActionRegistry</code>. * * @param action - * the action to add. */ protected void addAction(IAction action) { getActionRegistry().registerAction(action); } /** * Adds an <code>EditPart</code> action to this editor. * <p> * <code>EditPart</code> actions are actions that depend and work on the * selected <code>EditPart</code>s. * * @param action - * the <code>EditPart</code> action */ protected void addEditPartAction(SelectionAction action) { getActionRegistry().registerAction(action); editPartActionIDs.add(action.getId()); } /** * Returns the action registry of this editor. * * @return - the action registry */ public ActionRegistry getActionRegistry() { if (null == actionRegistry) { actionRegistry = new ActionRegistry(); } return actionRegistry; } /** * Creates the GraphicalViewer on the specified <code>Composite</code>. * * @param parent - * the parent composite */ public void createGraphicalViewer(Composite parent) { viewer = new ScrollingGraphicalViewer(); viewer.createControl(parent); // configure the viewer viewer.getControl().setBackground(parent.getBackground()); viewer.setRootEditPart(new ConfigurableRootEditPart()); // _viewer.setRootEditPart(new ScalableFreeformRootEditPart()); viewer.setKeyHandler(new GraphicalViewerKeyHandler(viewer)); // hook the viewer into the editor registerEditPartViewer(viewer); // configure the viewer with context menu and template drag and drop configureEditPartViewer(viewer); // initialize the viewer with input viewer.setEditPartFactory(new PageflowEditPartsFactory()); // viewer.setContents(getPageflow()); // support the resource drag&drop viewer .addDropTargetListener((TransferDropTargetListener) new ResourceTransferDropTargetListener( viewer, getParentEditor()) { protected CreationFactory getFactory(Object obj) { return getResourceFactory((IResource) obj); } }); // apply Editor's preferences // propertyChange(null); // add listener to Editor's preferences changing EditorPlugin.getDefault().getPreferenceStore() .addPropertyChangeListener(this); } private CreationFactory getResourceFactory(IResource resource) { return new PageflowResourceFactory(resource); } /* * (non-Javadoc) * * @see ISaveablePart#doSave(org.eclipse.core.runtime.IProgressMonitor) */ public final void doSave(IProgressMonitor monitor) { // our policy: delegate saving to the parent getParentEditor().doSave(monitor); } /* * (non-Javadoc) * * @see ISaveablePart#doSaveAs() */ public final void doSaveAs() { // our policy: delegate saving to the parent getParentEditor().doSaveAs(); } /** * Saves the pageflow under the specified path. * @param file * * @param progressMonitor * @throws CoreException */ public void doSave(IFile file, IProgressMonitor progressMonitor) throws CoreException { if (((FileEditorInput) getEditorInput()).getFile() != file) { // TODO: save to other page. } if (null == progressMonitor) { progressMonitor = new NullProgressMonitor(); } // Pageflow.Label.Saving = Saving progressMonitor.beginTask(PageflowMessages.Pageflow_Label_Saving + " " //$NON-NLS-1$ + file.getFullPath(), 2); if (null == getPageflowManager()) { // Pageflow.PageflowEditor.Alert.nullModelManager = No model manager // found for saving the file. EditorPlugin.getAlerts().throwCoreException( "Pageflow.PageflowEditor.Alert.nullModelManager"); //$NON-NLS-1$ } // save pageflow to file try { //Bug 291054 - faces-config should be checked out if the user tries to modify it IPath pageFlowFilePath = getPageflowFilePath(file); if (pageFlowFilePath != null) { IWorkspace workspace = ResourcesPlugin.getWorkspace(); IFile pageFlowFile = workspace.getRoot().getFile(pageFlowFilePath); if (pageFlowFile != null && pageFlowFile.isReadOnly()) { workspace.validateEdit(new IFile[]{pageFlowFile}, getEditorSite() != null ? getEditorSite().getShell() : null); } } getPageflowManager().save(getPageflowFilePath(file)); progressMonitor.worked(1); file.refreshLocal(IResource.DEPTH_ZERO, new SubProgressMonitor( progressMonitor, 1)); progressMonitor.done(); setDirty(false); } catch (FileNotFoundException e) { // Pageflow.PageflowEditor.Alert.errorSaveFileInfo = The current // pageflow model could not be saved. EditorPlugin.getAlerts().throwCoreException(e); } catch (IOException e) { // Pageflow.PageflowEditor.Alert.errorSaveFileInfo = The current // pageflow model could not be saved. EditorPlugin.getAlerts().throwCoreException(e); } } /* * (non-Javadoc) * * @see IEditorPart#init(org.eclipse.ui.IEditorSite, * org.eclipse.ui.IEditorInput) */ public void init(IEditorSite site, IEditorInput input) throws PartInitException { setSite(site); setInput(input); IFile fileFacesConfig = null; try { fileFacesConfig = ((FileEditorInput) input).getFile(); // load and validate pageflow if (null == createPageflow(getPageflowFilePath(fileFacesConfig))) { // Pageflow.PageflowEditor.Error.invalidPageflowFile = The // specified input is not a valid pageflow. log.error("Pageflow.PageflowEditor.Error.invalidPageflowFile"); //$NON-NLS-1$ throw new PartInitException( EditorPlugin .getResourceString("Pageflow.PageflowEditor.Error.invalidPageflowFile")); //$NON-NLS-1$ } } catch (CoreException e) { // Pageflow.PageflowEditor.Error.invalidPageflowFile = The specified // input is not a valid pageflow. log.error("Pageflow.PageflowEditor.Error.invalidPageflowFile", e); //$NON-NLS-1$ throw new PartInitException(e.getStatus()); } catch (IOException e) { // Pageflow.PageflowEditor.Alert.errorSaveFileInfo = The current // pageflow model could not be saved. log.error("Pageflow.PageflowEditor.Alert.errorSaveFileInfo", e); //$NON-NLS-1$ } // add selection change listener getSite().getWorkbenchWindow().getSelectionService() .addSelectionListener(getSelectionListener()); // Add resource change listener fileFacesConfig.getWorkspace().addResourceChangeListener( getResourceTracker()); } /* * (non-Javadoc) * * @see org.eclipse.ui.IWorkbenchPart#dispose() */ public void dispose() { // remove selection change listener getModelsTransform().dispose(); getSite().getWorkbenchWindow().getSelectionService() .removeSelectionListener(getSelectionListener()); // remove listener to Editor's preferences changing EditorPlugin.getDefault().getPreferenceStore() .removePropertyChangeListener(this); if (getEditorInput() != null) { IFile file = (IFile) getEditorInput().getAdapter(IResource.class); if (file != null) { file.getWorkspace().removeResourceChangeListener( getResourceTracker()); } } super.dispose(); } /** * get the pageflow file path based on faces-config.xml file path * * @return */ private IPath getPageflowFilePath(IFile file) { IPath pageflowFilePath; pageflowFilePath = PageflowModelManager.makePageflowPath(file .getFullPath()); return pageflowFilePath; } /** * Returns the pageflow object from the specified file. * * @param file - * the file resource * @return -the pageflow object from the specified file * @throws IOException */ private Pageflow createPageflow(IPath pathPageflow) throws CoreException, IOException { Pageflow pageflow = null; try { getPageflowManager().load(pathPageflow); } catch (Exception e) { // Pageflow.PageflowEditor.Error.invalidPageflowFile = The specified // input is not a valid pageflow. // _log.error("Pageflow.PageflowEditor.Error.invalidPageflowFile", // e); getPageflowManager().createPageflow(pathPageflow); } IFile fileFacesConfig = ((FileEditorInput) getEditorInput()).getFile(); // it should update related config file if (!fileFacesConfig.getFullPath().toString().trim().equalsIgnoreCase( getPageflowManager().getModel().getConfigfile())) { getPageflowManager().getModel().setConfigfile( fileFacesConfig.getFullPath().toString()); getPageflowManager().save(pathPageflow); } pageflow = getPageflowManager().getModel(); if (null == pageflow) { // Pageflow.PageflowEditor.Error.invalidPageflowModel = The model in // the pageflow file is not a valid pageflow model. log.error("Pageflow.PageflowEditor.Error.invalidPageflowModel"); //$NON-NLS-1$ EditorPlugin.getAlerts().throwCoreException( "Pageflow.PageflowEditor.Error.invalidPageflowModel"); //$NON-NLS-1$ } return pageflow; } /** get the pageflow manager for this page * @return the model manager */ public PageflowModelManager getPageflowManager() { if (pageflowManager == null) { pageflowManager = new PageflowModelManager(); } return pageflowManager; } /* * (non-Javadoc) * * @see ISaveablePart#isDirty() */ public final boolean isDirty() { return isDirty; } /** * Returns the <code>CommandStack</code> of this editor page. * * @return - the <code>CommandStack</code> of this editor page */ public final CommandStack getCommandStack() { if (commandStack == null) { commandStack = new PreExecuteCommandStack(); commandStack .addCommandStackEventListener(new PageCommandStackListener()); } return commandStack; } /** * Returns the default <code>PaletteRoot</code> for this editor and all * its pages. * * @return - the default <code>PaletteRoot</code> */ protected PaletteRoot getPaletteRoot() { if (null == paletteRoot) { // create root paletteRoot = new PageflowPaletteRoot(); } return paletteRoot; } /* * (non-Javadoc) * * @see ISaveablePart#isSaveAsAllowed() */ public final boolean isSaveAsAllowed() { // our policy: delegate saving to the parent return getParentEditor().isSaveAsAllowed(); } /* * (non-Javadoc) * * @see IWorkbenchPart#setFocus() */ public void setFocus() { getGraphicalViewer().getControl().setFocus(); } /** * Returns the multi page pageflow editor this editor page is contained in. * * @return - the parent multi page editor */ protected final IEditorPart getParentEditor() { return parentEditor; } /** * Returns the edit domain this editor page uses. * * @return - the edit domain this editor page uses */ public final DefaultEditDomain getEditDomain() { return domain; } /** * Hooks a <code>EditPartViewer</code> to the rest of the Editor. * <p> * 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. * * @param viewer_ - * the viewer to hook into the editor */ protected void registerEditPartViewer(EditPartViewer viewer_) { // register viewer to edit domain getEditDomain().addViewer(viewer_); // the multi page pageflow editor keeps track of synchronizing getSelectionSynchronizer().addViewer(viewer_); // add viewer as selection provider getSite().setSelectionProvider(viewer_); } /** * Configures the specified <code>EditPartViewer</code> including context * menu, key handler, etc. * * @param viewer_ - * the pageflow graphical viewer. */ protected void configureEditPartViewer(EditPartViewer viewer_) { // configure the shared key handler if (null != viewer_.getKeyHandler()) { viewer_.getKeyHandler().setParent(getSharedKeyHandler()); } // create the ActionRegistry createActions(); // append the parent editor's action registry. ActionRegistry actionRegistry_ = (ActionRegistry) getParentEditor() .getAdapter(ActionRegistry.class); if (actionRegistry_ != null) { for (Iterator iter = actionRegistry_.getActions(); iter.hasNext();) { getActionRegistry().registerAction((IAction) iter.next()); } } // configure and register the context menu ContextMenuProvider provider = new PageflowEditorContextMenuProvider( viewer_, getActionRegistry()); viewer_.setContextMenu(provider); getSite().registerContextMenu( EditorPlugin.getPluginId() + PAGEFLOW_CONTEXTMENU_REG_ID, provider, getSite().getSelectionProvider()); // enable viewer as drop target for template transfers viewer_ .addDropTargetListener((TransferDropTargetListener) new PageflowTemplateTransferDropTargetListener( viewer_)); } /** * Returns the pageflow that is edited. * * @return - the pageflow that is edited */ public Pageflow getPageflow() { return getPageflowManager().getModel(); } /* * (non-Javadoc) * * @see AbstractEditorPage#getGraphicalViewerForZoomSupport() */ public GraphicalViewer getGraphicalViewer() { return viewer; } /** * @param contents */ public void setGraphicalViewerContents(Object contents) { viewer.setContents(contents); propertyChange(null); } /* * (non-Javadoc) * * @see IAdaptable#getAdapter(Class) */ public Object getAdapter(Class type) { if (type == IContentOutlinePage.class) { return getOutlinePage(); } else if (type == CommandStack.class) { return getCommandStack(); } else if (type == ActionRegistry.class) { return getActionRegistry(); } else if (type == IPropertySheetPage.class) { return getPropertySheetPage(); } else if (type == ZoomManager.class) { return getZoomManager(getGraphicalViewer()); } return super.getAdapter(type); } /** * Returns the outline page for the outline view with lazy creation * * @return - the outline page */ protected PageflowEditorOutlinePage getOutlinePage() { PageflowEditorOutlinePage outlinePage = new PageflowEditorOutlinePage( this); outlinePage.initialize(this); return outlinePage; } /** * Returns the undoable <code>PropertySheetPage</code> for this editor. * * @return - the undoable <code>PropertySheetPage</code> */ protected IPropertySheetPage getPropertySheetPage() { if (null == undoablePropertySheetPage) { undoablePropertySheetPage = new PropertySheetPage(); /** set the property source for property sheet page */ undoablePropertySheetPage .setRootEntry(new org.eclipse.gef.ui.properties.UndoablePropertySheetEntry( (CommandStack) getAdapter(CommandStack.class))); } return undoablePropertySheetPage; } /** * 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 (null == synchronizer) { synchronizer = new SelectionSynchronizer(); } return synchronizer; } /** * Returns the shared KeyHandler that should be used for all viewers. * * @return - the shared KeyHandler */ protected KeyHandler getSharedKeyHandler() { if (null == sharedKeyHandler) { sharedKeyHandler = new KeyHandler(); // configure common keys for all viewers sharedKeyHandler .put(KeyStroke.getPressed(SWT.DEL, 127, 0), getActionRegistry().getAction( ActionFactory.DELETE.getId())); sharedKeyHandler.put(KeyStroke.getPressed(SWT.F2, 0), getActionRegistry().getAction( GEFActionConstants.DIRECT_EDIT)); } return sharedKeyHandler; } /** * Returns the selection listener. * * @return - the <code>ISelectionListener</code> */ protected ISelectionListener getSelectionListener() { return selectionListener; } /* * (non-Javadoc) * * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent) */ public void propertyChange(PropertyChangeEvent event) { String property = (event == null) ? null : event.getProperty(); propagateProperty(property, viewer.getRootEditPart()); } /** * propagate property change to children edit part * * @param property - * property's string name * @param part - * parent edit part. */ private void propagateProperty(String property, EditPart part) { processPropertyChange(property, part); if (part instanceof GraphicalEditPart) { // get the connections edit part Iterator iterConns = ((GraphicalEditPart) part) .getSourceConnections().iterator(); while (iterConns.hasNext()) { EditPart child = (EditPart) iterConns.next(); propagateProperty(property, child); } } Iterator iter = part.getChildren().iterator(); while (iter.hasNext()) { EditPart child = (EditPart) iter.next(); propagateProperty(property, child); } } /** * process the property change FIXME: The property change should be category * to improve the performance. * * @param property - * property's string name * @param part */ private void processPropertyChange(String property, EditPart part) { IPreferenceStore store = EditorPlugin.getDefault().getPreferenceStore(); if (property != null && property.equals(GEMPreferences.USE_SYSTEM_COLORS)) { // reload all properties - it's easiest property = null; } if (property == null || GEMPreferences.SNAP_TO_GRID.equals(property)) { boolean bSnapToGrid = store.getBoolean(GEMPreferences.SNAP_TO_GRID); if (part instanceof ILayerPanePreference) { ((ILayerPanePreference) part).setGridVisible(bSnapToGrid); } } if (property == null || GEMPreferences.GRID_WIDTH.equals(property) || GEMPreferences.GRID_HEIGHT.equals(property)) { Dimension gridSpacing = new Dimension(store .getInt(GEMPreferences.GRID_WIDTH), store .getInt(GEMPreferences.GRID_HEIGHT)); if (part instanceof ILayerPanePreference) { ((ILayerPanePreference) part).setGridSpacing(gridSpacing); } } if (property == null || GEMPreferences.GRID_COLOR.equals(property)) { Color gridFgColor = GEMPreferences.getColor(store, GEMPreferences.GRID_COLOR); if (part instanceof ILayerPanePreference) { ((ILayerPanePreference) part) .setGridForegroundColor(gridFgColor); } } if (property == null || GEMPreferences.CANVAS_COLOR.equals(property)) { Color containerBgColor = GEMPreferences.getColor(store, GEMPreferences.CANVAS_COLOR); if (part instanceof IFigurePreference) { ((IFigurePreference) part).setBackgroundColor(containerBgColor); } } if (property == null || GEMPreferences.LINE_WIDTH.equals(property)) { int linkLineWidth = store.getInt(GEMPreferences.LINE_WIDTH); if (part instanceof IConnectionPreference) { ((IConnectionPreference) part).setLineWidth(linkLineWidth); } } if (property == null || GEMPreferences.LINE_COLOR.equals(property)) { Color linkLineColor = GEMPreferences.getColor(store, GEMPreferences.LINE_COLOR); if (part instanceof IConnectionPreference) { ((IConnectionPreference) part) .setForegroundColor(linkLineColor); } } if (property == null || GEMPreferences.SHOW_LINE_LABELS.equals(property)) { boolean bLinkLabelVisible = store .getBoolean(GEMPreferences.SHOW_LINE_LABELS); if (part instanceof IConnectionPreference) { ((IConnectionPreference) part) .setLabelVisible(bLinkLabelVisible); } } if (property == null || GEMPreferences.LINE_LABEL_FONT.equals(property) || GEMPreferences.LINE_LABEL_FONT_COLOR.equals(property)) { Font linkLabelFont = getLinkLabelFont(); Color linkLabelFgColor = GEMPreferences.getColor(store, GEMPreferences.LINE_LABEL_FONT_COLOR); if (part instanceof IConnectionPreference) { ((IConnectionPreference) part).setFont(linkLabelFont); ((IConnectionPreference) part) .setLabelForegroundColor(linkLabelFgColor); } } if (property == null || GEMPreferences.LINE_LABEL_COLOR.equals(property)) { Color linkLabelBgColor = GEMPreferences.getColor(store, GEMPreferences.LINE_LABEL_COLOR); if (part instanceof IConnectionPreference) { ((IConnectionPreference) part) .setLabelBackgroundColor(linkLabelBgColor); } } if (property == null || GEMPreferences.LINE_ROUTING.equals(property)) { String connectionStyle = store .getString(GEMPreferences.LINE_ROUTING); int style; if (GEMPreferences.LINE_ROUTING_MANHATTAN.equals(connectionStyle)) { style = ILayerPanePreference.LINE_ROUTING_MANHATTAN; } else { style = ILayerPanePreference.LINE_ROUTING_MANUAL; } if (part instanceof ILayerPanePreference) { ((ILayerPanePreference) part).setConnectionRouterStyle(style); } else if (part instanceof IConnectionPreference) { ((IConnectionPreference) part).setConnectionRouterStyle(style); } } if (property == null || GEMPreferences.FIGURE_LABEL_FONT.equals(property) || GEMPreferences.FIGURE_LABEL_FONT_COLOR.equals(property)) { Font nodeLabelFont = getNodeLabelFont(); Color nodeLabelFgColor = GEMPreferences.getColor(store, GEMPreferences.FIGURE_LABEL_FONT_COLOR); if (part instanceof INodePreference) { ((INodePreference) part).setFont(nodeLabelFont); ((INodePreference) part).setForegroundColor(nodeLabelFgColor); } } if (property == null || GEMPreferences.LABEL_PLACEMENT.equals(property)) { int placement = PositionConstants.SOUTH; String nodeLabelPlacement = store .getString(GEMPreferences.LABEL_PLACEMENT); if (GEMPreferences.LABEL_PLACEMENT_TOP.equals(nodeLabelPlacement)) placement = PositionConstants.NORTH; else if (GEMPreferences.LABEL_PLACEMENT_BOTTOM .equals(nodeLabelPlacement)) placement = PositionConstants.SOUTH; else if (GEMPreferences.LABEL_PLACEMENT_LEFT .equals(nodeLabelPlacement)) placement = PositionConstants.WEST; else if (GEMPreferences.LABEL_PLACEMENT_RIGHT .equals(nodeLabelPlacement)) placement = PositionConstants.EAST; if (part instanceof INodePreference) ((INodePreference) part).setTextPlacement(placement); } } private Font getLinkLabelFont() { FontRegistry registry = JFaceResources.getFontRegistry(); IPreferenceStore store = EditorPlugin.getDefault().getPreferenceStore(); FontData fontData = PreferenceConverter.getFontData(store, GEMPreferences.LINE_LABEL_FONT); if (!registry.get(fontData.toString()).equals(registry.defaultFont())) return registry.get(fontData.toString()); registry.put(fontData.toString(), new FontData[] {fontData}); return registry.get(fontData.toString()); } private Font getNodeLabelFont() { FontRegistry registry = JFaceResources.getFontRegistry(); IPreferenceStore store = EditorPlugin.getDefault().getPreferenceStore(); FontData fontData = PreferenceConverter.getFontData(store, GEMPreferences.FIGURE_LABEL_FONT); if (!registry.get(fontData.toString()).equals(registry.defaultFont())) return registry.get(fontData.toString()); registry.put(fontData.toString(), new FontData[] {fontData}); return registry.get(fontData.toString()); } /* * (non-Javadoc) * * @see org.eclipse.ui.ide.IGotoMarker#gotoMarker(org.eclipse.core.resources.IMarker) */ public void gotoMarker(IMarker marker) { // The LOCATION attribute in the marker should be the ID string Object id = null; try { id = marker.getAttribute(IMarker.LOCATION); } catch (CoreException e) { // Pageflow.PageflowEditor.Error.invalidMarkerAttribute = Unable to // get marker's attribute log .error( "Pageflow.PageflowEditor.Error.invalidMarkerAttribute", //$NON-NLS-1$ e); } if (id instanceof String) { GraphicalEditPart part = EditPartMarkerUtil.findEditPart( (GraphicalEditPart) getGraphicalViewer().getRootEditPart(), (String) id); if (part != null) { getGraphicalViewer().reveal(part); getGraphicalViewer().select(part); return; } } } /** * the related web page is changed in outside editor, the pageflow should be * revalidated to update the validation icons * * @param fullPath */ public void webPageChanged(IPath fullPath) { PageflowPage page = getPageflowManager().foundPage( WebrootUtil.getWebPath(fullPath)); if (page != null && getGraphicalViewer() != null && getGraphicalViewer().getRootEditPart() != null) { GraphicalEditPart pagePart = EditPartMarkerUtil.findEditPart( (GraphicalEditPart) getGraphicalViewer().getRootEditPart(), page.getId()); PageflowAnnotationUtil .validatePage((PageflowNodeEditPart) pagePart); } } /** * Get the image desriptor from the view's id. * * @param viewid * @return */ private ImageDescriptor getImageDescriptorForView(String viewid) { IConfigurationElement[] elements = Platform.getExtensionRegistry() .getConfigurationElementsFor("org.eclipse.ui.views"); //$NON-NLS-1$ for (int i = 0; i < elements.length; i++) { String name = elements[i].getName(); String id = elements[i].getAttribute("id"); //$NON-NLS-1$ if ("view".equals(name) && viewid.equals(id)) { //$NON-NLS-1$ String iconPath = elements[i].getAttribute("icon"); //$NON-NLS-1$ if (iconPath != null) { return AbstractUIPlugin.imageDescriptorFromPlugin( elements[i].getDeclaringExtension().getContributor().getName(), iconPath); } } } return null; } }