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.registry;
011:
012: import java.util.ArrayList;
013: import java.util.Comparator;
014: import java.util.Iterator;
015: import java.util.List;
016: import java.util.SortedSet;
017: import java.util.TreeSet;
018:
019: import org.eclipse.core.runtime.IConfigurationElement;
020: import org.eclipse.core.runtime.IExtension;
021: import org.eclipse.core.runtime.IExtensionPoint;
022: import org.eclipse.core.runtime.IPath;
023: import org.eclipse.core.runtime.Path;
024: import org.eclipse.core.runtime.Platform;
025: import org.eclipse.core.runtime.dynamichelpers.ExtensionTracker;
026: import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;
027: import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
028: import org.eclipse.ui.IPluginContribution;
029: import org.eclipse.ui.PlatformUI;
030: import org.eclipse.ui.internal.WorkbenchPlugin;
031: import org.eclipse.ui.internal.util.Util;
032: import org.eclipse.ui.views.IStickyViewDescriptor;
033: import org.eclipse.ui.views.IViewCategory;
034: import org.eclipse.ui.views.IViewDescriptor;
035: import org.eclipse.ui.views.IViewRegistry;
036:
037: import com.ibm.icu.text.MessageFormat;
038:
039: /**
040: * The central manager for view descriptors.
041: */
042: public class ViewRegistry implements IViewRegistry,
043: IExtensionChangeHandler {
044:
045: /**
046: * Proxies a Category implementation.
047: *
048: * @since 3.1
049: */
050: private static class ViewCategoryProxy implements IViewCategory,
051: IPluginContribution {
052:
053: private Category rawCategory;
054:
055: /**
056: * Create a new instance of this class
057: *
058: * @param rawCategory the category
059: */
060: public ViewCategoryProxy(Category rawCategory) {
061: this .rawCategory = rawCategory;
062: }
063:
064: /* (non-Javadoc)
065: * @see org.eclipse.ui.views.IViewCategory#getViews()
066: */
067: public IViewDescriptor[] getViews() {
068: ArrayList elements = rawCategory.getElements();
069: if (elements == null) {
070: return new IViewDescriptor[0];
071: }
072: return (IViewDescriptor[]) elements
073: .toArray(new IViewDescriptor[elements.size()]);
074: }
075:
076: /* (non-Javadoc)
077: * @see org.eclipse.ui.views.IViewCategory#getId()
078: */
079: public String getId() {
080: return rawCategory.getId();
081: }
082:
083: /* (non-Javadoc)
084: * @see org.eclipse.ui.views.IViewCategory#getPath()
085: */
086: public IPath getPath() {
087: String rawParentPath = rawCategory.getRawParentPath();
088: if (rawParentPath == null) {
089: return new Path(""); //$NON-NLS-1$
090: }
091: return new Path(rawParentPath);
092: }
093:
094: /* (non-Javadoc)
095: * @see org.eclipse.ui.views.IViewCategory#getLabel()
096: */
097: public String getLabel() {
098: return rawCategory.getLabel();
099: }
100:
101: /* (non-Javadoc)
102: * @see org.eclipse.ui.IPluginContribution#getLocalId()
103: */
104: public String getLocalId() {
105: return getId();
106: }
107:
108: /* (non-Javadoc)
109: * @see org.eclipse.ui.IPluginContribution#getPluginId()
110: */
111: public String getPluginId() {
112: return rawCategory.getPluginId();
113: }
114:
115: /* (non-Javadoc)
116: * @see java.lang.Object#equals(java.lang.Object)
117: */
118: public boolean equals(Object o) {
119: if (o instanceof IViewCategory) {
120: return getId().equals(((IViewCategory) o).getId());
121: }
122: return false;
123: }
124:
125: /* (non-Javadoc)
126: * @see java.lang.Object#hashCode()
127: */
128: public int hashCode() {
129: return getId().hashCode();
130: }
131: }
132:
133: private static String EXTENSIONPOINT_UNIQUE_ID = WorkbenchPlugin.PI_WORKBENCH
134: + "." + IWorkbenchRegistryConstants.PL_VIEWS; //$NON-NLS-1$
135:
136: /**
137: * A set that will only ever contain ViewDescriptors.
138: */
139: private SortedSet views = new TreeSet(new Comparator() {
140: public int compare(Object o1, Object o2) {
141: String id1 = ((ViewDescriptor) o1).getId();
142: String id2 = ((ViewDescriptor) o2).getId();
143:
144: return id1.compareTo(id2);
145: }
146: });
147:
148: private List categories;
149:
150: private List sticky;
151:
152: private Category miscCategory;
153:
154: protected static final String TAG_DESCRIPTION = "description"; //$NON-NLS-1$
155:
156: private ViewRegistryReader reader = new ViewRegistryReader();
157:
158: private boolean dirtyViewCategoryMappings = true;
159:
160: /**
161: * Create a new ViewRegistry.
162: */
163: public ViewRegistry() {
164: super ();
165: categories = new ArrayList();
166: sticky = new ArrayList();
167: PlatformUI
168: .getWorkbench()
169: .getExtensionTracker()
170: .registerHandler(
171: this ,
172: ExtensionTracker
173: .createExtensionPointFilter(getExtensionPointFilter()));
174: reader.readViews(Platform.getExtensionRegistry(), this );
175: }
176:
177: /**
178: * Add a category to the registry.
179: *
180: * @param desc the descriptor to add
181: */
182: public void add(Category desc) {
183: /* fix for 1877 */
184: if (internalFindCategory(desc.getId()) == null) {
185: dirtyViewCategoryMappings = true;
186: // Mark categories list as dirty
187: categories.add(desc);
188: IConfigurationElement element = (IConfigurationElement) Util
189: .getAdapter(desc, IConfigurationElement.class);
190: if (element == null) {
191: return;
192: }
193: PlatformUI.getWorkbench().getExtensionTracker()
194: .registerObject(element.getDeclaringExtension(),
195: desc, IExtensionTracker.REF_WEAK);
196: }
197: }
198:
199: /**
200: * Add a descriptor to the registry.
201: *
202: * @param desc the descriptor to add
203: */
204: public void add(ViewDescriptor desc) {
205: if (views.add(desc)) {
206: dirtyViewCategoryMappings = true;
207: PlatformUI.getWorkbench().getExtensionTracker()
208: .registerObject(
209: desc.getConfigurationElement()
210: .getDeclaringExtension(), desc,
211: IExtensionTracker.REF_WEAK);
212: desc.activateHandler();
213: }
214: }
215:
216: /**
217: * Add a sticky descriptor to the registry.
218: *
219: * @param desc the descriptor to add
220: */
221: public void add(StickyViewDescriptor desc) {
222: if (!sticky.contains(desc)) {
223: sticky.add(desc);
224: PlatformUI.getWorkbench().getExtensionTracker()
225: .registerObject(
226: desc.getConfigurationElement()
227: .getDeclaringExtension(), desc,
228: IExtensionTracker.REF_WEAK);
229: }
230: }
231:
232: // /**
233: // * Return the sticky view descriptor.
234: // *
235: // * @param id the id to searc for
236: // * @return the sticky view descriptor
237: // */
238: // private IStickyViewDescriptor findSticky(String id) {
239: // for (Iterator i = sticky.iterator(); i.hasNext();) {
240: // IStickyViewDescriptor desc = (IStickyViewDescriptor) i.next();
241: // if (id.equals(desc.getId()))
242: // return desc;
243: // }
244: // return null;
245: // }
246:
247: /**
248: * Find a descriptor in the registry.
249: */
250: public IViewDescriptor find(String id) {
251: Iterator itr = views.iterator();
252: while (itr.hasNext()) {
253: IViewDescriptor desc = (IViewDescriptor) itr.next();
254: if (id.equals(desc.getId())) {
255: return desc;
256: }
257: }
258: return null;
259: }
260:
261: /**
262: * Find a category with a given name.
263: *
264: * @param id the id to search for
265: * @return the category or <code>null</code>
266: */
267: public IViewCategory findCategory(String id) {
268: mapViewsToCategories();
269: Category category = internalFindCategory(id);
270: if (category == null) {
271: return null;
272: }
273: return new ViewCategoryProxy(category);
274: }
275:
276: /**
277: * Returns the category with no updating of the view/category mappings.
278: *
279: * @param id the category id
280: * @return the Category
281: * @since 3.1
282: */
283: private Category internalFindCategory(String id) {
284: Iterator itr = categories.iterator();
285: while (itr.hasNext()) {
286: Category cat = (Category) itr.next();
287: if (id.equals(cat.getRootPath())) {
288: return cat;
289: }
290: }
291: return null;
292: }
293:
294: /**
295: * Get the list of view categories.
296: */
297: public IViewCategory[] getCategories() {
298: mapViewsToCategories();
299: int nSize = categories.size();
300: IViewCategory[] retArray = new IViewCategory[nSize];
301: int i = 0;
302: for (Iterator itr = categories.iterator(); itr.hasNext();) {
303: retArray[i++] = new ViewCategoryProxy((Category) itr.next());
304: }
305: return retArray;
306: }
307:
308: /**
309: * Get the list of sticky views.
310: */
311: public IStickyViewDescriptor[] getStickyViews() {
312: return (IStickyViewDescriptor[]) sticky
313: .toArray(new IStickyViewDescriptor[sticky.size()]);
314: }
315:
316: /**
317: * Returns the Misc category. This may be <code>null</code> if there are
318: * no miscellaneous views.
319: *
320: * @return the misc category or <code>null</code>
321: */
322: public Category getMiscCategory() {
323: return miscCategory;
324: }
325:
326: /**
327: * Get an enumeration of view descriptors.
328: */
329: public IViewDescriptor[] getViews() {
330: return (IViewDescriptor[]) views
331: .toArray(new IViewDescriptor[views.size()]);
332: }
333:
334: /**
335: * Adds each view in the registry to a particular category.
336: * The view category may be defined in xml. If not, the view is
337: * added to the "misc" category.
338: */
339: public void mapViewsToCategories() {
340: if (dirtyViewCategoryMappings) {
341: dirtyViewCategoryMappings = false;
342: // clear all category mappings
343: for (Iterator i = categories.iterator(); i.hasNext();) {
344: Category category = (Category) i.next();
345: category.clear(); // this is bad
346: }
347:
348: if (miscCategory != null) {
349: miscCategory.clear();
350: }
351:
352: for (Iterator i = views.iterator(); i.hasNext();) {
353: IViewDescriptor desc = (IViewDescriptor) i.next();
354: Category cat = null;
355: String[] catPath = desc.getCategoryPath();
356: if (catPath != null) {
357: String rootCat = catPath[0];
358: cat = internalFindCategory(rootCat);
359: }
360: if (cat != null) {
361: if (!cat.hasElement(desc)) {
362: cat.addElement(desc);
363: }
364: } else {
365: if (miscCategory == null) {
366: miscCategory = new Category();
367: add(miscCategory);
368: }
369: if (catPath != null) {
370: // If we get here, this view specified a category which
371: // does not exist. Add this view to the 'Other' category
372: // but give out a message (to the log only) indicating
373: // this has been done.
374: String fmt = "Category {0} not found for view {1}. This view added to ''{2}'' category."; //$NON-NLS-1$
375: WorkbenchPlugin.log(MessageFormat.format(fmt,
376: new Object[] { catPath[0],
377: desc.getId(),
378: miscCategory.getLabel() }));
379: }
380: miscCategory.addElement(desc);
381: }
382: }
383: }
384: }
385:
386: /**
387: * Dispose of this registry.
388: */
389: public void dispose() {
390: PlatformUI.getWorkbench().getExtensionTracker()
391: .unregisterHandler(this );
392: }
393:
394: /* (non-Javadoc)
395: * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#removeExtension(org.eclipse.core.runtime.IExtension, java.lang.Object[])
396: */
397: public void removeExtension(IExtension extension, Object[] objects) {
398: for (int i = 0; i < objects.length; i++) {
399: if (objects[i] instanceof StickyViewDescriptor) {
400: sticky.remove(objects[i]);
401: } else if (objects[i] instanceof ViewDescriptor) {
402: views.remove(objects[i]);
403: ((ViewDescriptor) objects[i]).deactivateHandler();
404: dirtyViewCategoryMappings = true;
405: } else if (objects[i] instanceof Category) {
406: categories.remove(objects[i]);
407: dirtyViewCategoryMappings = true;
408: }
409: }
410:
411: }
412:
413: private IExtensionPoint getExtensionPointFilter() {
414: return Platform.getExtensionRegistry().getExtensionPoint(
415: EXTENSIONPOINT_UNIQUE_ID);
416: }
417:
418: /* (non-Javadoc)
419: * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#addExtension(org.eclipse.core.runtime.dynamicHelpers.IExtensionTracker, org.eclipse.core.runtime.IExtension)
420: */
421: public void addExtension(IExtensionTracker tracker,
422: IExtension addedExtension) {
423: IConfigurationElement[] addedElements = addedExtension
424: .getConfigurationElements();
425: for (int i = 0; i < addedElements.length; i++) {
426: IConfigurationElement element = addedElements[i];
427: if (element.getName().equals(
428: IWorkbenchRegistryConstants.TAG_VIEW)) {
429: reader.readView(element);
430: } else if (element.getName().equals(
431: IWorkbenchRegistryConstants.TAG_CATEGORY)) {
432: reader.readCategory(element);
433: } else if (element.getName().equals(
434: IWorkbenchRegistryConstants.TAG_STICKYVIEW)) {
435: reader.readSticky(element);
436: }
437: }
438: }
439: }
|