001: package net.refractions.udig.style.sld;
002:
003: import java.util.ArrayList;
004: import java.util.Collections;
005: import java.util.Comparator;
006: import java.util.List;
007: import java.util.SortedMap;
008: import java.util.TreeMap;
009:
010: import net.refractions.udig.core.internal.ExtensionPointProcessor;
011: import net.refractions.udig.core.internal.ExtensionPointUtil;
012: import net.refractions.udig.project.internal.Layer;
013: import net.refractions.udig.style.IStyleConfigurator;
014: import net.refractions.udig.style.sld.internal.Messages;
015:
016: import org.eclipse.core.runtime.IConfigurationElement;
017: import org.eclipse.core.runtime.IExtension;
018: import org.eclipse.jface.action.Action;
019: import org.eclipse.jface.action.ActionContributionItem;
020: import org.eclipse.jface.action.IContributionItem;
021: import org.eclipse.jface.action.IMenuCreator;
022: import org.eclipse.jface.action.IToolBarManager;
023: import org.eclipse.jface.resource.ImageDescriptor;
024: import org.eclipse.swt.SWT;
025: import org.eclipse.swt.widgets.Composite;
026: import org.eclipse.swt.widgets.Control;
027: import org.eclipse.swt.widgets.Menu;
028: import org.eclipse.ui.part.PageBook;
029: import org.geotools.data.FeatureSource;
030: import org.geotools.feature.FeatureType;
031: import org.geotools.styling.Style;
032: import org.geotools.styling.Symbolizer;
033:
034: /**
035: * An abstract class for style configurators intended for SLD style objects.
036: * <p>
037: * This class makes use of the sldEditorPart configuration point to produce several ViewParts
038: * capable of editing individual Symbolizers.
039: * </p>
040: * <p>
041: *
042: * @author Justin Deoliveira, Refractions Research Inc.
043: */
044: public class SLDConfigurator extends IStyleConfigurator {
045:
046: /** The content manager for modifying the style. * */
047: SLDContentManager sldContentManager;
048:
049: /** The editor book * */
050: PageBook editorBook;
051:
052: /** blank page * */
053: Composite blank;
054:
055: /** class 2 menu mapping * */
056: List<SLDEditorMenuAction> toolbarItems;
057:
058: /** This is the data structure the extention point is processed into */
059: SortedMap<Class, List<SLDEditorPart>> classToEditors;
060:
061: // /** The sld editor parts **/
062: // private Map<Class, SLDEditorPart> editors;
063: //
064: // /** The cool bars **/
065: // private Map<Class, CoolBar> coolBars;
066: //
067: // /** page book pages **/
068: // private Map<Class, Composite> pages;
069: //
070: // private Map<Class, TabFolder> tabs;
071: //
072: // /** the cool bar / tool bar **/
073: // //private CoolBar coolBar;
074: //
075: // /** the dynamic part of the ui **/
076: // private PageBook pageBook;
077: //
078: // /** blank page **/
079: // private Composite blank;
080: //
081: // /** current page **/
082: // private Composite currentPage;
083: //
084: // /** current tab folder **/
085: // private TabFolder currentTabFolder;
086: //
087: // /** toolbar listener **/
088: // private SelectionListener toolListener;
089: //
090: // /** checkbox listener **/
091: // private SelectionListener checkListener;
092: //
093: // private Class geometryClass;
094:
095: /**
096: * Creates the configurator.
097: */
098: public SLDConfigurator() {
099: // editors = new HashMap<Class, SLDEditorPart>();
100: // pages = new HashMap<Class, Composite>();
101: // tabs = new HashMap<Class, TabFolder>();
102: }
103:
104: /**
105: * Checks if the layer is a feature layer or if the layer is a wms that supports post.
106: */
107: public boolean canStyle(Layer layer) {
108: if (layer.hasResource(FeatureSource.class))
109: return true;
110: if (layer.hasResource(org.geotools.data.ows.Layer.class))
111: return true;
112: return false; // TODO: check for wms supporting sld
113: }
114:
115: /**
116: * @see net.refractions.udig.style.IStyleConfigurator#init(org.eclipse.ui.IViewSite)
117: */
118: public void init() {
119: sldContentManager = new SLDContentManager();
120:
121: // process the extension point and add editors to the tool bar
122: Comparator<Class> compare = new Comparator<Class>() {
123: public int compare(Class a, Class b) {
124: return a.getSimpleName().compareTo(b.getSimpleName());
125: }
126: };
127: classToEditors = new TreeMap<Class, List<SLDEditorPart>>(
128: compare);
129:
130: ExtensionPointProcessor p = new ExtensionPointProcessor() {
131: public void process(IExtension ext,
132: IConfigurationElement element) throws Exception {
133: try {
134: SLDEditorPart editor = (SLDEditorPart) element
135: .createExecutableExtension("class"); //$NON-NLS-1$
136:
137: editor.setPluginId(element.getNamespace());
138: editor.setLabel(element.getAttribute("label")); //$NON-NLS-1$
139:
140: ImageDescriptor image = editor
141: .createImageDescriptor();
142: if (image == null) {
143: // TODO: set a default
144: } else
145: editor.setImageDescriptor(image);
146:
147: Class contentClass = editor.getContentType(); // aka symbolizer
148:
149: List<SLDEditorPart> list = classToEditors
150: .get(contentClass);
151: if (list == null) {
152: list = new ArrayList<SLDEditorPart>();
153: classToEditors.put(contentClass, list);
154: }
155: list.add(editor);
156: } catch (Exception e) {
157: SLDPlugin.log(null, e);
158: }
159: }
160: };
161: ExtensionPointUtil.process(SLDPlugin.getDefault(),
162: SLDEditorPart.XPID, p);
163: }
164:
165: /*
166: * (non-Javadoc)
167: *
168: * @see net.refractions.udig.style.IStyleConfigurator#createControl(org.eclipse.swt.widgets.Composite)
169: */
170: public void createControl(Composite parent) {
171: createToolbarItems(); // now we have toolbar items
172: editorBook = new PageBook(parent, SWT.NONE);
173: editorBook.setVisible(true);
174:
175: blank = new Composite(editorBook, SWT.NONE);
176: editorBook.showPage(blank);
177:
178: for (List<SLDEditorPart> parts : classToEditors.values()) {
179: for (SLDEditorPart part : parts) {
180: try {
181: part.createControl(editorBook);
182: } catch (Throwable t) {
183: SLDPlugin.log(null, t);
184: }
185: }
186: }
187: }
188:
189: /*
190: * Called when new layer and blackbard values are available. <p> This provides update
191: * information as a callback (rather than an event listener). </p>
192: */
193: protected void refresh() {
194: Layer layer = getLayer();
195: if (!canStyle(layer)) {
196: throw new IllegalStateException(
197: "Hey I can't style " + layer); //$NON-NLS-1$
198: }
199: // pull the sld style off the blackboard, and initialize the cm
200: Style style = (Style) getStyleBlackboard().get(SLDContent.ID);
201:
202: // if no style information, create default
203: if (style == null) {
204: style = SLDContent.createDefaultStyle();
205: getStyleBlackboard().put(SLDContent.ID, style);
206: }
207: sldContentManager.init(SLDContent.getStyleBuilder(), style);
208:
209: // pull the feature type name out of the layer
210: if (layer.getSchema() != null) {
211: FeatureType featureType = layer.getSchema();
212:
213: //set the name of the feature type style for the feature renderer
214: String name = featureType.getTypeName();
215: sldContentManager.getDefaultFeatureTypeStyle()
216: .setFeatureTypeName(name);
217: }
218:
219: // force the toolbar to refresh
220: //
221: IToolBarManager tbm = getViewSite().getActionBars()
222: .getToolBarManager();
223: tbm.markDirty();
224: tbm.update(true);
225: getViewSite().getActionBars().updateActionBars();
226:
227: for (IContributionItem item : tbm.getItems()) {
228: ActionContributionItem action = (ActionContributionItem) item;
229: action.getAction().setEnabled(
230: action.getAction().isEnabled());
231: }
232:
233: // focus the active editor if any exisits
234: SLDEditorPart editor = (SLDEditorPart) editorBook.getData();
235: List<Class> supported = SLD.getSupportedTypes(layer);
236: if (editor != null) {
237: if (supported.contains(editor.getContentType())) {
238: initEditor(editor);
239: editor.reset();
240: return; // current editor is still okay
241: }
242: }
243: // if we get here the current editor wasn't applicable, show first that works
244: for (Class type : classToEditors.keySet()) {
245: if (!supported.contains(type))
246: continue;
247:
248: for (SLDEditorPart part : classToEditors.get(type)) {
249: initEditor(part); // FIXME: we don't want the editor to have content it should not
250: part.reset();
251: editorBook.setData(part);
252: editorBook.showPage(part.getPage());
253: part.getPage().setVisible(true);
254: return;
255: }
256: }
257: editorBook.showPage(blank);
258:
259: }
260:
261: // public void focus(Layer layer, StyleBlackboard styleBlackboard) {
262: // //pull the sld style off the blackboard, and initialize the cm
263: // Style style = (Style) styleBlackboard.get(SLDContent.ID);
264: //
265: // //if no style information, create default
266: // if (style == null) {
267: // style = SLDContent.createDefaultStyle();
268: // getStyleBlackboard().put(SLDContent.ID, style);
269: // }
270: // sldContentManager.init(SLDContent.getStyleBuilder(), style);
271: //
272: // //pull the feature type name out of the layer
273: // if (layer.getResource(FeatureSource.class, null) != null) {
274: // FeatureType featureType = layer.getResource(FeatureSource.class, null).getSchema();
275: // String name = featureType.getTypeName();
276: //
277: // sldContentManager.getDefaultFeatureTypeStyle().setFeatureTypeName(name);
278: // }
279: // }
280:
281: //
282: // /**
283: // * Updates the SLD style on the blackboard. Subclasses overriding must call
284: // * this method in the last statement.
285: // */
286: // public void apply() {
287: //
288: // //update the blackboard
289: // getStyleBlackboard().put(SLDContent.ID, sldContentManager.getStyle());
290: // }
291: //
292: // /**
293: // * @return Returns the contentManager.
294: // */
295: // public SLDContentManager getContentManager() {
296: // return sldContentManager;
297: // }
298: //
299:
300: //
301: //
302: // /* (non-Javadoc)
303: // * @see
304: // net.refractions.udig.style.AbstractStyleConfigurator#createControl(org.eclipse.swt.widgets.Composite)
305: // */
306: // protected Control create(Composite parent) {
307: // createActions();
308: // pageBook = new PageBook(parent, SWT.NONE);
309: // blank = new Composite(pageBook, SWT.NONE);
310: //
311: // currentPage = blank;
312: // pageBook.showPage(blank);
313: //
314: // return pageBook;
315: // }
316: //
317: protected void createToolbarItems() {
318: toolbarItems = new ArrayList<SLDEditorMenuAction>(); // FIXME!
319: for (Class contentClass : classToEditors.keySet()) {
320: List<SLDEditorPart> editors = classToEditors
321: .get(contentClass);
322: if (editors == null || editors.isEmpty()) {
323: continue; // skip class with no editors
324: }
325: // add an editor for disable
326: editors.add(new SLDDisableEditorPart(contentClass));
327:
328: SLDEditorMenuAction action = new SLDEditorMenuAction(
329: editors);
330: // add to list of all
331: toolbarItems.add(action);
332: }
333:
334: // sort items so they dont randomly appear in the toolbar
335: Collections.sort(toolbarItems);
336:
337: // add em here
338: IToolBarManager tbm = getViewSite().getActionBars()
339: .getToolBarManager();
340: for (SLDEditorMenuAction item : toolbarItems) {
341: tbm.add(item);
342: }
343:
344: }
345:
346: /**
347: * Sets the editor up for a reset(). Ensures the editor has content.
348: */
349: void initEditor(SLDEditorPart editor) {
350: // enable the symbolizer if necessary
351: @SuppressWarnings("unchecked")
352: Class<Symbolizer> symbolizerType = editor.getContentType();
353:
354: Symbolizer content = sldContentManager
355: .getSymbolizer(symbolizerType);
356: if (content == null) {
357: sldContentManager.addSymbolizer(symbolizerType);
358: content = (Symbolizer) sldContentManager
359: .getSymbolizer(symbolizerType);
360: }
361:
362: editor.setStyleBuilder(sldContentManager.getStyleBuilder());
363: editor.setLayer(getLayer());
364: editor.setContent(content);
365: }
366:
367: /**
368: * Composite action made up of a drop down menu of actions.
369: */
370: class SLDEditorMenuAction extends Action implements IMenuCreator,
371: Comparable<SLDEditorMenuAction> {
372:
373: List<SLDEditorPart> editors;
374: Menu menu;
375:
376: public SLDEditorMenuAction(List<SLDEditorPart> editors) {
377: this .editors = editors;
378:
379: setMenuCreator(this );
380: setImageDescriptor(editors.get(0).getImageDescriptor());
381: }
382:
383: public Class getContentType() {
384: if (editors == null || editors.isEmpty())
385: return null;
386:
387: return editors.get(0).getContentType();
388: }
389:
390: public void dispose() {
391: if (menu != null) {
392: menu.dispose();
393: }
394: }
395:
396: public Menu getMenu(Control parent) {
397: if (menu != null) {
398: menu.dispose();
399: }
400: menu = new Menu(parent);
401:
402: for (SLDEditorPart editor : editors) {
403: Action action = new SLDEditorAction(editor, this );
404: addActionToMenu(menu, action);
405: }
406:
407: return menu;
408: }
409:
410: public Menu getMenu(Menu parent) {
411: return null;
412: }
413:
414: protected void addActionToMenu(Menu parent, Action action) {
415: ActionContributionItem item = new ActionContributionItem(
416: action);
417: item.fill(parent, -1);
418: }
419:
420: public int compareTo(SLDEditorMenuAction other) {
421: return editors.get(0).getContentType().getName().compareTo(
422: other.editors.get(0).getContentType().getName());
423: }
424:
425: /**
426: * @see org.eclipse.jface.action.Action#isEnabled()
427: */
428: public boolean isEnabled() {
429: Layer layer = getLayer();
430: if (layer == null)
431: return false;
432:
433: return SLD.getSupportedTypes(layer).contains(
434: getContentType());
435: }
436: }
437:
438: /**
439: * Action for firing up a specific editor.
440: */
441: class SLDEditorAction extends Action {
442:
443: SLDEditorMenuAction parent;
444: SLDEditorPart editor;
445:
446: public SLDEditorAction(SLDEditorPart editor,
447: SLDEditorMenuAction parent) {
448: super ();
449:
450: this .editor = editor;
451: this .parent = parent;
452:
453: setImageDescriptor(getImageDescriptor(editor));
454: setText(editor.getLabel());
455: }
456:
457: public void run() {
458: // update the icon to reflect the currently selected editor
459: //
460: parent.setImageDescriptor(getImageDescriptor());
461:
462: if (editor instanceof SLDDisableEditorPart) {
463: // disable the symbolizer
464: @SuppressWarnings("unchecked")
465: Class<Symbolizer> symbolizer = editor.getContentType();
466: sldContentManager.removeSymbolizer(symbolizer);
467: } else {
468: initEditor(editor);
469: }
470:
471: // signal editor to reset
472: editor.reset();
473:
474: // finally show the editor page
475: editorBook.setData(editor); // set the data of the editor book to be the active editor
476: Composite page = editor.getPage();
477: editorBook.setVisible(true);
478: editorBook.showPage(page);
479: // page.setVisible( true );
480: }
481:
482: protected ImageDescriptor getImageDescriptor(
483: SLDEditorPart editor1) {
484: return editor1.getImageDescriptor();
485: }
486: }
487:
488: /**
489: * A editor that does nothing except displays a "disabled" icon and creates a blank page.
490: */
491: class SLDDisableEditorPart extends SLDEditorPart {
492:
493: private Class<Symbolizer> contentType;
494:
495: public SLDDisableEditorPart(Class<Symbolizer> contentType) {
496: this .contentType = contentType;
497: setImageDescriptor(SLD
498: .createDisabledImageDescriptor(contentType));
499: setLabel(Messages.SLDConfigurator_disable);
500: }
501:
502: public void init() {
503: // do nothing
504: }
505:
506: /*
507: * (non-Javadoc)
508: *
509: * @see net.refractions.udig.style.sld.SLDEditorPart#getContentType()
510: */
511: public Class getContentType() {
512: return contentType;
513: }
514:
515: /*
516: * (non-Javadoc)
517: *
518: * @see net.refractions.udig.style.sld.SLDEditorPart#createPartControl(org.eclipse.swt.widgets.Composite)
519: */
520: protected Control createPartControl(Composite parent) {
521: return new Composite(parent, SWT.NONE);
522: }
523:
524: /*
525: * (non-Javadoc)
526: *
527: * @see net.refractions.udig.style.sld.SLDEditorPart#reset()
528: */
529: public void reset() {
530: // disable the content configurator
531: sldContentManager.removeSymbolizer(contentType);
532: }
533:
534: }
535:
536: }
|