/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.designer.diagram.ui.actions; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.emf.edit.provider.INotifyChangedListener; import org.eclipse.jface.action.GroupMarker; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.viewers.ISelection; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.IPartListener; import org.eclipse.ui.IWorkbenchPage; import org.teiid.core.designer.util.I18nUtil; import org.teiid.designer.diagram.ui.DiagramUiConstants; import org.teiid.designer.diagram.ui.DiagramUiPlugin; import org.teiid.designer.diagram.ui.editor.DiagramEditor; import org.teiid.designer.ui.UiPlugin; import org.teiid.designer.ui.actions.ModelerActionService; import org.teiid.designer.ui.actions.ModelerGlobalActionsMap; import org.teiid.designer.ui.common.actions.AbstractActionService; import org.teiid.designer.ui.common.actions.GlobalActionsMap; import org.teiid.designer.ui.editors.ModelEditor; import org.teiid.designer.ui.editors.ModelEditorPage; import org.teiid.designer.ui.viewsupport.ModelUtilities; /** * The <code>DiagramActionService</code> class is the Modeler Plugin's action service. It is responsible for managing all actions * for this plugin. * * @since 8.0 */ public final class DiagramActionService extends AbstractActionService implements DiagramUiConstants, IDiagramActionConstants { // ///////////////////////////////////////////////////////////////////////////////////////////// // CONSTANTS // ///////////////////////////////////////////////////////////////////////////////////////////// /** Delimeter used when constructing keys when registering/removing actions from the ActionService. */ private static final char DELIMITER = '|'; // ====================================================== // CONSTANTS // ====================================================== /** The logging prefix. */ private static final String PREFIX = I18nUtil.getPropertyPrefix(DiagramActionService.class); // ====================================================== // FIELDS // ====================================================== /** * Constructs the key that should be used when registering/removing an action in the <code>DiagramActionService</code>. * * @param theAction the action whose key is being requested * @param theEditorPage the editor page where the action is being installed * @return the key */ public static String constructKey( final IAction theAction, final ModelEditorPage theEditorPage ) { return new StringBuffer().append(Extensions.DIAGRAM_EDITOR).append(DELIMITER).append(((IFileEditorInput)theEditorPage.getEditorInput()).getFile().getFullPath()).append(DELIMITER).append(theAction.getId()).toString(); } /** * Constructs the key that should be used when registering/removing an action in the <code>DiagramActionService</code>. * * @param theActionId the actionId to construct the key (class name) * @param theEditorPage the editor page where the action is being installed * @return the key */ public static String constructKey( final String theActionId, final ModelEditorPage theEditorPage ) { return new StringBuffer().append(Extensions.DIAGRAM_EDITOR).append(DELIMITER).append(((IFileEditorInput)theEditorPage.getEditorInput()).getFile().getFullPath()).append(DELIMITER).append(theActionId).toString(); } // Variables // ================================================ // STATIC METHODS // ================================================ /** Map of default global actions. This map actually contains action for each action identifier. */ private DiagramGlobalActionsMap defaultActionsMap; /** The modeler plugin. */ // private AbstractUiPlugin plugin; private boolean bHasBeenInitialized; // ================================================ // CONSTRUCTORS // ================================================ /** * Constructs a <code>DiagramActionService</code> associated with the given <code>IWorkbenchWindow</code>. * * @param theWindow the associated workbench window */ public DiagramActionService( final IWorkbenchPage page ) { super(DiagramUiPlugin.getDefault(), page); // plugin = getPlugin(); // MOVED TO A LATER MOMENT: initializeGlobalActions(); } protected void addNotifyChangedListener( final INotifyChangedListener theListener ) { ModelUtilities.addNotifyChangedListener(theListener); } // ====================================================== // METHODS // ====================================================== /** * @see org.teiid.designer.ui.common.actions.ActionService#contributePermanentActionsToContextMenu(org.eclipse.jface.action.IMenuManager, * org.eclipse.jface.viewers.ISelection) * @since 4.2 */ @Override public void contributePermanentActionsToContextMenu( final IMenuManager theMenuMgr, final ISelection theSelection ) { super.contributePermanentActionsToContextMenu(theMenuMgr, theSelection); } /** * Fills the given menu with the standard items appropriate for a context menu of a part in the Modeler. * * @param theMenuMgr the menu being contributed to (should be a context menu) * @param theActionsMap the map of global action handlers * @param theSelection the selection used to determine how to build the new child and new sibling menus */ @Override public void contributeToContextMenu( final IMenuManager theMenuMgr, final GlobalActionsMap theActionsMap, final ISelection theSelection ) { // System.out.println("[DiagramActionService.contributeToContextMenu] top "); //$NON-NLS-1$ final DiagramEditor deDiagramEditor = getDiagramEditor(); ISelection selection = null; if (deDiagramEditor != null) { // establish the selection if (theSelection == null) selection = deDiagramEditor.getModelObjectSelectionProvider().getSelection(); else selection = theSelection; // if ( selection == null ) { // System.out.println("[DiagramActionService.contributeToContextMenu] selection is still NULL "); //$NON-NLS-1$ // } // init globals if (!bHasBeenInitialized) { bHasBeenInitialized = true; initializeGlobalActions(); } // get ModelerActionService's contribution getModelerActionService().contributeToContextMenu(theMenuMgr, theActionsMap, selection); /* * add 'diagram global' actions here * GlobalActionsMap actionsMap = (theActionsMap == null) ? new ModelerGlobalActionsMap() : theActionsMap; * */ // theMenuMgr.add( getAction( DiagramGlobalActions.ZOOM_IN, defaultActionsMap) ); // theMenuMgr.add( getAction( DiagramGlobalActions.ZOOM_OUT, defaultActionsMap) ); // theMenuMgr.add( getAction( DiagramGlobalActions.FONT_UP, defaultActionsMap) ); // theMenuMgr.add( getAction( DiagramGlobalActions.FONT_DOWN, defaultActionsMap) ); // theMenuMgr.add( getAction( DiagramGlobalActions.AUTOLAYOUT, defaultActionsMap) ); // add the notation submenu final MenuManager smNotationSubmenu = deDiagramEditor.getNotationActionGroup(); if (smNotationSubmenu != null && !smNotationSubmenu.isEmpty()) { theMenuMgr.add(new GroupMarker(ContextMenu.NOTATION_START)); theMenuMgr.insertAfter(ContextMenu.NOTATION_START, smNotationSubmenu); theMenuMgr.add(new GroupMarker(ContextMenu.NOTATION_END)); } } // will ModelerActionService already have done this???: // jhTODO: resolve the issue of how 'contributeExportedActions' is supposed to work. // // jh try commenting this out to prevent duplicates: // if (deDiagramEditor instanceof IEditorActionExporter) { // ((IEditorActionExporter)deDiagramEditor).contributeExportedActions(theMenuMgr); // } } /* (non-Javadoc) * see org.teiid.designer.ui.common.actions.AbstractActionService#getAction(String) */ @Override public IAction getAction( final String theActionId ) throws CoreException { // System.out.println("[DiagramActionService.getAction] looking up: " + theActionId ); //$NON-NLS-1$ if (!bHasBeenInitialized) { bHasBeenInitialized = true; initializeGlobalActions(); } final IAction action = defaultActionsMap.getAction(theActionId); if (action != null) // System.out.println("[DiagramActionService.getAction] returning action from our default map: " + // action ); return action; // registering actions to receive events is done by the getAction(Class) method return super.getAction(getActionId(theActionId)); } /** * If the key represents an Eclipse global action a second lookup is needed to get the actual action class name which is needed * by the action service to construct the action. For non-Eclipse global action, the key is already the action class name. * * @param theKey the action identifier whose "real" action identifier is being requested * @return the action identifier used by the action service */ private String getActionId( final String theKey ) { // System.out.println("[DiagramActionService.getActionId]"); //$NON-NLS-1$ String result = theKey; if (getModelerActionService().getActionId(theKey) != null) result = getModelerActionService().getActionId(theKey); return result; } private IEditorPart getActiveEditor() { final IWorkbenchPage activePage = getPlugin().getCurrentWorkbenchWindow().getActivePage(); IEditorPart editor; if (activePage != null) editor = activePage.getActiveEditor(); else editor = getPage().getActiveEditor(); if (editor instanceof ModelEditor) return editor; return null; } /* (non-Javadoc) * see org.teiid.designer.ui.common.actions.AbstractActionService#getDefaultAction(java.lang.String) */ @Override public IAction getDefaultAction( final String theActionId ) { //System.out.println("[DiagramActionService.getDefaultAction]"); //$NON-NLS-1$ try { // get the action from the ModelerActionService return UiPlugin.getDefault().getActionService(getWorkbenchWindow().getActivePage()).getAction(theActionId); } catch (final CoreException ce) { // complete this! } return null; } private DiagramEditor getDiagramEditor() { final IEditorPart editor = getActiveEditor(); final ModelEditor meEditor = ((ModelEditor)editor); if (meEditor.getCurrentPage() instanceof DiagramEditor) return (DiagramEditor)meEditor.getCurrentPage(); return null; } public ModelerActionService getModelerActionService() { // System.out.println("[DiagramActionService.getModelerActionService]"); //$NON-NLS-1$ return (ModelerActionService)UiPlugin.getDefault().getActionService(getPage()); } /** * Initializes the <code>Map</code> of all global actions. */ private void initializeGlobalActions() { // System.out.println("[DiagramActionService.initializeGlobalActions]"); //$NON-NLS-1$ // need to put the real actions into the map as the new constructed map only // contains identifiers which stand for "use default" action IAction action = null; defaultActionsMap = new DiagramGlobalActionsMap(); // load all default global actions since the map doesn't really have the default actions // as values. it just has a marker. for (final String actionId : DiagramGlobalActionsMap.ALL_DIAGRAM_GLOBAL_ACTIONS) { try { // the call to getAction(String) throws a CoreException if the action cannot be constructed. // also the call to getAction(String) registers the action to receive appropriate events. // if the action is registered in the modeler action service use it. if not there then it is // not a modeler global action and must be a diagram specific action /* * jh note: this seems backwards; it will always use the ModelerActionService action, * if present, and ignore the 'diagram' one that should be overriding it... */ // if (getModelerActionService().isRegistered(actionId)) { // action = getModelerActionService().getAction(actionId); // } else { // action = getAction(actionId); // } // rewrite: // System.out.println("[DiagramActionService.initializeGlobalActions] about to process actionId: " + actionId ); //$NON-NLS-1$ // get Eclipse and Modeler global actions from the ModelerActionService so that // only one instance is constructed. if (GlobalActionsMap.isEclipseGlobalAction(actionId) || ModelerGlobalActionsMap.isModelerGlobalAction(actionId)) action = getModelerActionService().getAction(actionId); else // must be a diagram global action action = getAction(actionId); defaultActionsMap.put(actionId, action); } catch (final CoreException e) { final String message = DiagramUiConstants.Util.getString(PREFIX + "actionErrorMessage", actionId); //$NON-NLS-1$ DiagramUiConstants.Util.log(IStatus.ERROR, e, message); } } // System.out.println("[DiagramActionService.initializeGlobalActions] final defaultActionsMap: " + defaultActionsMap ); //$NON-NLS-1$ // get global actions installed in edit menu // OBSOLETE???contributeToEditMenu(); } /* (non-Javadoc) * see org.teiid.designer.ui.common.actions.AbstractActionService#isRegistered(java.lang.String) */ @Override public boolean isRegistered( final String theActionId ) { if (!bHasBeenInitialized) { bHasBeenInitialized = true; initializeGlobalActions(); } return super.isRegistered(theActionId); } /* (non-Javadoc) * see org.teiid.designer.ui.common.actions.AbstractActionService#registerEventHandler(org.eclipse.jface.action.IAction) */ @Override protected void registerEventHandler( final IAction theAction ) { // System.out.println("[DiagramActionService.registerEventHandler] defId: " + theAction.getActionDefinitionId() ); //$NON-NLS-1$ // first let super register super.registerEventHandler(theAction); // EObject notifier events if (theAction instanceof INotifyChangedListener) addNotifyChangedListener((INotifyChangedListener)theAction); } /** * Removes the given listener from receiving workspace container {@link org.eclipse.emf.common.notify.Notification}s. This is a * pass-through helper method to the {@link org.teiid.designer.ui.viewsupport.ModelUtilities} method. * * @param listener the listener being removed */ public void removeNotifyChangedListener( final INotifyChangedListener theListener ) { ModelUtilities.removeNotifyChangedListener(theListener); } @Override public void removePartListener( final IPartListener theListener ) { super.removePartListener(theListener); } /* (non-Javadoc) * see org.teiid.designer.ui.common.actions.AbstractActionService#unregisterEventHandler(org.eclipse.jface.action.IAction) */ @Override protected void unregisterEventHandler( final IAction theAction ) { // first let super unregister super.unregisterEventHandler(theAction); // unregister EObject notifier events if (theAction instanceof INotifyChangedListener) removeNotifyChangedListener((INotifyChangedListener)theAction); if (theAction instanceof IPartListener) removePartListener((IPartListener)theAction); } }