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.dialogs;
011:
012: import java.lang.ref.SoftReference;
013: import java.util.ArrayList;
014: import java.util.Collection;
015: import java.util.HashMap;
016: import java.util.Iterator;
017: import java.util.Map;
018:
019: import org.eclipse.core.expressions.EvaluationContext;
020: import org.eclipse.core.expressions.EvaluationResult;
021: import org.eclipse.core.expressions.Expression;
022: import org.eclipse.core.expressions.ExpressionConverter;
023: import org.eclipse.core.runtime.CoreException;
024: import org.eclipse.core.runtime.IAdaptable;
025: import org.eclipse.core.runtime.IConfigurationElement;
026: import org.eclipse.core.runtime.IStatus;
027: import org.eclipse.core.runtime.Status;
028: import org.eclipse.jface.resource.ImageDescriptor;
029: import org.eclipse.ui.IActionFilter;
030: import org.eclipse.ui.IWorkbenchPropertyPage;
031: import org.eclipse.ui.SelectionEnabler;
032: import org.eclipse.ui.internal.LegacyResourceSupport;
033: import org.eclipse.ui.internal.WorkbenchPlugin;
034: import org.eclipse.ui.internal.registry.CategorizedPageRegistryReader;
035: import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
036: import org.eclipse.ui.internal.registry.PropertyPagesRegistryReader;
037: import org.eclipse.ui.internal.util.Util;
038: import org.eclipse.ui.model.IWorkbenchAdapter;
039: import org.eclipse.ui.plugin.AbstractUIPlugin;
040:
041: /**
042: * This property page contributor is created from page entry in the registry.
043: * Since instances of this class are created by the workbench, there is no
044: * danger of premature loading of plugins.
045: */
046:
047: public class RegistryPageContributor implements
048: IPropertyPageContributor, IAdaptable {
049: private static final String CHILD_ENABLED_WHEN = "enabledWhen"; //$NON-NLS-1$
050:
051: private String pageId;
052:
053: /**
054: * The list of subpages (immediate children) of this node (element type:
055: * <code>RegistryPageContributor</code>).
056: */
057: private Collection subPages = new ArrayList();
058:
059: private boolean adaptable = false;
060:
061: private IConfigurationElement pageElement;
062:
063: private SoftReference filterProperties;
064:
065: private Expression enablementExpression;
066:
067: /**
068: * PropertyPageContributor constructor.
069: *
070: * @param pageId
071: * the id
072: * @param element
073: * the element
074: */
075: public RegistryPageContributor(String pageId,
076: IConfigurationElement element) {
077: this .pageId = pageId;
078: this .pageElement = element;
079: adaptable = Boolean
080: .valueOf(
081: pageElement
082: .getAttribute(PropertyPagesRegistryReader.ATT_ADAPTABLE))
083: .booleanValue();
084: initializeEnablement(element);
085: }
086:
087: /*
088: * (non-Javadoc)
089: *
090: * @see org.eclipse.ui.internal.dialogs.IPropertyPageContributor#contributePropertyPages(org.eclipse.ui.internal.dialogs.PropertyPageManager,
091: * java.lang.Object)
092: */
093: public boolean contributePropertyPages(PropertyPageManager mng,
094: Object element) {
095: PropertyPageNode node = new PropertyPageNode(this , element);
096:
097: if (getCategory() == null) {
098: mng.addToRoot(node);
099: return true;
100: }
101: if (!mng.addToDeep(getCategory(), node))
102: mng.addToRoot(node);
103:
104: return true;
105: }
106:
107: /**
108: * Creates the page based on the information in the configuration element.
109: *
110: * @param element
111: * the adaptable element
112: * @return the property page
113: * @throws CoreException
114: * thrown if there is a problem creating the apge
115: */
116: public IWorkbenchPropertyPage createPage(Object element)
117: throws CoreException {
118: IWorkbenchPropertyPage ppage = null;
119: ppage = (IWorkbenchPropertyPage) WorkbenchPlugin
120: .createExtension(pageElement,
121: IWorkbenchRegistryConstants.ATT_CLASS);
122:
123: ppage.setTitle(getPageName());
124:
125: Object adapted = element;
126: if (adaptable) {
127: adapted = getAdaptedElement(element);
128: if (adapted == null) {
129: String message = "Error adapting selection to Property page " + pageId + " is being ignored"; //$NON-NLS-1$ //$NON-NLS-2$
130: throw new CoreException(new Status(IStatus.ERROR,
131: WorkbenchPlugin.PI_WORKBENCH, IStatus.ERROR,
132: message, null));
133: }
134: }
135:
136: if (adapted instanceof IAdaptable)
137: ppage.setElement((IAdaptable) adapted);
138: else
139: ppage.setElement(new AdaptableForwarder(adapted));
140:
141: return ppage;
142: }
143:
144: /**
145: * Find an adapted element from the receiver.
146: *
147: * @param element
148: * @return the adapted element or <code>null</code> if it could not be
149: * found.
150: */
151: private Object getAdaptedElement(Object element) {
152: Object adapted = LegacyResourceSupport.getAdapter(element,
153: getObjectClass());
154: if (adapted != null)
155: return adapted;
156:
157: return null;
158: }
159:
160: /**
161: * Return the object class name
162: *
163: * @return the object class name
164: */
165: public String getObjectClass() {
166: return pageElement
167: .getAttribute(PropertyPagesRegistryReader.ATT_OBJECTCLASS);
168: }
169:
170: /**
171: * Returns page icon as defined in the registry.
172: *
173: * @return the page icon
174: */
175: public ImageDescriptor getPageIcon() {
176: String iconName = pageElement
177: .getAttribute(IWorkbenchRegistryConstants.ATT_ICON);
178: if (iconName == null)
179: return null;
180: return AbstractUIPlugin.imageDescriptorFromPlugin(pageElement
181: .getNamespaceIdentifier(), iconName);
182: }
183:
184: /**
185: * Returns page ID as defined in the registry.
186: *
187: * @return the page id
188: */
189:
190: public String getPageId() {
191: return pageId;
192: }
193:
194: /**
195: * Returns page name as defined in the registry.
196: *
197: * @return the page name
198: */
199: public String getPageName() {
200: return pageElement
201: .getAttribute(IWorkbenchRegistryConstants.ATT_NAME);
202: }
203:
204: /**
205: * Return true if name filter is not defined in the registry for this page,
206: * or if name of the selected object matches the name filter.
207: */
208: public boolean isApplicableTo(Object object) {
209:
210: if (failsEnablement(object))
211: return false;
212:
213: // Test name filter
214: String nameFilter = pageElement
215: .getAttribute(PropertyPagesRegistryReader.ATT_NAME_FILTER);
216: if (nameFilter != null) {
217: String objectName = object.toString();
218: IWorkbenchAdapter adapter = (IWorkbenchAdapter) Util
219: .getAdapter(object, IWorkbenchAdapter.class);
220: if (adapter != null) {
221: String elementName = adapter.getLabel(object);
222: if (elementName != null) {
223: objectName = elementName;
224: }
225: }
226: if (!SelectionEnabler.verifyNameMatch(objectName,
227: nameFilter))
228: return false;
229: }
230:
231: // Test custom filter
232: if (getFilterProperties() == null)
233: return true;
234: IActionFilter filter = null;
235:
236: // Do the free IResource adapting
237: Object adaptedObject = LegacyResourceSupport
238: .getAdaptedResource(object);
239: if (adaptedObject != null) {
240: object = adaptedObject;
241: }
242:
243: filter = (IActionFilter) Util.getAdapter(object,
244: IActionFilter.class);
245:
246: if (filter != null)
247: return testCustom(object, filter);
248:
249: return true;
250: }
251:
252: /**
253: * Return whether or not object fails the enablement criterea.
254: *
255: * @param object
256: * @return boolean <code>true</code> if it fails the enablement test
257: */
258: private boolean failsEnablement(Object object) {
259: if (enablementExpression == null)
260: return false;
261: try {
262: return enablementExpression.evaluate(
263: new EvaluationContext(null, object)).equals(
264: EvaluationResult.FALSE);
265: } catch (CoreException e) {
266: WorkbenchPlugin.log(e);
267: return false;
268: }
269: }
270:
271: /**
272: * Initialize the enablement expression for this decorator
273: */
274: protected void initializeEnablement(
275: IConfigurationElement definingElement) {
276: IConfigurationElement[] elements = definingElement
277: .getChildren(CHILD_ENABLED_WHEN);
278:
279: if (elements.length == 0)
280: return;
281:
282: try {
283: IConfigurationElement[] enablement = elements[0]
284: .getChildren();
285: if (enablement.length == 0)
286: return;
287: enablementExpression = ExpressionConverter.getDefault()
288: .perform(enablement[0]);
289: } catch (CoreException e) {
290: WorkbenchPlugin.log(e);
291: }
292:
293: }
294:
295: /**
296: * Returns whether the object passes a custom key value filter implemented
297: * by a matcher.
298: */
299: private boolean testCustom(Object object, IActionFilter filter) {
300: Map filterProperties = getFilterProperties();
301:
302: if (filterProperties == null)
303: return false;
304: Iterator iter = filterProperties.keySet().iterator();
305: while (iter.hasNext()) {
306: String key = (String) iter.next();
307: String value = (String) filterProperties.get(key);
308: if (!filter.testAttribute(object, key, value))
309: return false;
310: }
311: return true;
312: }
313:
314: /*
315: * @see IObjectContributor#canAdapt()
316: */
317: public boolean canAdapt() {
318: return adaptable;
319: }
320:
321: /**
322: * Get the id of the category.
323: *
324: * @return String
325: * @since 3.1
326: */
327: public String getCategory() {
328: return pageElement
329: .getAttribute(CategorizedPageRegistryReader.ATT_CATEGORY);
330: }
331:
332: /**
333: * Return the children of the receiver.
334: *
335: * @return Collection
336: */
337: public Collection getSubPages() {
338: return subPages;
339: }
340:
341: /**
342: * Add child to the list of children.
343: *
344: * @param child
345: */
346: public void addSubPage(RegistryPageContributor child) {
347: subPages.add(child);
348: }
349:
350: private Map getFilterProperties() {
351: if (filterProperties == null || filterProperties.get() == null) {
352: Map map = new HashMap();
353: filterProperties = new SoftReference(map);
354: IConfigurationElement[] children = pageElement
355: .getChildren();
356: for (int i = 0; i < children.length; i++) {
357: processChildElement(map, children[i]);
358: }
359: }
360: return (Map) filterProperties.get();
361: }
362:
363: /**
364: * Get the child with the given id.
365: *
366: * @param id
367: * @return RegistryPageContributor
368: */
369: public Object getChild(String id) {
370: Iterator iterator = subPages.iterator();
371: while (iterator.hasNext()) {
372: RegistryPageContributor next = (RegistryPageContributor) iterator
373: .next();
374: if (next.getPageId().equals(id))
375: return next;
376: }
377: return null;
378: }
379:
380: /**
381: * Parses child element and processes it.
382: *
383: * @since 3.1
384: */
385: private void processChildElement(Map map,
386: IConfigurationElement element) {
387: String tag = element.getName();
388: if (tag.equals(PropertyPagesRegistryReader.TAG_FILTER)) {
389: String key = element
390: .getAttribute(PropertyPagesRegistryReader.ATT_FILTER_NAME);
391: String value = element
392: .getAttribute(PropertyPagesRegistryReader.ATT_FILTER_VALUE);
393: if (key == null || value == null)
394: return;
395: map.put(key, value);
396: }
397: }
398:
399: /*
400: * (non-Javadoc)
401: *
402: * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
403: * @since 3.1
404: */
405: public Object getAdapter(Class adapter) {
406: if (adapter.equals(IConfigurationElement.class)) {
407: return getConfigurationElement();
408: }
409: return null;
410: }
411:
412: /**
413: * @return the configuration element
414: * @since 3.1
415: */
416: IConfigurationElement getConfigurationElement() {
417: return pageElement;
418: }
419: }
|