001: /* uDig - User Friendly Desktop Internet GIS client
002: * http://udig.refractions.net
003: * (C) 2004, Refractions Research Inc.
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation;
008: * version 2.1 of the License.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: */
015: package net.refractions.udig.style.sld.simple;
016:
017: import java.awt.Color;
018: import java.text.MessageFormat;
019:
020: import net.refractions.udig.style.sld.AbstractSimpleConfigurator;
021: import net.refractions.udig.style.sld.SLDPlugin;
022: import net.refractions.udig.style.sld.internal.Messages;
023: import net.refractions.udig.style.sld.internal.StolenColorEditor;
024: import net.refractions.udig.ui.graphics.SLDs;
025:
026: import org.eclipse.swt.SWT;
027: import org.eclipse.swt.events.KeyListener;
028: import org.eclipse.swt.events.ModifyEvent;
029: import org.eclipse.swt.events.ModifyListener;
030: import org.eclipse.swt.events.SelectionEvent;
031: import org.eclipse.swt.events.SelectionListener;
032: import org.eclipse.swt.widgets.Button;
033: import org.eclipse.swt.widgets.Combo;
034: import org.eclipse.swt.widgets.Composite;
035: import org.geotools.styling.Fill;
036: import org.geotools.styling.StyleBuilder;
037:
038: /**
039: * Allows editing/viewing of a Style Layer Descriptor "Stroke".
040: * <p>
041: * Here is the pretty picture: <pre><code>
042: * +-+ +-------+ +------+
043: * Fill: |x| | color | | 90%\/|
044: * +-+ +-------+ +------+
045: * </code></pre>
046: * </p>
047: * <p>
048: * Workflow:
049: * <ol>
050: * <li>createControl( parent ) - set up controls
051: * <li>setFill( stroke, 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>getFill( StyleBuilder ) - construct a Fill based on fields
061: * </ul>
062: * </p>
063: * @author Jody Garnett
064: * @since 1.0.0
065: */
066: public class FillViewer {
067: boolean enabled;
068: Color color;
069: double opacity;
070:
071: Button on;
072: StolenColorEditor chooser;
073: Combo percent;
074:
075: private class Listener implements SelectionListener, ModifyListener {
076: public void widgetSelected(SelectionEvent e) {
077: sync(e);
078: };
079:
080: public void widgetDefaultSelected(SelectionEvent e) {
081: sync(e);
082: };
083:
084: public void modifyText(ModifyEvent e) {
085: sync(AbstractSimpleConfigurator.selectionEvent(e));
086: };
087:
088: private void sync(SelectionEvent selectionEvent) {
089: try {
090: FillViewer.this .enabled = FillViewer.this .on
091: .getSelection();
092: FillViewer.this .color = FillViewer.this .chooser
093: .getColor();
094: try {
095: String ptext = FillViewer.this .percent.getText();
096: if (ptext.endsWith("%")) { //$NON-NLS-1$
097: ptext = ptext.substring(0, ptext.length() - 1);
098: FillViewer.this .opacity = Double
099: .parseDouble(ptext) / 100.0;
100: } else {
101: FillViewer.this .opacity = Double
102: .parseDouble(ptext);
103: if (FillViewer.this .opacity > 1) {
104: FillViewer.this .opacity /= 100.0;
105: }
106: }
107: SLDPlugin.trace(
108: "opacity:" + FillViewer.this .opacity, null); //$NON-NLS-1$
109: } catch (NumberFormatException nan) {
110: // well lets just leave opacity alone
111: SLDPlugin.trace("opacity:" + nan, nan); //$NON-NLS-1$
112: throw nan;
113: }
114: fire(selectionEvent); // everything worked
115: } catch (Throwable t) {
116: SLDPlugin.trace("Fill sync failure", t); //$NON-NLS-1$
117: } finally {
118: FillViewer.this .chooser
119: .setEnabled(FillViewer.this .enabled);
120: FillViewer.this .percent
121: .setEnabled(FillViewer.this .enabled);
122: }
123: }
124:
125: };
126:
127: Listener sync = new Listener();
128: private SelectionListener listener;
129:
130: /**
131: * Accepts a listener that will be notified when content changes.
132: * @param listener1
133: */
134: public void addListener(SelectionListener listener1) {
135: this .listener = listener1;
136: }
137:
138: /**
139: * Remove listener.
140: * @param listener1
141: */
142: public void removeListener(SelectionListener listener1) {
143: if (this .listener == listener1)
144: this .listener = null;
145: }
146:
147: /**
148: * TODO summary sentence for fire ...
149: *
150: * @param event
151: */
152: protected void fire(SelectionEvent event) {
153: if (this .listener == null)
154: return;
155: this .listener.widgetSelected(event);
156: }
157:
158: /**
159: * TODO summary sentence for createControl ...
160: *
161: * @param parent
162: * @param kListener
163: * @return Generated composite
164: */
165: public Composite createControl(Composite parent,
166: KeyListener kListener) {
167: Composite part = AbstractSimpleConfigurator.subpart(parent,
168: Messages.SimpleStyleConfigurator_fill_label);
169:
170: this .on = new Button(part, SWT.CHECK);
171: this .on.addSelectionListener(this .sync);
172:
173: this .chooser = new StolenColorEditor(part, this .sync);
174:
175: this .percent = new Combo(part, SWT.DROP_DOWN);
176: this .percent.setItems(new String[] {
177: "0%", "25%", "50%", "75%", "100%" }); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
178: this .percent.setTextLimit(4);
179: this .percent.addKeyListener(kListener);
180: this .percent
181: .setToolTipText(Messages.FillViewer_percent_tooltip);
182: return part;
183: }
184:
185: /**
186: * TODO summary sentence for getFill ...
187: * @param build
188: *
189: * @return Fill defined by this model
190: */
191: public Fill getFill(StyleBuilder build) {
192: if (!this .enabled)
193: return null;
194: if (this .opacity != Double.NaN) {
195: return build.createFill(this .color, this .opacity);
196: }
197: return build.createFill(this .color);
198: }
199:
200: void listen(boolean listen) {
201: if (listen) {
202: this .on.addSelectionListener(this .sync);
203: this .chooser.setListener(this .sync);
204: this .percent.addSelectionListener(this .sync);
205: this .percent.addModifyListener(this .sync);
206: } else {
207: this .on.removeSelectionListener(this .sync);
208: this .chooser.setListener(null);
209: this .percent.removeSelectionListener(this .sync);
210: this .percent.removeModifyListener(this .sync);
211: }
212: }
213:
214: /**
215: * TODO summary sentence for setFill ...
216: *
217: * @param fill
218: * @param mode
219: * @param enabled
220: */
221: public void setFill(Fill fill2, Mode mode, Color defaultColor) {
222: listen(false);
223: try {
224:
225: boolean enabled = true;
226: Fill fill = fill2;
227: if (fill == null) {
228: StyleBuilder builder = new StyleBuilder();
229: fill = builder.createFill(defaultColor, 0.5);
230: enabled = false;
231: }
232:
233: this .enabled = enabled
234: && ((mode != Mode.NONE && mode != Mode.LINE) && fill != null);
235: this .color = SLDs.color(fill);
236: this .opacity = SLDs.opacity(fill);
237:
238: // Fill is used in point and polygon
239: this .on.setEnabled(mode != Mode.NONE && mode != Mode.LINE);
240: this .chooser.setColor(this .color);
241:
242: String text = MessageFormat.format(
243: "{0,number,#0%}", this .opacity); //$NON-NLS-1$
244: this .percent.setText(text);
245: this .percent.select(this .percent.indexOf(text));
246:
247: this .on.setSelection(this .enabled);
248: this .chooser.setEnabled(this .enabled);
249: this .percent.setEnabled(this .enabled);
250: } finally {
251: listen(true);
252: }
253: }
254: }
|