All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.ui.internal.PerspectiveSwitcher Maven / Gradle / Ivy

Go to download

This plug-in contains the bulk of the Workbench implementation, and depends on JFace, SWT, and Core Runtime. It cannot be used independently from org.eclipse.ui. Workbench client plug-ins should not depend directly on this plug-in.

The newest version!
/*******************************************************************************
 * Copyright (c) 2004, 2007 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *     Chris Grindstaff  - Fix for bug 158016     
 *******************************************************************************/
package org.eclipse.ui.internal;

import java.util.Arrays;
import java.util.StringTokenizer;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CBanner;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.CoolBar;
import org.eclipse.swt.widgets.CoolItem;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IPageListener;
import org.eclipse.ui.IPerspectiveDescriptor;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPreferenceConstants;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PerspectiveAdapter;
import org.eclipse.ui.internal.StartupThreading.StartupRunnable;
import org.eclipse.ui.internal.dnd.AbstractDropTarget;
import org.eclipse.ui.internal.dnd.DragUtil;
import org.eclipse.ui.internal.dnd.IDragOverListener;
import org.eclipse.ui.internal.dnd.IDropTarget;
import org.eclipse.ui.internal.layout.CacheWrapper;
import org.eclipse.ui.internal.layout.CellLayout;
import org.eclipse.ui.internal.layout.ITrimManager;
import org.eclipse.ui.internal.layout.IWindowTrim;
import org.eclipse.ui.internal.layout.LayoutUtil;
import org.eclipse.ui.internal.layout.Row;
import org.eclipse.ui.internal.util.PrefUtil;
import org.eclipse.ui.presentations.PresentationUtil;

/**
 * A utility class to manage the perspective switcher.  At some point, it might be nice to
 * move all this into PerspectiveViewBar.
 * 
 * @since 3.0
 */
public class PerspectiveSwitcher implements IWindowTrim {

	/**
	 * The minimal width for the switcher (i.e. for the open button and chevron).
	 */
	private static final int MIN_WIDTH = 45;
	
	/**
	 * The average width for each perspective button.
	 */
	private static final int ITEM_WIDTH = 80;
	
	/**
	 * The minimum default width.
	 */
	private static final int MIN_DEFAULT_WIDTH = 160;
	
	private IWorkbenchWindow window;

    private CBanner topBar;

    private int style;

    private Composite parent;

    private Composite trimControl;

    private Label trimSeparator;

    private GridData trimLayoutData;

    private boolean trimVisible = false;

    private int trimOldLength = 0;

    private PerspectiveBarManager perspectiveBar;

    private CoolBar perspectiveCoolBar;

    private CacheWrapper perspectiveCoolBarWrapper;

    private CoolItem coolItem;

    private CacheWrapper toolbarWrapper;

    // The menus are cached, so the radio buttons should not be disposed until
    // the switcher is disposed.
    private Menu popupMenu;

    private Menu genericMenu;

    private static final int INITIAL = -1;

    private static final int TOP_RIGHT = 1;

    private static final int TOP_LEFT = 2;

    private static final int LEFT = 3;

    private int currentLocation = INITIAL;

    private IPreferenceStore apiPreferenceStore = PrefUtil
            .getAPIPreferenceStore();

    private IPropertyChangeListener propertyChangeListener;

    private Listener popupListener = new Listener() {
        public void handleEvent(Event event) {
            if (event.type == SWT.MenuDetect) {
                showPerspectiveBarPopup(new Point(event.x, event.y));
            }
        }
    };

    class ChangeListener extends PerspectiveAdapter implements IPageListener {
        public void perspectiveOpened(IWorkbenchPage page,
                IPerspectiveDescriptor perspective) {
        	if (findPerspectiveShortcut(perspective, page) == null) {
				addPerspectiveShortcut(perspective, page);
			}
        }
        public void perspectiveClosed(IWorkbenchPage page,
                IPerspectiveDescriptor perspective) {
        	// Don't remove the shortcut if the workbench is
        	// closing. This causes a spurious 'layout' on the
        	// shell during close, leading to possible life-cycle issues
        	if (page != null && !page.getWorkbenchWindow().getWorkbench().isClosing()) {
        		removePerspectiveShortcut(perspective, page);
        	}
        }
        public void perspectiveActivated(IWorkbenchPage page, IPerspectiveDescriptor perspective) {
            selectPerspectiveShortcut(perspective, page, true);
        }
        public void perspectiveDeactivated(IWorkbenchPage page, IPerspectiveDescriptor perspective) {
            selectPerspectiveShortcut(perspective, page, false);
        }
        public void perspectiveSavedAs(IWorkbenchPage page,
                IPerspectiveDescriptor oldPerspective,
                IPerspectiveDescriptor newPerspective) {
            updatePerspectiveShortcut(oldPerspective, newPerspective, page);
        }
		public void pageActivated(IWorkbenchPage page) {
		}

		public void pageClosed(IWorkbenchPage page) {
		}

		public void pageOpened(IWorkbenchPage page) {
		}
    }
    
    private ChangeListener changeListener = new ChangeListener();
    
	private Listener dragListener;

	private IDragOverListener dragTarget;

	private DisposeListener toolBarListener;

	private IReorderListener reorderListener;

	/**
     * Creates an instance of the perspective switcher.
	 * @param window  it's window
	 * @param topBar  the CBanner to place this widget in
	 * @param style   the widget style to use
	 */
	public PerspectiveSwitcher(IWorkbenchWindow window, CBanner topBar, int style) {
		this.window = window;
		this.topBar = topBar;
		this.style = style;
		setPropertyChangeListener();
		// this listener will only be run when the Shell is being disposed
		// and each WorkbenchWindow has its own PerspectiveSwitcher
		toolBarListener = new DisposeListener() {
			public void widgetDisposed(DisposeEvent e) {
				dispose();
			}
		};
        window.addPerspectiveListener(changeListener);
        window.addPageListener(changeListener);
	}

	private static int convertLocation(String preference) {
		if (IWorkbenchPreferenceConstants.TOP_RIGHT.equals(preference)) {
			return TOP_RIGHT;
		}
		if (IWorkbenchPreferenceConstants.TOP_LEFT.equals(preference)) {
			return TOP_LEFT;
		}
		if (IWorkbenchPreferenceConstants.LEFT.equals(preference)) {
			return LEFT;
		}

		return TOP_RIGHT;
	}

	/**
     * Create the contents of the receiver
	 * @param parent
	 */
	public void createControl(Composite parent) {
		Assert.isTrue(this.parent == null);
		this.parent = parent;
		// set the initial location read from the preference
		setPerspectiveBarLocation(PrefUtil.getAPIPreferenceStore().getString(
				IWorkbenchPreferenceConstants.DOCK_PERSPECTIVE_BAR));
	}

	private void addPerspectiveShortcut(IPerspectiveDescriptor perspective,
			IWorkbenchPage workbenchPage) {
		if (perspectiveBar == null) {
			return;
		}

		PerspectiveBarContributionItem item = new PerspectiveBarContributionItem(
				perspective, workbenchPage);
		perspectiveBar.addItem(item);
		setCoolItemSize(coolItem);
		// This is need to update the vertical size of the tool bar on GTK+ when
		// using large fonts.
		if (perspectiveBar != null) {
			perspectiveBar.update(true);
		}
	}

	/**
     * Find a contribution item that matches the perspective provided.
     * 
	 * @param perspective
	 * @param page
	 * @return the IContributionItem or null if no matches were found
	 */
	public IContributionItem findPerspectiveShortcut(
			IPerspectiveDescriptor perspective, IWorkbenchPage page) {
		if (perspectiveBar == null) {
			return null;
		}

		IContributionItem[] items = perspectiveBar.getItems();
		int length = items.length;
		for (int i = 0; i < length; i++) {
			IContributionItem item = items[i];
			if (item instanceof PerspectiveBarContributionItem
					&& ((PerspectiveBarContributionItem) item).handles(
							perspective, page)) {
				return item;
			}
		}
		return null;
	}

	private void removePerspectiveShortcut(IPerspectiveDescriptor perspective,
			IWorkbenchPage page) {
		if (perspectiveBar == null) {
			return;
		}

		IContributionItem item = findPerspectiveShortcut(perspective, page);
		if (item != null) {
			if (item instanceof PerspectiveBarContributionItem) {
				perspectiveBar
						.removeItem((PerspectiveBarContributionItem) item);
			}
			item.dispose();
			perspectiveBar.update(false);
			setCoolItemSize(coolItem);
		}
	}

	/**
     * Locate the perspective bar according to the provided location
	 * @param preference the location to put the perspective bar at
	 */
	public void setPerspectiveBarLocation(String preference) {
		// return if the control has not been created. createControl(...) will
		// handle updating the state in that case
		if (parent == null) {
			return;
		}
		int newLocation = convertLocation(preference);
		if (newLocation == currentLocation) {
			return;
		}
		createControlForLocation(newLocation);
		currentLocation = newLocation;
		showPerspectiveBar();
		if (newLocation == TOP_LEFT || newLocation == TOP_RIGHT) {
			updatePerspectiveBar();
			updateBarParent();
		}
	}

	/**
	 * Make the perspective bar visible in its current location. This method
	 * should not be used unless the control has been successfully created.
	 */
	private void showPerspectiveBar() {
		switch (currentLocation) {
		case TOP_LEFT:
			topBar.setRight(null);
			topBar.setBottom(perspectiveCoolBarWrapper.getControl());
			break;
		case TOP_RIGHT:
			topBar.setBottom(null);
			topBar.setRight(perspectiveCoolBarWrapper.getControl());
			topBar.setRightWidth(getDefaultWidth());
			break;
		case LEFT:
			topBar.setBottom(null);
			topBar.setRight(null);
			LayoutUtil.resize(topBar);
			getTrimManager().addTrim(SWT.LEFT, this);
			break;
		default:
			return;
		}

		LayoutUtil.resize(perspectiveBar.getControl());
	}

	/**
	 * Returns the default width for the switcher.
	 */
	private int getDefaultWidth() {
        String extras = PrefUtil.getAPIPreferenceStore().getString(
				IWorkbenchPreferenceConstants.PERSPECTIVE_BAR_EXTRAS);
        StringTokenizer tok = new StringTokenizer(extras, ", "); //$NON-NLS-1$
        int numExtras = tok.countTokens();
        int numPersps = Math.max(numExtras, 1); // assume initial perspective is also listed in extras
		return Math.max(MIN_DEFAULT_WIDTH, MIN_WIDTH + (numPersps*ITEM_WIDTH));
	}

	/**
	 * Get the trim manager from the default workbench window. If the current
	 * workbench window is -not- the WorkbenchWindow then return null.
	 *  
	 * @return The trim manager for the current workbench window
	 */
	private ITrimManager getTrimManager() {
		if (window instanceof WorkbenchWindow)
			return ((WorkbenchWindow)window).getTrimManager();
		
		return null; // not using the default workbench window
	}

	/**
     * Update the receiver
	 * @param force
	 */
	public void update(boolean force) {
		if (perspectiveBar == null) {
			return;
		}

		perspectiveBar.update(force);

		if (currentLocation == LEFT) {
			ToolItem[] items = perspectiveBar.getControl().getItems();
			boolean shouldExpand = items.length > 0;
			if (shouldExpand != trimVisible) {
				perspectiveBar.getControl().setVisible(true);
				trimVisible = shouldExpand;
			}

			if (items.length != trimOldLength) {
				LayoutUtil.resize(trimControl);
				trimOldLength = items.length;
			}
		}
	}

	private void selectPerspectiveShortcut(IPerspectiveDescriptor perspective,
			IWorkbenchPage page, boolean selected) {
		IContributionItem item = findPerspectiveShortcut(perspective, page);
		if (item != null && (item instanceof PerspectiveBarContributionItem)) {
			if (selected) {
				// check if not visible and ensure visible
				PerspectiveBarContributionItem contribItem = (PerspectiveBarContributionItem) item;
				perspectiveBar.select(contribItem);
			}
			// select or de-select
			((PerspectiveBarContributionItem) item).setSelection(selected);
		}
	}

	private void updatePerspectiveShortcut(IPerspectiveDescriptor oldDesc,
			IPerspectiveDescriptor newDesc, IWorkbenchPage page) {
		IContributionItem item = findPerspectiveShortcut(oldDesc, page);
		if (item != null && (item instanceof PerspectiveBarContributionItem)) {
			((PerspectiveBarContributionItem) item).update(newDesc);
		}
	}

	/**
     * Answer the perspective bar manager
	 * @return the manager
	 */
	public PerspectiveBarManager getPerspectiveBar() {
		return perspectiveBar;
	}

	/**
	 * Dispose resources being held by the receiver
	 */
	public void dispose() {
        window.removePerspectiveListener(changeListener);
        window.removePageListener(changeListener);
		if (propertyChangeListener != null) {
			apiPreferenceStore
					.removePropertyChangeListener(propertyChangeListener);
			propertyChangeListener = null;
		}
		unhookDragSupport();
		disposeChildControls();
		toolBarListener = null;
	}

	private void disposeChildControls() {

		if (trimControl != null) {
			trimControl.dispose();
			trimControl = null;
		}

		if (trimSeparator != null) {
			trimSeparator.dispose();
			trimSeparator = null;
		}

		if (perspectiveCoolBar != null) {
			perspectiveCoolBar.dispose();
			perspectiveCoolBar = null;
		}

		if (toolbarWrapper != null) {
			toolbarWrapper.dispose();
			toolbarWrapper = null;
		}

		if (perspectiveBar != null) {
			perspectiveBar.dispose();
			perspectiveBar = null;
		}

		perspectiveCoolBarWrapper = null;
	}

	/**
	 * Ensures the control has been set for the argument location. If the
	 * control already exists and can be used the argument location, nothing
	 * happens. Updates the location attribute.
	 * 
	 * @param newLocation
	 */
	private void createControlForLocation(int newLocation) {
		// if there is a control, then perhaps it can be reused
		if (perspectiveBar != null && perspectiveBar.getControl() != null
				&& !perspectiveBar.getControl().isDisposed()) {
			if (newLocation == LEFT && currentLocation == LEFT) {
				return;
			}
			if ((newLocation == TOP_LEFT || newLocation == TOP_RIGHT)
					&& (currentLocation == TOP_LEFT || currentLocation == TOP_RIGHT)) {
				return;
			}
		}

		if (perspectiveBar != null) {
			perspectiveBar.getControl().removeDisposeListener(toolBarListener);
			unhookDragSupport();
		}
		// otherwise dispose the current controls and make new ones
		
		// First, make sure that the existing verion is removed from the trim layout
		getTrimManager().removeTrim(this);

		disposeChildControls();
		if (newLocation == LEFT) {
			createControlForLeft();
		} else {
			createControlForTop();
		}
		hookDragSupport();

		perspectiveBar.getControl().addDisposeListener(toolBarListener);
	}

	/**
	 * Remove any drag and drop support and associated listeners hooked for the
	 * perspective switcher.
	 */
	private void unhookDragSupport() {
		ToolBar bar = perspectiveBar.getControl();

		if (bar == null || bar.isDisposed() || dragListener == null) {
			return;
		}
		PresentationUtil.removeDragListener(bar, dragListener);
		DragUtil.removeDragTarget(perspectiveBar.getControl(), dragTarget);
		dragListener = null;
		dragTarget = null;
	}

    /**
	 * Attach drag and drop support and associated listeners hooked for 
	 * the perspective switcher.
	 */
	 private void hookDragSupport() {
        dragListener = new Listener() {
        	/* (non-Javadoc)
			 * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
			 */
			public void handleEvent(Event event) {
				ToolBar toolbar = perspectiveBar.getControl();
                ToolItem item = toolbar.getItem(new Point(event.x, event.y));
                
                if (item != null) {
                	//ignore the first item, which remains in position Zero
                    if (item.getData() instanceof PerspectiveBarNewContributionItem) {
						return;
					}
                    
                	Rectangle bounds = item.getBounds();
                	Rectangle parentBounds = toolbar.getBounds();
                	bounds.x += parentBounds.x;
                	bounds.y += parentBounds.y;
                	startDragging(item.getData(), toolbar.getDisplay().map(toolbar, null, bounds));
                } else { 
                    //startDragging(toolbar, toolbar.getDisplay().map(toolbar, null, toolbar.getBounds()));
                }
            }
			
			private void startDragging(Object widget, Rectangle bounds) {
				if(!DragUtil.performDrag(widget, bounds, new Point(bounds.x, bounds.y), true)) {
				       //currently do nothing on a failed drag 
                }
		    }
        };

		dragTarget = new IDragOverListener() {
			protected PerspectiveDropTarget perspectiveDropTarget;

			class PerspectiveDropTarget extends AbstractDropTarget {

				private PerspectiveBarContributionItem perspective;

				private Point location;

                /**
				 * @param location
				 * @param draggedObject
				 */
				public PerspectiveDropTarget(Object draggedObject,
						Point location) {
					update(draggedObject, location);
				}

				/**
				 * 
				 * @param draggedObject
				 * @param location
				 */
				private void update(Object draggedObject, Point location) {
					this.location = location;
					this.perspective = (PerspectiveBarContributionItem) draggedObject;
				}

				/*
				 * (non-Javadoc)
				 * 
				 * @see org.eclipse.ui.internal.dnd.IDropTarget#drop()
				 */
				public void drop() {
					ToolBar toolBar = perspectiveBar.getControl();
					ToolItem item = toolBar.getItem(toolBar.getDisplay().map(
							null, toolBar, location));
					if (toolBar.getItem(0) == item) {
						return;
					}
					ToolItem[] items = toolBar.getItems();
					ToolItem droppedItem = null;
					int dropIndex = -1;
					for (int i = 0; i < items.length; i++) {
						if (item == items[i]) {
							dropIndex = i;
						}
						if (items[i].getData() == perspective) {
							droppedItem = items[i];
						}
					}
					if (dropIndex != -1 && droppedItem != null && (droppedItem != item)) {
						PerspectiveBarContributionItem barItem = (PerspectiveBarContributionItem) droppedItem.getData();
						// policy is to insert at the beginning so mirror the value when indicating a 
						// new position for the perspective
						if (reorderListener != null) {
							reorderListener.reorder(barItem.getPerspective(), Math.abs(dropIndex - (items.length - 1)));
						}

						perspectiveBar.relocate(barItem, dropIndex);
					}
				}

				/*
				 * (non-Javadoc)
				 * 
				 * @see org.eclipse.ui.internal.dnd.IDropTarget#getCursor()
				 */
				public Cursor getCursor() {
					return DragCursors.getCursor(DragCursors.CENTER);
				}

				boolean sameShell() {
					return perspective.getToolItem().getParent().getShell().equals(perspectiveBar.getControl().getShell());
				}
				
				public Rectangle getSnapRectangle() {
					ToolBar toolBar = perspectiveBar.getControl();
					ToolItem item = toolBar.getItem(toolBar.getDisplay().map(
							null, toolBar, location));
					Rectangle bounds;
					if (item != null && item != toolBar.getItem(0)) {
						bounds = item.getBounds();
					} else {
						// it should not be possible to start a drag with item 0
						return null;
					}
					return toolBar.getDisplay().map(toolBar, null, bounds);
				}
			}

			public IDropTarget drag(Control currentControl,
					Object draggedObject, Point position,
					Rectangle dragRectangle) {
				if (draggedObject instanceof PerspectiveBarContributionItem) {
					if (perspectiveDropTarget == null) {
						perspectiveDropTarget = new PerspectiveDropTarget(
								draggedObject, position);
					} else {
						perspectiveDropTarget.update(draggedObject, position);
					}
					// do not support drag to perspective bars between shells.
					if (!perspectiveDropTarget.sameShell()) {
						return null;
					}
					
					return perspectiveDropTarget;
				}// else if (draggedObject instanceof IPerspectiveBar) {
				//	return new PerspectiveBarDropTarget();
				//}

				return null;
			}

		};

		PresentationUtil.addDragListener(perspectiveBar.getControl(),
				dragListener);
		DragUtil.addDragTarget(perspectiveBar.getControl(), dragTarget);
	}

	private void setPropertyChangeListener() {
        propertyChangeListener = new IPropertyChangeListener() {

            public void propertyChange(PropertyChangeEvent propertyChangeEvent) {
                if (IWorkbenchPreferenceConstants.SHOW_TEXT_ON_PERSPECTIVE_BAR
                        .equals(propertyChangeEvent.getProperty())) {
                    if (perspectiveBar == null) {
						return;
					}
                    updatePerspectiveBar();
                    updateBarParent();
                }
            }
        };
        apiPreferenceStore.addPropertyChangeListener(propertyChangeListener);
    }

    private void createControlForLeft() {
        trimControl = new Composite(parent, SWT.NONE);

        trimControl.setLayout(new CellLayout(1).setMargins(0, 0).setSpacing(3,
                3).setDefaultRow(Row.fixed()).setDefaultColumn(Row.growing()));

        perspectiveBar = createBarManager(SWT.VERTICAL);

        perspectiveBar.createControl(trimControl);
        perspectiveBar.getControl().addListener(SWT.MenuDetect, popupListener);

//        trimSeparator = new Label(trimControl, SWT.SEPARATOR | SWT.HORIZONTAL);
//        GridData sepData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING
//                | GridData.HORIZONTAL_ALIGN_CENTER);
//        sepData.widthHint = SEPARATOR_LENGTH;
//        trimSeparator.setLayoutData(sepData);
//        trimSeparator.setVisible(false);

        trimLayoutData = new GridData(GridData.FILL_BOTH);
        trimVisible = false;
        perspectiveBar.getControl().setLayoutData(trimLayoutData);
    }

    private void createControlForTop() {
        perspectiveBar = createBarManager(SWT.HORIZONTAL);

        perspectiveCoolBarWrapper = new CacheWrapper(topBar);
        perspectiveCoolBar = new CoolBar(
                perspectiveCoolBarWrapper.getControl(), SWT.FLAT);
        coolItem = new CoolItem(perspectiveCoolBar, SWT.DROP_DOWN);
        toolbarWrapper = new CacheWrapper(perspectiveCoolBar);
        perspectiveBar.createControl(toolbarWrapper.getControl());
        coolItem.setControl(toolbarWrapper.getControl());
        perspectiveCoolBar.setLocked(true);
        perspectiveBar.setParent(perspectiveCoolBar);
        perspectiveBar.update(true);

        // adjust the toolbar size to display as many items as possible
        perspectiveCoolBar.addControlListener(new ControlAdapter() {
            public void controlResized(ControlEvent e) {
                setCoolItemSize(coolItem);
            }
        });

        coolItem.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                if (e.detail == SWT.ARROW) {
                    if (perspectiveBar != null) {
                        perspectiveBar.handleChevron(e);
                    }
                }
            }
        });
        coolItem.setMinimumSize(0, 0);
        perspectiveBar.getControl().addListener(SWT.MenuDetect, popupListener);
    }

    /**
     * @param coolItem
     */
    private void setCoolItemSize(final CoolItem coolItem) {
        // there is no coolItem when the bar is on the left
        if (currentLocation == LEFT) {
			return;
		}

        ToolBar toolbar = perspectiveBar.getControl();
        if (toolbar == null) {
			return;
		}

        int rowHeight = 0;
        ToolItem[] toolItems = toolbar.getItems();
        for (int i = 0; i < toolItems.length; i++) {
            rowHeight = Math.max(rowHeight, toolItems[i].getBounds().height);
        }

        Rectangle area = perspectiveCoolBar.getClientArea();
        int rows = rowHeight <= 0 ? 1 : (int) Math.max(1, Math
                .floor(area.height / rowHeight));
        if (rows == 1 || (toolbar.getStyle() & SWT.WRAP) == 0
                || currentLocation == TOP_LEFT) {
            Point p = toolbar.computeSize(SWT.DEFAULT, SWT.DEFAULT);
            coolItem.setSize(coolItem.computeSize(p.x, p.y));
            return;
        }
        Point offset = coolItem.computeSize(0, 0);
        Point wrappedSize = toolbar.computeSize(area.width - offset.x,
                SWT.DEFAULT);
        int h = rows * rowHeight;
        int w = wrappedSize.y <= h ? wrappedSize.x : wrappedSize.x + 1;
        coolItem.setSize(coolItem.computeSize(w, h));
    }

    private void showPerspectiveBarPopup(Point pt) {
        if (perspectiveBar == null) {
			return;
		}

        // Get the tool item under the mouse.
        ToolBar toolBar = perspectiveBar.getControl();
        ToolItem toolItem = toolBar.getItem(toolBar.toControl(pt));
        
        // Get the action for the tool item.
        Object data = null;
        if (toolItem != null){
            data = toolItem.getData();
        }
        if (toolItem == null
                || !(data instanceof PerspectiveBarContributionItem)) {
            if (genericMenu == null) {
                Menu menu = new Menu(toolBar);
                addDockOnSubMenu(menu);
                addShowTextItem(menu);
                genericMenu = menu;
            }

            // set the state of the menu items to match the preferences
            genericMenu
                    .getItem(1)
                    .setSelection(
                            PrefUtil
                                    .getAPIPreferenceStore()
                                    .getBoolean(
                                            IWorkbenchPreferenceConstants.SHOW_TEXT_ON_PERSPECTIVE_BAR));
            updateLocationItems(genericMenu.getItem(0).getMenu(),
                    currentLocation);

            // Show popup menu.
            genericMenu.setLocation(pt.x, pt.y);
            genericMenu.setVisible(true);
            return;
        }

        if (data == null || !(data instanceof PerspectiveBarContributionItem)) {
			return;
		}

        PerspectiveBarContributionItem pbci = (PerspectiveBarContributionItem) data;
        IPerspectiveDescriptor selectedPerspective = pbci.getPerspective();

        // The perspective bar menu is created lazily here.
        // Its data is set (each time) to the tool item, which refers to the SetPagePerspectiveAction
        // which in turn refers to the page and perspective.
        // It is important not to refer to the action, the page or the perspective directly
        // since otherwise the menu hangs on to them after they are closed.
        // By hanging onto the tool item instead, these references are cleared when the
        // corresponding page or perspective is closed.
        // See bug 11282 for more details on why it is done this way.
        if (popupMenu != null) {
        	popupMenu.dispose();
        	popupMenu = null;
        }
        popupMenu = createPopup(toolBar, selectedPerspective);
        popupMenu.setData(toolItem);
        
        // Show popup menu.
        popupMenu.setLocation(pt.x, pt.y);
        popupMenu.setVisible(true);
    }

    /**
     * @param persp the perspective
     * @return true if the perspective is active in the active page 
     */
    private boolean perspectiveIsActive(IPerspectiveDescriptor persp) {
    	IWorkbenchPage page = window.getActivePage();
        return page != null && persp.equals(page.getPerspective());
    }

    /**
     * @param persp the perspective
     * @return true if the perspective is open in the active page 
     */
    private boolean perspectiveIsOpen(IPerspectiveDescriptor persp) {
    	IWorkbenchPage page = window.getActivePage();
    	return page != null && Arrays.asList(page.getOpenPerspectives()).contains(persp);
    }

	private Menu createPopup(ToolBar toolBar, IPerspectiveDescriptor persp){
		Menu menu = new Menu(toolBar);
		if (perspectiveIsActive(persp)) {
			addCustomizeItem(menu);
			addSaveAsItem(menu);
			addResetItem(menu);
		}
		if (perspectiveIsOpen(persp)) {
			addCloseItem(menu);
		}

		new MenuItem(menu, SWT.SEPARATOR);
		addDockOnSubMenu(menu);
		addShowTextItem(menu);
		return menu;
	}

    private void addCloseItem(Menu menu) {
        MenuItem menuItem = new MenuItem(menu, SWT.NONE);
        menuItem.setText(WorkbenchMessages.WorkbenchWindow_close); 
        window.getWorkbench().getHelpSystem().setHelp(menuItem,
        		IWorkbenchHelpContextIds.CLOSE_PAGE_ACTION);
        menuItem.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                ToolItem perspectiveToolItem = (ToolItem) popupMenu
                        .getData();
                if (perspectiveToolItem != null
                        && !perspectiveToolItem.isDisposed()) {
                    PerspectiveBarContributionItem item = (PerspectiveBarContributionItem) perspectiveToolItem
                            .getData();
                    item.getPage().closePerspective(item.getPerspective(),
                            true, true);
                }
            }
        });
    }

    /**
     * @param direction one of SWT.HORIZONTAL or SWT.VERTICAL
     */
    private PerspectiveBarManager createBarManager(int direction) {
        PerspectiveBarManager barManager = new PerspectiveBarManager(style
                | direction);
        barManager.add(new PerspectiveBarNewContributionItem(window));

        // add an item for all open perspectives
        IWorkbenchPage page = window.getActivePage();
        if (page != null) {
            // these are returned with the most recently opened one first
            IPerspectiveDescriptor[] perspectives = page
                    .getOpenPerspectives();
            for (int i = 0; i < perspectives.length; i++) {
                barManager.insert(1, new PerspectiveBarContributionItem(
                        perspectives[i], page));
            }
        }

        return barManager;
    }


    private void updateLocationItems(Menu parent, int newLocation) {
        MenuItem left;
        MenuItem topLeft;
        MenuItem topRight;

        topRight = parent.getItem(0);
        topLeft = parent.getItem(1);
        left = parent.getItem(2);

        if (newLocation == LEFT) {
            left.setSelection(true);
            topRight.setSelection(false);
            topLeft.setSelection(false);
        } else if (newLocation == TOP_LEFT) {
            topLeft.setSelection(true);
            left.setSelection(false);
            topRight.setSelection(false);
        } else {
            topRight.setSelection(true);
            left.setSelection(false);
            topLeft.setSelection(false);
        }
    }

    private void addDockOnSubMenu(Menu menu) {
        MenuItem item = new MenuItem(menu, SWT.CASCADE);
        item.setText(WorkbenchMessages.PerspectiveSwitcher_dockOn);

        final Menu subMenu = new Menu(item);

        final MenuItem menuItemTopRight = new MenuItem(subMenu, SWT.RADIO);
        menuItemTopRight.setText(WorkbenchMessages.PerspectiveSwitcher_topRight); 
        
        window.getWorkbench().getHelpSystem().setHelp(menuItemTopRight,
        		IWorkbenchHelpContextIds.DOCK_ON_PERSPECTIVE_ACTION);

        final MenuItem menuItemTopLeft = new MenuItem(subMenu, SWT.RADIO);
        menuItemTopLeft.setText(WorkbenchMessages.PerspectiveSwitcher_topLeft); 
        
        window.getWorkbench().getHelpSystem().setHelp(menuItemTopLeft,
        		IWorkbenchHelpContextIds.DOCK_ON_PERSPECTIVE_ACTION);

        final MenuItem menuItemLeft = new MenuItem(subMenu, SWT.RADIO);
        menuItemLeft.setText(WorkbenchMessages.PerspectiveSwitcher_left); 
        
        window.getWorkbench().getHelpSystem().setHelp(menuItemLeft,
        		IWorkbenchHelpContextIds.DOCK_ON_PERSPECTIVE_ACTION);

        SelectionListener listener = new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                MenuItem item = (MenuItem) e.widget;
                String pref = null;
                if (item.equals(menuItemLeft)) {
                    updateLocationItems(subMenu, LEFT);
                    pref = IWorkbenchPreferenceConstants.LEFT;
                } else if (item.equals(menuItemTopLeft)) {
                    updateLocationItems(subMenu, TOP_LEFT);
                    pref = IWorkbenchPreferenceConstants.TOP_LEFT;
                } else {
                    updateLocationItems(subMenu, TOP_RIGHT);
                    pref = IWorkbenchPreferenceConstants.TOP_RIGHT;
                }
                IPreferenceStore apiStore = PrefUtil.getAPIPreferenceStore();
                if (!pref
						.equals(apiStore
								.getDefaultString(IWorkbenchPreferenceConstants.DOCK_PERSPECTIVE_BAR))) {
					PrefUtil.getInternalPreferenceStore().setValue(
							IPreferenceConstants.OVERRIDE_PRESENTATION, true);
				}
                apiStore.setValue(
                        IWorkbenchPreferenceConstants.DOCK_PERSPECTIVE_BAR,
                        pref);
            }
        };

        menuItemTopRight.addSelectionListener(listener);
        menuItemTopLeft.addSelectionListener(listener);
        menuItemLeft.addSelectionListener(listener);
        item.setMenu(subMenu);
        updateLocationItems(subMenu, currentLocation);
    }

    private void addShowTextItem(Menu menu) {
        final MenuItem showtextMenuItem = new MenuItem(menu, SWT.CHECK);
        showtextMenuItem.setText(WorkbenchMessages.PerspectiveBar_showText);
        window.getWorkbench().getHelpSystem().setHelp(showtextMenuItem,
        		IWorkbenchHelpContextIds.SHOW_TEXT_PERSPECTIVE_ACTION);

        showtextMenuItem.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                if (perspectiveBar == null) {
					return;
				}

                boolean preference = showtextMenuItem.getSelection();
                if (preference != PrefUtil
						.getAPIPreferenceStore()
						.getDefaultBoolean(
								IWorkbenchPreferenceConstants.SHOW_TEXT_ON_PERSPECTIVE_BAR)) {
                	PrefUtil.getInternalPreferenceStore().setValue(
							IPreferenceConstants.OVERRIDE_PRESENTATION, true);
				}
                PrefUtil
                        .getAPIPreferenceStore()
                        .setValue(
                                IWorkbenchPreferenceConstants.SHOW_TEXT_ON_PERSPECTIVE_BAR,
                                preference);
            }
        });
        showtextMenuItem.setSelection(
                PrefUtil
                        .getAPIPreferenceStore()
                        .getBoolean(
                                IWorkbenchPreferenceConstants.SHOW_TEXT_ON_PERSPECTIVE_BAR));        
    }

    private void addCustomizeItem(Menu menu) {
        final MenuItem customizeMenuItem = new MenuItem(menu, SWT.Activate);
        customizeMenuItem.setText(WorkbenchMessages.PerspectiveBar_customize);
        window.getWorkbench().getHelpSystem().setHelp(customizeMenuItem,
        		IWorkbenchHelpContextIds.EDIT_ACTION_SETS_ACTION);
        customizeMenuItem.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                if (perspectiveBar == null) {
					return;
				}
                EditActionSetsAction editAction=new EditActionSetsAction(window);
                editAction.setEnabled(true);
                editAction.run();
            }
        });
    }
    
    private void addSaveAsItem(Menu menu) {
        final MenuItem saveasMenuItem = new MenuItem(menu, SWT.Activate);
        saveasMenuItem.setText(WorkbenchMessages.PerspectiveBar_saveAs); 
        window.getWorkbench().getHelpSystem().setHelp(saveasMenuItem,
        		IWorkbenchHelpContextIds.SAVE_PERSPECTIVE_ACTION);
        saveasMenuItem.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                if (perspectiveBar == null) {
					return;
				}
                SavePerspectiveAction saveAction=new SavePerspectiveAction(window);
                saveAction.setEnabled(true);
                saveAction.run();
            }
        });
    }
    
    private void addResetItem(Menu menu) {
        final MenuItem resetMenuItem = new MenuItem(menu, SWT.Activate);
        resetMenuItem.setText(WorkbenchMessages.PerspectiveBar_reset);
        window.getWorkbench().getHelpSystem().setHelp(resetMenuItem,
        		IWorkbenchHelpContextIds.RESET_PERSPECTIVE_ACTION);
        resetMenuItem.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                if (perspectiveBar == null) {
					return;
				}
                ResetPerspectiveAction resetAction=new ResetPerspectiveAction(window);
                resetAction.setEnabled(true);
                resetAction.run(); 
             }
        });
    }
    
    /**
     * Method to save the width of the perspective bar in the 
     * @param persBarMem 
     */
    public void saveState(IMemento persBarMem) {
        // save the width of the perspective bar
        IMemento childMem = persBarMem
                .createChild(IWorkbenchConstants.TAG_ITEM_SIZE);

        int x;
        if (currentLocation == TOP_RIGHT && topBar != null) {
			x = topBar.getRightWidth();
		} else {
			x = getDefaultWidth();
		}

        childMem.putString(IWorkbenchConstants.TAG_X, Integer.toString(x));
    }

    /**
     * Method to restore the width of the perspective bar
     * @param memento 
     */
    public void restoreState(IMemento memento) {
        if (memento == null) {
			return;
		}
        // restore the width of the perspective bar
        IMemento attributes = memento
                .getChild(IWorkbenchConstants.TAG_PERSPECTIVE_BAR);
        IMemento size = null;
        if (attributes != null) {
			size = attributes.getChild(IWorkbenchConstants.TAG_ITEM_SIZE);
		}
        if (size != null && currentLocation == TOP_RIGHT && topBar != null) {
            final Integer x = size.getInteger(IWorkbenchConstants.TAG_X);
            StartupThreading.runWithoutExceptions(new StartupRunnable() {

				public void runWithException() {
					if (x != null) {
						topBar.setRightWidth(x.intValue());
					} else {
						topBar.setRightWidth(getDefaultWidth());
					}
				}});
        }
    }

    /**
     * Method to rebuild and update the toolbar when necessary
     */
    void updatePerspectiveBar() {
        // Update each item as the text may have to be shortened.
        IContributionItem[] items = perspectiveBar.getItems();
        for (int i = 0; i < items.length; i++) {
			items[i].update();
		}
        // make sure the selected item is visible
        perspectiveBar.arrangeToolbar();
        setCoolItemSize(coolItem);
        perspectiveBar.getControl().redraw();
    }

    /**
     * Updates the height of the CBanner if the perspective bar
     * is docked on the top right
     */
    public void updateBarParent() {
        if (perspectiveBar == null || perspectiveBar.getControl() == null) {
			return;
		}

        // TOP_LEFT and LEFT need only relayout in this case, however TOP_RIGHT
        // will need to set the minimum height of the CBanner as it might have changed.
        if (currentLocation == TOP_RIGHT && topBar != null) {
            // This gets the height of the tallest tool item.
            int maxRowHeight = 0;
            ToolItem[] toolItems = perspectiveBar.getControl().getItems();
            for (int i = 0; i < toolItems.length; i++) {
                maxRowHeight = Math.max(maxRowHeight,
                        toolItems[i].getBounds().height);
            }
            // This sets the CBanner's minimum height to support large fonts
            // TODO: Actually calculate the correct 'min' size for the right side
            topBar.setRightMinimumSize(new Point(MIN_WIDTH, maxRowHeight));
        }

        LayoutUtil.resize(perspectiveBar.getControl());
    }

	/**
	 * Add a listener for reordering of perspectives (usually done through drag
	 * and drop).
	 * 
	 * @param listener
	 */
	public void addReorderListener(IReorderListener listener) {
		reorderListener = listener;	
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.internal.IWindowTrim#dock(int)
	 */
	public void dock(int dropSide) {
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.internal.IWindowTrim#getControl()
	 */
	public Control getControl() {
		return trimControl;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.internal.IWindowTrim#getId()
	 */
	public String getId() {
		return "org.eclipse.ui.internal.PerspectiveSwitcher"; //$NON-NLS-1$
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.internal.IWindowTrim#getDisplayName()
	 */
	public String getDisplayName() {
		return WorkbenchMessages.TrimCommon_PerspectiveSwitcher_TrimName;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.internal.IWindowTrim#getValidSides()
	 */
	public int getValidSides() {
		return SWT.NONE;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.internal.IWindowTrim#isCloseable()
	 */
	public boolean isCloseable() {
		return false;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.internal.IWindowTrim#handleClose()
	 */
	public void handleClose() {
		// nothing to do...		
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.IWindowTrim#getWidthHint()
	 */
	public int getWidthHint() {
		return SWT.DEFAULT;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.IWindowTrim#getHeightHint()
	 */
	public int getHeightHint() {
		return SWT.DEFAULT;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.IWindowTrim#isResizeable()
	 */
	public boolean isResizeable() {
		return false;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy