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: *******************************************************************************/package org.eclipse.ui.internal.dialogs;
011:
012: import java.util.ArrayList;
013: import java.util.Collection;
014: import java.util.Collections;
015: import java.util.Comparator;
016: import java.util.Hashtable;
017: import java.util.Iterator;
018: import java.util.List;
019:
020: import org.eclipse.core.runtime.IConfigurationElement;
021: import org.eclipse.core.runtime.IExtension;
022: import org.eclipse.core.runtime.Platform;
023: import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
024: import org.eclipse.ui.internal.IWorkbenchConstants;
025: import org.eclipse.ui.internal.ObjectContributorManager;
026: import org.eclipse.ui.internal.WorkbenchPlugin;
027: import org.eclipse.ui.internal.registry.PropertyPagesRegistryReader;
028:
029: import com.ibm.icu.text.Collator;
030:
031: /**
032: * Extends generic object contributor manager by loading property page
033: * contributors from the registry.
034: */
035:
036: public class PropertyPageContributorManager extends
037: ObjectContributorManager {
038: private static PropertyPageContributorManager sharedInstance = null;
039:
040: private class CategorizedPageNode {
041: RegistryPageContributor contributor;
042:
043: CategorizedPageNode parent;
044:
045: String qualifiedName;
046:
047: CategorizedPageNode(RegistryPageContributor page) {
048: contributor = page;
049: }
050:
051: void setParent(CategorizedPageNode node) {
052: parent = node;
053: }
054:
055: String getQualifiedName() {
056:
057: if (qualifiedName == null) {
058: if (parent == null) {
059: qualifiedName = contributor.getPageName();
060: } else {
061: StringBuffer nameBuffer = new StringBuffer();
062: nameBuffer.append(parent.getQualifiedName());
063: nameBuffer
064: .append(WorkbenchPlugin.PREFERENCE_PAGE_CATEGORY_SEPARATOR);
065: nameBuffer.append(contributor.getPageName());
066: qualifiedName = nameBuffer.toString();
067: }
068: }
069: return qualifiedName;
070:
071: }
072: }
073:
074: private static final Comparator comparer = new Comparator() {
075: private Collator collator = Collator.getInstance();
076:
077: public int compare(Object arg0, Object arg1) {
078: // Make sure the workbench info page is always at the top.
079: CategorizedPageNode c1 = (CategorizedPageNode) arg0;
080: CategorizedPageNode c2 = (CategorizedPageNode) arg1;
081: if (IWorkbenchConstants.WORKBENCH_PROPERTIES_PAGE_INFO
082: .equals(c1.contributor.getPageId())) {
083: // c1 is the info page
084: if (IWorkbenchConstants.WORKBENCH_PROPERTIES_PAGE_INFO
085: .equals(c2.contributor.getPageId())) {
086: // both are the info page so c2 is not greater
087: return 0;
088: }
089: // c2 is any other page so it must be greater
090: return -1;
091: }
092: if (IWorkbenchConstants.WORKBENCH_PROPERTIES_PAGE_INFO
093: .equals(c2.contributor.getPageId())) {
094: // c1 is any other page so it is greater
095: return 1;
096: }
097: // The other pages are sorted in alphabetical order
098: String s1 = c1.getQualifiedName();
099: String s2 = c2.getQualifiedName();
100: return collator.compare(s1, s2);
101: }
102: };
103:
104: /**
105: * The constructor.
106: */
107: public PropertyPageContributorManager() {
108: super ();
109: // load contributions on startup so that getContributors() returns the
110: // proper content
111: loadContributors();
112: }
113:
114: /**
115: * Given the object class, this method will find all the registered matching
116: * contributors and sequentially invoke them to contribute to the property
117: * page manager. Matching algorithm will also check subclasses and
118: * implemented interfaces.
119: * @param manager
120: * @param object
121: * @return true if contribution took place, false otherwise.
122: */
123: public boolean contribute(PropertyPageManager manager, Object object) {
124:
125: List result = getContributors(object);
126:
127: if (result == null || result.size() == 0) {
128: return false;
129: }
130:
131: // Sort the results
132: List sortedResult = buildNodeList(result);
133: Collections.sort(sortedResult, comparer);
134:
135: Iterator resultIterator = sortedResult.iterator();
136:
137: // Allow each contributor to add its page to the manager.
138: boolean actualContributions = false;
139: while (resultIterator.hasNext()) {
140: for (int i = 0; i < sortedResult.size(); i++) {
141: CategorizedPageNode next = (CategorizedPageNode) resultIterator
142: .next();
143: IPropertyPageContributor ppcont = next.contributor;
144: if (!ppcont.isApplicableTo(object)) {
145: continue;
146: }
147: if (ppcont.contributePropertyPages(manager, object)) {
148: actualContributions = true;
149: }
150: }
151: }
152: return actualContributions;
153: }
154:
155: /**
156: * Build the list of nodes to be sorted.
157: * @param nodes
158: * @return List of CategorizedPageNode
159: */
160: private List buildNodeList(List nodes) {
161: Hashtable mapping = new Hashtable();
162:
163: Iterator nodesIterator = nodes.iterator();
164: while (nodesIterator.hasNext()) {
165: RegistryPageContributor page = (RegistryPageContributor) nodesIterator
166: .next();
167: mapping
168: .put(page.getPageId(),
169: new CategorizedPageNode(page));
170: }
171:
172: Iterator values = mapping.values().iterator();
173: List returnValue = new ArrayList();
174: while (values.hasNext()) {
175: CategorizedPageNode next = (CategorizedPageNode) values
176: .next();
177: returnValue.add(next);
178: if (next.contributor.getCategory() == null) {
179: continue;
180: }
181: Object parent = mapping.get(next.contributor.getCategory());
182: if (parent != null) {
183: next.setParent((CategorizedPageNode) parent);
184: }
185: }
186: return returnValue;
187: }
188:
189: /**
190: * Ideally, shared instance should not be used and manager should be located
191: * in the workbench class.
192: * @return PropertyPageContributorManager
193: */
194: public static PropertyPageContributorManager getManager() {
195: if (sharedInstance == null) {
196: sharedInstance = new PropertyPageContributorManager();
197: }
198: return sharedInstance;
199: }
200:
201: /**
202: * Loads property page contributors from the registry.
203: */
204: private void loadContributors() {
205: PropertyPagesRegistryReader reader = new PropertyPagesRegistryReader(
206: this );
207: reader.registerPropertyPages(Platform.getExtensionRegistry());
208: }
209:
210: /* (non-Javadoc)
211: * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#addExtension(org.eclipse.core.runtime.dynamicHelpers.IExtensionTracker, org.eclipse.core.runtime.IExtension)
212: */
213: public void addExtension(IExtensionTracker tracker,
214: IExtension extension) {
215: IConfigurationElement[] addedElements = extension
216: .getConfigurationElements();
217: for (int i = 0; i < addedElements.length; i++) {
218: PropertyPagesRegistryReader reader = new PropertyPagesRegistryReader(
219: this );
220: reader.readElement(addedElements[i]);
221: }
222: }
223:
224: /**
225: * Return the contributors for element filters on the
226: * enablement. This is currently
227: * only used for test suites.
228: * @param element
229: * @return Collection of PropertyPageContribution
230: */
231: public Collection getApplicableContributors(Object element) {
232: Collection contributors = getContributors(element);
233: Collection result = new ArrayList();
234: for (Iterator iter = contributors.iterator(); iter.hasNext();) {
235: RegistryPageContributor contributor = (RegistryPageContributor) iter
236: .next();
237: if (contributor.isApplicableTo(element))
238: result.add(contributor);
239:
240: }
241: return result;
242: }
243: }
|