001: /*******************************************************************************
002: * Copyright (c) 2000, 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 java.util.HashMap;
013: import java.util.Iterator;
014: import java.util.List;
015: import java.util.Map;
016:
017: import org.eclipse.core.runtime.IExtension;
018: import org.eclipse.core.runtime.IStatus;
019: import org.eclipse.core.runtime.MultiStatus;
020: import org.eclipse.core.runtime.SafeRunner;
021: import org.eclipse.core.runtime.Status;
022: import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;
023: import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
024: import org.eclipse.jface.util.SafeRunnable;
025: import org.eclipse.osgi.util.NLS;
026: import org.eclipse.ui.IMemento;
027: import org.eclipse.ui.IViewPart;
028: import org.eclipse.ui.IViewReference;
029: import org.eclipse.ui.IWorkbenchPart3;
030: import org.eclipse.ui.PartInitException;
031: import org.eclipse.ui.PlatformUI;
032: import org.eclipse.ui.views.IViewDescriptor;
033: import org.eclipse.ui.views.IViewRegistry;
034:
035: /**
036: * The ViewFactory is used to control the creation and disposal of views.
037: * It implements a reference counting strategy so that one view can be shared
038: * by more than one client.
039: */
040: /*package*/class ViewFactory implements IExtensionChangeHandler {
041:
042: private ReferenceCounter counter;
043:
044: private HashMap mementoTable = new HashMap();
045:
046: WorkbenchPage page;
047:
048: IViewRegistry viewReg;
049:
050: /**
051: * Separates a view's primary id from its secondary id in view key strings.
052: */
053: static final String ID_SEP = ":"; //$NON-NLS-1$
054:
055: /**
056: * Returns a string representing a view with the given id and (optional) secondary id,
057: * suitable for use as a key in a map.
058: *
059: * @param id primary id of the view
060: * @param secondaryId secondary id of the view or <code>null</code>
061: * @return the key
062: */
063: static String getKey(String id, String secondaryId) {
064: return secondaryId == null ? id : id + ID_SEP + secondaryId;
065: }
066:
067: /**
068: * Returns a string representing the given view reference, suitable for use as a key in a map.
069: *
070: * @param viewRef the view reference
071: * @return the key
072: */
073: static String getKey(IViewReference viewRef) {
074: return getKey(viewRef.getId(), viewRef.getSecondaryId());
075: }
076:
077: /**
078: * Extracts ths primary id portion of a compound id.
079: * @param compoundId a compound id of the form: primaryId [':' secondaryId]
080: * @return the primary id
081: */
082: static String extractPrimaryId(String compoundId) {
083: int i = compoundId.lastIndexOf(ID_SEP);
084: if (i == -1) {
085: return compoundId;
086: }
087: return compoundId.substring(0, i);
088: }
089:
090: /**
091: * Extracts ths secondary id portion of a compound id.
092: * @param compoundId a compound id of the form: primaryId [':' secondaryId]
093: * @return the secondary id, or <code>null</code> if none
094: */
095: static String extractSecondaryId(String compoundId) {
096: int i = compoundId.lastIndexOf(ID_SEP);
097: if (i == -1) {
098: return null;
099: }
100: return compoundId.substring(i + 1);
101: }
102:
103: /**
104: * Returns whether the given view id contains a wildcard. Wildcards cannot
105: * be used in regular view ids, only placeholders.
106: *
107: * @param viewId the view id
108: * @return <code>true</code> if the given view id contains a wildcard,
109: * <code>false</code> otherwise
110: *
111: * @since 3.1
112: */
113: static boolean hasWildcard(String viewId) {
114: return viewId.indexOf(PartPlaceholder.WILD_CARD) >= 0;
115: }
116:
117: /**
118: * Constructs a new view factory.
119: */
120: public ViewFactory(WorkbenchPage page, IViewRegistry reg) {
121: super ();
122: this .page = page;
123: this .viewReg = reg;
124: counter = new ReferenceCounter();
125: page.getExtensionTracker().registerHandler(this , null);
126: }
127:
128: /**
129: * Creates an instance of a view defined by id.
130: *
131: * This factory implements reference counting. The first call to this
132: * method will return a new view. Subsequent calls will return the
133: * first view with an additional reference count. The view is
134: * disposed when releaseView is called an equal number of times
135: * to getView.
136: */
137: public IViewReference createView(final String id)
138: throws PartInitException {
139: return createView(id, null);
140: }
141:
142: /**
143: * Creates an instance of a view defined by id and secondary id.
144: *
145: * This factory implements reference counting. The first call to this
146: * method will return a new view. Subsequent calls will return the
147: * first view with an additional reference count. The view is
148: * disposed when releaseView is called an equal number of times
149: * to createView.
150: */
151: public IViewReference createView(String id, String secondaryId)
152: throws PartInitException {
153: IViewDescriptor desc = viewReg.find(id);
154: // ensure that the view id is valid
155: if (desc == null) {
156: throw new PartInitException(NLS.bind(
157: WorkbenchMessages.ViewFactory_couldNotCreate, id));
158: }
159: // ensure that multiple instances are allowed if a secondary id is given
160: if (secondaryId != null) {
161: if (!desc.getAllowMultiple()) {
162: throw new PartInitException(NLS.bind(
163: WorkbenchMessages.ViewFactory_noMultiple, id));
164: }
165: }
166: String key = getKey(id, secondaryId);
167: IViewReference ref = (IViewReference) counter.get(key);
168: if (ref == null) {
169: IMemento memento = (IMemento) mementoTable.get(key);
170: ref = new ViewReference(this , id, secondaryId, memento);
171: mementoTable.remove(key);
172: counter.put(key, ref);
173: getWorkbenchPage().partAdded((ViewReference) ref);
174: } else {
175: counter.addRef(key);
176: }
177: return ref;
178: }
179:
180: /**
181: * Returns the set of views being managed by this factory
182: *
183: * @return the set of views being managed by this factory
184: */
185: public IViewReference[] getViewReferences() {
186: List values = counter.values();
187:
188: return (IViewReference[]) values
189: .toArray(new IViewReference[values.size()]);
190: }
191:
192: /**
193: * Returns the view with the given id, or <code>null</code> if not found.
194: */
195: public IViewReference getView(String id) {
196: return getView(id, null);
197: }
198:
199: /**
200: * Returns the view with the given id and secondary id, or <code>null</code> if not found.
201: */
202: public IViewReference getView(String id, String secondaryId) {
203: String key = getKey(id, secondaryId);
204: return (IViewReference) counter.get(key);
205: }
206:
207: /**
208: * @return the <code>IViewRegistry</code> used by this factory.
209: * @since 3.0
210: */
211: public IViewRegistry getViewRegistry() {
212: return viewReg;
213: }
214:
215: /**
216: * Returns a list of views which are open.
217: */
218: public IViewReference[] getViews() {
219: List list = counter.values();
220: IViewReference[] array = new IViewReference[list.size()];
221: list.toArray(array);
222: return array;
223: }
224:
225: /**
226: * @return the <code>WorkbenchPage</code> used by this factory.
227: * @since 3.0
228: */
229: public WorkbenchPage getWorkbenchPage() {
230: return page;
231: }
232:
233: /**
234: *
235: * @param viewRef
236: * @return the current reference count for the given view
237: */
238: public int getReferenceCount(IViewReference viewRef) {
239: String key = getKey(viewRef);
240: IViewReference ref = (IViewReference) counter.get(key);
241: return ref == null ? 0 : counter.getRef(key);
242: }
243:
244: /**
245: * Releases an instance of a view.
246: *
247: * This factory does reference counting. For more info see
248: * getView.
249: */
250: public void releaseView(IViewReference viewRef) {
251: String key = getKey(viewRef);
252: IViewReference ref = (IViewReference) counter.get(key);
253: if (ref == null) {
254: return;
255: }
256: int count = counter.removeRef(key);
257: if (count <= 0) {
258: getWorkbenchPage().partRemoved((ViewReference) ref);
259: }
260: }
261:
262: /**
263: * Restore view states.
264: *
265: * @param memento the <code>IMemento</code> to restore from.
266: * @return <code>IStatus</code>
267: */
268: public IStatus restoreState(IMemento memento) {
269: IMemento mem[] = memento
270: .getChildren(IWorkbenchConstants.TAG_VIEW);
271: for (int i = 0; i < mem.length; i++) {
272: //for dynamic UI - add the next line to replace subsequent code that is commented out
273: restoreViewState(mem[i]);
274: }
275: return new Status(IStatus.OK, PlatformUI.PLUGIN_ID, 0, "", null); //$NON-NLS-1$
276: }
277:
278: /**
279: * Save view states.
280: *
281: * @param memento the <code>IMemento</code> to save to.
282: * @return <code>IStatus</code>
283: */
284: public IStatus saveState(IMemento memento) {
285: final MultiStatus result = new MultiStatus(
286: PlatformUI.PLUGIN_ID, IStatus.OK,
287: WorkbenchMessages.ViewFactory_problemsSavingViews, null);
288:
289: final IViewReference refs[] = getViews();
290: for (int i = 0; i < refs.length; i++) {
291: //for dynamic UI - add the following line to replace subsequent code which is commented out
292: saveViewState(memento, refs[i], result);
293: }
294: return result;
295: }
296:
297: // for dynamic UI
298: public IMemento saveViewState(IMemento memento, IViewReference ref,
299: MultiStatus res) {
300: final MultiStatus result = res;
301: final IMemento viewMemento = memento
302: .createChild(IWorkbenchConstants.TAG_VIEW);
303: viewMemento.putString(IWorkbenchConstants.TAG_ID, ViewFactory
304: .getKey(ref));
305: if (ref instanceof ViewReference) {
306: viewMemento.putString(IWorkbenchConstants.TAG_PART_NAME,
307: ((ViewReference) ref).getPartName());
308: }
309: final IViewReference viewRef = ref;
310: final IViewPart view = (IViewPart) ref.getPart(false);
311: if (view != null) {
312: SafeRunner.run(new SafeRunnable() {
313: public void run() {
314: if (view instanceof IWorkbenchPart3) {
315: Map properties = ((IWorkbenchPart3) view)
316: .getPartProperties();
317: if (!properties.isEmpty()) {
318: IMemento propBag = viewMemento
319: .createChild(IWorkbenchConstants.TAG_PROPERTIES);
320: Iterator i = properties.entrySet()
321: .iterator();
322: while (i.hasNext()) {
323: Map.Entry entry = (Map.Entry) i.next();
324: IMemento p = propBag
325: .createChild(
326: IWorkbenchConstants.TAG_PROPERTY,
327: (String) entry.getKey());
328: p
329: .putTextData((String) entry
330: .getValue());
331: }
332: }
333: }
334: view
335: .saveState(viewMemento
336: .createChild(IWorkbenchConstants.TAG_VIEW_STATE));
337: }
338:
339: public void handleException(Throwable e) {
340: result
341: .add(new Status(
342: IStatus.ERROR,
343: PlatformUI.PLUGIN_ID,
344: 0,
345: NLS
346: .bind(
347: WorkbenchMessages.ViewFactory_couldNotSave,
348: viewRef.getTitle()),
349: e));
350: }
351: });
352: } else {
353: IMemento mem = null;
354: IMemento props = null;
355:
356: // if we've created the reference once, any previous workbench
357: // state memento is there. After once, there is no previous
358: // session state, so it should be null.
359: if (ref instanceof ViewReference) {
360: mem = ((ViewReference) ref).getMemento();
361: if (mem != null) {
362: props = mem
363: .getChild(IWorkbenchConstants.TAG_PROPERTIES);
364: }
365: if (mem != null) {
366: mem = mem
367: .getChild(IWorkbenchConstants.TAG_VIEW_STATE);
368: }
369: }
370: if (props != null) {
371: viewMemento.createChild(
372: IWorkbenchConstants.TAG_PROPERTIES).putMemento(
373: props);
374: }
375: if (mem != null) {
376: IMemento child = viewMemento
377: .createChild(IWorkbenchConstants.TAG_VIEW_STATE);
378: child.putMemento(mem);
379: }
380: }
381: return viewMemento;
382: }
383:
384: // for dynamic UI
385: public void restoreViewState(IMemento memento) {
386: String compoundId = memento
387: .getString(IWorkbenchConstants.TAG_ID);
388: mementoTable.put(compoundId, memento);
389: }
390:
391: IMemento getViewState(String key) {
392: IMemento memento = (IMemento) mementoTable.get(key);
393:
394: if (memento == null) {
395: return null;
396: }
397:
398: return memento.getChild(IWorkbenchConstants.TAG_VIEW_STATE);
399: }
400:
401: /* (non-Javadoc)
402: * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#removeExtension(org.eclipse.core.runtime.IExtension, java.lang.Object[])
403: */
404: public void removeExtension(IExtension source, Object[] objects) {
405: for (int i = 0; i < objects.length; i++) {
406: if (objects[i] instanceof IViewPart) {
407: IViewPart part = (IViewPart) objects[i];
408: // String primaryViewId = part.getViewSite().getId();
409: // String secondaryViewId = part.getViewSite().getSecondaryId();
410: // IViewReference viewRef = page.findViewReference(
411: // primaryViewId, secondaryViewId);
412: // IPerspectiveDescriptor[] descs =
413: // page.getOpenedPerspectives();
414: // Perspective active = page.getActivePerspective();
415: // for (int i = 0; i < descs.length; i++) {
416: // Perspective nextPerspective = page.findPerspective(descs[i]);
417: //
418: // if (nextPerspective == null || active == nextPerspective)
419: // continue;
420: //
421: // page.hideView(nextPerspective, viewRef);
422: // }
423: page.hideView(part);
424: }
425:
426: }
427: }
428:
429: /* (non-Javadoc)
430: * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#addExtension(org.eclipse.core.runtime.dynamicHelpers.IExtensionTracker, org.eclipse.core.runtime.IExtension)
431: */
432: public void addExtension(IExtensionTracker tracker,
433: IExtension extension) {
434: //Do nothing
435: }
436:
437: }
|