001: package net.refractions.udig.style.sld.editor;
002:
003: import java.io.File;
004: import java.text.MessageFormat;
005: import java.util.ArrayList;
006: import java.util.List;
007:
008: import net.refractions.udig.project.internal.Layer;
009: import net.refractions.udig.project.internal.StyleBlackboard;
010: import net.refractions.udig.style.internal.StyleLayer;
011: import net.refractions.udig.style.sld.IStyleEditorPageContainer;
012: import net.refractions.udig.style.sld.SLDContent;
013: import net.refractions.udig.style.sld.editor.internal.FilteredEditorDialog;
014: import net.refractions.udig.style.sld.editor.internal.IEditorNode;
015: import net.refractions.udig.style.sld.internal.Messages;
016: import net.refractions.udig.ui.graphics.SLDs;
017:
018: import org.eclipse.jface.action.Action;
019: import org.eclipse.jface.action.IAction;
020: import org.eclipse.jface.dialogs.IDialogConstants;
021: import org.eclipse.swt.SWT;
022: import org.eclipse.swt.events.SelectionEvent;
023: import org.eclipse.swt.events.SelectionListener;
024: import org.eclipse.swt.layout.GridData;
025: import org.eclipse.swt.layout.GridLayout;
026: import org.eclipse.swt.widgets.Button;
027: import org.eclipse.swt.widgets.Composite;
028: import org.eclipse.swt.widgets.Control;
029: import org.eclipse.swt.widgets.Display;
030: import org.eclipse.swt.widgets.Event;
031: import org.eclipse.swt.widgets.MessageBox;
032: import org.eclipse.swt.widgets.Shell;
033: import org.eclipse.ui.IWorkbench;
034: import org.eclipse.ui.IWorkbenchWindow;
035: import org.eclipse.ui.PlatformUI;
036: import org.geotools.event.GTListener;
037: import org.geotools.styling.Style;
038: import org.geotools.styling.StyledLayerDescriptor;
039: import org.geotools.styling.UserLayer;
040: import org.geotools.util.NullProgressListener;
041: import org.geotools.util.ProgressListener;
042:
043: /**
044: * Prefence dialog for the workbench including the ability to load/save preferences.
045: */
046: public class StyleEditorDialog extends FilteredEditorDialog implements
047: IStyleEditorPageContainer {
048:
049: public final static int IMPORT_ID = 32;
050: public final static int EXPORT_ID = 33;
051: public final static int APPLY_ID = 34;
052: public final static int REVERT_ID = 35;
053: public final static int CLOSE_ID = 36;
054:
055: private static StyleEditorDialog instance = null;
056:
057: private List<GTListener> sldListeners = new ArrayList<GTListener>();
058: private StyleLayer selectedLayer;
059:
060: private boolean cancelMode = false;
061:
062: private static ProgressListener cancelProgress = new NullProgressListener();
063:
064: public ProgressListener getProgressListener() {
065: return cancelProgress;
066: }
067:
068: public void setCancelMode(boolean showCancel) {
069: cancelMode = showCancel;
070: }
071:
072: /**
073: * Creates an style editor dialog open to a particular page. It is the responsibility of the
074: * caller to then call <code>open()</code>. The call to <code>open()</code> will not return
075: * until the dialog closes, so this is the last chance to manipulate the dialog.
076: *
077: * @param shell The Shell to parent the dialog off of if it is not already created. May be
078: * <code>null</code> in which case the active workbench window will be used if
079: * available.
080: * @param pageId The identifier of the page to open; may be <code>null</code>.
081: * @return The dialog
082: */
083: public static final StyleEditorDialog createDialogOn(Shell shell,
084: final String pageId, Layer selectedLayer,
085: EditorPageManager manager) {
086: final StyleEditorDialog dialog;
087:
088: Shell parentShell = shell;
089: if (parentShell == null) {
090: // Determine a decent parent shell.
091: final IWorkbench workbench = PlatformUI.getWorkbench();
092: final IWorkbenchWindow workbenchWindow = workbench
093: .getActiveWorkbenchWindow();
094: if (workbenchWindow != null) {
095: parentShell = workbenchWindow.getShell();
096: } else {
097: parentShell = null;
098: }
099: }
100:
101: dialog = new StyleEditorDialog(parentShell, manager);
102: dialog.setSelectedNode(pageId);
103: dialog.setSelectedLayer(selectedLayer);
104: dialog.create();
105: dialog.getShell().setText(Messages.StyleEditor_name);
106: dialog.filteredTree.getFilterCombo().setEnabled(true); // allow filtering
107:
108: if (pageId != null) {
109: dialog.findNodeMatching(pageId);
110: }
111: return dialog;
112: }
113:
114: /**
115: * Creates a new dialog under the control of the given manager manager.
116: *
117: * @param parentShell the parent shell
118: * @param manager the preference manager
119: */
120: public StyleEditorDialog(Shell parentShell,
121: EditorPageManager manager) {
122: super (parentShell, manager);
123: instance = this ;
124: }
125:
126: /*
127: * (non-Javadoc)
128: *
129: * @see org.eclipse.jface.window.Window#close()
130: */
131: @Override
132: public boolean close() {
133: Style style = getStyle();
134: // only called on actual close of dialog
135: for (int i = sldListeners.size(); i > 0; i--) {
136: GTListener ear = (GTListener) sldListeners.get(i - 1);
137: if (style != null) {
138: StyledLayerDescriptor sld = SLDs
139: .styledLayerDescriptor(style);
140: if (sld != null) {
141: sld.removeListener(ear);
142: }
143: }
144: sldListeners.remove(ear);
145: ear = null;
146: }
147: instance = null;
148: return super .close();
149: }
150:
151: public void setSelectedLayer(Layer layer) {
152: if (selectedLayer == null && layer == null) {
153: return;
154: }
155: if (layer != null && layer.equals(selectedLayer)) {
156: return;
157: }
158: if (layer == null) {
159: selectedLayer = null;
160: } else {
161: selectedLayer = new StyleLayer(layer);
162: }
163: // TODO: determine if we need to deal with layer listeners
164: }
165:
166: public StyleLayer getSelectedLayer() {
167: return selectedLayer;
168: }
169:
170: public Style getStyle() {
171: if (selectedLayer != null) {
172: Object styleObject = selectedLayer.getStyleBlackboard()
173: .get(SLDContent.ID);
174: if (styleObject instanceof Style) {
175: // the style blackboard is a clone, therefore we don't need to clone the style or
176: // anything like that
177: return (Style) styleObject;
178: }
179: }
180: return null;
181: }
182:
183: public void setStyle(Style newStyle) {
184: Style oldStyle = getStyle();
185: StyledLayerDescriptor oldSLD = getSLD(oldStyle);
186: StyledLayerDescriptor newSLD = getSLD(newStyle);
187: if (newSLD == oldSLD) {
188: // rip out the old style and put in the new
189: Object layer = oldStyle.getNote().getParent();
190: if (layer instanceof UserLayer) {
191: UserLayer this Layer = (UserLayer) layer;
192: Style[] styles = this Layer.getUserStyles();
193: for (int i = 0; i < styles.length; i++) {
194: if (styles[i] == oldStyle) {
195: // this is the style to replace...
196: styles[i] = newStyle;
197: // reconnect events
198: this Layer.setUserStyles(styles);
199: break;
200: }
201: }
202: } else {
203: System.out.println("Style.getParent not a UserLayer"); //$NON-NLS-1$
204: // TODO: exception
205: }
206: } else {
207: // move the listeners to the new SLD object
208: moveListeners(oldSLD, newSLD);
209: }
210: StyleBlackboard styleBlackboard = selectedLayer
211: .getStyleBlackboard();
212: // put the style on the blackboard
213: styleBlackboard.put(SLDContent.ID, newStyle);
214: (styleBlackboard).setSelected(new String[] { SLDContent.ID });
215: }
216:
217: private StyledLayerDescriptor getSLD(Style style) {
218: if (style != null) {
219: StyledLayerDescriptor sld = SLDs
220: .styledLayerDescriptor(style);
221: if (sld == null) {
222: sld = SLDContent
223: .createDefaultStyledLayerDescriptor(style);
224: }
225: return sld;
226: }
227: return null;
228: }
229:
230: public StyledLayerDescriptor getSLD() {
231: Style style = getStyle();
232: return getSLD(style);
233: }
234:
235: @Override
236: public boolean showPage(IEditorNode node) {
237: return super .showPage(node);
238: }
239:
240: @Override
241: protected Button createButton(Composite parent, int id,
242: String label, boolean defaultButton) {
243: return super .createButton(parent, id, label, defaultButton);
244: }
245:
246: @Override
247: protected Control createButtonBar(Composite parent) {
248: Composite composite = new Composite(parent, SWT.NONE);
249: GridLayout layout = new GridLayout(2, false);
250: layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
251: layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
252: layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
253: layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
254: composite.setLayout(layout);
255: GridData data = new GridData(SWT.FILL, SWT.CENTER, true, false);
256: composite.setLayoutData(data);
257: composite.setFont(parent.getFont());
258:
259: // add import/export buttons
260: Composite compLeft = new Composite(composite, SWT.NONE);
261: layout = new GridLayout(0, true); // columns are incremented by createButton
262: layout.marginWidth = 0;
263: layout.marginHeight = 0;
264: layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
265: layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
266: compLeft.setLayout(layout);
267:
268: Button importButton = createButton(compLeft, IMPORT_ID,
269: Messages.StyleEditor_import, false);
270: importButton.setEnabled(false);
271: importButton.addSelectionListener(new ImportButtonListener());
272: Button exportButton = createButton(compLeft, EXPORT_ID,
273: Messages.StyleEditor_export, false);
274: exportButton.setEnabled(false);
275: exportButton.addSelectionListener(new ExportButtonListener());
276:
277: // add apply/revert/close buttons
278: Composite compRight = new Composite(composite, SWT.NONE);
279: layout = new GridLayout(0, true); // columns are incremented by createButton
280: layout.marginWidth = 0;
281: layout.marginHeight = 0;
282: layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
283: layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
284: compRight.setLayout(layout);
285: data = new GridData(SWT.END, SWT.CENTER, true, false);
286: compRight.setLayoutData(data);
287: compRight.setFont(parent.getFont());
288:
289: Button applyButton = createButton(compRight, APPLY_ID,
290: Messages.StyleEditor_apply, false);
291: applyButton.setEnabled(false);
292: applyButton.addSelectionListener(new ApplyButtonListener());
293: Button revertButton = createButton(compRight, REVERT_ID,
294: Messages.StyleEditor_revert, false);
295: revertButton.setEnabled(false);
296: revertButton.addSelectionListener(new RevertButtonListener());
297: Button closeButton = createButton(compRight, CLOSE_ID,
298: Messages.StyleEditor_close, false);
299: closeButton.setEnabled(true);
300: closeButton.addSelectionListener(new CloseButtonListener());
301:
302: return composite;
303: }
304:
305: @Override
306: protected void createButtonsForButtonBar(Composite parent) {
307: // too rigid... doing my own thing
308: }
309:
310: @Override
311: public void updateButtons() {
312: // TODO: button logic, SLD listeners
313: getButton(IMPORT_ID).setEnabled(true);
314: getButton(EXPORT_ID).setEnabled(true);
315:
316: getButton(APPLY_ID).setEnabled(true);
317: getButton(REVERT_ID).setEnabled(true);
318: getButton(CLOSE_ID).setEnabled(true);
319: }
320:
321: public void setExitButtonState(boolean dirty) {
322:
323: getButton(APPLY_ID).setEnabled(true);
324: if (dirty) {
325: getButton(CLOSE_ID).setText(Messages.StyleEditor_cancel);
326: } else {
327: getButton(CLOSE_ID).setText(Messages.StyleEditor_close);
328: }
329: }
330:
331: public IAction getApplyAction() {
332: final Button applyButton = getButton(APPLY_ID);
333: return new Action() {
334: @Override
335: public void setText(String text) {
336: applyButton.setText(text);
337: }
338:
339: @Override
340: public String getText() {
341: return applyButton.getText();
342: }
343:
344: @Override
345: public void setToolTipText(String toolTipText) {
346: applyButton.setToolTipText(toolTipText);
347: }
348:
349: @Override
350: public String getToolTipText() {
351: return applyButton.getToolTipText();
352: }
353:
354: @Override
355: public void setEnabled(boolean enabled) {
356: applyButton.setEnabled(enabled);
357: }
358:
359: @Override
360: public void run() {
361: Event event = new Event();
362: event.display = applyButton.getDisplay();
363: event.button = 1;
364: event.widget = applyButton;
365: applyButton.notifyListeners(SWT.Selection, event);
366: }
367:
368: @Override
369: public void setChecked(boolean checked) {
370: applyButton.setSelection(checked);
371: }
372:
373: };
374: }
375:
376: private class ApplyButtonListener implements SelectionListener {
377: public void widgetSelected(SelectionEvent e) {
378: if (instance.getCurrentPage().performApply()) {
379: setExitButtonState(false);
380: selectedLayer.apply();
381: selectedLayer.getMap().getRenderManager().refresh(
382: selectedLayer, null);
383: }
384: }
385:
386: public void widgetDefaultSelected(SelectionEvent e) {
387: widgetSelected(e);
388: }
389:
390: }
391:
392: private class RevertButtonListener implements SelectionListener {
393: public void widgetSelected(SelectionEvent e) {
394: //store the old sld
395: StyledLayerDescriptor oldSLD = getSLD();
396: //return to the blackboard state before we loaded the dialog
397: selectedLayer.revertAll();
398: selectedLayer.apply();
399: selectedLayer.getMap().getRenderManager().refresh(
400: selectedLayer, null);
401: //move listeners to new sld
402: StyledLayerDescriptor newSLD = getSLD();
403: moveListeners(oldSLD, newSLD);
404: setExitButtonState(false);
405: // TODO: update button states, page updates
406: instance.getCurrentPage().refresh();
407: }
408:
409: public void widgetDefaultSelected(SelectionEvent e) {
410: widgetSelected(e);
411: }
412: }
413:
414: private class ImportButtonListener implements SelectionListener {
415: public void widgetSelected(SelectionEvent e) {
416: ImportSLD importe = new ImportSLD();
417: StyledLayerDescriptor sld = null;
418: File file = importe.promptFile(Display.getDefault(), sld);
419: if (file != null) {
420: try {
421: sld = (StyledLayerDescriptor) importe.importFrom(
422: file, null);
423: } catch (Exception e1) {
424: MessageBox mb = new MessageBox(instance.getShell(),
425: SWT.ICON_ERROR | SWT.OK);
426: mb.setMessage(MessageFormat.format(
427: Messages.StyleEditor_import_failed, e1
428: .getLocalizedMessage()));
429: mb.open();
430: throw (RuntimeException) new RuntimeException()
431: .initCause(e1);
432: }
433: }
434: if (sld != null) {
435: Style newStyle = SLDs.getDefaultStyle(sld);
436: // TODO: assert there is only 1 style
437: setStyle(newStyle);
438: //refresh the page (there's a new SLD in town)
439: instance.getCurrentPage().refresh();
440: }
441: }
442:
443: public void widgetDefaultSelected(SelectionEvent e) {
444: widgetSelected(e);
445: }
446: }
447:
448: private class ExportButtonListener implements SelectionListener {
449: public void widgetSelected(SelectionEvent e) {
450: Object sld = getSLD();
451: ExportSLD export = new ExportSLD();
452: File file = export.promptFile(Display.getDefault(), sld);
453: if (file != null) {
454: try {
455: export.exportTo(sld, file, null);
456: } catch (Exception e1) {
457: // TODO Handle Exception
458: throw (RuntimeException) new RuntimeException()
459: .initCause(e1);
460: }
461: }
462: }
463:
464: public void widgetDefaultSelected(SelectionEvent e) {
465: widgetSelected(e);
466: }
467: }
468:
469: private class CloseButtonListener implements SelectionListener {
470: public void widgetSelected(SelectionEvent e) {
471: try {
472: if (cancelMode) {
473: cancelProgress.setCanceled(true);
474: } else {
475: instance.close();
476: }
477: } catch (Exception e1) {
478: // TODO Handle Exception
479: e1.printStackTrace();
480: }
481: }
482:
483: public void widgetDefaultSelected(SelectionEvent e) {
484: widgetSelected(e);
485: }
486:
487: }
488:
489: private void moveListeners(StyledLayerDescriptor oldSLD,
490: StyledLayerDescriptor newSLD) {
491: GTListener listener;
492: for (int i = 0; i < sldListeners.size(); i++) {
493: listener = (GTListener) sldListeners.get(i - 1);
494: if (oldSLD != null)
495: oldSLD.removeListener(listener);
496: if (newSLD != null)
497: newSLD.addListener(listener);
498: }
499: }
500:
501: public void addListener(GTListener listener) {
502: sldListeners.add(listener);
503: }
504:
505: public void removeListener(GTListener listener) {
506: sldListeners.remove(listener);
507: }
508: }
|