001: /*******************************************************************************
002: * Copyright (c) 2005, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.internal;
011:
012: import org.eclipse.core.runtime.IConfigurationElement;
013: import org.eclipse.core.runtime.IStatus;
014: import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
015: import org.eclipse.jface.action.ContributionManager;
016: import org.eclipse.jface.action.IAction;
017: import org.eclipse.jface.resource.ImageDescriptor;
018: import org.eclipse.osgi.util.NLS;
019: import org.eclipse.swt.SWT;
020: import org.eclipse.swt.layout.FillLayout;
021: import org.eclipse.swt.widgets.Composite;
022: import org.eclipse.ui.IKeyBindingService;
023: import org.eclipse.ui.IMemento;
024: import org.eclipse.ui.IViewPart;
025: import org.eclipse.ui.IViewReference;
026: import org.eclipse.ui.IWorkbenchPage;
027: import org.eclipse.ui.IWorkbenchPart;
028: import org.eclipse.ui.IWorkbenchPart2;
029: import org.eclipse.ui.IWorkbenchPart3;
030: import org.eclipse.ui.PartInitException;
031: import org.eclipse.ui.PlatformUI;
032: import org.eclipse.ui.internal.misc.StatusUtil;
033: import org.eclipse.ui.internal.misc.UIStats;
034: import org.eclipse.ui.internal.registry.ViewDescriptor;
035: import org.eclipse.ui.internal.util.Util;
036: import org.eclipse.ui.menus.IMenuService;
037: import org.eclipse.ui.part.IWorkbenchPartOrientation;
038: import org.eclipse.ui.statushandlers.StatusManager;
039: import org.eclipse.ui.views.IViewDescriptor;
040: import org.eclipse.ui.views.IViewRegistry;
041:
042: class ViewReference extends WorkbenchPartReference implements
043: IViewReference {
044:
045: /**
046: *
047: */
048: private final ViewFactory factory;
049:
050: String secondaryId;
051:
052: private IMemento memento;
053:
054: private ViewActionBuilder actionBuilder;
055:
056: public ViewReference(ViewFactory factory, String id,
057: String secondaryId, IMemento memento) {
058: super ();
059: this .memento = memento;
060: this .factory = factory;
061: ViewDescriptor desc = (ViewDescriptor) this .factory.viewReg
062: .find(id);
063: ImageDescriptor iDesc = null;
064: String title = null;
065: if (desc != null) {
066: iDesc = desc.getImageDescriptor();
067: title = desc.getLabel();
068: }
069:
070: String name = null;
071:
072: if (memento != null) {
073: name = memento.getString(IWorkbenchConstants.TAG_PART_NAME);
074: IMemento propBag = memento
075: .getChild(IWorkbenchConstants.TAG_PROPERTIES);
076: if (propBag != null) {
077: IMemento[] props = propBag
078: .getChildren(IWorkbenchConstants.TAG_PROPERTY);
079: for (int i = 0; i < props.length; i++) {
080: propertyCache.put(props[i].getID(), props[i]
081: .getTextData());
082: }
083: }
084: }
085: if (name == null) {
086: name = title;
087: }
088:
089: init(id, title, "", iDesc, name, ""); //$NON-NLS-1$//$NON-NLS-2$
090: this .secondaryId = secondaryId;
091: }
092:
093: protected PartPane createPane() {
094: return new ViewPane(this , this .factory.page);
095: }
096:
097: /*
098: * (non-Javadoc)
099: *
100: * @see org.eclipse.ui.internal.WorkbenchPartReference#dispose()
101: */
102: protected void doDisposePart() {
103: IViewPart view = (IViewPart) part;
104: if (view != null) {
105: // Free action bars, pane, etc.
106: PartSite site = (PartSite) view.getSite();
107: ViewActionBars actionBars = (ViewActionBars) site
108: .getActionBars();
109: //
110: // 3.3 start
111: //
112: IMenuService menuService = (IMenuService) site
113: .getService(IMenuService.class);
114: menuService.releaseContributions((ContributionManager) site
115: .getActionBars().getMenuManager());
116: menuService.releaseContributions((ContributionManager) site
117: .getActionBars().getToolBarManager());
118: // 3.3 end
119: actionBars.dispose();
120:
121: // and now dispose the delegates since the
122: // PluginActionContributionItem
123: // can no longer do that
124: if (actionBuilder != null) {
125: actionBuilder.dispose();
126: actionBuilder = null;
127: }
128:
129: // Free the site.
130: site.dispose();
131: }
132:
133: super .doDisposePart();
134: }
135:
136: /*
137: * (non-Javadoc)
138: *
139: * @see org.eclipse.ui.IWorkbenchPartReference#getPage()
140: */
141: public IWorkbenchPage getPage() {
142: return this .factory.page;
143: }
144:
145: /*
146: * (non-Javadoc)
147: *
148: * @see org.eclipse.ui.internal.WorkbenchPartReference#getRegisteredName()
149: */
150: public String getRegisteredName() {
151: if (part != null && part.getSite() != null) {
152: return part.getSite().getRegisteredName();
153: }
154:
155: IViewRegistry reg = this .factory.viewReg;
156: IViewDescriptor desc = reg.find(getId());
157: if (desc != null) {
158: return desc.getLabel();
159: }
160: return getTitle();
161: }
162:
163: protected String computePartName() {
164: if (part instanceof IWorkbenchPart2) {
165: return super .computePartName();
166: } else {
167: return getRegisteredName();
168: }
169: }
170:
171: protected String computeContentDescription() {
172: if (part instanceof IWorkbenchPart2) {
173: return super .computeContentDescription();
174: } else {
175: String rawTitle = getRawTitle();
176:
177: if (!Util.equals(rawTitle, getRegisteredName())) {
178: return rawTitle;
179: }
180:
181: return ""; //$NON-NLS-1$
182: }
183: }
184:
185: /*
186: * (non-Javadoc)
187: *
188: * @see org.eclipse.ui.IViewReference
189: */
190: public String getSecondaryId() {
191: return secondaryId;
192: }
193:
194: /*
195: * (non-Javadoc)
196: *
197: * @see org.eclipse.ui.IViewReference#getView(boolean)
198: */
199: public IViewPart getView(boolean restore) {
200: return (IViewPart) getPart(restore);
201: }
202:
203: /*
204: * (non-Javadoc)
205: *
206: * @see org.eclipse.ui.IViewReference#isFastView()
207: */
208: public boolean isFastView() {
209: return this .factory.page.isFastView(this );
210: }
211:
212: /**
213: * Wrapper for restoring the view. First, this delegates to
214: * busyRestoreViewHelper to do the real work of restoring the view. If
215: * unable to restore the view, this method tries to substitute an error part
216: * and return success.
217: *
218: * @param factory
219: * TODO
220: * @return
221: */
222: protected IWorkbenchPart createPart() {
223:
224: // Check the status of this part
225:
226: IWorkbenchPart result = null;
227: PartInitException exception = null;
228:
229: // Try to restore the view -- this does the real work of restoring the
230: // view
231: //
232: try {
233: result = createPartHelper();
234: } catch (PartInitException e) {
235: exception = e;
236: }
237:
238: // If unable to create the part, create an error part instead
239: // and pass the error to the status handling facility
240: if (exception != null) {
241: IStatus partStatus = exception.getStatus();
242: IStatus displayStatus = StatusUtil.newStatus(partStatus,
243: WorkbenchMessages.ViewFactory_initException);
244: IStatus logStatus = StatusUtil
245: .newStatus(
246: partStatus,
247: NLS
248: .bind(
249: "Unable to create view ID {0}: {1}", getId(), partStatus.getMessage())); //$NON-NLS-1$
250:
251: // Pass the error to the status handling facility
252: StatusManager.getManager().handle(logStatus);
253: StatusManager.getManager().handle(displayStatus,
254: StatusManager.SHOW);
255:
256: IViewDescriptor desc = factory.viewReg.find(getId());
257: String label = getId();
258: if (desc != null) {
259: label = desc.getLabel();
260: }
261:
262: ErrorViewPart part = new ErrorViewPart(displayStatus);
263:
264: PartPane pane = getPane();
265: ViewSite site = new ViewSite(this , part, factory.page,
266: getId(), PlatformUI.PLUGIN_ID, label);
267: site.setActionBars(new ViewActionBars(factory.page
268: .getActionBars(), site, (ViewPane) pane));
269: try {
270: part.init(site);
271: } catch (PartInitException e) {
272: StatusUtil.handleStatus(e, StatusManager.SHOW
273: | StatusManager.LOG);
274: return null;
275: }
276: part.setPartName(label);
277:
278: Composite parent = (Composite) pane.getControl();
279: Composite content = new Composite(parent, SWT.NONE);
280: content.setLayout(new FillLayout());
281:
282: try {
283: part.createPartControl(content);
284: } catch (Exception e) {
285: content.dispose();
286: StatusUtil.handleStatus(e, StatusManager.SHOW
287: | StatusManager.LOG);
288: return null;
289: }
290:
291: result = part;
292: }
293:
294: return result;
295: }
296:
297: private IWorkbenchPart createPartHelper() throws PartInitException {
298:
299: IWorkbenchPart result = null;
300:
301: IMemento stateMem = null;
302: if (memento != null) {
303: stateMem = memento
304: .getChild(IWorkbenchConstants.TAG_VIEW_STATE);
305: }
306:
307: IViewDescriptor desc = factory.viewReg.find(getId());
308: if (desc == null) {
309: throw new PartInitException(
310: WorkbenchMessages.ViewFactory_couldNotCreate);
311: }
312:
313: // Create the part pane
314: PartPane pane = getPane();
315:
316: // Create the pane's top-level control
317: pane.createControl(factory.page.getClientComposite());
318:
319: String label = desc.getLabel(); // debugging only
320:
321: // Things that will need to be disposed if an exception occurs (they are
322: // listed here
323: // in the order they should be disposed)
324: Composite content = null;
325: IViewPart initializedView = null;
326: ViewSite site = null;
327: ViewActionBars actionBars = null;
328: // End of things that need to be explicitly disposed from the try block
329:
330: try {
331: IViewPart view = null;
332: try {
333: UIStats.start(UIStats.CREATE_PART, label);
334: view = desc.createView();
335: } finally {
336: UIStats.end(UIStats.CREATE_PART, view, label);
337: }
338:
339: if (view instanceof IWorkbenchPart3) {
340: createPartProperties((IWorkbenchPart3) view);
341: }
342: // Create site
343: site = new ViewSite(this , view, factory.page, desc);
344: actionBars = new ViewActionBars(factory.page
345: .getActionBars(), site, (ViewPane) pane);
346: site.setActionBars(actionBars);
347:
348: try {
349: UIStats.start(UIStats.INIT_PART, label);
350: view.init(site, stateMem);
351: // Once we've called init, we MUST dispose the view. Remember
352: // the fact that
353: // we've initialized the view in case an exception is thrown.
354: initializedView = view;
355:
356: } finally {
357: UIStats.end(UIStats.INIT_PART, view, label);
358: }
359:
360: if (view.getSite() != site) {
361: throw new PartInitException(
362: WorkbenchMessages.ViewFactory_siteException,
363: null);
364: }
365: int style = SWT.NONE;
366: if (view instanceof IWorkbenchPartOrientation) {
367: style = ((IWorkbenchPartOrientation) view)
368: .getOrientation();
369: }
370:
371: // Create the top-level composite
372: {
373: Composite parent = (Composite) pane.getControl();
374: content = new Composite(parent, style);
375: content.setLayout(new FillLayout());
376:
377: try {
378: UIStats.start(UIStats.CREATE_PART_CONTROL, label);
379: view.createPartControl(content);
380:
381: parent.layout(true);
382: } finally {
383: UIStats.end(UIStats.CREATE_PART_CONTROL, view,
384: label);
385: }
386: }
387:
388: // Install the part's tools and menu
389: {
390: //
391: // 3.3 start
392: //
393: IMenuService menuService = (IMenuService) site
394: .getService(IMenuService.class);
395: menuService.populateContributionManager(
396: (ContributionManager) site.getActionBars()
397: .getMenuManager(), "menu:" //$NON-NLS-1$
398: + site.getId());
399: menuService.populateContributionManager(
400: (ContributionManager) site.getActionBars()
401: .getToolBarManager(),
402: "toolbar:" + site.getId()); //$NON-NLS-1$
403: // 3.3 end
404:
405: actionBuilder = new ViewActionBuilder();
406: actionBuilder.readActionExtensions(view);
407: ActionDescriptor[] actionDescriptors = actionBuilder
408: .getExtendedActions();
409: IKeyBindingService keyBindingService = view.getSite()
410: .getKeyBindingService();
411:
412: if (actionDescriptors != null) {
413: for (int i = 0; i < actionDescriptors.length; i++) {
414: ActionDescriptor actionDescriptor = actionDescriptors[i];
415:
416: if (actionDescriptor != null) {
417: IAction action = actionDescriptors[i]
418: .getAction();
419:
420: if (action != null
421: && action.getActionDefinitionId() != null) {
422: keyBindingService
423: .registerAction(action);
424: }
425: }
426: }
427: }
428:
429: site.getActionBars().updateActionBars();
430: }
431:
432: // The editor should now be fully created. Exercise its public
433: // interface, and sanity-check
434: // it wherever possible. If it's going to throw exceptions or behave
435: // badly, it's much better
436: // that it does so now while we can still cancel creation of the
437: // part.
438: PartTester.testView(view);
439:
440: result = view;
441:
442: IConfigurationElement element = (IConfigurationElement) Util
443: .getAdapter(desc, IConfigurationElement.class);
444: if (element != null) {
445: factory.page.getExtensionTracker().registerObject(
446: element.getDeclaringExtension(), view,
447: IExtensionTracker.REF_WEAK);
448: }
449: } catch (Throwable e) {
450: if ((e instanceof Error) && !(e instanceof LinkageError)) {
451: throw (Error) e;
452: }
453:
454: // An exception occurred. First deallocate anything we've allocated
455: // in the try block (see the top
456: // of the try block for a list of objects that need to be explicitly
457: // disposed)
458: if (content != null) {
459: try {
460: content.dispose();
461: } catch (RuntimeException re) {
462: StatusManager.getManager().handle(
463: StatusUtil.newStatus(
464: WorkbenchPlugin.PI_WORKBENCH, re));
465: }
466: }
467:
468: if (initializedView != null) {
469: try {
470: initializedView.dispose();
471: } catch (RuntimeException re) {
472: StatusManager.getManager().handle(
473: StatusUtil.newStatus(
474: WorkbenchPlugin.PI_WORKBENCH, re));
475: }
476: }
477:
478: if (site != null) {
479: try {
480: site.dispose();
481: } catch (RuntimeException re) {
482: StatusManager.getManager().handle(
483: StatusUtil.newStatus(
484: WorkbenchPlugin.PI_WORKBENCH, re));
485: }
486: }
487:
488: if (actionBars != null) {
489: try {
490: actionBars.dispose();
491: } catch (RuntimeException re) {
492: StatusManager.getManager().handle(
493: StatusUtil.newStatus(
494: WorkbenchPlugin.PI_WORKBENCH, re));
495: }
496: }
497:
498: throw new PartInitException(WorkbenchPlugin.getStatus(e));
499: }
500:
501: return result;
502: }
503:
504: /**
505: * The memento is that last view state saved by the workbench.
506: *
507: * @return the last state that was saved by the workbench. It can return
508: * <code>null</code>.
509: * @since 3.1.1
510: */
511: public IMemento getMemento() {
512: return memento;
513: }
514: }
|