0001: /*******************************************************************************
0002: * Copyright (c) 2000, 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.part;
0011:
0012: import java.util.HashMap;
0013: import java.util.Iterator;
0014: import java.util.Map;
0015: import java.util.Set;
0016:
0017: import org.eclipse.core.commands.common.EventManager;
0018: import org.eclipse.core.runtime.Platform;
0019: import org.eclipse.jface.action.IAction;
0020: import org.eclipse.jface.util.IPropertyChangeListener;
0021: import org.eclipse.jface.util.PropertyChangeEvent;
0022: import org.eclipse.jface.util.SafeRunnable;
0023: import org.eclipse.jface.viewers.IPostSelectionProvider;
0024: import org.eclipse.jface.viewers.ISelection;
0025: import org.eclipse.jface.viewers.ISelectionChangedListener;
0026: import org.eclipse.jface.viewers.ISelectionProvider;
0027: import org.eclipse.jface.viewers.SelectionChangedEvent;
0028: import org.eclipse.jface.viewers.StructuredSelection;
0029: import org.eclipse.swt.SWT;
0030: import org.eclipse.swt.widgets.Composite;
0031: import org.eclipse.swt.widgets.Control;
0032: import org.eclipse.ui.IActionBars;
0033: import org.eclipse.ui.IPartListener;
0034: import org.eclipse.ui.IViewSite;
0035: import org.eclipse.ui.IWorkbenchPart;
0036: import org.eclipse.ui.PartInitException;
0037: import org.eclipse.ui.SubActionBars;
0038: import org.eclipse.ui.internal.WorkbenchPlugin;
0039: import org.eclipse.ui.internal.util.Util;
0040:
0041: /**
0042: * Abstract superclass of all multi-page workbench views.
0043: * <p>
0044: * Within the workbench there are many views which track the active part. If a
0045: * part is activated these views display some properties for the active part. A
0046: * simple example is the <code>Outline View</code>, which displays the
0047: * outline for the active editor. To avoid loss of context when part activation
0048: * changes, these views may implement a multi-page approach. A separate page is
0049: * maintained within the view for each source view. If a part is activated the
0050: * associated page for the part is brought to top. If a part is closed the
0051: * associated page is disposed. <code>PageBookView</code> is a base
0052: * implementation for multi page views.
0053: * </p>
0054: * <p>
0055: * <code>PageBookView</code>s provide an <code>IPageSite</code> for each of
0056: * their pages. This site is supplied during the page's initialization. The page
0057: * may supply a selection provider for this site. <code>PageBookView</code>s
0058: * deal with these selection providers in a similar way to a workbench page's
0059: * <code>SelectionService</code>. When a page is made visible, if its site
0060: * has a selection provider, then changes in the selection are listened for and
0061: * the current selection is obtained and fired as a selection change event.
0062: * Selection changes are no longer listened for when a page is made invisible.
0063: * </p>
0064: * <p>
0065: * This class should be subclassed by clients wishing to define new multi-page
0066: * views.
0067: * </p>
0068: * <p>
0069: * When a <code>PageBookView</code> is created the following methods are
0070: * invoked. Subclasses must implement these.
0071: * <ul>
0072: * <li><code>createDefaultPage</code> - called to create a default page for
0073: * the view. This page is displayed when the active part in the workbench does
0074: * not have a page.</li>
0075: * <li><code>getBootstrapPart</code> - called to determine the active part in
0076: * the workbench. A page will be created for this part</li>
0077: * </ul>
0078: * </p>
0079: * <p>
0080: * When a part is activated the base implementation does not know if a page
0081: * should be created for the part. Therefore, it delegates creation to the
0082: * subclass.
0083: * <ul>
0084: * <li><code>isImportant</code> - called when a workbench part is activated.
0085: * Subclasses return whether a page should be created for the new part.</li>
0086: * <li><code>doCreatePage</code> - called to create a page for a particular
0087: * part in the workbench. This is only invoked when <code>isImportant</code>
0088: * returns </code>true</code>.</li>
0089: * </ul>
0090: * </p>
0091: * <p>
0092: * When a part is closed the base implementation will destroy the page
0093: * associated with the particular part. The page was created by a subclass, so
0094: * the subclass must also destroy it. Subclasses must implement these.
0095: * <ul>
0096: * <li><code>doDestroyPage</code> - called to destroy a page for a particular
0097: * part in the workbench.</li>
0098: * </ul>
0099: * </p>
0100: */
0101: public abstract class PageBookView extends ViewPart implements
0102: IPartListener {
0103: /**
0104: * The pagebook control, or <code>null</code> if not initialized.
0105: */
0106: private PageBook book;
0107:
0108: /**
0109: * The page record for the default page.
0110: */
0111: private PageRec defaultPageRec;
0112:
0113: /**
0114: * Map from parts to part records (key type: <code>IWorkbenchPart</code>;
0115: * value type: <code>PartRec</code>).
0116: */
0117: private Map mapPartToRec = new HashMap();
0118:
0119: /**
0120: * Map from pages to view sites Note that view sites were not added to page
0121: * recs to avoid breaking binary compatibility with previous builds
0122: */
0123: private Map mapPageToSite = new HashMap();
0124:
0125: /**
0126: * Map from pages to the number of pageRecs actively associated with a page.
0127: */
0128: private Map mapPageToNumRecs = new HashMap();
0129:
0130: /**
0131: * The page rec which provided the current page or <code>null</code>
0132: */
0133: private PageRec activeRec;
0134:
0135: /**
0136: * The action bar property listener.
0137: */
0138: private IPropertyChangeListener actionBarPropListener = new IPropertyChangeListener() {
0139: public void propertyChange(PropertyChangeEvent event) {
0140: if (event.getProperty().equals(
0141: SubActionBars.P_ACTION_HANDLERS)
0142: && activeRec != null
0143: && event.getSource() == activeRec.subActionBars) {
0144: refreshGlobalActionHandlers();
0145: }
0146: }
0147: };
0148:
0149: /**
0150: * Selection change listener to listen for page selection changes
0151: */
0152: private ISelectionChangedListener selectionChangedListener = new ISelectionChangedListener() {
0153: public void selectionChanged(SelectionChangedEvent event) {
0154: pageSelectionChanged(event);
0155: }
0156: };
0157:
0158: /**
0159: * Selection change listener to listen for page selection changes
0160: */
0161: private ISelectionChangedListener postSelectionListener = new ISelectionChangedListener() {
0162: public void selectionChanged(SelectionChangedEvent event) {
0163: postSelectionChanged(event);
0164: }
0165: };
0166:
0167: /**
0168: * Selection provider for this view's site
0169: */
0170: private SelectionProvider selectionProvider = new SelectionProvider();
0171:
0172: /**
0173: * A data structure used to store the information about a single page within
0174: * a pagebook view.
0175: */
0176: protected static class PageRec {
0177:
0178: /**
0179: * The part.
0180: */
0181: public IWorkbenchPart part;
0182:
0183: /**
0184: * The page.
0185: */
0186: public IPage page;
0187:
0188: /**
0189: * The page's action bars
0190: */
0191: public SubActionBars subActionBars;
0192:
0193: /**
0194: * Creates a new page record initialized to the given part and page.
0195: *
0196: * @param part
0197: * @param page
0198: */
0199: public PageRec(IWorkbenchPart part, IPage page) {
0200: this .part = part;
0201: this .page = page;
0202: }
0203:
0204: /**
0205: * Disposes of this page record by <code>null</code>ing its fields.
0206: */
0207: public void dispose() {
0208: part = null;
0209: page = null;
0210: }
0211: }
0212:
0213: private static class SelectionManager extends EventManager {
0214: /**
0215: *
0216: * @param listener
0217: * listen
0218: */
0219: public void addSelectionChangedListener(
0220: ISelectionChangedListener listener) {
0221: addListenerObject(listener);
0222: }
0223:
0224: /**
0225: *
0226: * @param listener
0227: * listen
0228: */
0229: public void removeSelectionChangedListener(
0230: ISelectionChangedListener listener) {
0231: removeListenerObject(listener);
0232: }
0233:
0234: /**
0235: *
0236: * @param event
0237: * the event
0238: */
0239: public void selectionChanged(final SelectionChangedEvent event) {
0240: // pass on the notification to listeners
0241: Object[] listeners = getListeners();
0242: for (int i = 0; i < listeners.length; ++i) {
0243: final ISelectionChangedListener l = (ISelectionChangedListener) listeners[i];
0244: Platform.run(new SafeRunnable() {
0245: public void run() {
0246: l.selectionChanged(event);
0247: }
0248: });
0249: }
0250: }
0251:
0252: }
0253:
0254: /**
0255: * A selection provider/listener for this view. It is a selection provider
0256: * for this view's site.
0257: */
0258: protected class SelectionProvider implements IPostSelectionProvider {
0259:
0260: private SelectionManager fSelectionListener = new SelectionManager();
0261:
0262: private SelectionManager fPostSelectionListeners = new SelectionManager();
0263:
0264: /*
0265: * (non-Javadoc) Method declared on ISelectionProvider.
0266: */
0267: public void addSelectionChangedListener(
0268: ISelectionChangedListener listener) {
0269: fSelectionListener.addSelectionChangedListener(listener);
0270: }
0271:
0272: /*
0273: * (non-Javadoc) Method declared on ISelectionProvider.
0274: */
0275: public ISelection getSelection() {
0276: // get the selection provider from the current page
0277: IPage currentPage = getCurrentPage();
0278: // during workbench startup we may be in a state when
0279: // there is no current page
0280: if (currentPage == null) {
0281: return StructuredSelection.EMPTY;
0282: }
0283: IPageSite site = getPageSite(currentPage);
0284: if (site == null) {
0285: return StructuredSelection.EMPTY;
0286: }
0287: ISelectionProvider selProvider = site
0288: .getSelectionProvider();
0289: if (selProvider != null) {
0290: return selProvider.getSelection();
0291: }
0292: return StructuredSelection.EMPTY;
0293: }
0294:
0295: /*
0296: * (non-Javadoc) Method declared on ISelectionProvider.
0297: */
0298: public void removeSelectionChangedListener(
0299: ISelectionChangedListener listener) {
0300: fSelectionListener.removeSelectionChangedListener(listener);
0301: }
0302:
0303: /**
0304: * The selection has changed. Process the event, notifying selection
0305: * listeners and post selection listeners.
0306: *
0307: * @param event
0308: * the change
0309: */
0310: public void selectionChanged(final SelectionChangedEvent event) {
0311: fSelectionListener.selectionChanged(event);
0312: }
0313:
0314: /**
0315: * The selection has changed, so notify any post-selection listeners.
0316: *
0317: * @param event
0318: * the change
0319: */
0320: public void postSelectionChanged(
0321: final SelectionChangedEvent event) {
0322: fPostSelectionListeners.selectionChanged(event);
0323: }
0324:
0325: /*
0326: * (non-Javadoc) Method declared on ISelectionProvider.
0327: */
0328: public void setSelection(ISelection selection) {
0329: // get the selection provider from the current page
0330: IPage currentPage = getCurrentPage();
0331: // during workbench startup we may be in a state when
0332: // there is no current page
0333: if (currentPage == null) {
0334: return;
0335: }
0336: IPageSite site = getPageSite(currentPage);
0337: if (site == null) {
0338: return;
0339: }
0340: ISelectionProvider selProvider = site
0341: .getSelectionProvider();
0342: // and set its selection
0343: if (selProvider != null) {
0344: selProvider.setSelection(selection);
0345: }
0346: }
0347:
0348: /*
0349: * (non-Javadoc)
0350: *
0351: * @see org.eclipse.jface.viewers.IPostSelectionProvider#addPostSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
0352: */
0353: public void addPostSelectionChangedListener(
0354: ISelectionChangedListener listener) {
0355: fPostSelectionListeners
0356: .addSelectionChangedListener(listener);
0357: }
0358:
0359: /*
0360: * (non-Javadoc)
0361: *
0362: * @see org.eclipse.jface.viewers.IPostSelectionProvider#removePostSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
0363: */
0364: public void removePostSelectionChangedListener(
0365: ISelectionChangedListener listener) {
0366: fPostSelectionListeners
0367: .removeSelectionChangedListener(listener);
0368: }
0369: }
0370:
0371: /**
0372: * Creates a new pagebook view.
0373: */
0374: protected PageBookView() {
0375: super ();
0376: }
0377:
0378: /**
0379: * Creates and returns the default page for this view.
0380: * <p>
0381: * Subclasses must implement this method.
0382: * </p>
0383: * <p>
0384: * Subclasses must call initPage with the new page (if it is an
0385: * <code>IPageBookViewPage</code>) before calling createControl on the
0386: * page.
0387: * </p>
0388: *
0389: * @param book
0390: * the pagebook control
0391: * @return the default page
0392: */
0393: protected abstract IPage createDefaultPage(PageBook book);
0394:
0395: /**
0396: * Creates a page for a given part. Adds it to the pagebook but does not
0397: * show it.
0398: *
0399: * @param part
0400: * The part we are making a page for.
0401: * @return IWorkbenchPart
0402: */
0403: private PageRec createPage(IWorkbenchPart part) {
0404: PageRec rec = doCreatePage(part);
0405: if (rec != null) {
0406: mapPartToRec.put(part, rec);
0407: preparePage(rec);
0408: }
0409: return rec;
0410: }
0411:
0412: /**
0413: * Prepares the page in the given page rec for use in this view.
0414: *
0415: * @param rec
0416: */
0417: private void preparePage(PageRec rec) {
0418: IPageSite site = null;
0419: Integer count;
0420:
0421: if (!doesPageExist(rec.page)) {
0422: if (rec.page instanceof IPageBookViewPage) {
0423: site = ((IPageBookViewPage) rec.page).getSite();
0424: }
0425: if (site == null) {
0426: // We will create a site for our use
0427: site = new PageSite(getViewSite());
0428: }
0429: mapPageToSite.put(rec.page, site);
0430:
0431: rec.subActionBars = (SubActionBars) site.getActionBars();
0432: rec.subActionBars
0433: .addPropertyChangeListener(actionBarPropListener);
0434: // for backward compability with IPage
0435: rec.page.setActionBars(rec.subActionBars);
0436:
0437: count = new Integer(0);
0438: } else {
0439: site = (IPageSite) mapPageToSite.get(rec.page);
0440: rec.subActionBars = (SubActionBars) site.getActionBars();
0441: count = ((Integer) mapPageToNumRecs.get(rec.page));
0442: }
0443:
0444: mapPageToNumRecs.put(rec.page,
0445: new Integer(count.intValue() + 1));
0446: }
0447:
0448: /**
0449: * Initializes the given page with a page site.
0450: * <p>
0451: * Subclasses should call this method after the page is created but before
0452: * creating its controls.
0453: * </p>
0454: * <p>
0455: * Subclasses may override
0456: * </p>
0457: *
0458: * @param page
0459: * The page to initialize
0460: */
0461: protected void initPage(IPageBookViewPage page) {
0462: try {
0463: page.init(new PageSite(getViewSite()));
0464: } catch (PartInitException e) {
0465: WorkbenchPlugin.log(getClass(), "initPage", e); //$NON-NLS-1$
0466: }
0467: }
0468:
0469: /**
0470: * The <code>PageBookView</code> implementation of this
0471: * <code>IWorkbenchPart</code> method creates a <code>PageBook</code>
0472: * control with its default page showing. Subclasses may extend.
0473: */
0474: public void createPartControl(Composite parent) {
0475:
0476: // Create the page book.
0477: book = new PageBook(parent, SWT.NONE);
0478:
0479: // Create the default page rec.
0480: IPage defaultPage = createDefaultPage(book);
0481: defaultPageRec = new PageRec(null, defaultPage);
0482: preparePage(defaultPageRec);
0483:
0484: // Show the default page
0485: showPageRec(defaultPageRec);
0486:
0487: // Listen to part activation events.
0488: getSite().getPage().addPartListener(this );
0489: showBootstrapPart();
0490: }
0491:
0492: /**
0493: * The <code>PageBookView</code> implementation of this
0494: * <code>IWorkbenchPart</code> method cleans up all the pages. Subclasses
0495: * may extend.
0496: */
0497: public void dispose() {
0498: // stop listening to part activation
0499: getSite().getPage().removePartListener(this );
0500:
0501: // Deref all of the pages.
0502: activeRec = null;
0503: if (defaultPageRec != null) {
0504: // check for null since the default page may not have
0505: // been created (ex. perspective never visible)
0506: defaultPageRec.page.dispose();
0507: defaultPageRec = null;
0508: }
0509: Map clone = (Map) ((HashMap) mapPartToRec).clone();
0510: Iterator itr = clone.values().iterator();
0511: while (itr.hasNext()) {
0512: PageRec rec = (PageRec) itr.next();
0513: removePage(rec);
0514: }
0515:
0516: // Run super.
0517: super .dispose();
0518: }
0519:
0520: /**
0521: * Creates a new page in the pagebook for a particular part. This page will
0522: * be made visible whenever the part is active, and will be destroyed with a
0523: * call to <code>doDestroyPage</code>.
0524: * <p>
0525: * Subclasses must implement this method.
0526: * </p>
0527: * <p>
0528: * Subclasses must call initPage with the new page (if it is an
0529: * <code>IPageBookViewPage</code>) before calling createControl on the
0530: * page.
0531: * </p>
0532: *
0533: * @param part
0534: * the input part
0535: * @return the record describing a new page for this view
0536: * @see #doDestroyPage
0537: */
0538: protected abstract PageRec doCreatePage(IWorkbenchPart part);
0539:
0540: /**
0541: * Destroys a page in the pagebook for a particular part. This page was
0542: * returned as a result from <code>doCreatePage</code>.
0543: * <p>
0544: * Subclasses must implement this method.
0545: * </p>
0546: *
0547: * @param part
0548: * the input part
0549: * @param pageRecord
0550: * a page record for the part
0551: * @see #doCreatePage
0552: */
0553: protected abstract void doDestroyPage(IWorkbenchPart part,
0554: PageRec pageRecord);
0555:
0556: /**
0557: * Returns true if the page has already been created.
0558: *
0559: * @param page
0560: * the page to test
0561: * @return true if this page has already been created.
0562: */
0563: protected boolean doesPageExist(IPage page) {
0564: return mapPageToNumRecs.containsKey(page);
0565: }
0566:
0567: /**
0568: * The <code>PageBookView</code> implementation of this
0569: * <code>IAdaptable</code> method delegates to the current page, if it
0570: * implements <code>IAdaptable</code>.
0571: */
0572: public Object getAdapter(Class key) {
0573: // delegate to the current page, if supported
0574: IPage page = getCurrentPage();
0575: Object adapter = Util.getAdapter(page, key);
0576: if (adapter != null) {
0577: return adapter;
0578: }
0579: // if the page did not find the adapter, look for one provided by
0580: // this view before delegating to super.
0581: adapter = getViewAdapter(key);
0582: if (adapter != null) {
0583: return adapter;
0584: }
0585: // delegate to super
0586: return super .getAdapter(key);
0587: }
0588:
0589: /**
0590: * Returns an adapter of the specified type, as provided by this view (not
0591: * the current page), or <code>null</code> if this view does not provide
0592: * an adapter of the specified adapter.
0593: * <p>
0594: * The default implementation returns <code>null</code>. Subclasses may
0595: * override.
0596: * </p>
0597: *
0598: * @param adapter
0599: * the adapter class to look up
0600: * @return a object castable to the given class, or <code>null</code> if
0601: * this object does not have an adapter for the given class
0602: * @since 3.2
0603: */
0604: protected Object getViewAdapter(Class adapter) {
0605: return null;
0606: }
0607:
0608: /**
0609: * Returns the active, important workbench part for this view.
0610: * <p>
0611: * When the page book view is created it has no idea which part within the
0612: * workbook should be used to generate the first page. Therefore, it
0613: * delegates the choice to subclasses of <code>PageBookView</code>.
0614: * </p>
0615: * <p>
0616: * Implementors of this method should return an active, important part in
0617: * the workbench or <code>null</code> if none found.
0618: * </p>
0619: * <p>
0620: * Subclasses must implement this method.
0621: * </p>
0622: *
0623: * @return the active important part, or <code>null</code> if none
0624: */
0625: protected abstract IWorkbenchPart getBootstrapPart();
0626:
0627: /**
0628: * Returns the part which contributed the current page to this view.
0629: *
0630: * @return the part which contributed the current page or <code>null</code>
0631: * if no part contributed the current page
0632: */
0633: protected IWorkbenchPart getCurrentContributingPart() {
0634: if (activeRec == null) {
0635: return null;
0636: }
0637: return activeRec.part;
0638: }
0639:
0640: /**
0641: * Returns the currently visible page for this view or <code>null</code>
0642: * if no page is currently visible.
0643: *
0644: * @return the currently visible page
0645: */
0646: public IPage getCurrentPage() {
0647: if (activeRec == null) {
0648: return null;
0649: }
0650: return activeRec.page;
0651: }
0652:
0653: /**
0654: * Returns the view site for the given page of this view.
0655: *
0656: * @param page
0657: * the page
0658: * @return the corresponding site, or <code>null</code> if not found
0659: */
0660: protected PageSite getPageSite(IPage page) {
0661: return (PageSite) mapPageToSite.get(page);
0662: }
0663:
0664: /**
0665: * Returns the default page for this view.
0666: *
0667: * @return the default page
0668: */
0669: public IPage getDefaultPage() {
0670: return defaultPageRec.page;
0671: }
0672:
0673: /**
0674: * Returns the pagebook control for this view.
0675: *
0676: * @return the pagebook control, or <code>null</code> if not initialized
0677: */
0678: protected PageBook getPageBook() {
0679: return book;
0680: }
0681:
0682: /**
0683: * Returns the page record for the given part.
0684: *
0685: * @param part
0686: * the part
0687: * @return the corresponding page record, or <code>null</code> if not
0688: * found
0689: */
0690: protected PageRec getPageRec(IWorkbenchPart part) {
0691: return (PageRec) mapPartToRec.get(part);
0692: }
0693:
0694: /**
0695: * Returns the page record for the given page of this view.
0696: *
0697: * @param page
0698: * the page
0699: * @return the corresponding page record, or <code>null</code> if not
0700: * found
0701: */
0702: protected PageRec getPageRec(IPage page) {
0703: Iterator itr = mapPartToRec.values().iterator();
0704: while (itr.hasNext()) {
0705: PageRec rec = (PageRec) itr.next();
0706: if (rec.page == page) {
0707: return rec;
0708: }
0709: }
0710: return null;
0711: }
0712:
0713: /**
0714: * Returns whether the given part should be added to this view.
0715: * <p>
0716: * Subclasses must implement this method.
0717: * </p>
0718: *
0719: * @param part
0720: * the input part
0721: * @return <code>true</code> if the part is relevant, and
0722: * <code>false</code> otherwise
0723: */
0724: protected abstract boolean isImportant(IWorkbenchPart part);
0725:
0726: /*
0727: * (non-Javadoc) Method declared on IViewPart.
0728: */
0729: public void init(IViewSite site) throws PartInitException {
0730: site.setSelectionProvider(selectionProvider);
0731: super .init(site);
0732: }
0733:
0734: /**
0735: * The <code>PageBookView</code> implementation of this
0736: * <code>IPartListener</code> method shows the page when the given part is
0737: * activated. Subclasses may extend.
0738: */
0739: public void partActivated(IWorkbenchPart part) {
0740: // Is this an important part? If not just return.
0741: if (!isImportant(part)) {
0742: return;
0743: }
0744:
0745: // Create a page for the part.
0746: PageRec rec = getPageRec(part);
0747: if (rec == null) {
0748: rec = createPage(part);
0749: }
0750:
0751: // Show the page.
0752: if (rec != null) {
0753: showPageRec(rec);
0754: } else {
0755: showPageRec(defaultPageRec);
0756: }
0757: }
0758:
0759: /**
0760: * The <code>PageBookView</code> implementation of this
0761: * <code>IPartListener</code> method does nothing. Subclasses may extend.
0762: */
0763: public void partBroughtToTop(IWorkbenchPart part) {
0764: // Do nothing by default
0765: }
0766:
0767: /**
0768: * The <code>PageBookView</code> implementation of this
0769: * <code>IPartListener</code> method deal with the closing of the active
0770: * part. Subclasses may extend.
0771: */
0772: public void partClosed(IWorkbenchPart part) {
0773: // Update the active part.
0774: if (activeRec != null && activeRec.part == part) {
0775: showPageRec(defaultPageRec);
0776: }
0777:
0778: // Find and remove the part page.
0779: PageRec rec = getPageRec(part);
0780: if (rec != null) {
0781: removePage(rec);
0782: }
0783: }
0784:
0785: /**
0786: * The <code>PageBookView</code> implementation of this
0787: * <code>IPartListener</code> method does nothing. Subclasses may extend.
0788: */
0789: public void partDeactivated(IWorkbenchPart part) {
0790: // Do nothing.
0791: }
0792:
0793: /*
0794: * (non-Javadoc)
0795: *
0796: * @see org.eclipse.ui.IPartListener#partOpened(org.eclipse.ui.IWorkbenchPart)
0797: */
0798: public void partOpened(IWorkbenchPart part) {
0799: // Do nothing by default.
0800: }
0801:
0802: /**
0803: * Refreshes the global actions for the active page.
0804: */
0805: private void refreshGlobalActionHandlers() {
0806: // Clear old actions.
0807: IActionBars bars = getViewSite().getActionBars();
0808: bars.clearGlobalActionHandlers();
0809:
0810: // Set new actions.
0811: Map newActionHandlers = activeRec.subActionBars
0812: .getGlobalActionHandlers();
0813: if (newActionHandlers != null) {
0814: Set keys = newActionHandlers.entrySet();
0815: Iterator iter = keys.iterator();
0816: while (iter.hasNext()) {
0817: Map.Entry entry = (Map.Entry) iter.next();
0818: bars.setGlobalActionHandler((String) entry.getKey(),
0819: (IAction) entry.getValue());
0820: }
0821: }
0822: }
0823:
0824: /**
0825: * Removes a page record. If it is the last reference to the page dispose of
0826: * it - otherwise just decrement the reference count.
0827: *
0828: * @param rec
0829: */
0830: private void removePage(PageRec rec) {
0831: mapPartToRec.remove(rec.part);
0832:
0833: int newCount = ((Integer) mapPageToNumRecs.get(rec.page))
0834: .intValue() - 1;
0835:
0836: if (newCount == 0) {
0837: Object site = mapPageToSite.remove(rec.page);
0838: mapPageToNumRecs.remove(rec.page);
0839:
0840: if (rec.subActionBars != null) {
0841: rec.subActionBars.dispose();
0842: }
0843:
0844: Control control = rec.page.getControl();
0845: if (control != null && !control.isDisposed()) {
0846: // Dispose the page's control so pages don't have to do this in
0847: // their
0848: // dispose method.
0849: // The page's control is a child of this view's control so if
0850: // this view
0851: // is closed, the page's control will already be disposed.
0852: control.dispose();
0853: }
0854:
0855: if (site instanceof PageSite) {
0856: ((PageSite) site).dispose();
0857: }
0858:
0859: // free the page
0860: doDestroyPage(rec.part, rec);
0861: } else {
0862: mapPageToNumRecs.put(rec.page, new Integer(newCount));
0863: }
0864: }
0865:
0866: /*
0867: * (non-Javadoc) Method declared on IWorkbenchPart.
0868: */
0869: public void setFocus() {
0870: // first set focus on the page book, in case the page
0871: // doesn't properly handle setFocus
0872: if (book != null) {
0873: book.setFocus();
0874: }
0875: // then set focus on the page, if any
0876: if (activeRec != null) {
0877: activeRec.page.setFocus();
0878: }
0879: }
0880:
0881: /**
0882: * Handle page selection changes.
0883: *
0884: * @param event
0885: */
0886: private void pageSelectionChanged(SelectionChangedEvent event) {
0887: // forward this change from a page to our site's selection provider
0888: SelectionProvider provider = (SelectionProvider) getSite()
0889: .getSelectionProvider();
0890: if (provider != null) {
0891: provider.selectionChanged(event);
0892: }
0893: }
0894:
0895: /**
0896: * Handle page selection changes.
0897: *
0898: * @param event
0899: */
0900: private void postSelectionChanged(SelectionChangedEvent event) {
0901: // forward this change from a page to our site's selection provider
0902: SelectionProvider provider = (SelectionProvider) getSite()
0903: .getSelectionProvider();
0904: if (provider != null) {
0905: provider.postSelectionChanged(event);
0906: }
0907: }
0908:
0909: /**
0910: * Shows a page for the active workbench part.
0911: */
0912: private void showBootstrapPart() {
0913: IWorkbenchPart part = getBootstrapPart();
0914: if (part != null) {
0915: partActivated(part);
0916: }
0917: }
0918:
0919: /**
0920: * Shows page contained in the given page record in this view. The page
0921: * record must be one from this pagebook view.
0922: * <p>
0923: * The <code>PageBookView</code> implementation of this method asks the
0924: * pagebook control to show the given page's control, and records that the
0925: * given page is now current. Subclasses may extend.
0926: * </p>
0927: *
0928: * @param pageRec
0929: * the page record containing the page to show
0930: */
0931: protected void showPageRec(PageRec pageRec) {
0932: // If already showing do nothing
0933: if (activeRec == pageRec) {
0934: return;
0935: }
0936: // If the page is the same, just set activeRec to pageRec
0937: if (activeRec != null && pageRec != null
0938: && activeRec.page == pageRec.page) {
0939: activeRec = pageRec;
0940: return;
0941: }
0942:
0943: // Hide old page.
0944: if (activeRec != null) {
0945: PageSite pageSite = (PageSite) mapPageToSite
0946: .get(activeRec.page);
0947:
0948: activeRec.subActionBars.deactivate();
0949:
0950: // deactivate the nested services
0951: pageSite.deactivate();
0952:
0953: // remove our selection listener
0954: ISelectionProvider provider = pageSite
0955: .getSelectionProvider();
0956: if (provider != null) {
0957: provider
0958: .removeSelectionChangedListener(selectionChangedListener);
0959: if (provider instanceof IPostSelectionProvider) {
0960: ((IPostSelectionProvider) provider)
0961: .removePostSelectionChangedListener(postSelectionListener);
0962: }
0963: }
0964: }
0965:
0966: // Show new page.
0967: activeRec = pageRec;
0968: Control pageControl = activeRec.page.getControl();
0969: if (pageControl != null && !pageControl.isDisposed()) {
0970: PageSite pageSite = (PageSite) mapPageToSite
0971: .get(activeRec.page);
0972:
0973: // Verify that the page control is not disposed
0974: // If we are closing, it may have already been disposed
0975: book.showPage(pageControl);
0976: activeRec.subActionBars.activate();
0977: refreshGlobalActionHandlers();
0978:
0979: // activate the nested services
0980: pageSite.activate();
0981:
0982: // add our selection listener
0983: ISelectionProvider provider = pageSite
0984: .getSelectionProvider();
0985: if (provider != null) {
0986: provider
0987: .addSelectionChangedListener(selectionChangedListener);
0988: if (provider instanceof IPostSelectionProvider) {
0989: ((IPostSelectionProvider) provider)
0990: .addPostSelectionChangedListener(postSelectionListener);
0991: }
0992: }
0993: // Update action bars.
0994: getViewSite().getActionBars().updateActionBars();
0995: }
0996: }
0997:
0998: /**
0999: * Returns the selectionProvider for this page book view.
1000: *
1001: * @return a SelectionProvider
1002: */
1003: protected SelectionProvider getSelectionProvider() {
1004: return selectionProvider;
1005: }
1006: }
|