/*******************************************************************************
* Copyright (c) 2011 Wind River Systems, 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:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.tm.te.ui.terminals.tabs;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.jface.action.IMenuListener2;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.tm.internal.terminal.control.ITerminalViewControl;
import org.eclipse.tm.internal.terminal.control.actions.AbstractTerminalAction;
import org.eclipse.tm.internal.terminal.control.actions.TerminalActionClearAll;
import org.eclipse.tm.internal.terminal.control.actions.TerminalActionCopy;
import org.eclipse.tm.internal.terminal.control.actions.TerminalActionPaste;
import org.eclipse.tm.internal.terminal.control.actions.TerminalActionSelectAll;
import org.eclipse.tm.te.ui.terminals.actions.TabScrollLockAction;
import org.eclipse.tm.te.ui.terminals.interfaces.ITerminalsView;
import org.eclipse.ui.IWorkbenchActionConstants;
/**
* Terminals tab folder menu handler.
*/
@SuppressWarnings("restriction")
public class TabFolderMenuHandler extends PlatformObject {
// Reference to the parent terminal console view
private final ITerminalsView parentView;
// Reference to the tab folder context menu manager
private MenuManager contextMenuManager;
// Reference to the tab folder context menu
private Menu contextMenu;
// The list of actions available within the context menu
private final List<AbstractTerminalAction> contextMenuActions = new ArrayList<AbstractTerminalAction>();
/**
* Default menu listener implementation.
*/
protected class MenuListener implements IMenuListener2 {
/* (non-Javadoc)
* @see org.eclipse.jface.action.IMenuListener2#menuAboutToHide(org.eclipse.jface.action.IMenuManager)
*/
@Override
public void menuAboutToHide(IMenuManager manager) {
// CQ:WIND00192293 and CQ:WIND194204 - don't update actions on menuAboutToHide
// See also http://bugs.eclipse.org/296212
// updateMenuItems(false);
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.IMenuListener#menuAboutToShow(org.eclipse.jface.action.IMenuManager)
*/
@Override
public void menuAboutToShow(IMenuManager manager) {
updateMenuItems(true);
}
}
/**
* Constructor.
*
* @param parentView The parent terminal console view. Must not be <code>null</code>.
*/
public TabFolderMenuHandler(ITerminalsView parentView) {
super();
Assert.isNotNull(parentView);
this.parentView = parentView;
}
/**
* Returns the parent terminal console view.
*
* @return The parent terminal console view instance.
*/
protected final ITerminalsView getParentView() {
return parentView;
}
/**
* Returns the tab folder associated with the parent view.
*
* @return The tab folder or <code>null</code>.
*/
protected final CTabFolder getTabFolder() {
return (CTabFolder)getParentView().getAdapter(CTabFolder.class);
}
/**
* Dispose the tab folder menu handler instance.
*/
public void dispose() {
// Dispose the context menu
if (contextMenu != null) { contextMenu.dispose(); contextMenu = null; }
// Dispose the context menu manager
if (contextMenuManager != null) { contextMenuManager.dispose(); contextMenuManager = null; }
// Clear all actions
contextMenuActions.clear();
}
/**
* Setup the context menu for the tab folder. The method will return
* immediately if the menu handler had been initialized before.
*
* @param tabFolder The tab folder control. Must not be <code>null</code>.
*/
public void initialize() {
// Return immediately if the menu manager and menu got initialized already
if (contextMenuManager != null && contextMenu != null) {
return;
}
// Get the tab folder
CTabFolder tabFolder = getTabFolder();
if (tabFolder == null) {
return;
}
// Create the menu manager if not done before
contextMenuManager = new MenuManager("#PopupMenu"); //$NON-NLS-1$
// Create and associated the menu listener
contextMenuManager.addMenuListener(new MenuListener());
// Create the context menu
contextMenu = contextMenuManager.createContextMenu(tabFolder);
// Create the context menu action instances
doCreateContextMenuActions();
// Fill the context menu
doFillContextMenu(contextMenuManager);
// Register to the view site to open the menu for contributions
getParentView().getSite().registerContextMenu(contextMenuManager, getParentView().getSite().getSelectionProvider());
}
/**
* Adds the given action to the context menu actions list.
*
* @param action The action instance. Must be not <code>null</code>.
*/
protected final void add(AbstractTerminalAction action) {
Assert.isNotNull(action);
contextMenuActions.add(action);
}
/**
* Create the context menu actions.
*/
protected void doCreateContextMenuActions() {
// Create and add the copy action
add(new TerminalActionCopy() {
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.control.actions.AbstractTerminalAction#getTarget()
*/
@Override
protected ITerminalViewControl getTarget() {
return getActiveTerminalViewControl();
}
});
// Create and add the paste action
add(new TerminalActionPaste() {
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.control.actions.AbstractTerminalAction#getTarget()
*/
@Override
protected ITerminalViewControl getTarget() {
return getActiveTerminalViewControl();
}
});
// Create and add the clear all action
add(new TerminalActionClearAll() {
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.control.actions.AbstractTerminalAction#getTarget()
*/
@Override
protected ITerminalViewControl getTarget() {
return getActiveTerminalViewControl();
}
});
// Create and add the select all action
add(new TerminalActionSelectAll() {
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.control.actions.AbstractTerminalAction#getTarget()
*/
@Override
protected ITerminalViewControl getTarget() {
return getActiveTerminalViewControl();
}
});
// Create and add the scroll lock action
add (new TabScrollLockAction() {
/* (non-Javadoc)
* @see org.eclipse.tm.internal.terminal.control.actions.AbstractTerminalAction#getTarget()
*/
@Override
protected ITerminalViewControl getTarget() {
return getActiveTerminalViewControl();
}
});
}
/**
* Returns the currently active terminal control.
*
* @return The currently active terminal control or <code>null</code>.
*/
protected ITerminalViewControl getActiveTerminalViewControl() {
ITerminalViewControl terminal = null;
// Get the active tab item from the tab folder manager
TabFolderManager manager = (TabFolderManager)getParentView().getAdapter(TabFolderManager.class);
if (manager != null) {
// If we have the active tab item, we can get the active terminal control
CTabItem activeTabItem = manager.getActiveTabItem();
if (activeTabItem != null) {
terminal = (ITerminalViewControl)activeTabItem.getData();
}
}
return terminal;
}
/**
* Fill in the context menu content within the given manager.
*
* @param manager The menu manager. Must not be <code>null</code>.
*/
protected void doFillContextMenu(MenuManager manager) {
Assert.isNotNull(manager);
// Loop all actions and add them to the menu manager
for (AbstractTerminalAction action : contextMenuActions) {
manager.add(action);
// Add a separator after the paste action
if (action instanceof TerminalActionPaste) {
manager.add(new Separator());
}
// Add a separator after the select all action
if (action instanceof TerminalActionSelectAll) {
manager.add(new Separator());
}
}
// Menu contributions will end up here
manager.add(new Separator());
manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
}
/**
* Update the context menu items on showing or hiding the context menu.
*
* @param aboutToShow <code>True</code> if the menu is about to show, <code>false</code> otherwise.
*/
protected void updateMenuItems(boolean aboutToShow) {
// Loop all actions and update the status
for (AbstractTerminalAction action : contextMenuActions) {
action.updateAction(aboutToShow);
}
}
/* (non-Javadoc)
* @see org.eclipse.ui.part.WorkbenchPart#getAdapter(java.lang.Class)
*/
@Override
public Object getAdapter(Class adapter) {
if (MenuManager.class.isAssignableFrom(adapter)) {
return contextMenuManager;
} else if (Menu.class.isAssignableFrom(adapter)) {
return contextMenu;
}
// Try the parent view
Object adapted = getParentView().getAdapter(adapter);
if (adapted != null) {
return adapted;
}
return super.getAdapter(adapter);
}
}