0001: /*******************************************************************************
0002: * Copyright (c) 2007 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: ******************************************************************************/package org.eclipse.ui.internal;
0011:
0012: import java.util.ArrayList;
0013: import java.util.HashMap;
0014: import java.util.Iterator;
0015: import java.util.List;
0016: import java.util.Map;
0017:
0018: import org.eclipse.core.runtime.MultiStatus;
0019: import org.eclipse.jface.util.Geometry;
0020: import org.eclipse.swt.SWT;
0021: import org.eclipse.swt.graphics.Point;
0022: import org.eclipse.swt.graphics.Rectangle;
0023: import org.eclipse.ui.IMemento;
0024: import org.eclipse.ui.IPerspectiveDescriptor;
0025: import org.eclipse.ui.IPerspectiveListener2;
0026: import org.eclipse.ui.IViewReference;
0027: import org.eclipse.ui.IWorkbenchPage;
0028: import org.eclipse.ui.IWorkbenchPart;
0029: import org.eclipse.ui.IWorkbenchPartReference;
0030: import org.eclipse.ui.internal.StartupThreading.StartupRunnable;
0031: import org.eclipse.ui.internal.layout.IWindowTrim;
0032: import org.eclipse.ui.internal.layout.LayoutUtil;
0033: import org.eclipse.ui.internal.layout.TrimLayout;
0034: import org.eclipse.ui.internal.presentations.PresentablePart;
0035: import org.eclipse.ui.internal.presentations.util.TabbedStackPresentation;
0036: import org.eclipse.ui.internal.tweaklets.Animations;
0037: import org.eclipse.ui.internal.tweaklets.Tweaklets;
0038: import org.eclipse.ui.internal.util.Util;
0039: import org.eclipse.ui.presentations.IPresentablePart;
0040: import org.eclipse.ui.presentations.IStackPresentationSite;
0041:
0042: /**
0043: * Manage all Fast views for a particular perspective. As of 3.3 fast views
0044: * appear in more than one manner (legacy FVB and Trim Stacks). The manager is
0045: * responsible for providing a single implementation for the methods relating to
0046: * fast views regardless of their UI presentation.
0047: *
0048: * @since 3.3
0049: *
0050: */
0051: public class FastViewManager {
0052: private Perspective perspective;
0053: private WorkbenchPage page;
0054: private WorkbenchWindow wbw;
0055: private TrimLayout tbm;
0056:
0057: /**
0058: * Maps a String to a list of IViewReferences. The string represents the
0059: * 'id' of either the legacy FBV or the ViewStack id of some stack which may
0060: * have elements in the trim.
0061: * <p>
0062: * NOTE: For TrimStacks, the order of the view ref's in the contained list
0063: * is the order in which they will appear in the tab folder when the stack
0064: * un-minimizes.
0065: * </p>
0066: */
0067: private Map idToFastViewsMap = new HashMap();
0068:
0069: /**
0070: * Batch update management
0071: */
0072: private boolean deferringUpdates = false;
0073:
0074: /**
0075: * animation whose life-cycle spans a
0076: * 'deferUpdates' cycle.
0077: */
0078: private AnimationEngine batchAnimation = null;
0079:
0080: /**
0081: * Used for non-deferred animations
0082: */
0083: private AnimationEngine oneShotAnimation = null;
0084: //private RectangleAnimation oneShotAnimation = null;
0085:
0086: private IPerspectiveListener2 perspListener = new IPerspectiveListener2() {
0087: public void perspectiveActivated(IWorkbenchPage page,
0088: IPerspectiveDescriptor perspective) {
0089: // Only listen for changes in -this- perspective
0090: if (FastViewManager.this .perspective.getDesc() == perspective)
0091: handlePerspectiveActivation(page, perspective);
0092: }
0093:
0094: public void perspectiveChanged(IWorkbenchPage changedPage,
0095: IPerspectiveDescriptor perspective,
0096: IWorkbenchPartReference partRef, String changeId) {
0097: // Only listen for changes in -this- perspective
0098: if (FastViewManager.this .perspective.getDesc() == perspective)
0099: handlePerspectiveChange(changedPage, perspective,
0100: partRef, changeId);
0101: }
0102:
0103: public void perspectiveChanged(IWorkbenchPage changedPage,
0104: IPerspectiveDescriptor perspective, String changeId) {
0105: // Only listen for changes in -this- perspective
0106: if (FastViewManager.this .perspective.getDesc() == perspective)
0107: handlePerspectiveChange(changedPage, perspective,
0108: changeId);
0109: }
0110: };
0111:
0112: /**
0113: * Creates a new manager for a particular perspective
0114: *
0115: * @param perspective
0116: * @param page
0117: */
0118: public FastViewManager(Perspective perspective, WorkbenchPage page) {
0119: this .perspective = perspective;
0120: this .page = page;
0121:
0122: // Access the trim manager for this window
0123: wbw = (WorkbenchWindow) page.getWorkbenchWindow();
0124: tbm = (TrimLayout) wbw.getTrimManager();
0125: }
0126:
0127: protected void handlePerspectiveActivation(
0128: IWorkbenchPage activatingPage,
0129: IPerspectiveDescriptor activatingPerspective) {
0130: // If this perspective is activating then update the
0131: // legacy FVB to show this perspective's refs
0132: if (activatingPage == page
0133: && perspective.getDesc() == activatingPerspective)
0134: updateTrim(FastViewBar.FASTVIEWBAR_ID);
0135: }
0136:
0137: protected void handlePerspectiveChange(IWorkbenchPage changedPage,
0138: IPerspectiveDescriptor changedPerspective,
0139: IWorkbenchPartReference partRef, String changeId) {
0140: // Only handle changes for our perspective
0141: if (changedPage != page
0142: && perspective.getDesc() != changedPerspective)
0143: return;
0144:
0145: if (changeId.equals(IWorkbenchPage.CHANGE_VIEW_HIDE)) {
0146: if (partRef instanceof IViewReference) {
0147: ViewReference ref = (ViewReference) partRef;
0148: if (ref.getPane().getContainer() instanceof ViewStack) {
0149: int viewCount = 0;
0150: LayoutPart[] children = ref.getPane()
0151: .getContainer().getChildren();
0152: for (int i = 0; i < children.length; i++) {
0153: if (children[i] instanceof ViewPane
0154: && children[i] != ref.getPane())
0155: viewCount++;
0156: }
0157:
0158: if (viewCount == 0)
0159: ref.getPane().getStack().setState(
0160: IStackPresentationSite.STATE_RESTORED);
0161: }
0162: }
0163: // Remove the view from any FV list that it may be in
0164: // Do this here since the view's controls may be about
0165: // to be disposed...
0166: removeViewReference((IViewReference) partRef, false, true);
0167: }
0168:
0169: if (changeId.equals(IWorkbenchPage.CHANGE_FAST_VIEW_REMOVE)) {
0170: // Remove the view from any FV list that it may be in
0171: // Do this here since the view's controls may be about
0172: // to be disposed...
0173: removeViewReference((IViewReference) partRef, false, true);
0174: }
0175: }
0176:
0177: protected void handlePerspectiveChange(IWorkbenchPage changedPage,
0178: IPerspectiveDescriptor changedPerspective, String changeId) {
0179: }
0180:
0181: /**
0182: * @return The list of current fast views associated with the given id or
0183: * the complete list of fastviews if the id == null.
0184: */
0185: public List getFastViews(String forId) {
0186: List fvs = new ArrayList();
0187:
0188: Iterator mapIter = idToFastViewsMap.keySet().iterator();
0189: while (mapIter.hasNext()) {
0190: String id = (String) mapIter.next();
0191: if (forId == null || forId.equals(id)) {
0192: List fvList = (List) idToFastViewsMap.get(id);
0193: for (Iterator fvIter = fvList.iterator(); fvIter
0194: .hasNext();) {
0195: fvs.add(fvIter.next());
0196: }
0197: }
0198: }
0199:
0200: return fvs;
0201: }
0202:
0203: /**
0204: * Casues the given {@link IViewReference} to be added to the list
0205: * identified by the 'id' parameter. The reference is added at the specified
0206: * index or at the end if the index is -1. If there was a previous entry for
0207: * this ref it will be removed so that only the ref will only ever be in one
0208: * list at a time.
0209: * <p>
0210: * NOTE: The trim life-cycle is managed at the stack level so there -must-
0211: * be an entry in the map and a corresponding trim element before calling
0212: * this method,
0213: * </p>
0214: * <p>
0215: * The page/perspective are updated to make the view a fastview if
0216: * necessary.
0217: * </p>
0218: *
0219: * @param id
0220: * The id of the {@link IWindowTrim} that is to show the ref
0221: * @param index
0222: * The index to insert the ref at
0223: * @param ref
0224: * The {@link IViewReference} to add
0225: * @param update
0226: * cause the trim to update if <code>true</code>
0227: */
0228: public void addViewReference(String id, int index,
0229: IViewReference ref, boolean update) {
0230: if (id == null || ref == null)
0231: return;
0232:
0233: List fvList = (List) idToFastViewsMap.get(id);
0234: if (fvList == null) {
0235: // Not in the model yet, add it
0236: fvList = new ArrayList();
0237: idToFastViewsMap.put(id, fvList);
0238: }
0239:
0240: // bounds checking
0241: if (index < 0 || index > fvList.size())
0242: index = fvList.size();
0243:
0244: // Is it already in a list?
0245: String curLocation = getIdForRef(ref);
0246: if (curLocation != null) {
0247: // is it the same list that it's being added to?
0248: if (id.equals(curLocation)) {
0249: int curIndex = fvList.indexOf(ref);
0250: if (index == curIndex)
0251: return; // No-Op
0252:
0253: // If we're inserting after where we
0254: // were then decrement the index to
0255: // account for the removal of the old ref
0256: if (index > curIndex)
0257: index--;
0258: }
0259:
0260: // Remove it...
0261: removeViewReference(ref, false, true);
0262: } else {
0263: // It's not a fastview, make it one
0264: makeFast(ref, true, false);
0265: }
0266:
0267: fvList.add(index, ref);
0268:
0269: // Note that the update call will create and show the ViewStackTrimToolbar
0270: // if necessary
0271: if (update)
0272: updateTrim(id);
0273: }
0274:
0275: /**
0276: * Create the Trim element for the stack containing the given reference
0277: *
0278: * @param suggestedSide
0279: * @param paneOrientation
0280: * @param ref
0281: * The {@link IViewReference} whose stack needs trim creation.
0282: */
0283: private ViewStackTrimToolBar getTrimForViewStack(String id,
0284: int suggestedSide, int paneOrientation) {
0285: // Do we already have one??
0286: ViewStackTrimToolBar trim = (ViewStackTrimToolBar) tbm
0287: .getTrim(id);
0288: if (trim == null) {
0289: int cachedSide = tbm.getPreferredArea(id);
0290: if (cachedSide != -1)
0291: suggestedSide = cachedSide;
0292:
0293: IWindowTrim beforeMe = tbm.getPreferredLocation(id);
0294:
0295: trim = new ViewStackTrimToolBar(id, suggestedSide,
0296: paneOrientation, wbw);
0297: tbm.addTrim(suggestedSide, trim, beforeMe);
0298: updateTrim(trim.getId());
0299: }
0300:
0301: return trim;
0302: }
0303:
0304: /**
0305: * Causes the trim element associated with the id to synch itself with the
0306: * current list of views. This method will create a new ViewStackTrimToolbar
0307: * if necessary (i.e. on the first call after views have been added to the map)
0308: * and will also hide the trim element when the number of views in the mapped
0309: * list goes to zero.
0310: *
0311: * @param id
0312: * The id of the {@link IWindowTrim} to update
0313: */
0314: private void updateTrim(String id) {
0315: // Get the trim part from the trim manager
0316: IWindowTrim trim = tbm.getTrim(id);
0317:
0318: // If it's not there there's not much we can do
0319: if (trim == null)
0320: return;
0321:
0322: // If there are no fast views for the bar then hide it
0323: List fvs = (List) idToFastViewsMap.get(id);
0324: if (fvs != null && fvs.size() == 0
0325: && !FastViewBar.FASTVIEWBAR_ID.equals(id)) {
0326: if (trim.getControl().getVisible()) {
0327: tbm.setTrimVisible(trim, false);
0328: tbm.forceLayout();
0329: }
0330: return;
0331: }
0332:
0333: // Ensure that the trim is displayed
0334: if (!trim.getControl().getVisible()) {
0335: tbm.setTrimVisible(trim, true);
0336: }
0337:
0338: if (trim instanceof FastViewBar) {
0339: FastViewBar fvb = (FastViewBar) trim;
0340: fvb.update(true);
0341: } else if (trim instanceof ViewStackTrimToolBar) {
0342: ViewStackTrimToolBar vstb = (ViewStackTrimToolBar) trim;
0343: vstb.update(true);
0344: vstb.getControl().pack();
0345: LayoutUtil.resize(trim.getControl());
0346: }
0347:
0348: tbm.forceLayout();
0349: }
0350:
0351: /**
0352: * Remove the view reference from its existing location
0353: *
0354: * @param ref
0355: * The {@link IViewReference} to remove
0356: */
0357: public void removeViewReference(IViewReference ref,
0358: boolean makeUnfast, boolean update) {
0359: String id = getIdForRef(ref);
0360:
0361: if (id != null) {
0362: // Remove the ref
0363: List fvList = (List) idToFastViewsMap.get(id);
0364: fvList.remove(ref);
0365:
0366: if (makeUnfast)
0367: makeFast(ref, false, false);
0368:
0369: if (update)
0370: updateTrim(id);
0371: }
0372: }
0373:
0374: /**
0375: *
0376: * @param ref
0377: * @param makeFast
0378: * @param activate
0379: */
0380: private void makeFast(IViewReference ref, boolean makeFast,
0381: boolean activate) {
0382: if (ref == null || page == null)
0383: return;
0384:
0385: if (makeFast) {
0386: page.makeFastView(ref);
0387: } else {
0388: page.removeFastView(ref);
0389:
0390: if (activate) {
0391: IWorkbenchPart toActivate = ref.getPart(true);
0392: if (toActivate != null) {
0393: page.activate(toActivate);
0394: }
0395: }
0396: }
0397: }
0398:
0399: /**
0400: * @param ref
0401: * The IViewRference to check
0402: * @return true iff the ref is in -any- list
0403: */
0404: boolean isFastView(IViewReference ref) {
0405: return getIdForRef(ref) != null;
0406: }
0407:
0408: /**
0409: * @param ref
0410: * The IViewRference to check
0411: * @return The id of the trim bar currently showing the reference or
0412: * <code>null</code> if it's not in any list
0413: */
0414: public String getIdForRef(IViewReference ref) {
0415: Iterator mapIter = idToFastViewsMap.keySet().iterator();
0416: while (mapIter.hasNext()) {
0417: String id = (String) mapIter.next();
0418: List fvList = (List) idToFastViewsMap.get(id);
0419: if (fvList.contains(ref))
0420: return id;
0421: }
0422:
0423: return null;
0424: }
0425:
0426: /**
0427: * @return The side that the fast view pane should be attached to based on
0428: * the position of the trim element containing the ref.
0429: */
0430: public int getViewSide(IViewReference ref) {
0431: IWindowTrim trim = getTrimForRef(ref);
0432: if (trim == null)
0433: return SWT.BOTTOM;
0434:
0435: int curSide = SWT.BOTTOM;
0436: int paneOrientation = SWT.BOTTOM;
0437:
0438: if (trim instanceof ViewStackTrimToolBar) {
0439: curSide = ((ViewStackTrimToolBar) trim).getCurrentSide();
0440: paneOrientation = ((ViewStackTrimToolBar) trim)
0441: .getPaneOrientation();
0442: } else if (trim instanceof FastViewBar) {
0443: curSide = ((FastViewBar) trim).getSide();
0444: paneOrientation = ((FastViewBar) trim).getOrientation(ref);
0445: }
0446:
0447: // Get trim layout info
0448: Point trimCenter = Geometry.centerPoint(trim.getControl()
0449: .getBounds());
0450: Point shellCenter = Geometry.centerPoint(trim.getControl()
0451: .getShell().getClientArea());
0452:
0453: // Horizontal has to snap to either TOP or BOTTOM...
0454: if (paneOrientation == SWT.HORIZONTAL) {
0455: if (curSide == SWT.TOP || curSide == SWT.BOTTOM)
0456: return curSide;
0457:
0458: // Are we on the top or bottom 'end' of the trim area?
0459: return (trimCenter.y < shellCenter.y) ? SWT.TOP
0460: : SWT.BOTTOM;
0461: }
0462:
0463: if (paneOrientation == SWT.VERTICAL) {
0464: if (curSide == SWT.LEFT || curSide == SWT.RIGHT)
0465: return curSide;
0466:
0467: // Are we on the left or right 'end' of the trim area?
0468: return (trimCenter.x < shellCenter.x) ? SWT.LEFT
0469: : SWT.RIGHT;
0470: }
0471:
0472: return SWT.BOTTOM;
0473: }
0474:
0475: /**
0476: * Return the trim element showing the given reference
0477: *
0478: * @param ref
0479: * The reference to find
0480: * @return the IWindowTrim showing the ref
0481: */
0482: private IWindowTrim getTrimForRef(IViewReference ref) {
0483: String id = getIdForRef(ref);
0484: if (id == null)
0485: return null; // Not in trim
0486:
0487: return tbm.getTrim(id);
0488: }
0489:
0490: /**
0491: * @return a List of <code>IViewReference</code> sorted into the order in
0492: * which they appear in the visual stack.
0493: */
0494: private List getTrueViewOrder(ViewStack stack) {
0495: List orderedViews = new ArrayList();
0496: IPresentablePart[] parts = null;
0497: if (stack.getPresentation() instanceof TabbedStackPresentation) {
0498: TabbedStackPresentation tsp = (TabbedStackPresentation) stack
0499: .getPresentation();
0500: // KLUDGE!! uses a 'testing only' API to get the parts in their 'visible' order
0501: parts = tsp.getPartList();
0502: }
0503:
0504: // If we didn't get the parts from the tab list then try the presentable part API
0505: // ViewStack's declared 'no title' fail the call above, returning an empty array
0506: if (parts == null || parts.length == 0) {
0507: // We'll have to process the parts in the order given...
0508: // This is certain to fail on drag re-ordering of the
0509: // icons in the trim since we have no API to inform the
0510: // custom presentation
0511: List partList = stack.getPresentableParts();
0512: parts = (IPresentablePart[]) partList
0513: .toArray(new IPresentablePart[partList.size()]);
0514: }
0515:
0516: // Now, process the parts...
0517: for (int i = 0; i < parts.length; i++) {
0518: if (parts[i] instanceof PresentablePart) {
0519: PresentablePart part = (PresentablePart) parts[i];
0520: IWorkbenchPartReference ref = part.getPane()
0521: .getPartReference();
0522: if (ref instanceof IViewReference)
0523: orderedViews.add(ref);
0524: }
0525: }
0526:
0527: return orderedViews;
0528: }
0529:
0530: public void moveToTrim(ViewStack vs, boolean restoreOnUnzoom) {
0531: // Don't do anything when initializing...
0532: if (vs.getBounds().width == 0)
0533: return; // indicates that we're startin up
0534:
0535: // If we're part of a 'maximize' operation then use the cached
0536: // bounds...
0537: Rectangle stackBounds = perspective.getPresentation()
0538: .getCachedBoundsFor(vs.getID());
0539:
0540: // OK, no cache means that we use the current stack position
0541: if (stackBounds == null)
0542: stackBounds = vs.getBounds();
0543:
0544: int paneOrientation = (stackBounds.width > stackBounds.height) ? SWT.HORIZONTAL
0545: : SWT.VERTICAL;
0546:
0547: // Remember the tab that was selected when we minimized
0548: String selId = ""; //$NON-NLS-1$
0549: PartPane selectedTab = vs.getSelection();
0550: if (selectedTab != null)
0551: selId = selectedTab.getCompoundId();
0552:
0553: vs.deferUpdates(true);
0554:
0555: // animate the minimize
0556: RectangleAnimationFeedbackBase animation = (RectangleAnimationFeedbackBase) getDeferrableAnimation()
0557: .getFeedback();
0558: animation.addStartRect(vs.getControl());
0559:
0560: //long startTick = System.currentTimeMillis();
0561: // Update the model first
0562: List toMove = getTrueViewOrder(vs);
0563: for (Iterator viewIter = toMove.iterator(); viewIter.hasNext();) {
0564: IViewReference ref = (IViewReference) viewIter.next();
0565: addViewReference(vs.getID(), -1, ref, false);
0566: }
0567:
0568: vs.deferUpdates(false);
0569:
0570: // Find (or create) the trim stack to move to
0571: ViewStackTrimToolBar vstb = getTrimForViewStack(vs.getID(),
0572: perspective.calcStackSide(stackBounds), paneOrientation);
0573: vstb.setRestoreOnUnzoom(restoreOnUnzoom);
0574: vstb.setSelectedTabId(selId);
0575: updateTrim(vstb.getId());
0576:
0577: //System.out.println("minimize time: " + (System.currentTimeMillis()-startTick)); //$NON-NLS-1$
0578: if (vstb != null) {
0579: animation.addEndRect(vstb.getControl());
0580: scheduleDeferrableAnimation();
0581: }
0582: }
0583:
0584: /**
0585: * Restore the trim element representing a ViewStack back into the
0586: * presentation.
0587: *
0588: * @param viewStackTrimToolBar
0589: * The trim version to restore
0590: */
0591: public void restoreToPresentation(String id) {
0592: ViewStackTrimToolBar vstb = getViewStackTrimToolbar(id);
0593:
0594: // The IntroPart uses the old min/max behavior; ensure that
0595: // we were really a minimized trim stack
0596: if (vstb == null)
0597: return;
0598:
0599: // remove any showing fast view
0600: page.hideFastView();
0601:
0602: // The stored id may be 'compound' if it's a multi-instance
0603: // view; split out the secondary id (if any)
0604: String selectedTabId = vstb.getSelectedTabId();
0605: String[] idParts = Util.split(selectedTabId, ':');
0606: if (idParts[0].length() == selectedTabId.length())
0607: idParts[1] = null;
0608:
0609: List fvs = getFastViews(id);
0610: for (Iterator fvIter = fvs.iterator(); fvIter.hasNext();) {
0611: IViewReference ref = (IViewReference) fvIter.next();
0612: removeViewReference(ref, true, !fvIter.hasNext());
0613: }
0614:
0615: // Restore the correct tab to the 'top'
0616: LayoutPart stack = perspective.getPresentation().findPart(id,
0617: null);
0618: if (stack instanceof PartStack) {
0619: LayoutPart selTab = perspective.getPresentation().findPart(
0620: idParts[0], idParts[1]);
0621: if (selTab instanceof PartPane
0622: && selTab instanceof ViewPane) {
0623: ((PartStack) stack).setSelection(selTab);
0624:
0625: // activate the view if we're not doing a compound operation
0626: if (!deferringUpdates)
0627: ((ViewPane) selTab).requestActivation();
0628: }
0629: }
0630:
0631: // Hide the Trim
0632: updateTrim(id);
0633: }
0634:
0635: /**
0636: * Restore all fact view stacks created as part of a zoom
0637: */
0638: public void restoreZoomedViewStacks() {
0639: Iterator mapIter = idToFastViewsMap.keySet().iterator();
0640: while (mapIter.hasNext()) {
0641: String id = (String) mapIter.next();
0642: IWindowTrim trim = tbm.getTrim(id);
0643: if (trim != null && trim instanceof ViewStackTrimToolBar) {
0644: ViewStackTrimToolBar vstb = (ViewStackTrimToolBar) trim;
0645: if (vstb.restoreOnUnzoom())
0646: restoreToPresentation(vstb.getId());
0647: }
0648: }
0649: }
0650:
0651: /**
0652: * @param ref
0653: * Sets the ref of the icon
0654: * @param selected
0655: * the selection state of the icon
0656: */
0657: public void setFastViewIconSelection(IViewReference ref,
0658: boolean selected) {
0659: String id = getIdForRef(ref);
0660: IWindowTrim trim = tbm.getTrim(id);
0661: if (trim instanceof ViewStackTrimToolBar) {
0662: ViewStackTrimToolBar vstb = (ViewStackTrimToolBar) trim;
0663: vstb.setIconSelection(ref, selected);
0664: } else if (trim instanceof FastViewBar) {
0665: FastViewBar fvb = (FastViewBar) trim;
0666: if (selected) {
0667: fvb.setSelection(ref);
0668: } else {
0669: if (ref == fvb.getSelection()) {
0670: fvb.setSelection(null);
0671: }
0672: }
0673: }
0674:
0675: }
0676:
0677: /**
0678: * Activate the manager. Called from the Perspecive's 'onActivate'
0679: */
0680: public void activate() {
0681: wbw.addPerspectiveListener(perspListener);
0682: setTrimStackVisibility(true);
0683: }
0684:
0685: /**
0686: * Activate the manager. Called from the Perspecive's 'onActivate'
0687: */
0688: public void deActivate() {
0689: wbw.removePerspectiveListener(perspListener);
0690: setTrimStackVisibility(false);
0691: }
0692:
0693: /**
0694: * Restore any trim stacks. This method is used when the presentation
0695: * is switched back to 3.0; if we aren't using the new min/max story
0696: * then we shouldn't -have- any trim stacks.
0697: */
0698: public boolean restoreAllTrimStacks() {
0699: boolean stacksWereRestored = false;
0700:
0701: Iterator mapIter = idToFastViewsMap.keySet().iterator();
0702: while (mapIter.hasNext()) {
0703: String id = (String) mapIter.next();
0704:
0705: // Skip the legacy FstViewBar
0706: if (id.equals(FastViewBar.FASTVIEWBAR_ID))
0707: continue;
0708:
0709: // Restore the views
0710: List fvs = getFastViews(id);
0711: for (Iterator fvIter = fvs.iterator(); fvIter.hasNext();) {
0712: IViewReference ref = (IViewReference) fvIter.next();
0713: removeViewReference(ref, true, !fvIter.hasNext());
0714: }
0715:
0716: // Blow the trim away
0717: IWindowTrim trim = tbm.getTrim(id);
0718: if (trim != null && trim instanceof ViewStackTrimToolBar) {
0719: tbm.removeTrim(trim);
0720: trim.getControl().dispose();
0721:
0722: stacksWereRestored = true;
0723: }
0724: }
0725:
0726: tbm.forceLayout();
0727:
0728: return stacksWereRestored;
0729: }
0730:
0731: /**
0732: * Show all non-empty trim stacks. Create the stack if necessary
0733: */
0734: private void setTrimStackVisibility(boolean visible) {
0735: Iterator mapIter = idToFastViewsMap.keySet().iterator();
0736: while (mapIter.hasNext()) {
0737: String id = (String) mapIter.next();
0738: List fvs = getFastViews(id);
0739:
0740: // Never show 'empty' stacks
0741: if (visible && fvs.size() == 0)
0742: continue;
0743:
0744: IWindowTrim trim = tbm.getTrim(id);
0745: if (trim != null && trim instanceof ViewStackTrimToolBar) {
0746: ((ViewStackTrimToolBar) trim).update(true);
0747: tbm.setTrimVisible(trim, visible);
0748: }
0749: }
0750: }
0751:
0752: public void saveState(IMemento memento) {
0753: // Output legacy fastviews
0754: FastViewBar fvb = wbw.getFastViewBar();
0755: if (fvb != null) {
0756: List fvRefs = getFastViews(FastViewBar.FASTVIEWBAR_ID);
0757: if (fvRefs.size() > 0) {
0758: IMemento childMem = memento
0759: .createChild(IWorkbenchConstants.TAG_FAST_VIEWS);
0760: Iterator itr = fvRefs.iterator();
0761: while (itr.hasNext()) {
0762: IViewReference ref = (IViewReference) itr.next();
0763: IMemento viewMemento = childMem
0764: .createChild(IWorkbenchConstants.TAG_VIEW);
0765: String id = ViewFactory.getKey(ref);
0766: viewMemento.putString(IWorkbenchConstants.TAG_ID,
0767: id);
0768: float ratio = perspective
0769: .getFastViewWidthRatio(ref);
0770: viewMemento.putFloat(IWorkbenchConstants.TAG_RATIO,
0771: ratio);
0772: }
0773: }
0774: }
0775:
0776: // Write all the current (non-empty) bars
0777: IMemento barsMemento = memento
0778: .createChild(IWorkbenchConstants.TAG_FAST_VIEW_BARS);
0779:
0780: Iterator mapIter = idToFastViewsMap.keySet().iterator();
0781: while (mapIter.hasNext()) {
0782: String id = (String) mapIter.next();
0783:
0784: // Legacy FV's are stored above...
0785: if (FastViewBar.FASTVIEWBAR_ID.equals(id))
0786: continue;
0787:
0788: List fvs = getFastViews(id);
0789: if (fvs.size() > 0) {
0790: IMemento barMemento = barsMemento
0791: .createChild(IWorkbenchConstants.TAG_FAST_VIEW_BAR);
0792: barMemento.putString(IWorkbenchConstants.TAG_ID, id);
0793:
0794: // Orientation / restore
0795: ViewStackTrimToolBar vstb = (ViewStackTrimToolBar) tbm
0796: .getTrim(id);
0797: if (vstb != null) {
0798: barMemento.putInteger(
0799: IWorkbenchConstants.TAG_FAST_VIEW_SIDE,
0800: vstb.getCurrentSide());
0801:
0802: barMemento
0803: .putInteger(
0804: IWorkbenchConstants.TAG_FAST_VIEW_ORIENTATION,
0805: vstb.getPaneOrientation());
0806:
0807: int boolVal = vstb.restoreOnUnzoom() ? 1 : 0;
0808: barMemento.putInteger(
0809: IWorkbenchConstants.TAG_FAST_VIEW_STYLE,
0810: boolVal);
0811:
0812: barMemento.putString(
0813: IWorkbenchConstants.TAG_FAST_VIEW_SEL_ID,
0814: vstb.getSelectedTabId());
0815: }
0816:
0817: IMemento viewsMem = barMemento
0818: .createChild(IWorkbenchConstants.TAG_FAST_VIEWS);
0819: Iterator itr = fvs.iterator();
0820: while (itr.hasNext()) {
0821: IMemento refMem = viewsMem
0822: .createChild(IWorkbenchConstants.TAG_VIEW);
0823: IViewReference ref = (IViewReference) itr.next();
0824:
0825: // id
0826: String viewId = ViewFactory.getKey(ref);
0827: refMem
0828: .putString(IWorkbenchConstants.TAG_ID,
0829: viewId);
0830:
0831: // width ratio
0832: float ratio = perspective
0833: .getFastViewWidthRatio(ref);
0834: refMem.putFloat(IWorkbenchConstants.TAG_RATIO,
0835: ratio);
0836: }
0837: }
0838: }
0839: }
0840:
0841: public void restoreState(IMemento memento, MultiStatus result) {
0842: // Load the fast views
0843: IMemento fastViewsMem = memento
0844: .getChild(IWorkbenchConstants.TAG_FAST_VIEWS);
0845:
0846: // -Replace- the current list with the one from the store
0847: List refsList = new ArrayList();
0848: idToFastViewsMap.put(FastViewBar.FASTVIEWBAR_ID, refsList);
0849:
0850: if (fastViewsMem != null) {
0851: IMemento[] views = fastViewsMem
0852: .getChildren(IWorkbenchConstants.TAG_VIEW);
0853: for (int x = 0; x < views.length; x++) {
0854: // Get the view details.
0855: IMemento childMem = views[x];
0856: IViewReference ref = perspective.restoreFastView(
0857: childMem, result);
0858: if (ref != null)
0859: refsList.add(ref);
0860: }
0861: }
0862:
0863: // Load the Trim Stack info
0864: IMemento barsMem = memento
0865: .getChild(IWorkbenchConstants.TAG_FAST_VIEW_BARS);
0866:
0867: // It's not there for old workspaces
0868: if (barsMem == null)
0869: return;
0870:
0871: IMemento[] bars = barsMem
0872: .getChildren(IWorkbenchConstants.TAG_FAST_VIEW_BAR);
0873: for (int i = 0; i < bars.length; i++) {
0874: final String id = bars[i]
0875: .getString(IWorkbenchConstants.TAG_ID);
0876: fastViewsMem = bars[i]
0877: .getChild(IWorkbenchConstants.TAG_FAST_VIEWS);
0878:
0879: // -Replace- the current list with the one from the store
0880: refsList = new ArrayList();
0881: idToFastViewsMap.put(id, refsList);
0882:
0883: if (fastViewsMem != null) {
0884: IMemento[] views = fastViewsMem
0885: .getChildren(IWorkbenchConstants.TAG_VIEW);
0886: result.merge(perspective.createReferences(views));
0887:
0888: // Create the trim area for the trim stack
0889: // Only create the TB if there are views in it
0890: if (views.length > 0) {
0891: final int side = bars[i].getInteger(
0892: IWorkbenchConstants.TAG_FAST_VIEW_SIDE)
0893: .intValue();
0894: final int orientation = bars[i]
0895: .getInteger(
0896: IWorkbenchConstants.TAG_FAST_VIEW_ORIENTATION)
0897: .intValue();
0898: int boolVal = bars[i].getInteger(
0899: IWorkbenchConstants.TAG_FAST_VIEW_STYLE)
0900: .intValue();
0901: final boolean restoreOnUnzoom = (boolVal > 0);
0902:
0903: final String selId = bars[i]
0904: .getString(IWorkbenchConstants.TAG_FAST_VIEW_SEL_ID);
0905:
0906: // Create the stack
0907: StartupThreading
0908: .runWithoutExceptions(new StartupRunnable() {
0909: public void runWithException()
0910: throws Throwable {
0911: ViewStackTrimToolBar vstb = getTrimForViewStack(
0912: id, side, orientation);
0913: vstb
0914: .setRestoreOnUnzoom(restoreOnUnzoom);
0915: if (selId != null)
0916: vstb.setSelectedTabId(selId);
0917: }
0918: });
0919: }
0920:
0921: for (int x = 0; x < views.length; x++) {
0922: // Get the view details.
0923: IMemento childMem = views[x];
0924: IViewReference ref = perspective.restoreFastView(
0925: childMem, result);
0926: if (ref != null)
0927: refsList.add(ref);
0928: }
0929: }
0930: }
0931: }
0932:
0933: /**
0934: * Returns the trim element for the given id if it exists. This
0935: * will not be <code>null</code> if there are entries in the
0936: * 'idToFastViewsMap' for this id.
0937: *
0938: * @param id The id of the view stack to get the trim toolbar for.
0939: */
0940: public ViewStackTrimToolBar getViewStackTrimToolbar(String id) {
0941: return (ViewStackTrimToolBar) tbm.getTrim(id);
0942: }
0943:
0944: public void printFVModel() {
0945: Iterator mapIter = idToFastViewsMap.keySet().iterator();
0946: while (mapIter.hasNext()) {
0947: String id = (String) mapIter.next();
0948: List fvList = (List) idToFastViewsMap.get(id);
0949: System.out
0950: .println("FastView: " + id + " count = " + fvList.size()); //$NON-NLS-1$//$NON-NLS-2$
0951: for (Iterator fvIter = fvList.iterator(); fvIter.hasNext();) {
0952: IViewReference ref = (IViewReference) fvIter.next();
0953: System.out.println(" Ref: " + ref.getId()); //$NON-NLS-1$
0954: }
0955: }
0956: }
0957:
0958: /**
0959: * Informs the manager that a batch operation has started
0960: * (say 'maximize', where many stacks will change state).
0961: *
0962: * @param defer
0963: * true when starting a batch operation
0964: * false when ending the operation
0965: */
0966: public void deferUpdates(boolean defer) {
0967: if (defer && !deferringUpdates) {
0968: deferringUpdates = defer;
0969:
0970: deferAnimations(true);
0971:
0972: return;
0973: }
0974:
0975: // 'false': reset and run any necessary updates
0976: deferringUpdates = false;
0977: deferAnimations(false);
0978: }
0979:
0980: /**
0981: * When 'defer' is true we create a RectangleAnimation object
0982: * to be used for any desired feedback. When ending it
0983: * schedules the animation and resets.
0984: *
0985: * @param defer
0986: * true when starting a batch operation
0987: * false when ending the operation
0988: */
0989: private void deferAnimations(boolean defer) {
0990: if (defer) {
0991: RectangleAnimationFeedbackBase feedback = ((Animations) Tweaklets
0992: .get(Animations.KEY))
0993: .createFeedback(wbw.getShell());
0994: batchAnimation = new AnimationEngine(feedback, 400);
0995: return;
0996: }
0997:
0998: if (batchAnimation != null)
0999: batchAnimation.schedule();
1000: batchAnimation = null;
1001: }
1002:
1003: /**
1004: * Returns the animation object appropriate for the deferred state
1005: * @return Either a 'one-shot' or a 'batch' animation object
1006: */
1007: private AnimationEngine getDeferrableAnimation() {
1008: if (deferringUpdates)
1009: return batchAnimation;
1010:
1011: // Create a 'one-shot' animation
1012: RectangleAnimationFeedbackBase feedback = ((Animations) Tweaklets
1013: .get(Animations.KEY)).createFeedback(wbw.getShell());
1014: oneShotAnimation = new AnimationEngine(feedback, 400);
1015: return oneShotAnimation;
1016: }
1017:
1018: private void scheduleDeferrableAnimation() {
1019: if (deferringUpdates)
1020: return;
1021:
1022: // We can only schedule the 'one-shot' animations
1023: // the batch ones are sheduled at batch end
1024: if (oneShotAnimation != null)
1025: oneShotAnimation.schedule();
1026: oneShotAnimation = null;
1027: }
1028:
1029: /**
1030: * Returns the 'bottom/right' trim stack. This is used to
1031: * match the old behavior when opening a new view that has no placeholder
1032: * in the case where there WB is maximized.
1033: *
1034: * @return The 'bottom/right' trim stack or null if there are no
1035: * defined trim stacks
1036: */
1037: public ViewStackTrimToolBar getBottomRightTrimStack() {
1038: ViewStackTrimToolBar blTrimStack = null;
1039: Point blPt = new Point(0, 0);
1040:
1041: Iterator mapIter = idToFastViewsMap.keySet().iterator();
1042: while (mapIter.hasNext()) {
1043: String id = (String) mapIter.next();
1044:
1045: // Skip the legacy FstViewBar
1046: if (id.equals(FastViewBar.FASTVIEWBAR_ID))
1047: continue;
1048:
1049: if (getFastViews(id).size() > 0) {
1050: // if we have views in the model then 'vstt' will not be null
1051: ViewStackTrimToolBar vstt = getViewStackTrimToolbar(id);
1052: Point loc = vstt.getControl().getLocation();
1053: if (loc.y > blPt.y
1054: || (loc.y == blPt.y && loc.x > blPt.x)) {
1055: blPt = loc;
1056: blTrimStack = vstt;
1057: }
1058: }
1059: }
1060:
1061: return blTrimStack;
1062: }
1063: }
|