Package org.eclipse.ui.internal

Source Code of org.eclipse.ui.internal.PerspectiveSwitcher

/*******************************************************************************
* 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 <chris@gstaff.org> - 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 <code>IContributionItem</code> 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 <code>WorkbenchWindow</code> 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 <code>true</code> 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 <code>true</code> 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 <code>SWT.HORIZONTAL</code> or <code>SWT.VERTICAL</code>
     */
    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;
  }
}
TOP

Related Classes of org.eclipse.ui.internal.PerspectiveSwitcher

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.