Package org.eclipse.ui.internal

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

/*******************************************************************************
* Copyright (c) 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
******************************************************************************/

package org.eclipse.ui.internal;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.jface.util.Geometry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IPerspectiveDescriptor;
import org.eclipse.ui.IPerspectiveListener2;
import org.eclipse.ui.IViewReference;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.internal.StartupThreading.StartupRunnable;
import org.eclipse.ui.internal.layout.IWindowTrim;
import org.eclipse.ui.internal.layout.LayoutUtil;
import org.eclipse.ui.internal.layout.TrimLayout;
import org.eclipse.ui.internal.presentations.PresentablePart;
import org.eclipse.ui.internal.presentations.util.TabbedStackPresentation;
import org.eclipse.ui.internal.tweaklets.Animations;
import org.eclipse.ui.internal.tweaklets.Tweaklets;
import org.eclipse.ui.internal.util.Util;
import org.eclipse.ui.presentations.IPresentablePart;
import org.eclipse.ui.presentations.IStackPresentationSite;

/**
* Manage all Fast views for a particular perspective. As of 3.3 fast views
* appear in more than one manner (legacy FVB and Trim Stacks). The manager is
* responsible for providing a single implementation for the methods relating to
* fast views regardless of their UI presentation.
*
* @since 3.3
*
*/
public class FastViewManager {
  private Perspective perspective;
  private WorkbenchPage page;
  private WorkbenchWindow wbw;
  private TrimLayout tbm;

  /**
   * Maps a String to a list of IViewReferences. The string represents the
   * 'id' of either the legacy FBV or the ViewStack id of some stack which may
   * have elements in the trim.
   * <p>
   * NOTE: For TrimStacks, the order of the view ref's in the contained list
   * is the order in which they will appear in the tab folder when the stack
   * un-minimizes.
   * </p>
   */
  private Map idToFastViewsMap = new HashMap();

  /**
   * Batch update management
   */
  private boolean deferringUpdates = false;

  /**
   * animation whose life-cycle spans a
   * 'deferUpdates' cycle.
   */
  private AnimationEngine batchAnimation = null;
 
  /**
   * Used for non-deferred animations
   */
  private AnimationEngine oneShotAnimation = null;
  //private RectangleAnimation oneShotAnimation = null;
 
  private IPerspectiveListener2 perspListener = new IPerspectiveListener2() {
    public void perspectiveActivated(IWorkbenchPage page,
        IPerspectiveDescriptor perspective) {
      // Only listen for changes in -this- perspective
      if (FastViewManager.this.perspective.getDesc() == perspective)
        handlePerspectiveActivation(page, perspective);
    }

    public void perspectiveChanged(IWorkbenchPage changedPage,
        IPerspectiveDescriptor perspective,
        IWorkbenchPartReference partRef, String changeId) {
      // Only listen for changes in -this- perspective
      if (FastViewManager.this.perspective.getDesc() == perspective)
        handlePerspectiveChange(changedPage, perspective, partRef,
          changeId);
    }

    public void perspectiveChanged(IWorkbenchPage changedPage,
        IPerspectiveDescriptor perspective, String changeId) {
      // Only listen for changes in -this- perspective
      if (FastViewManager.this.perspective.getDesc() == perspective)
        handlePerspectiveChange(changedPage, perspective, changeId);
    }
  };
 
  /**
   * Creates a new manager for a particular perspective
   *
   * @param perspective
   * @param page
   */
  public FastViewManager(Perspective perspective, WorkbenchPage page) {
    this.perspective = perspective;
    this.page = page;

    // Access the trim manager for this window
    wbw = (WorkbenchWindow) page.getWorkbenchWindow();
    tbm = (TrimLayout) wbw.getTrimManager();
  }

  protected void handlePerspectiveActivation(IWorkbenchPage activatingPage,
      IPerspectiveDescriptor activatingPerspective) {
    // If this perspective is activating then update the
    // legacy FVB to show this perspective's refs
    if (activatingPage == page
        && perspective.getDesc() == activatingPerspective)
      updateTrim(FastViewBar.FASTVIEWBAR_ID);
  }

  protected void handlePerspectiveChange(IWorkbenchPage changedPage,
      IPerspectiveDescriptor changedPerspective,
      IWorkbenchPartReference partRef, String changeId) {
    // Only handle changes for our perspective
    if (changedPage != page && perspective.getDesc() != changedPerspective)
      return;

    if (changeId.equals(IWorkbenchPage.CHANGE_VIEW_HIDE)) {
      if (partRef instanceof IViewReference) {
        ViewReference ref = (ViewReference) partRef;
        if (ref.getPane().getContainer() instanceof ViewStack) {
          int viewCount = 0;
          LayoutPart[] children = ref.getPane().getContainer().getChildren();
          for (int i = 0; i < children.length; i++) {
            if (children[i] instanceof ViewPane && children[i] != ref.getPane())
              viewCount++;
          }
         
          if (viewCount == 0)
            ref.getPane().getStack().setState(IStackPresentationSite.STATE_RESTORED);
        }
      }
      // Remove the view from any FV list that it may be in
      // Do this here since the view's controls may be about
      // to be disposed...
      removeViewReference((IViewReference) partRef, false, true);
    }

    if (changeId.equals(IWorkbenchPage.CHANGE_FAST_VIEW_REMOVE)) {
      // Remove the view from any FV list that it may be in
      // Do this here since the view's controls may be about
      // to be disposed...
      removeViewReference((IViewReference) partRef, false, true);
    }
  }

  protected void handlePerspectiveChange(IWorkbenchPage changedPage,
      IPerspectiveDescriptor changedPerspective, String changeId) {
  }

  /**
   * @return The list of current fast views associated with the given id or
   *         the complete list of fastviews if the id == null.
   */
  public List getFastViews(String forId) {
    List fvs = new ArrayList();

    Iterator mapIter = idToFastViewsMap.keySet().iterator();
    while (mapIter.hasNext()) {
      String id = (String) mapIter.next();
      if (forId == null || forId.equals(id)) {
        List fvList = (List) idToFastViewsMap.get(id);
        for (Iterator fvIter = fvList.iterator(); fvIter.hasNext();) {
          fvs.add(fvIter.next());
        }
      }
    }

    return fvs;
  }

  /**
   * Casues the given {@link IViewReference} to be added to the list
   * identified by the 'id' parameter. The reference is added at the specified
   * index or at the end if the index is -1. If there was a previous entry for
   * this ref it will be removed so that only the ref will only ever be in one
   * list at a time.
   * <p>
   * NOTE: The trim life-cycle is managed at the stack level so there -must-
   * be an entry in the map and a corresponding trim element before calling
   * this method,
   * </p>
   * <p>
   * The page/perspective are updated to make the view a fastview if
   * necessary.
   * </p>
   *
   * @param id
   *            The id of the {@link IWindowTrim} that is to show the ref
   * @param index
   *            The index to insert the ref at
   * @param ref
   *            The {@link IViewReference} to add
   * @param update
   *            cause the trim to update if <code>true</code>
   */
  public void addViewReference(String id, int index, IViewReference ref,
      boolean update) {
    if (id == null || ref == null)
      return;

    List fvList = (List) idToFastViewsMap.get(id);
    if (fvList == null) {
      // Not in the model yet, add it
      fvList = new ArrayList();
      idToFastViewsMap.put(id, fvList);
    }

    // bounds checking
    if (index < 0 || index > fvList.size())
      index = fvList.size();

    // Is it already in a list?
    String curLocation = getIdForRef(ref);
    if (curLocation != null) {
      // is it the same list that it's being added to?
      if (id.equals(curLocation)) {
        int curIndex = fvList.indexOf(ref);
        if (index == curIndex)
          return; // No-Op

        // If we're inserting after where we
        // were then decrement the index to
        // account for the removal of the old ref
        if (index > curIndex)
          index--;
      }

      // Remove it...
      removeViewReference(ref, false, true);
    } else {
      // It's not a fastview, make it one
      makeFast(ref, true, false);
    }

    fvList.add(index, ref);

    // Note that the update call will create and show the ViewStackTrimToolbar
    // if necessary
    if (update)
      updateTrim(id);
  }

  /**
   * Create the Trim element for the stack containing the given reference
   *
   * @param suggestedSide
   * @param paneOrientation
   * @param ref
   *            The {@link IViewReference} whose stack needs trim creation.
   */
  private ViewStackTrimToolBar getTrimForViewStack(String id,
      int suggestedSide, int paneOrientation) {
    // Do we already have one??
    ViewStackTrimToolBar trim = (ViewStackTrimToolBar) tbm.getTrim(id);
    if (trim == null) {
      int cachedSide = tbm.getPreferredArea(id);
      if (cachedSide != -1)
        suggestedSide = cachedSide;
     
      IWindowTrim beforeMe = tbm.getPreferredLocation(id);
     
      trim = new ViewStackTrimToolBar(id, suggestedSide,
          paneOrientation, wbw);
      tbm.addTrim(suggestedSide, trim, beforeMe);
      updateTrim(trim.getId());
    }

    return trim;
  }

  /**
   * Causes the trim element associated with the id to synch itself with the
   * current list of views. This method will create a new ViewStackTrimToolbar
   * if necessary (i.e. on the first call after views have been added to the map)
   * and will also hide the trim element when the number of views in the mapped
   * list goes to zero.
   *
   * @param id
   *            The id of the {@link IWindowTrim} to update
   */
  private void updateTrim(String id) {
    // Get the trim part from the trim manager
    IWindowTrim trim = tbm.getTrim(id);

    // If it's not there there's not much we can do
    if (trim == null)
      return;

    // If there are no fast views for the bar then hide it
    List fvs = (List) idToFastViewsMap.get(id);
    if (fvs != null && fvs.size() == 0
        && !FastViewBar.FASTVIEWBAR_ID.equals(id)) {
      if (trim.getControl().getVisible()) {
        tbm.setTrimVisible(trim, false);
        tbm.forceLayout();
      }
      return;
    }

    // Ensure that the trim is displayed
    if (!trim.getControl().getVisible()) {
      tbm.setTrimVisible(trim, true);
    }

    if (trim instanceof FastViewBar) {
      FastViewBar fvb = (FastViewBar) trim;
      fvb.update(true);
    } else if (trim instanceof ViewStackTrimToolBar) {
      ViewStackTrimToolBar vstb = (ViewStackTrimToolBar) trim;
      vstb.update(true);
      vstb.getControl().pack();
      LayoutUtil.resize(trim.getControl());
    }

    tbm.forceLayout();
  }

  /**
   * Remove the view reference from its existing location
   *
   * @param ref
   *            The {@link IViewReference} to remove
   */
  public void removeViewReference(IViewReference ref, boolean makeUnfast, boolean update) {
    String id = getIdForRef(ref);

    if (id != null) {
      // Remove the ref
      List fvList = (List) idToFastViewsMap.get(id);
      fvList.remove(ref);

      if (makeUnfast)
        makeFast(ref, false, false);
     
      if (update)
        updateTrim(id);
    }
  }

  /**
   *
   * @param ref
   * @param makeFast
   * @param activate
   */
  private void makeFast(IViewReference ref, boolean makeFast, boolean activate) {
    if (ref == null || page == null)
      return;

    if (makeFast) {
      page.makeFastView(ref);
    } else {
      page.removeFastView(ref);

      if (activate) {
        IWorkbenchPart toActivate = ref.getPart(true);
        if (toActivate != null) {
          page.activate(toActivate);
        }
      }
    }
  }

  /**
   * @param ref
   *            The IViewRference to check
   * @return true iff the ref is in -any- list
   */
  boolean isFastView(IViewReference ref) {
    return getIdForRef(ref) != null;
  }

  /**
   * @param ref
   *            The IViewRference to check
   * @return The id of the trim bar currently showing the reference or
   *         <code>null</code> if it's not in any list
   */
  public String getIdForRef(IViewReference ref) {
    Iterator mapIter = idToFastViewsMap.keySet().iterator();
    while (mapIter.hasNext()) {
      String id = (String) mapIter.next();
      List fvList = (List) idToFastViewsMap.get(id);
      if (fvList.contains(ref))
        return id;
    }

    return null;
  }

  /**
   * @return The side that the fast view pane should be attached to based on
   *         the position of the trim element containing the ref.
   */
  public int getViewSide(IViewReference ref) {
    IWindowTrim trim = getTrimForRef(ref);
    if (trim == null)
      return SWT.BOTTOM;

    int curSide = SWT.BOTTOM;
    int paneOrientation = SWT.BOTTOM;

    if (trim instanceof ViewStackTrimToolBar) {
      curSide = ((ViewStackTrimToolBar) trim).getCurrentSide();
      paneOrientation = ((ViewStackTrimToolBar) trim)
          .getPaneOrientation();
    } else if (trim instanceof FastViewBar) {
      curSide = ((FastViewBar) trim).getSide();
      paneOrientation = ((FastViewBar) trim).getOrientation(ref);
    }

    // Get trim layout info
    Point trimCenter = Geometry.centerPoint(trim.getControl().getBounds());
    Point shellCenter = Geometry.centerPoint(trim.getControl().getShell()
        .getClientArea());

    // Horizontal has to snap to either TOP or BOTTOM...
    if (paneOrientation == SWT.HORIZONTAL) {
      if (curSide == SWT.TOP || curSide == SWT.BOTTOM)
        return curSide;

      // Are we on the top or bottom 'end' of the trim area?
      return (trimCenter.y < shellCenter.y) ? SWT.TOP : SWT.BOTTOM;
    }

    if (paneOrientation == SWT.VERTICAL) {
      if (curSide == SWT.LEFT || curSide == SWT.RIGHT)
        return curSide;

      // Are we on the left or right 'end' of the trim area?
      return (trimCenter.x < shellCenter.x) ? SWT.LEFT : SWT.RIGHT;
    }

    return SWT.BOTTOM;
  }

  /**
   * Return the trim element showing the given reference
   *
   * @param ref
   *            The reference to find
   * @return the IWindowTrim showing the ref
   */
  private IWindowTrim getTrimForRef(IViewReference ref) {
    String id = getIdForRef(ref);
    if (id == null)
      return null; // Not in trim

    return tbm.getTrim(id);
  }

  /**
   * @return a List of <code>IViewReference</code> sorted into the order in
   *         which they appear in the visual stack.
   */
  private List getTrueViewOrder(ViewStack stack) {
    List orderedViews = new ArrayList();
    IPresentablePart[] parts = null;
    if (stack.getPresentation() instanceof TabbedStackPresentation) {
      TabbedStackPresentation tsp = (TabbedStackPresentation) stack
          .getPresentation();
      // KLUDGE!! uses a 'testing only' API to get the parts in their 'visible' order
      parts = tsp.getPartList();
    }

    // If we didn't get the parts from the tab list then try the presentable part API
    // ViewStack's declared 'no title' fail the call above, returning an empty array
    if (parts == null || parts.length == 0){
      // We'll have to process the parts in the order given...
      // This is certain to fail on drag re-ordering of the
      // icons in the trim since we have no API to inform the
      // custom presentation
      List partList = stack.getPresentableParts();
      parts = (IPresentablePart[]) partList.toArray(new IPresentablePart[partList.size()]);
    }     

    // Now, process the parts...
    for (int i = 0; i < parts.length; i++) {
      if (parts[i] instanceof PresentablePart) {
        PresentablePart part = (PresentablePart) parts[i];
        IWorkbenchPartReference ref = part.getPane()
            .getPartReference();
        if (ref instanceof IViewReference)
          orderedViews.add(ref);
      }
    }

    return orderedViews;
  }

  public void moveToTrim(ViewStack vs, boolean restoreOnUnzoom) {
    // Don't do anything when initializing...
    if (vs.getBounds().width == 0)
      return; // indicates that we're startin up
     
    // If we're part of a 'maximize' operation then use the cached
    // bounds...
    Rectangle stackBounds = perspective.getPresentation().getCachedBoundsFor(vs.getID());

    // OK, no cache means that we use the current stack position
    if (stackBounds == null)
      stackBounds = vs.getBounds();
   
    int paneOrientation = (stackBounds.width > stackBounds.height) ? SWT.HORIZONTAL
        : SWT.VERTICAL;

    // Remember the tab that was selected when we minimized
    String selId = ""; //$NON-NLS-1$
    PartPane selectedTab = vs.getSelection();
    if (selectedTab != null)
      selId  = selectedTab.getCompoundId();
   
    vs.deferUpdates(true);
   
    // animate the minimize
    RectangleAnimationFeedbackBase animation = (RectangleAnimationFeedbackBase) getDeferrableAnimation().getFeedback();
    animation.addStartRect(vs.getControl());

    //long startTick = System.currentTimeMillis();
    // Update the model first
    List toMove = getTrueViewOrder(vs);
    for (Iterator viewIter = toMove.iterator(); viewIter.hasNext();) {
      IViewReference ref = (IViewReference) viewIter.next();
      addViewReference(vs.getID(), -1, ref, false);
    }

    vs.deferUpdates(false);
   
    // Find (or create) the trim stack to move to
    ViewStackTrimToolBar vstb = getTrimForViewStack(vs.getID(), perspective
        .calcStackSide(stackBounds), paneOrientation);
    vstb.setRestoreOnUnzoom(restoreOnUnzoom);
    vstb.setSelectedTabId(selId);
    updateTrim(vstb.getId());
   
    //System.out.println("minimize time: " + (System.currentTimeMillis()-startTick)); //$NON-NLS-1$
    if (vstb != null) {
      animation.addEndRect(vstb.getControl());
      scheduleDeferrableAnimation();
    }
  }

  /**
   * Restore the trim element representing a ViewStack back into the
   * presentation.
   *
   * @param viewStackTrimToolBar
   *            The trim version to restore
   */
  public void restoreToPresentation(String id) {
    ViewStackTrimToolBar vstb = getViewStackTrimToolbar(id);
   
    // The IntroPart uses the old min/max behavior; ensure that
    // we were really a minimized trim stack
    if (vstb == null)
      return;
   
    // remove any showing fast view
    page.hideFastView();

    // The stored id may be 'compound' if it's a multi-instance
    // view; split out the secondary id (if any)
    String selectedTabId = vstb.getSelectedTabId();
    String[] idParts = Util.split(selectedTabId, ':');
    if (idParts[0].length() == selectedTabId.length())
      idParts[1] = null;
   
    List fvs = getFastViews(id);
    for (Iterator fvIter = fvs.iterator(); fvIter.hasNext();) {
      IViewReference ref = (IViewReference) fvIter.next();
      removeViewReference(ref, true, !fvIter.hasNext());
    }

    // Restore the correct tab to the 'top'
    LayoutPart stack = perspective.getPresentation().findPart(id, null);
    if (stack instanceof PartStack) {
      LayoutPart selTab = perspective.getPresentation().findPart(idParts[0], idParts[1]);
      if (selTab instanceof PartPane && selTab instanceof ViewPane) {
        ((PartStack)stack).setSelection(selTab);
       
        // activate the view if we're not doing a compound operation
        if (!deferringUpdates)
          ((ViewPane)selTab).requestActivation();
      }
    }
   
    // Hide the Trim
    updateTrim(id);
  }

  /**
   * Restore all fact view stacks created as part of a zoom
   */
  public void restoreZoomedViewStacks() {
    Iterator mapIter = idToFastViewsMap.keySet().iterator();
    while (mapIter.hasNext()) {
      String id = (String) mapIter.next();
      IWindowTrim trim = tbm.getTrim(id);
      if (trim != null && trim instanceof ViewStackTrimToolBar) {
        ViewStackTrimToolBar vstb = (ViewStackTrimToolBar) trim;
        if (vstb.restoreOnUnzoom())
          restoreToPresentation(vstb.getId());
      }
    }
  }

  /**
   * @param ref
   *            Sets the ref of the icon
   * @param selected
   *            the selection state of the icon
   */
  public void setFastViewIconSelection(IViewReference ref, boolean selected) {
    String id = getIdForRef(ref);
    IWindowTrim trim = tbm.getTrim(id);
    if (trim instanceof ViewStackTrimToolBar) {
      ViewStackTrimToolBar vstb = (ViewStackTrimToolBar) trim;
      vstb.setIconSelection(ref, selected);
    } else if (trim instanceof FastViewBar) {
      FastViewBar fvb = (FastViewBar) trim;
      if (selected) {
        fvb.setSelection(ref);
      } else {
        if (ref == fvb.getSelection()) {
          fvb.setSelection(null);
        }
      }
    }

  }

  /**
   * Activate the manager. Called from the Perspecive's 'onActivate'
   */
  public void activate() {
    wbw.addPerspectiveListener(perspListener);
    setTrimStackVisibility(true);
  }

  /**
   * Activate the manager. Called from the Perspecive's 'onActivate'
   */
  public void deActivate() {
    wbw.removePerspectiveListener(perspListener);
    setTrimStackVisibility(false);
  }

  /**
   * Restore any trim stacks. This method is used when the presentation
   * is switched back to 3.0; if we aren't using the new min/max story
   * then we shouldn't -have- any trim stacks.
   */
  public boolean restoreAllTrimStacks() {
    boolean stacksWereRestored = false;
   
    Iterator mapIter = idToFastViewsMap.keySet().iterator();
    while (mapIter.hasNext()) {
      String id = (String) mapIter.next();
     
      // Skip the legacy FstViewBar
      if (id.equals(FastViewBar.FASTVIEWBAR_ID))
        continue;
     
      // Restore the views
      List fvs = getFastViews(id);
      for (Iterator fvIter = fvs.iterator(); fvIter.hasNext();) {
        IViewReference ref = (IViewReference) fvIter.next();
        removeViewReference(ref, true, !fvIter.hasNext());
      }

      // Blow the trim away
      IWindowTrim trim = tbm.getTrim(id);
      if (trim != null && trim instanceof ViewStackTrimToolBar) {
        tbm.removeTrim(trim);
        trim.getControl().dispose();
       
        stacksWereRestored = true;
      }
    }
   
    tbm.forceLayout();
   
    return stacksWereRestored;
  }

  /**
   * Show all non-empty trim stacks. Create the stack if necessary
   */
  private void setTrimStackVisibility(boolean visible) {
    Iterator mapIter = idToFastViewsMap.keySet().iterator();
    while (mapIter.hasNext()) {
      String id = (String) mapIter.next();
      List fvs = getFastViews(id);
     
      // Never show 'empty' stacks
      if (visible && fvs.size() == 0)
        continue;

      IWindowTrim trim = tbm.getTrim(id);
      if (trim != null && trim instanceof ViewStackTrimToolBar) {
        ((ViewStackTrimToolBar)trim).update(true);
        tbm.setTrimVisible(trim, visible);
      }
    }
  }

  public void saveState(IMemento memento) {
    // Output legacy fastviews
    FastViewBar fvb = wbw.getFastViewBar();
    if (fvb != null) {
      List fvRefs = getFastViews(FastViewBar.FASTVIEWBAR_ID);
      if (fvRefs.size() > 0) {
        IMemento childMem = memento
            .createChild(IWorkbenchConstants.TAG_FAST_VIEWS);
        Iterator itr = fvRefs.iterator();
        while (itr.hasNext()) {
          IViewReference ref = (IViewReference) itr.next();
          IMemento viewMemento = childMem
              .createChild(IWorkbenchConstants.TAG_VIEW);
          String id = ViewFactory.getKey(ref);
          viewMemento.putString(IWorkbenchConstants.TAG_ID, id);
          float ratio = perspective.getFastViewWidthRatio(ref);
          viewMemento.putFloat(IWorkbenchConstants.TAG_RATIO, ratio);
        }
      }
    }

    // Write all the current (non-empty) bars
    IMemento barsMemento = memento
        .createChild(IWorkbenchConstants.TAG_FAST_VIEW_BARS);

    Iterator mapIter = idToFastViewsMap.keySet().iterator();
    while (mapIter.hasNext()) {
      String id = (String) mapIter.next();

      // Legacy FV's are stored above...
      if (FastViewBar.FASTVIEWBAR_ID.equals(id))
        continue;

      List fvs = getFastViews(id);
      if (fvs.size() > 0) {
        IMemento barMemento = barsMemento
            .createChild(IWorkbenchConstants.TAG_FAST_VIEW_BAR);
        barMemento.putString(IWorkbenchConstants.TAG_ID, id);

        // Orientation / restore
        ViewStackTrimToolBar vstb = (ViewStackTrimToolBar) tbm
            .getTrim(id);
        if (vstb != null) {
          barMemento.putInteger(
              IWorkbenchConstants.TAG_FAST_VIEW_SIDE,
              vstb.getCurrentSide());
         
          barMemento.putInteger(
              IWorkbenchConstants.TAG_FAST_VIEW_ORIENTATION,
              vstb.getPaneOrientation());
         
          int boolVal = vstb.restoreOnUnzoom() ? 1 : 0;
          barMemento.putInteger(IWorkbenchConstants.TAG_FAST_VIEW_STYLE, boolVal);
         
          barMemento.putString(IWorkbenchConstants.TAG_FAST_VIEW_SEL_ID, vstb.getSelectedTabId());
        }

        IMemento viewsMem = barMemento
            .createChild(IWorkbenchConstants.TAG_FAST_VIEWS);
        Iterator itr = fvs.iterator();
        while (itr.hasNext()) {
          IMemento refMem = viewsMem
              .createChild(IWorkbenchConstants.TAG_VIEW);
          IViewReference ref = (IViewReference) itr.next();

          // id
          String viewId = ViewFactory.getKey(ref);
          refMem.putString(IWorkbenchConstants.TAG_ID, viewId);
         
          // width ratio
          float ratio = perspective.getFastViewWidthRatio(ref);
          refMem.putFloat(IWorkbenchConstants.TAG_RATIO, ratio);
        }
      }
    }
  }

  public void restoreState(IMemento memento, MultiStatus result) {
    // Load the fast views
    IMemento fastViewsMem = memento
        .getChild(IWorkbenchConstants.TAG_FAST_VIEWS);

    // -Replace- the current list with the one from the store
    List refsList = new ArrayList();
    idToFastViewsMap.put(FastViewBar.FASTVIEWBAR_ID, refsList);

    if (fastViewsMem != null) {
      IMemento[] views = fastViewsMem
          .getChildren(IWorkbenchConstants.TAG_VIEW);
      for (int x = 0; x < views.length; x++) {
        // Get the view details.
        IMemento childMem = views[x];
        IViewReference ref = perspective.restoreFastView(childMem,
            result);
        if (ref != null)
          refsList.add(ref);
      }
    }

    // Load the Trim Stack info
    IMemento barsMem = memento
        .getChild(IWorkbenchConstants.TAG_FAST_VIEW_BARS);
   
    // It's not there for old workspaces
    if (barsMem == null)
      return;
   
    IMemento[] bars = barsMem
        .getChildren(IWorkbenchConstants.TAG_FAST_VIEW_BAR);
    for (int i = 0; i < bars.length; i++) {
      final String id = bars[i].getString(IWorkbenchConstants.TAG_ID);
      fastViewsMem = bars[i].getChild(IWorkbenchConstants.TAG_FAST_VIEWS);

      // -Replace- the current list with the one from the store
      refsList = new ArrayList();
      idToFastViewsMap.put(id, refsList);

      if (fastViewsMem != null) {
        IMemento[] views = fastViewsMem
            .getChildren(IWorkbenchConstants.TAG_VIEW);
              result.merge(perspective.createReferences(views));
       
        // Create the trim area for the trim stack
        // Only create the TB if there are views in it
        if (views.length > 0) {
          final int side = bars[i].getInteger(
              IWorkbenchConstants.TAG_FAST_VIEW_SIDE)
              .intValue();
          final int orientation = bars[i].getInteger(
              IWorkbenchConstants.TAG_FAST_VIEW_ORIENTATION)
              .intValue();
          int boolVal = bars[i].getInteger(
              IWorkbenchConstants.TAG_FAST_VIEW_STYLE).intValue();
          final boolean restoreOnUnzoom = (boolVal > 0);
         
          final String selId = bars[i].getString(IWorkbenchConstants.TAG_FAST_VIEW_SEL_ID);
         
          // Create the stack
              StartupThreading.runWithoutExceptions(new StartupRunnable() {
            public void runWithException() throws Throwable {
              ViewStackTrimToolBar vstb = getTrimForViewStack(id, side, orientation);
              vstb.setRestoreOnUnzoom(restoreOnUnzoom);
              if (selId != null)
                vstb.setSelectedTabId(selId);
            }
          });
        }
       
        for (int x = 0; x < views.length; x++) {
          // Get the view details.
          IMemento childMem = views[x];
          IViewReference ref = perspective.restoreFastView(childMem,
              result);
          if (ref != null)
            refsList.add(ref);
        }
      }
    }
  }

  /**
   * Returns the trim element for the given id if it exists. This
   * will not be <code>null</code> if there are entries in the
   * 'idToFastViewsMap' for this id.
   *
   * @param id The id of the view stack to get the trim toolbar for.
   */
  public ViewStackTrimToolBar getViewStackTrimToolbar(String id) {
    return (ViewStackTrimToolBar) tbm.getTrim(id);
  }
 
  public void printFVModel() {
    Iterator mapIter = idToFastViewsMap.keySet().iterator();
    while (mapIter.hasNext()) {
      String id = (String) mapIter.next();
      List fvList = (List) idToFastViewsMap.get(id);
      System.out.println("FastView: " + id + " count = " + fvList.size())//$NON-NLS-1$//$NON-NLS-2$
      for (Iterator fvIter = fvList.iterator(); fvIter.hasNext();) {
        IViewReference ref = (IViewReference) fvIter.next();
        System.out.println("  Ref: " + ref.getId()); //$NON-NLS-1$
      }
    }
  }

  /**
   * Informs the manager that a batch operation has started
   * (say 'maximize', where many stacks will change state).
   *
   * @param defer
   *  true when starting a batch operation
   *  false when ending the operation
   */
  public void deferUpdates(boolean defer) {
    if (defer && !deferringUpdates) {
      deferringUpdates = defer;
     
      deferAnimations(true);
     
      return;
    }
   
    // 'false': reset and run any necessary updates
    deferringUpdates = false;
    deferAnimations(false);
  }

  /**
   * When 'defer' is true we create a RectangleAnimation object
   * to be used for any desired feedback. When ending it
   * schedules the animation and resets.
   *
   * @param defer
   *  true when starting a batch operation
   *  false when ending the operation
   */
  private void deferAnimations(boolean defer) {
    if (defer) {
      RectangleAnimationFeedbackBase feedback = ((Animations) Tweaklets
          .get(Animations.KEY)).createFeedback(wbw.getShell());
      batchAnimation = new AnimationEngine(feedback, 400);
      return;
    }

    if (batchAnimation != null)
      batchAnimation.schedule();
    batchAnimation = null;
  }

  /**
   * Returns the animation object appropriate for the deferred state
   * @return Either a 'one-shot' or a 'batch' animation object
   */
  private AnimationEngine getDeferrableAnimation() {
    if (deferringUpdates)
      return batchAnimation;
   
    // Create a 'one-shot' animation
    RectangleAnimationFeedbackBase feedback = ((Animations) Tweaklets
        .get(Animations.KEY)).createFeedback(wbw.getShell());
    oneShotAnimation = new AnimationEngine(feedback, 400);
    return oneShotAnimation;
  }
 
  private void scheduleDeferrableAnimation() {
    if (deferringUpdates)
      return;
   
    // We can only schedule the 'one-shot' animations
    // the batch ones are sheduled at batch end
    if (oneShotAnimation != null)
      oneShotAnimation.schedule();
    oneShotAnimation = null;
  }

  /**
   * Returns the 'bottom/right' trim stack. This is used to
   * match the old behavior when opening a new view that has no placeholder
   * in the case where there WB is maximized.
   *
   * @return The 'bottom/right' trim stack or null if there are no
   * defined trim stacks
   */
  public ViewStackTrimToolBar getBottomRightTrimStack() {
    ViewStackTrimToolBar blTrimStack = null;
    Point blPt = new Point(0,0);
   
    Iterator mapIter = idToFastViewsMap.keySet().iterator();
    while (mapIter.hasNext()) {
      String id = (String) mapIter.next();
     
      // Skip the legacy FstViewBar
      if (id.equals(FastViewBar.FASTVIEWBAR_ID))
        continue;

      if (getFastViews(id).size() > 0) {
        // if we have views in the model then 'vstt' will not be null
        ViewStackTrimToolBar vstt = getViewStackTrimToolbar(id);
        Point loc = vstt.getControl().getLocation();
        if (loc.y > blPt.y || (loc.y == blPt.y && loc.x > blPt.x)) {
          blPt = loc;
          blTrimStack = vstt;
        }
      }
    }

    return blTrimStack;
  }
}
TOP

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

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.