001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 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: * Brock Janiczak (brockj_eclipse@ihug.com.au) - handler registration
011: *******************************************************************************/package org.eclipse.ui.internal.registry;
012:
013: import org.eclipse.core.runtime.CoreException;
014: import org.eclipse.core.runtime.IConfigurationElement;
015: import org.eclipse.core.runtime.IStatus;
016: import org.eclipse.core.runtime.Status;
017: import org.eclipse.jface.resource.ImageDescriptor;
018: import org.eclipse.ui.IMemento;
019: import org.eclipse.ui.IPerspectiveDescriptor;
020: import org.eclipse.ui.IPerspectiveFactory;
021: import org.eclipse.ui.IPluginContribution;
022: import org.eclipse.ui.PlatformUI;
023: import org.eclipse.ui.internal.IWorkbenchConstants;
024: import org.eclipse.ui.internal.IWorkbenchGraphicConstants;
025: import org.eclipse.ui.internal.WorkbenchImages;
026: import org.eclipse.ui.internal.WorkbenchPlugin;
027: import org.eclipse.ui.plugin.AbstractUIPlugin;
028:
029: /**
030: * PerspectiveDescriptor.
031: * <p>
032: * A PerspectiveDesciptor has 3 states:
033: * </p>
034: * <ol>
035: * <li>It <code>isPredefined()</code>, in which case it was defined from an
036: * extension point.</li>
037: * <li>It <code>isPredefined()</code> and <code>hasCustomFile</code>, in
038: * which case the user has customized a predefined perspective.</li>
039: * <li>It <code>hasCustomFile</code>, in which case the user created a new
040: * perspective.</li>
041: * </ol>
042: *
043: */
044: public class PerspectiveDescriptor implements IPerspectiveDescriptor,
045: IPluginContribution {
046: private String id;
047:
048: private String pluginId;
049:
050: private String originalId;
051:
052: private String label;
053:
054: private String className;
055:
056: private String description;
057:
058: private boolean singleton;
059:
060: private boolean fixed;
061:
062: private ImageDescriptor image;
063:
064: private IConfigurationElement configElement;
065:
066: /**
067: * Create a new empty descriptor.
068: *
069: * @param id
070: * the id of the new descriptor
071: * @param label
072: * the label of the new descriptor
073: * @param originalDescriptor
074: * the descriptor that this descriptor is based on
075: */
076: public PerspectiveDescriptor(String id, String label,
077: PerspectiveDescriptor originalDescriptor) {
078: this .id = id;
079: this .label = label;
080: if (originalDescriptor != null) {
081: this .originalId = originalDescriptor.getOriginalId();
082: this .image = originalDescriptor.image;
083:
084: // This perspective is based on a perspective in some bundle -- if
085: // that
086: // bundle goes away then I think it makes sense to treat this
087: // perspective
088: // the same as any other -- so store it with the original
089: // descriptor's
090: // bundle's list.
091: //
092: // It might also make sense the other way...removing the following
093: // line
094: // will allow the perspective to stay around when the originating
095: // bundle
096: // is unloaded.
097: //
098: // This might also have an impact on upgrade cases -- should we
099: // really be
100: // destroying all user customized perspectives when the older
101: // version is
102: // removed?
103: //
104: // I'm leaving this here for now since its a good example, but
105: // wouldn't be
106: // surprised if we ultimately decide on the opposite.
107: //
108: // The reason this line is important is that this is the value used
109: // to
110: // put the object into the UI level registry. When that bundle goes
111: // away,
112: // the registry will remove the entire list of objects. So if this
113: // desc
114: // has been put into that list -- it will go away.
115: this .pluginId = originalDescriptor.getPluginId();
116: }
117: }
118:
119: /**
120: * Create a descriptor from a config element.
121: *
122: * @param id
123: * the id of the element to create
124: * @param configElement
125: * the element to base this perspective on
126: * @throws CoreException
127: * thrown if there are any missing attributes
128: */
129: public PerspectiveDescriptor(String id,
130: IConfigurationElement configElement) throws CoreException {
131: this .configElement = configElement;
132: this .id = id;
133: // Sanity check.
134: if ((getId() == null) || (getLabel() == null)
135: || (getClassName() == null)) {
136: throw new CoreException(
137: new Status(
138: IStatus.ERROR,
139: WorkbenchPlugin.PI_WORKBENCH,
140: 0,
141: "Invalid extension (missing label, id or class name): " + getId(),//$NON-NLS-1$
142: null));
143: }
144: }
145:
146: /**
147: * Creates a factory for a predefined perspective. If the perspective is not
148: * predefined return <code>null</code>.
149: *
150: * @return the IPerspectiveFactory or <code>null</code>
151: * @throws CoreException
152: * if the object could not be instantiated.
153: */
154: public IPerspectiveFactory createFactory() throws CoreException {
155: // if there is an originalId, then use that descriptor instead
156: if (originalId != null) {
157: // Get the original descriptor to create the factory. If the
158: // original is gone then nothing can be done.
159: IPerspectiveDescriptor target = ((PerspectiveRegistry) WorkbenchPlugin
160: .getDefault().getPerspectiveRegistry())
161: .findPerspectiveWithId(originalId);
162:
163: return target == null ? null
164: : ((PerspectiveDescriptor) target).createFactory();
165: }
166:
167: // otherwise try to create the executable extension
168: if (configElement != null) {
169: try {
170: return (IPerspectiveFactory) configElement
171: .createExecutableExtension(IWorkbenchRegistryConstants.ATT_CLASS);
172: } catch (CoreException e) {
173: // do nothing
174: }
175: }
176:
177: return null;
178: }
179:
180: /**
181: * Deletes the custom definition for a perspective..
182: */
183: public void deleteCustomDefinition() {
184: ((PerspectiveRegistry) WorkbenchPlugin.getDefault()
185: .getPerspectiveRegistry()).deleteCustomDefinition(this );
186: }
187:
188: /*
189: * (non-Javadoc)
190: *
191: * @see org.eclipse.ui.IPerspectiveDescriptor#getDescription()
192: */
193: public String getDescription() {
194: return configElement == null ? description : RegistryReader
195: .getDescription(configElement);
196: }
197:
198: /**
199: * Returns whether or not this perspective is fixed.
200: *
201: * @return whether or not this perspective is fixed
202: */
203: public boolean getFixed() {
204: return configElement == null ? fixed
205: : Boolean
206: .valueOf(
207: configElement
208: .getAttribute(IWorkbenchRegistryConstants.ATT_FIXED))
209: .booleanValue();
210: }
211:
212: /*
213: * (non-Javadoc)
214: *
215: * @see org.eclipse.ui.IPerspectiveDescriptor#getId()
216: */
217: public String getId() {
218: return id;
219: }
220:
221: /*
222: * (non-Javadoc)
223: *
224: * @see org.eclipse.ui.IPerspectiveDescriptor#getImageDescriptor()
225: */
226: public ImageDescriptor getImageDescriptor() {
227: if (image == null) {
228: if (configElement != null) {
229: String icon = configElement
230: .getAttribute(IWorkbenchRegistryConstants.ATT_ICON);
231: if (icon != null) {
232: image = AbstractUIPlugin.imageDescriptorFromPlugin(
233: configElement.getNamespace(), icon);
234: }
235: if (image == null) {
236: image = WorkbenchImages
237: .getImageDescriptor(IWorkbenchGraphicConstants.IMG_ETOOL_DEF_PERSPECTIVE);
238: }
239: }
240: }
241: return image;
242: }
243:
244: /*
245: * (non-Javadoc)
246: *
247: * @see org.eclipse.ui.IPerspectiveDescriptor#getLabel()
248: */
249: public String getLabel() {
250: return configElement == null ? label : configElement
251: .getAttribute(IWorkbenchRegistryConstants.ATT_NAME);
252: }
253:
254: /**
255: * Return the original id of this descriptor.
256: *
257: * @return the original id of this descriptor
258: */
259: public String getOriginalId() {
260: if (originalId == null) {
261: return getId();
262: }
263: return originalId;
264: }
265:
266: /**
267: * Returns <code>true</code> if this perspective has a custom definition.
268: *
269: * @return whether this perspective has a custom definition
270: */
271: public boolean hasCustomDefinition() {
272: return ((PerspectiveRegistry) WorkbenchPlugin.getDefault()
273: .getPerspectiveRegistry()).hasCustomDefinition(this );
274: }
275:
276: /**
277: * Returns <code>true</code> if this perspective wants to be default.
278: *
279: * @return whether this perspective wants to be default
280: */
281: public boolean hasDefaultFlag() {
282: if (configElement == null) {
283: return false;
284: }
285:
286: return Boolean
287: .valueOf(
288: configElement
289: .getAttribute(IWorkbenchRegistryConstants.ATT_DEFAULT))
290: .booleanValue();
291: }
292:
293: /**
294: * Returns <code>true</code> if this perspective is predefined by an
295: * extension.
296: *
297: * @return boolean whether this perspective is predefined by an extension
298: */
299: public boolean isPredefined() {
300: return getClassName() != null && configElement != null;
301: }
302:
303: /**
304: * Returns <code>true</code> if this perspective is a singleton.
305: *
306: * @return whether this perspective is a singleton
307: */
308: public boolean isSingleton() {
309: return configElement == null ? singleton
310: : configElement
311: .getAttributeAsIs(IWorkbenchRegistryConstants.ATT_SINGLETON) != null;
312: }
313:
314: /**
315: * Restore the state of a perspective from a memento.
316: *
317: * @param memento
318: * the memento to restore from
319: * @return the <code>IStatus</code> of the operation
320: * @see org.eclipse.ui.IPersistableElement
321: */
322: public IStatus restoreState(IMemento memento) {
323: IMemento childMem = memento
324: .getChild(IWorkbenchConstants.TAG_DESCRIPTOR);
325: if (childMem != null) {
326: id = childMem.getString(IWorkbenchConstants.TAG_ID);
327: originalId = childMem
328: .getString(IWorkbenchConstants.TAG_DESCRIPTOR);
329: label = childMem.getString(IWorkbenchConstants.TAG_LABEL);
330: className = childMem
331: .getString(IWorkbenchConstants.TAG_CLASS);
332: singleton = (childMem
333: .getInteger(IWorkbenchConstants.TAG_SINGLETON) != null);
334:
335: // Find a descriptor in the registry.
336: IPerspectiveDescriptor descriptor = WorkbenchPlugin
337: .getDefault().getPerspectiveRegistry()
338: .findPerspectiveWithId(getOriginalId());
339:
340: if (descriptor != null) {
341: // Copy the state from the registred descriptor.
342: image = descriptor.getImageDescriptor();
343: }
344: }
345: return new Status(IStatus.OK, PlatformUI.PLUGIN_ID, 0, "", null); //$NON-NLS-1$
346: }
347:
348: /**
349: * Revert to the predefined extension template. Does nothing if this
350: * descriptor is user defined.
351: */
352: public void revertToPredefined() {
353: if (isPredefined()) {
354: deleteCustomDefinition();
355: }
356: }
357:
358: /**
359: * Save the state of a perspective to a memento.
360: *
361: * @param memento
362: * the memento to restore from
363: * @return the <code>IStatus</code> of the operation
364: * @see org.eclipse.ui.IPersistableElement
365: */
366: public IStatus saveState(IMemento memento) {
367: IMemento childMem = memento
368: .createChild(IWorkbenchConstants.TAG_DESCRIPTOR);
369: childMem.putString(IWorkbenchConstants.TAG_ID, getId());
370: if (originalId != null) {
371: childMem.putString(IWorkbenchConstants.TAG_DESCRIPTOR,
372: originalId);
373: }
374: childMem.putString(IWorkbenchConstants.TAG_LABEL, getLabel());
375: childMem.putString(IWorkbenchConstants.TAG_CLASS,
376: getClassName());
377: if (singleton) {
378: childMem.putInteger(IWorkbenchConstants.TAG_SINGLETON, 1);
379: }
380: return new Status(IStatus.OK, PlatformUI.PLUGIN_ID, 0, "", null); //$NON-NLS-1$
381: }
382:
383: /**
384: * Return the configuration element used to create this perspective, if one
385: * was used.
386: *
387: * @return the configuration element used to create this perspective
388: * @since 3.0
389: */
390: public IConfigurationElement getConfigElement() {
391: return configElement;
392: }
393:
394: /*
395: * (non-Javadoc)
396: *
397: * @see org.eclipse.ui.activities.support.IPluginContribution#getLocalId()
398: */
399: public String getLocalId() {
400: return getId();
401: }
402:
403: /*
404: * (non-Javadoc)
405: *
406: * @see org.eclipse.ui.activities.support.IPluginContribution#getPluginId()
407: */
408: public String getPluginId() {
409: return configElement == null ? pluginId : configElement
410: .getNamespace();
411: }
412:
413: /**
414: * Returns the factory class name for this descriptor.
415: *
416: * @return the factory class name for this descriptor
417: * @since 3.1
418: */
419: public String getClassName() {
420: return configElement == null ? className : RegistryReader
421: .getClassValue(configElement,
422: IWorkbenchRegistryConstants.ATT_CLASS);
423: }
424: }
|