001: /*
002: * uDig - User Friendly Desktop Internet GIS client
003: * http://udig.refractions.net
004: * (C) 2004, Refractions Research Inc.
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: */
017: package net.refractions.udig.style.sld.simple;
018:
019: import java.text.MessageFormat;
020:
021: import net.refractions.udig.style.sld.AbstractSimpleConfigurator;
022: import net.refractions.udig.style.sld.internal.Messages;
023:
024: import org.eclipse.swt.SWT;
025: import org.eclipse.swt.events.KeyListener;
026: import org.eclipse.swt.events.ModifyEvent;
027: import org.eclipse.swt.events.ModifyListener;
028: import org.eclipse.swt.events.SelectionEvent;
029: import org.eclipse.swt.events.SelectionListener;
030: import org.eclipse.swt.widgets.Button;
031: import org.eclipse.swt.widgets.Combo;
032: import org.eclipse.swt.widgets.Composite;
033: import org.geotools.filter.FilterFactoryFinder;
034: import org.geotools.styling.RasterSymbolizer;
035: import org.geotools.styling.SLD;
036: import org.geotools.styling.StyleBuilder;
037:
038: /**
039: * Allows editing/viewing of a Style Layer Descriptor "Raster".
040: * <p>
041: * Here is the pretty picture: <pre><code>
042: * +-+ +----------------+
043: * Label: |x| | opacity\/|
044: * +-+ +----------------+
045: * </code></pre>
046: * </p>
047: * <p>
048: * Workflow:
049: * <ol>
050: * <li>createControl( parent ) - set up controls
051: * <li>set( raster, mode ) - provide content from SimpleStyleConfigurator
052: * <ol>
053: * <li> Symbolizer values copied into fields based on mode
054: * <li> fields copied into controls
055: * <li> controls enabled based on mode & fields
056: * </ol>
057: * <li>Listener.widgetSelected/modifyText - User performs an "edit"
058: * <li>Listener.sync( SelectionEvent ) - update fields with values of controls
059: * <li>fire( SelectionSevent ) - notify SimpleStyleConfigurator of change
060: * <li>get( StyleBuilder ) - construct based on fields
061: * </ul>
062: * </p>
063: * @author mleslie
064: * @since 1.0.0
065: */
066: public class RasterViewer {
067: boolean enabled = false;
068: double opacity = Double.NaN;
069:
070: Button on;
071: Combo percent;
072: private SelectionListener listener;
073:
074: private class Listener implements SelectionListener, ModifyListener {
075: public void widgetSelected(SelectionEvent e) {
076: sync(e);
077: };
078:
079: public void widgetDefaultSelected(SelectionEvent e) {
080: sync(e);
081: };
082:
083: public void modifyText(ModifyEvent e) {
084: sync(AbstractSimpleConfigurator.selectionEvent(e));
085: };
086:
087: private void sync(SelectionEvent e) {
088: try {
089: RasterViewer.this .enabled = RasterViewer.this .on
090: .getSelection();
091: try {
092: String ptext = RasterViewer.this .percent.getText();
093: if (ptext.endsWith("%")) { //$NON-NLS-1$
094: ptext = ptext.substring(0, ptext.length() - 1);
095: RasterViewer.this .opacity = Double
096: .parseDouble(ptext);
097: RasterViewer.this .opacity /= 100.0;
098: } else {
099: RasterViewer.this .opacity = Double
100: .parseDouble(ptext);
101: if (RasterViewer.this .opacity > 1) {
102: RasterViewer.this .opacity /= 100.0;
103: }
104: }
105: } catch (NumberFormatException nan) {
106: // well lets just leave opacity alone
107: }
108: fire(e); // everything worked
109: } catch (Throwable t) {
110: // meh
111: } finally {
112: RasterViewer.this .percent
113: .setEnabled(RasterViewer.this .enabled);
114: }
115: }
116:
117: };
118:
119: Listener sync = new Listener();
120:
121: /**
122: * TODO summary sentence for createControl ...
123: *
124: * @param parent
125: * @param listener1
126: * @return Generated composite
127: */
128: public Composite createControl(Composite parent,
129: KeyListener listener1) {
130: Composite part = AbstractSimpleConfigurator.subpart(parent,
131: Messages.SimpleStyleConfigurator_raster_label);
132:
133: this .on = new Button(part, SWT.CHECK);
134:
135: this .percent = new Combo(part, SWT.DROP_DOWN);
136: this .percent.setItems(new String[] {
137: "0%", "25%", "50%", "75%", "100%" }); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$//$NON-NLS-4$//$NON-NLS-5$
138: this .percent.setTextLimit(4);
139: this .percent.addKeyListener(listener1);
140: this .percent
141: .setToolTipText(Messages.RasterViewer_percent_tooltip);
142: return part;
143: }
144:
145: void listen(boolean listen) {
146: if (listen) {
147: this .on.addSelectionListener(this .sync);
148: this .percent.addSelectionListener(this .sync);
149: this .percent.addModifyListener(this .sync);
150: } else {
151: this .on.removeSelectionListener(this .sync);
152: this .percent.removeSelectionListener(this .sync);
153: this .percent.removeModifyListener(this .sync);
154: }
155: }
156:
157: /**
158: * Accepts a listener that will be notified when content changes.
159: * @param listener1
160: */
161: public void addListener(SelectionListener listener1) {
162: this .listener = listener1;
163: }
164:
165: /**
166: * Remove listener.
167: * @param listener1
168: */
169: public void removeListener(SelectionListener listener1) {
170: if (this .listener == listener1)
171: this .listener = null;
172: }
173:
174: /**
175: * TODO summary sentence for fire ...
176: *
177: * @param event
178: */
179: protected void fire(SelectionEvent event) {
180: if (this .listener == null)
181: return;
182: this .listener.widgetSelected(event);
183: }
184:
185: /**
186: * Called to set up this "viewer" based on the provided symbolizer
187: * @param sym
188: */
189: public void set(RasterSymbolizer sym2) {
190: listen(false); // don't sync when setting up
191: try {
192: RasterSymbolizer sym = sym2;
193: this .enabled = (sym != null);
194:
195: if (sym == null) {
196: StyleBuilder builder = new StyleBuilder();
197: sym = builder.createRasterSymbolizer();
198: sym.setOpacity(FilterFactoryFinder
199: .createFilterFactory().createLiteralExpression(
200: 1.0));
201: }
202: this .opacity = SLD.rasterOpacity(sym);
203: String text = MessageFormat.format(
204: "{0,number,#0%}", this .opacity); //$NON-NLS-1$
205: this .percent.setText(text);
206: this .percent.select(this .percent.indexOf(text));
207: this .on.setSelection(this .enabled);
208: this .percent.setEnabled(this .enabled);
209: } finally {
210: listen(true); // listen to user now
211: }
212: }
213:
214: /**
215: * TODO summary sentence for getStroke ...
216: * @param build
217: *
218: * @return Stroke defined by this model
219: */
220: public RasterSymbolizer get(StyleBuilder build) {
221: return (opacity == Double.NaN || !enabled) ? null : build
222: .createRasterSymbolizer(null, this.opacity);
223: }
224: }
|