001: package net.refractions.udig.style.sld.editor;
002:
003: import java.util.ArrayList;
004: import java.util.Collection;
005: import java.util.Collections;
006: import java.util.HashSet;
007: import java.util.Iterator;
008: import java.util.List;
009:
010: import net.refractions.udig.style.IStyleConfigurator;
011: import net.refractions.udig.style.sld.IEditorPage;
012: import net.refractions.udig.style.sld.IEditorPageContainer;
013: import net.refractions.udig.style.sld.IStyleEditorPage;
014: import net.refractions.udig.style.sld.SLDPlugin;
015: import net.refractions.udig.style.sld.editor.internal.IEditorNode;
016:
017: import org.eclipse.core.runtime.CoreException;
018: import org.eclipse.core.runtime.IConfigurationElement;
019: import org.eclipse.core.runtime.IStatus;
020: import org.eclipse.core.runtime.InvalidRegistryObjectException;
021: import org.eclipse.core.runtime.Status;
022: import org.eclipse.jface.resource.ImageDescriptor;
023: import org.eclipse.jface.util.Assert;
024: import org.eclipse.swt.custom.BusyIndicator;
025: import org.eclipse.swt.graphics.Image;
026: import org.eclipse.swt.widgets.Composite;
027: import org.eclipse.ui.IPluginContribution;
028: import org.eclipse.ui.PlatformUI;
029: import org.eclipse.ui.internal.WorkbenchMessages;
030: import org.eclipse.ui.internal.registry.KeywordRegistry;
031: import org.eclipse.ui.internal.util.BundleUtility;
032: import org.eclipse.ui.plugin.AbstractUIPlugin;
033:
034: /**
035: * The EditorNode is the abstract class for all page nodes.
036: */
037: public class EditorNode implements IPluginContribution, IEditorNode {
038:
039: private static final String TAG_KEYWORD_REFERENCE = "keywordReference"; //$NON-NLS-1$
040: public static final String ATT_CLASS = "class"; //$NON-NLS-1$
041: public static final String ATT_ID = "id"; //$NON-NLS-1$
042: public static final String ATT_ICON = "icon"; //$NON-NLS-1$
043: public static final String ATT_LABEL = "label"; //$NON-NLS-1$
044: public static final String ATT_CATEGORY = "category"; //$NON-NLS-1$
045: public static final String ATT_REQUIRES = "requires"; //$NON-NLS-1$
046:
047: private Collection keywordReferences;
048:
049: private IConfigurationElement configurationElement;
050:
051: private ImageDescriptor imageDescriptor;
052:
053: private Image image;
054:
055: /**
056: * Editor page, or <code>null</code> if not yet loaded.
057: */
058: private IEditorPage page;
059:
060: /**
061: * The list of subnodes (immediate children) of this node (element type: <code>SLDEditorPageNode</code>).
062: */
063: private List<EditorNode> subNodes;
064:
065: /**
066: * Name of class that implements <code>SLDEditorPageNode</code>, or <code>null</code> if none.
067: */
068: private String classname;
069:
070: /**
071: * The id of this node.
072: */
073: private String id;
074:
075: /**
076: * Text label for this node. Note that this field is only used prior to the creation of the preference page.
077: */
078: private String label;
079:
080: private Collection keywordLabelCache;
081:
082: /**
083: * Create a new instance of the receiver.
084: *
085: * @param id
086: * @param configurationElement
087: */
088: public EditorNode(String id,
089: IConfigurationElement configurationElement) {
090: this (id);
091: this .configurationElement = configurationElement;
092: }
093:
094: /**
095: * Get the ids of the keywords the receiver is bound to.
096: *
097: * @return Collection of <code>String</code>. Never <code>null</code>.
098: */
099: public Collection getKeywordReferences() {
100: if (keywordReferences == null) {
101: IConfigurationElement[] references = getConfigurationElement()
102: .getChildren(TAG_KEYWORD_REFERENCE);
103: HashSet<String> list = new HashSet<String>(
104: references.length);
105: for (int i = 0; i < references.length; i++) {
106: IConfigurationElement page = references[i];
107: String id = page.getAttribute(ATT_ID);
108: if (id != null)
109: list.add(id);
110: }
111:
112: if (!list.isEmpty())
113: keywordReferences = list;
114: else
115: keywordReferences = Collections.EMPTY_SET;
116:
117: }
118: return keywordReferences;
119: }
120:
121: /**
122: * Get the labels of all of the keywords of the receiver.
123: *
124: * @return Collection of <code>String</code>. Never <code>null</code>.
125: */
126: public Collection getKeywordLabels() {
127: if (keywordLabelCache != null)
128: return keywordLabelCache;
129:
130: Collection refs = getKeywordReferences();
131:
132: if (refs == Collections.EMPTY_SET) {
133: keywordLabelCache = Collections.EMPTY_SET;
134: return keywordLabelCache;
135: }
136:
137: keywordLabelCache = new ArrayList(refs.size());
138: Iterator referenceIterator = refs.iterator();
139: while (referenceIterator.hasNext()) {
140: Object label = KeywordRegistry.getInstance()
141: .getKeywordLabel((String) referenceIterator.next());
142: if (label != null)
143: keywordLabelCache.add(label);
144: }
145:
146: return keywordLabelCache;
147: }
148:
149: /**
150: * Clear the keyword cache, if any.
151: */
152: public void clearKeywords() {
153: keywordLabelCache = null;
154: }
155:
156: /* (non-Javadoc)
157: * @see org.eclipse.jface.preference.SLDEditorPageNode#disposeResources()
158: */
159: public void disposeResources() {
160: if (image != null) {
161: image.dispose();
162: image = null;
163: }
164: if (page != null) {
165: page.dispose();
166: page = null;
167: }
168: configurationElement = null;
169: imageDescriptor = null;
170: }
171:
172: /* (non-Javadoc)
173: * @see org.eclipse.jface.preference.SLDEditorPageNode#getLabelImage()
174: */
175: public Image getLabelImage() {
176: if (image == null) {
177: ImageDescriptor desc = getImageDescriptor();
178: if (desc != null)
179: image = imageDescriptor.createImage();
180: }
181: return image;
182: }
183:
184: /* (non-Javadoc)
185: * @see org.eclipse.jface.preference.SLDEditorPageNode#getLabelText()
186: */
187: public String getLabelText() {
188: return getConfigurationElement().getAttribute(ATT_LABEL);
189: }
190:
191: /**
192: * Returns the image descriptor for this node.
193: *
194: * @return the image descriptor
195: */
196: public ImageDescriptor getImageDescriptor() {
197: if (imageDescriptor != null)
198: return imageDescriptor;
199:
200: String imageName = getConfigurationElement().getAttribute(
201: ATT_ICON);
202: if (imageName != null) {
203: String contributingPluginId = getConfigurationElement()
204: .getNamespace();
205: imageDescriptor = AbstractUIPlugin
206: .imageDescriptorFromPlugin(contributingPluginId,
207: imageName);
208: }
209: return imageDescriptor;
210: }
211:
212: /**
213: * Return the configuration element.
214: *
215: * @return the configuration element
216: */
217: public IConfigurationElement getConfigurationElement() {
218: return configurationElement;
219: }
220:
221: /* (non-Javadoc)
222: * @see org.eclipse.ui.activities.support.IPluginContribution#getLocalId()
223: */
224: public String getLocalId() {
225: return getId();
226: }
227:
228: /* (non-Javadoc)
229: * @see org.eclipse.ui.activities.support.IPluginContribution#getPluginId()
230: */
231: public String getPluginId() {
232: return getConfigurationElement().getNamespace();
233: }
234:
235: /**
236: * Creates the page this node stands for.
237: * The page is created, but its composite won't exist
238: */
239: public void createPage(Composite parent,
240: IEditorPageContainer container) {
241: StyleEditorPage page;
242: try {
243: Object pageInstance = createExtension(
244: getConfigurationElement(), ATT_CLASS);
245: if (pageInstance instanceof IStyleConfigurator) {
246: page = new StyleEditorPageAdapter(
247: (IStyleConfigurator) pageInstance);
248: } else if (pageInstance instanceof StyleEditorPage) {
249: page = (StyleEditorPage) pageInstance;
250: } else {
251: //TODO: log
252: return;
253: }
254: } catch (CoreException e) {
255: throw (RuntimeException) new RuntimeException()
256: .initCause(e);
257: }
258: page.setContainer(container);
259: page.init(PlatformUI.getWorkbench());
260: if (page.getControl() == null) {
261: //create the control
262: page.createControl(parent);
263: }
264: if (getLabelImage() != null)
265: page.setImageDescriptor(getImageDescriptor());
266: page.setTitle(getLabelText());
267: setPage(page);
268: }
269:
270: /**
271: * Return the category name for the node.
272: * @return java.lang.String
273: */
274: public String getCategory() {
275: return getConfigurationElement().getAttribute(ATT_CATEGORY);
276: }
277:
278: /**
279: * Return the required class the layer must resolve to.
280: *
281: * @return java.lang.String (Class)
282: */
283: public String getRequires() {
284: String requires = null;
285: try {
286: requires = getConfigurationElement().getAttribute(
287: ATT_REQUIRES);
288: } catch (InvalidRegistryObjectException e) {
289: }
290: return requires;
291: }
292:
293: /**
294: * Creates a new preference node with the given id. The new node has no
295: * subnodes.
296: *
297: * @param id
298: * the node id
299: */
300: public EditorNode(String id) {
301: Assert.isNotNull(id);
302: this .id = id;
303: }
304:
305: /**
306: * Creates a preference node with the given id, label, and image, and
307: * lazily-loaded preference page. The preference node assumes (sole)
308: * responsibility for disposing of the image; this will happen when the node
309: * is disposed.
310: *
311: * @param id
312: * the node id
313: * @param label
314: * the label used to display the node in the preference dialog's
315: * tree
316: * @param image
317: * the image displayed left of the label in the preference
318: * dialog's tree, or <code>null</code> if none
319: * @param className
320: * the class name of the preference page; this class must
321: * implement <code>IPreferencePage</code>
322: */
323: public EditorNode(String id, String label, ImageDescriptor image,
324: String className) {
325: this (id);
326: this .imageDescriptor = image;
327: Assert.isNotNull(label);
328: this .label = label;
329: this .classname = className;
330: }
331:
332: /**
333: * Creates an editor node with the given id and editor page. The
334: * title of the editor page is used for the node label. The node will
335: * not have an image.
336: *
337: * @param id
338: * the node id
339: * @param page
340: * the editor page
341: */
342: public EditorNode(String id, IEditorPage page) {
343: this (id);
344: Assert.isNotNull(page);
345: this .page = page;
346: }
347:
348: /*
349: * (non-Javadoc) Method declared on SLDEditorPageNode.
350: */
351: public void add(EditorNode node) {
352: if (subNodes == null)
353: subNodes = new ArrayList<EditorNode>();
354: subNodes.add(node);
355: }
356:
357: /*
358: * (non-Javadoc) Method declared on IContributionNode.
359: */
360: public EditorNode findSubNode(String id) {
361: Assert.isNotNull(id);
362: Assert.isTrue(id.length() > 0);
363: if (subNodes == null)
364: return null;
365: int size = subNodes.size();
366: for (int i = 0; i < size; i++) {
367: EditorNode node = (EditorNode) subNodes.get(i);
368: if (id.equals(node.getId()))
369: return node;
370: }
371: return null;
372: }
373:
374: /*
375: * (non-Javadoc) Method declared on SLDEditorPageNode.
376: */
377: public String getId() {
378: return this .id;
379: }
380:
381: /*
382: * (non-Javadoc) Method declared on SLDEditorPageNode.
383: */
384: public IEditorPage getPage() {
385: return page;
386: }
387:
388: /*
389: * (non-Javadoc) Method declared on SLDEditorPageNode.
390: */
391: public EditorNode[] getSubNodes() {
392: if (subNodes == null)
393: return new EditorNode[0];
394: return (EditorNode[]) subNodes.toArray(new EditorNode[subNodes
395: .size()]);
396: }
397:
398: /*
399: * (non-Javadoc) Method declared on SLDEditorPageNode.
400: */
401: public EditorNode remove(String id) {
402: EditorNode node = findSubNode(id);
403: if (node != null)
404: remove(node);
405: return node;
406: }
407:
408: /*
409: * (non-Javadoc) Method declared on SLDEditorPageNode.
410: */
411: public boolean remove(EditorNode node) {
412: if (subNodes == null)
413: return false;
414: return subNodes.remove(node);
415: }
416:
417: /**
418: * Set the current page to be newPage.
419: *
420: * @param newPage
421: */
422: public void setPage(IStyleEditorPage newPage) {
423: page = newPage;
424: }
425:
426: public void add(IEditorNode node) {
427: System.out.println("ADD called, but no code here"); //$NON-NLS-1$
428: }
429:
430: public boolean remove(IEditorNode node) {
431: return false;
432: }
433:
434: /**
435: * Creates an extension. If the extension plugin has not
436: * been loaded a busy cursor will be activated during the duration of
437: * the load.
438: *
439: * @param element the config element defining the extension
440: * @param classAttribute the name of the attribute carrying the class
441: * @return the extension object
442: * @throws CoreException if the extension cannot be created
443: */
444: public static Object createExtension(
445: final IConfigurationElement element,
446: final String classAttribute) throws CoreException {
447: try {
448: // If plugin has been loaded create extension.
449: // Otherwise, show busy cursor then create extension.
450: if (BundleUtility.isActivated(element
451: .getDeclaringExtension().getNamespace())) {
452: return element
453: .createExecutableExtension(classAttribute);
454: }
455: final Object[] ret = new Object[1];
456: final CoreException[] exc = new CoreException[1];
457: BusyIndicator.showWhile(null, new Runnable() {
458: public void run() {
459: try {
460: ret[0] = element
461: .createExecutableExtension(classAttribute);
462: } catch (CoreException e) {
463: exc[0] = e;
464: }
465: }
466: });
467: if (exc[0] != null)
468: throw exc[0];
469: return ret[0];
470:
471: } catch (CoreException core) {
472: throw core;
473: } catch (Exception e) {
474: throw new CoreException(new Status(IStatus.ERROR,
475: SLDPlugin.ID, IStatus.ERROR,
476: WorkbenchMessages.WorkbenchPlugin_extension, e));
477: }
478: }
479: }
|