blob: 28628c7621df2d40dc780e1d2f6119a3e4da3980 [file] [log] [blame]
package org.eclipse.ui.actions;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import org.eclipse.ui.*;
import org.eclipse.ui.internal.*;
import org.eclipse.ui.internal.dialogs.*;
import org.eclipse.jface.action.*;
import org.eclipse.jface.action.ContributionItem;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.Image;
import java.text.Collator;
import java.util.*;
import java.util.List;
/**
* A menu for perspective selection.
* <p>
* A <code>PerspectiveMenu</code> is used to populate a menu with
* perspective shortcut items. If the user selects one of these items
* an action is performed for the selected perspective.
* </p><p>
* The visible perspective items within the menu are dynamic and reflect the
* available set generated by each subclass. The default available set consists
* of a limited combination of the perspective shortcut list of the current
* perspective, and the most recently used perspective list.
* </p><p>
* This class is abstract. Subclasses must implement the <code>run</code> method,
* which performs a specialized action for the selected perspective.
* </p>
*/
public abstract class PerspectiveMenu extends ContributionItem {
private static final int MAX_PERSPECTIVE_ITEMS = 9;
private static IPerspectiveRegistry reg;
private IWorkbenchWindow window;
private boolean showActive = false;
private boolean dirty = true;
private IMenuListener menuListener = new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
manager.markDirty();
dirty = true;
}
};
private Comparator comparator = new Comparator() {
private Collator collator = Collator.getInstance();
public int compare(Object ob1, Object ob2) {
IPerspectiveDescriptor d1 = (IPerspectiveDescriptor) ob1;
IPerspectiveDescriptor d2 = (IPerspectiveDescriptor) ob2;
return collator.compare(d1.getLabel(), d2.getLabel());
}
};
private static Hashtable imageCache = new Hashtable(11);
/**
* Constructs a new instance of <code>PerspectiveMenu</code>.
*
* @param window the window containing this menu
* @param id the menu id
*/
public PerspectiveMenu(IWorkbenchWindow window, String id) {
super(id);
this.window = window;
if (reg == null)
reg = PlatformUI.getWorkbench().getPerspectiveRegistry();
}
/* (non-Javadoc)
* Creates a menu item for a perspective.
*/
/* package */
void createMenuItem(
Menu menu,
int index,
final IPerspectiveDescriptor desc,
boolean bCheck) {
MenuItem mi = new MenuItem(menu, bCheck ? SWT.RADIO : SWT.PUSH, index);
mi.setText(desc.getLabel());
Image image = getImage(desc);
if (image != null) {
mi.setImage(image);
}
mi.setSelection(bCheck);
mi.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
run(desc, e);
}
});
}
/* (non-Javadoc)
* Creates a menu item for "Other...".
*/
/* package */
void createOtherItem(Menu menu, int index) {
MenuItem mi = new MenuItem(menu, SWT.PUSH, index);
mi.setText(WorkbenchMessages.getString("PerspectiveMenu.otherItem")); //$NON-NLS-1$
mi.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
runOther(e);
}
});
}
/* (non-Javadoc)
* Fills the menu with perspective items.
*/
public void fill(Menu menu, int index) {
if(getParent() instanceof MenuManager)
((MenuManager)getParent()).addMenuListener(menuListener);
if(!dirty)
return;
String checkID = null;
if (showActive) {
IWorkbenchPage activePage = window.getActivePage();
if ((activePage != null) && (activePage.getPerspective() != null))
checkID = activePage.getPerspective().getId();
}
// Collect and sort perspective items.
ArrayList persps = getPerspectiveItems();
Collections.sort(persps, comparator);
// Add perspective shortcut
for (int i = 0; i < persps.size(); i++) {
IPerspectiveDescriptor desc = (IPerspectiveDescriptor) persps.get(i);
createMenuItem(menu, index++, desc, desc.getId().equals(checkID));
}
// Add others item..
if (persps.size() > 0) {
new MenuItem(menu, SWT.SEPARATOR, index++);
}
createOtherItem(menu, index);
dirty = false;
}
/**
* Returns an image to show for the corresponding perspective descriptor.
*
* @param perspDesc the perspective descriptor
* @return the image or null
*/
private Image getImage(IPerspectiveDescriptor perspDesc) {
ImageDescriptor imageDesc = perspDesc.getImageDescriptor();
if (imageDesc == null) {
imageDesc =
WorkbenchImages.getImageDescriptor(
IWorkbenchGraphicConstants.IMG_CTOOL_DEF_PERSPECTIVE_HOVER);
}
if (imageDesc == null) {
return null;
}
Image image = (Image) imageCache.get(imageDesc);
if (image == null) {
image = imageDesc.createImage();
imageCache.put(imageDesc, image);
}
return image;
}
/* (non-Javadoc)
* Returns the perspective shortcut items for the active perspective.
*
* @return a list of <code>IPerspectiveDescriptor</code> items
*/
private ArrayList getPerspectiveShortcuts() {
ArrayList list = new ArrayList();
IWorkbenchPage page = window.getActivePage();
if (page == null)
return list;
ArrayList ids = ((WorkbenchPage) page).getPerspectiveActionIds();
if (ids == null)
return list;
for (int i = 0; i < ids.size(); i++) {
String perspID = (String) ids.get(i);
IPerspectiveDescriptor desc = reg.findPerspectiveWithId(perspID);
if (desc != null && !list.contains(desc))
list.add(desc);
}
return list;
}
/* (non-Javadoc)
* Gets the most recently used (MRU) shortcut perspectives
* (<code>IPerspectiveDescriptor</code> items)
* <p>
* The list is formed from the global perspective history
* in the workbench.
* </p>
* @param dest destination list to contain the items
* @param destStart index in destination list to start copying items at
* @param count number of items to copy from history
* @return the number of items actually copied
*/
private int getPerspectiveMru(List dest, int destStart, int count) {
Workbench wb = (Workbench) WorkbenchPlugin.getDefault().getWorkbench();
return wb.getPerspectiveHistory().copyItems(dest, destStart, count);
}
/**
* Returns the available list of perspectives to display
* in the menu.
* <p>
* By default, the list contains the perspective shortcuts
* for the current perspective, the most recently used
* perspectives, and the default perspective.
* </p><p>
* Subclasses can override this method to return a different list.
* Care should be taken to keep this list to a minimum (7 +/- 2 items
* is a good guideline to follow).
* </p>
*
* @return an <code>ArrayList<code> of perspective items <code>IPerspectiveDescriptor</code>
*/
protected ArrayList getPerspectiveItems() {
/* Allow the user to see all the perspectives they have
* selected via Customize Perspective. Bugzilla bug #23445 */
ArrayList shortcuts = getPerspectiveShortcuts();
int emptySlots = shortcuts.size();
if (emptySlots < MAX_PERSPECTIVE_ITEMS)
emptySlots = MAX_PERSPECTIVE_ITEMS;
ArrayList list = new ArrayList(emptySlots);
// Add default perspective.
String id = reg.getDefaultPerspective();
IPerspectiveDescriptor desc = reg.findPerspectiveWithId(id);
if (desc != null) {
list.add(desc);
emptySlots--;
}
// Add perspective shortcuts from the active perspective
int size = shortcuts.size();
for (int i = 0; i < size && emptySlots > 0; i++) {
if (!list.contains(shortcuts.get(i))) {
list.add(shortcuts.get(i));
emptySlots--;
}
}
// Add perspectives from MRU list
if (emptySlots > 0) {
ArrayList mru = new ArrayList(MAX_PERSPECTIVE_ITEMS);
int count = getPerspectiveMru(mru, 0, MAX_PERSPECTIVE_ITEMS);
for (int i = 0; i < count && emptySlots > 0; i++) {
if (!list.contains(mru.get(i))) {
list.add(mru.get(i));
emptySlots--;
}
}
}
return list;
}
/**
* Returns whether the menu item representing the active perspective
* will have a check mark.
*
* @return <code>true</code> if a check mark is shown, <code>false</code> otherwise
*/
protected boolean getShowActive() {
return showActive;
}
/**
* Returns the window for this menu.
*
* @returns the window
*/
protected IWorkbenchWindow getWindow() {
return window;
}
/* (non-Javadoc)
* Returns whether this menu is dynamic.
*/
public boolean isDirty() {
return dirty;
}
/* (non-Javadoc)
* Returns whether this menu is dynamic.
*/
public boolean isDynamic() {
return true;
}
/**
* Runs an action for a particular perspective. The behavior of the
* action is defined by the subclass.
*
* @param desc the selected perspective
*/
protected abstract void run(IPerspectiveDescriptor desc);
/**
* Runs an action for a particular perspective. The behavior of the
* action is defined by the subclass.
*
* @param desc the selected perspective
* @param event SelectionEvent - the event send along with the selection callback
*/
protected void run(IPerspectiveDescriptor desc, SelectionEvent event) {
//Do a run without the event by default
run(desc);
}
/* (non-Javadoc)
* Show the "other" dialog, select a perspective, and run it. Pass on the selection
* event should the meny need it.
*/
void runOther(SelectionEvent event) {
SelectPerspectiveDialog dlg =
new SelectPerspectiveDialog(window.getShell(), reg);
dlg.open();
if (dlg.getReturnCode() == Window.CANCEL)
return;
IPerspectiveDescriptor desc = dlg.getSelection();
if (desc != null) {
run(desc, event);
}
}
/**
* Sets the showActive flag. If <code>showActive == true</code> then the
* active perspective is hilighted with a check mark.
*
* @param the new showActive flag
*/
protected void showActive(boolean b) {
showActive = b;
}
}