/* * 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.editor; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.action.ActionContributionItem; import org.eclipse.jface.action.ContributionItem; import org.eclipse.jface.action.GroupMarker; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IContributionItem; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.swt.widgets.Menu; import org.eclipse.ui.IActionBars; 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.actions.ActionWrapper; import org.teiid.designer.diagram.ui.actions.AutoLayoutWrapper; import org.teiid.designer.diagram.ui.actions.DiagramActionService; import org.teiid.designer.diagram.ui.actions.DiagramGlobalActionsMap; import org.teiid.designer.diagram.ui.actions.FontDownWrapper; import org.teiid.designer.diagram.ui.actions.FontUpWrapper; import org.teiid.designer.diagram.ui.actions.IDiagramActionConstants; import org.teiid.designer.diagram.ui.actions.ZoomComboActionContributeItem; import org.teiid.designer.diagram.ui.actions.ZoomComboWrapper; import org.teiid.designer.diagram.ui.actions.ZoomInWrapper; import org.teiid.designer.diagram.ui.actions.ZoomOutWrapper; import org.teiid.designer.ui.actions.IModelerActionConstants; import org.teiid.designer.ui.actions.ModelerActionBarIdManager; import org.teiid.designer.ui.common.actions.AbstractAction; import org.teiid.designer.ui.common.actions.ActionService; import org.teiid.designer.ui.common.actions.GlobalActionsMap; import org.teiid.designer.ui.editors.AbstractModelEditorPageActionBarContributor; import org.teiid.designer.ui.editors.ModelEditorPage; /** * @since 8.0 */ public final class DiagramActionContributor extends AbstractModelEditorPageActionBarContributor implements DiagramUiConstants, IDiagramActionConstants { private static final String PREFIX = I18nUtil.getPropertyPrefix(DiagramActionContributor.class); private ActionContributionItem zoomIn; private ActionContributionItem zoomOut; private ActionContributionItem zoomCombo; private ActionContributionItem fontUp; private ActionContributionItem fontDown; private ActionContributionItem autoLayout; private GroupMarker diagramGroupStart; private GroupMarker diagramGroupEnd; // actions map is needed since we want to override the default print action private DiagramGlobalActionsMap actionsMap; // collection of ActionContributionItems and GroupMarkers private List<ContributionItem> contributionItems; // Hashmap of registered actions that can be used to cleanup during dispose method private HashMap<AbstractAction, String> allRegisteredActions = new HashMap<AbstractAction, String>(); private String CONTEXT_MENU_ID = ContextMenu.DIAGRAM_EDITOR_PAGE; // cached to know if this adapter should be deactivated private IDiagramActionAdapter cachedAdapter; private boolean firstTime = true; private boolean contributed = false; private IMenuManager editMenu; private List<IDiagramActionAdapter> contributors = new ArrayList<IDiagramActionAdapter>(); /** * @since 4.0 */ public DiagramActionContributor( final ModelEditorPage page ) { super(page); actionsMap = new DiagramGlobalActionsMap(); actionsMap.reset(); contributionItems = new ArrayList<ContributionItem>(); initActions(); } /** * @see org.teiid.designer.ui.editors.AbstractModelEditorPageActionBarContributor#getGlobalActions() */ @Override public GlobalActionsMap getGlobalActions() { /* * 1. get map from 'adapter' contributors (ex: TransformationActionsAdapter) * 2. merge our map and that map (?) * 3. return it in this method * */ DiagramGlobalActionsMap gamAdapterMap = null; IDiagramActionAdapter diagramActionAdapter = getCurrentDiagramActionAdapter(); if (diagramActionAdapter != null) { gamAdapterMap = (DiagramGlobalActionsMap)diagramActionAdapter.getGlobalActions(); initDiagramGLobalActionDetails(); } if (gamAdapterMap == null) { return actionsMap; } gamAdapterMap = provideMissingActions(gamAdapterMap); return gamAdapterMap; } private DiagramGlobalActionsMap provideMissingActions( DiagramGlobalActionsMap dgaMap ) { /* * any actions that are 'global' to eclipse and also global (occuring once) across all * diagram types must be added here to the current action adapter's global actions map. * 'Print' is the only one currently treated this way. */ actionsMap.put(IModelerActionConstants.EclipseGlobalActions.PRINT, getAction(IModelerActionConstants.EclipseGlobalActions.PRINT)); if (dgaMap.get(IModelerActionConstants.EclipseGlobalActions.PRINT) == null) { IAction actPrint = getAction(IModelerActionConstants.EclipseGlobalActions.PRINT); dgaMap.put(IModelerActionConstants.EclipseGlobalActions.PRINT, actPrint); } return dgaMap; } @Override public void init( IActionBars bars, IWorkbenchPage page ) { super.init(bars, page); } /** * @see org.eclipse.ui.part.EditorActionBarContributor#contributeToMenu(org.eclipse.jface.action.IMenuManager) * @since 5.0 */ @Override public void contributeToMenu( IMenuManager theMenuManager ) { // this menu is called once by the Eclipse framework super.contributeToMenu(theMenuManager); IContributionItem item = theMenuManager.find(ModelerActionBarIdManager.getEditMenuId()); // cache the edit menu so that we can pass it to the adapters if ((item != null) && (item instanceof IMenuManager)) { this.editMenu = (IMenuManager)item; } } /** * Retrieves the requested action from the action service. * * @param theActionId the action identifier * @return the action or <code>null</code> if not found in the service */ private IAction getRegisteredAction( String theActionId ) { IAction result = null; ActionService actionService = getActionService(); /** Key for accessing the global print action. This constant should NOT show up in ALL_ACTIONS. */ String key = DiagramActionService.constructKey(theActionId, getEditorPage()); if (actionService.isRegistered(key)) { try { result = actionService.getAction(key); } catch (CoreException theException) { Util.log(IStatus.ERROR, Util.getString(PREFIX + "actionProblem", new Object[] {theActionId})); //$NON-NLS-1$ } } return result; } /** * Registers the specified action with the action service and wires it to receive selection events. * * @param theAction the action being registered */ private void registerAction( AbstractAction theAction ) { DiagramUiPlugin.registerDiagramActionForSelection(theAction); String actionKey = DiagramActionService.constructKey(theAction, getEditorPage()); getActionService().registerAction(actionKey, theAction); allRegisteredActions.put(theAction, actionKey); } /** * Unregisters the specified action with the action service. * * @param theAction the action being unregistered */ protected void unregisterAction( AbstractAction theAction ) { DiagramUiPlugin.unregisterDiagramActionForSelection(theAction); String actionKey = allRegisteredActions.get(theAction); getActionService().removeAction(actionKey); } /** * @since 4.0 */ private void initActions() { // Each DiagramActionContributor will have their own actions so don't them from the DiagramActionService // create these in order that they willl appear // construct start group marker /** Key for accessing the global print action. This constant should NOT show up in ALL_ACTIONS. */ diagramGroupStart = new GroupMarker(Toolbar.DIAGRAM_START); contributionItems.add(diagramGroupStart); // ----- ZoomInWrapper -----// AbstractAction action = (AbstractAction)getRegisteredAction(ZoomInWrapper.class.getName()); if (action == null) { action = new ZoomInWrapper(); registerAction(action); } zoomIn = createActionContributionItem(action); // ----- ZoomOutWrapper -----// action = (AbstractAction)getRegisteredAction(ZoomOutWrapper.class.getName()); if (action == null) { action = new ZoomOutWrapper(); registerAction(action); } zoomOut = createActionContributionItem(action); // ----- ZoomComboWrapper -----// action = (AbstractAction)getRegisteredAction(ZoomComboWrapper.class.getName()); /** Key for accessing the global print action. This constant should NOT show up in ALL_ACTIONS. */ if (action == null) { action = new ZoomComboWrapper(); registerAction(action); } zoomCombo = new ZoomComboActionContributeItem( action, DiagramUiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getPartService()); contributionItems.add(zoomCombo); // ----- FontUpWrapper -----// action = (AbstractAction)getRegisteredAction(FontUpWrapper.class.getName()); if (action == null) { action = new FontUpWrapper((DiagramEditor)getEditorPage()); registerAction(action); } fontUp = createActionContributionItem(action); // ----- FontDownWrapper -----// action = (AbstractAction)getRegisteredAction(FontDownWrapper.class.getName()); if (action == null) { action = new FontDownWrapper((DiagramEditor)getEditorPage()); registerAction(action); } fontDown = createActionContributionItem(action); // ----- AutoLayoutWrapper -----// action = (AbstractAction)getRegisteredAction(AutoLayoutWrapper.class.getName()); if (action == null) { action = new AutoLayoutWrapper(); registerAction(action); } autoLayout = createActionContributionItem(action); // construct end group marker diagramGroupEnd = new GroupMarker(Toolbar.DIAGRAM_END); contributionItems.add(diagramGroupEnd); // override default action so that Print in the menu and toolbar is the diagram print actionsMap.put(IModelerActionConstants.EclipseGlobalActions.PRINT, getAction(IModelerActionConstants.EclipseGlobalActions.PRINT)); } private IAction getAction( String sActionId ) { try { return getActionService().getAction(sActionId); } catch (CoreException ce) { String message = this.getClass().getName() + ": getAction() error "; //$NON-NLS-1$ DiagramUiConstants.Util.log(IStatus.ERROR, ce, message); } return null; } /** * Creates an <code>ActionContributionItem</code> using the given action. Also hides the item and registers the action in the * service. * * @param theAction the action whose <code>ActionContributionItem</code> is being created * @since 4.0 */ private ActionContributionItem createActionContributionItem( final IAction theAction ) { ActionContributionItem item = new ActionContributionItem(theAction); item.setVisible(false); contributionItems.add(item); return item; } /** * @since 4.0 */ @Override public ActionService getActionService() { return DiagramUiPlugin.getDefault().getActionService(getEditorPage().getSite().getPage()); } /** * @see org.teiid.designer.ui.editors.AbstractModelEditorPageActionBarContributor#createContextMenu() */ @Override public void createContextMenu() { // create menu // jh fix: 2 arg ctor for MenuManager is: MenuManager(text, id) // 1 arg ctor only sets the text, not the id MenuManager mgr = new MenuManager(CONTEXT_MENU_ID, CONTEXT_MENU_ID); mgr.setRemoveAllWhenShown(true); Menu contextMenu = mgr.createContextMenu(getEditorPage().getControl()); getEditorPage().getControl().setMenu(contextMenu); // wire up the listening mgr.addMenuListener(this); } /** * @see org.eclipse.jface.action.IMenuListener#menuAboutToShow(org.eclipse.jface.action.IMenuManager) */ @Override public void menuAboutToShow( IMenuManager theMenuMgr ) { ISelectionProvider selProvider = getEditorPage().getModelObjectSelectionProvider(); boolean override = false; IDiagramActionAdapter diagramActionAdapter = getCurrentDiagramActionAdapter(); if (diagramActionAdapter != null) { override = diagramActionAdapter.shouldOverrideMenu(selProvider.getSelection()); } if (!override) { getActionService().contributeToContextMenu(theMenuMgr, getGlobalActions(), null); } if (diagramActionAdapter != null) { diagramActionAdapter.contributeToMenuManager(theMenuMgr, selProvider.getSelection()); } if (!override) { if (theMenuMgr.find(IModelerActionConstants.ContextMenu.ADDITIONS) == null) { theMenuMgr.add(new Separator(IModelerActionConstants.ContextMenu.ADDITIONS)); } } } private IDiagramActionAdapter getCurrentDiagramActionAdapter() { ModelEditorPage mep = getEditorPage(); IDiagramActionAdapter idapDiagramActionAdapter = (IDiagramActionAdapter)mep.getAdapter(IDiagramActionAdapter.class); return idapDiagramActionAdapter; } private void initDiagramGLobalActionDetails() { if (firstTime) { IAction action = null; for (int i = 0; i < DiagramGlobalActionsMap.ALL_DIAGRAM_GLOBAL_ACTIONS.length; i++) { String actionId = DiagramGlobalActionsMap.ALL_DIAGRAM_GLOBAL_ACTIONS[i]; try { action = getActionService().getAction(actionId); } catch (CoreException ce) { System.out.println("[DiagramActionContributor] actionService.getAction failed"); //$NON-NLS-1$ } if (action instanceof ActionWrapper) { ((ActionWrapper)action).initialize(); } } firstTime = false; } } /** * @See org.teiid.designer.ui.editors.ModelEditorPageActionBarContributor#pageActivated() * @since 4.0 */ @Override public void pageActivated() { /* * 1. show global actions on the toolbar * 2. call pageActivated on the contributor */ IDiagramActionAdapter diagramActionAdapter = getCurrentDiagramActionAdapter(); // deactivate if necessary // deactivate does NOT get called if a new diagram type in the same model is displayed. // for instance, a model's package diagram is displayed and the user double-clicks the same model's // transformation diagram in the model explorer tree. this will display the transformation diagram. // however since the editor page stayed the same deactivate did not get called. so need to do here. if ((diagramActionAdapter != cachedAdapter) && (cachedAdapter != null)) { // deactivate page contributor if (cachedAdapter instanceof AbstractModelEditorPageActionBarContributor) { ((AbstractModelEditorPageActionBarContributor)cachedAdapter).pageDeactivated(); } } // activate current adapter if ((diagramActionAdapter != null) && (diagramActionAdapter instanceof AbstractModelEditorPageActionBarContributor)) { cachedAdapter = diagramActionAdapter; initDiagramGLobalActionDetails(); // have adapter contribute if it hasn't already if (!this.contributors.contains(cachedAdapter)) { this.contributors.add(cachedAdapter); cachedAdapter.contributeExportedActions(this.editMenu); } ((AbstractModelEditorPageActionBarContributor)diagramActionAdapter).pageActivated(); this.editMenu.update(true); } // set the merged actions visible, subject to what the contributor's map says to do contributeToToolBar(actionBars.getToolBarManager()); setActionsVisible(true); getActionBars().updateActionBars(); // Need to tell the zoomCombo to update it's text if (zoomCombo != null) { ((ZoomComboActionContributeItem)zoomCombo).refreshText(); } } /** * @See org.teiid.designer.ui.editors.ModelEditorPageActionBarContributor#pageDeactivated() * @since 4.0 */ @Override public void pageDeactivated() { IDiagramActionAdapter diagramActionAdapter = getCurrentDiagramActionAdapter(); if (diagramActionAdapter != null) { if (diagramActionAdapter instanceof AbstractModelEditorPageActionBarContributor) { ((AbstractModelEditorPageActionBarContributor)diagramActionAdapter).pageDeactivated(); } } // set the merged actions hidden, subject to what the contributor's map says to do setActionsVisible(false); decontributeToToolBar(actionBars.getToolBarManager()); getActionBars().updateActionBars(); } /** * Helper method to show/hide action contributions. * * @param theShowFlag indicates if the actions should be visible or not */ private void setActionsVisible( boolean theShowFlag ) { // includes ActionContributionItems and GroupMarkers for (int size = contributionItems.size(), i = 0; i < size; i++) { ContributionItem item = contributionItems.get(i); item.setVisible(theShowFlag); } if (getActionBars() != null && getActionBars().getToolBarManager() != null) getActionBars().getToolBarManager().update(true); } public void decontributeToToolBar( final IToolBarManager toolBarManager ) { toolBarManager.remove(diagramGroupStart); toolBarManager.remove(zoomIn); toolBarManager.remove(zoomCombo); toolBarManager.remove(zoomOut); toolBarManager.remove(fontUp); toolBarManager.remove(fontDown); toolBarManager.remove(autoLayout); toolBarManager.remove(diagramGroupEnd); contributed = false; } /** * @see org.eclipse.ui.part.EditorActionBarContributor#contributeToToolBar(org.eclipse.jface.action.IToolBarManager) * @since 4.0 */ @Override public void contributeToToolBar( final IToolBarManager toolBarManager ) { if (!contributed) { super.contributeToToolBar(toolBarManager); // add diagram custom actions if (toolBarManager.find(diagramGroupStart.getId()) == null) toolBarManager.add(diagramGroupStart); toolBarManager.appendToGroup(Toolbar.DIAGRAM_START, zoomIn); toolBarManager.appendToGroup(Toolbar.DIAGRAM_START, zoomCombo); toolBarManager.appendToGroup(Toolbar.DIAGRAM_START, zoomOut); toolBarManager.appendToGroup(Toolbar.DIAGRAM_START, fontUp); toolBarManager.appendToGroup(Toolbar.DIAGRAM_START, fontDown); toolBarManager.appendToGroup(Toolbar.DIAGRAM_START, autoLayout); if (toolBarManager.find(diagramGroupEnd.getId()) == null) toolBarManager.add(diagramGroupEnd); contributed = true; } } /** * @see org.eclipse.ui.part.EditorActionBarContributor#dispose() * @since 4.0 */ @Override public void dispose() { for (Iterator<AbstractAction> iter = allRegisteredActions.keySet().iterator(); iter.hasNext();) { AbstractAction theAction = iter.next(); unregisterAction(theAction); } ActionService service = getActionService(); IToolBarManager tbMgr = getActionBars().getToolBarManager(); for (int size = contributionItems.size(), i = 0; i < size; i++) { ContributionItem item = contributionItems.get(i); tbMgr.remove(item); if (item instanceof ActionContributionItem) { service.removeAction(DiagramActionService.constructKey(((ActionContributionItem)item).getAction(), getEditorPage())); } } tbMgr.update(true); } @Override public List<IAction> getAdditionalModelingActions( ISelection theSelection ) { MenuManager menu = new MenuManager("TempMenu", "TempMenuID"); //$NON-NLS-1$ //$NON-NLS-2$ List<IAction> theActions = new ArrayList<IAction>(); contributeExportedActions(menu); IContributionItem[] theItems = menu.getItems(); if (theItems != null && theItems.length > 0) { for (int i = 0; i < theItems.length; i++) { if (theItems[i] instanceof IAction) { theActions.add((IAction) theItems[i]); } else if( theItems[i] instanceof ActionContributionItem ) { theActions.add(((ActionContributionItem) theItems[i]).getAction()); } } } return theActions; } @Override public void contributeExportedActions( IMenuManager theMenuMgr ) { /* * Get the current 'diagram type adapter' and call the same method * on it. Example: TransformationActionAdapter. */ // do not export to our own menu if (CONTEXT_MENU_ID.equals(theMenuMgr.getId())) { return; } IDiagramActionAdapter diagramActionAdapter = getCurrentDiagramActionAdapter(); if (diagramActionAdapter != null) { diagramActionAdapter.contributeExportedActions(theMenuMgr); theMenuMgr.update(); } } public void tellZoomWrappersToClose() { ((ZoomInWrapper)zoomIn.getAction()).closeZoomManager(); ((ZoomOutWrapper)zoomOut.getAction()).closeZoomManager(); } }