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.internal.Messages;
022:
023: import org.eclipse.swt.SWT;
024: import org.eclipse.swt.events.KeyListener;
025: import org.eclipse.swt.events.ModifyEvent;
026: import org.eclipse.swt.events.ModifyListener;
027: import org.eclipse.swt.events.SelectionEvent;
028: import org.eclipse.swt.events.SelectionListener;
029: import org.eclipse.swt.widgets.Button;
030: import org.eclipse.swt.widgets.Combo;
031: import org.eclipse.swt.widgets.Composite;
032: import org.geotools.styling.Fill;
033: import org.geotools.styling.Graphic;
034: import org.geotools.styling.Mark;
035: import org.geotools.styling.SLD;
036: import org.geotools.styling.Stroke;
037: import org.geotools.styling.StyleBuilder;
038:
039: /**
040: * Allows editing/viewing of a Style Layer Descriptor "Graphic".
041: * <p>
042: * Here is the pretty picture: <pre><code>
043: * +-+ +-------+ +------+
044: * Point: |x| | star\/| |size\/|
045: * +-+ +-------+ +------+
046: * </code></pre>
047: * </p>
048: * <p>
049: * Workflow:
050: * <ol>
051: * <li>createControl( parent ) - set up controls
052: * <li>setGraphic( graphic, mode ) - provide content from SimpleStyleConfigurator
053: * <ol>
054: * <li> Symbolizer values copied into fields based on mode
055: * <li> fields copied into controls
056: * <li> controls enabled based on mode & fields
057: * </ol>
058: * <li>Listener.widgetSelected/modifyText - User performs an "edit"
059: * <li>Listener.sync( SelectionEvent ) - update fields with values of controls
060: * <li>fire( SelectionSevent ) - notify SimpleStyleConfigurator of change
061: * <li>getGraphic( Fill, Stroke, StyleBuilder ) - construct a Graphic based on fields
062: * </ul>
063: * </p>
064: * @author Jody Garnett
065: * @since 1.0.0
066: */
067: public class GraphicViewer {
068: boolean enabled;
069: String type;
070: double width;
071:
072: Button on;
073: Combo name;
074: Combo size;
075:
076: private class Listener implements SelectionListener, ModifyListener {
077: public void widgetSelected(SelectionEvent e) {
078: sync(e);
079: };
080:
081: public void widgetDefaultSelected(SelectionEvent e) {
082: sync(e);
083: };
084:
085: public void modifyText(final ModifyEvent e) {
086: sync(AbstractSimpleConfigurator.selectionEvent(e));
087: };
088:
089: private void sync(SelectionEvent selectionEvent) {
090: try {
091: GraphicViewer.this .enabled = GraphicViewer.this .on
092: .getSelection();
093: GraphicViewer.this .type = GraphicViewer.this .name
094: .getText();
095: try {
096: GraphicViewer.this .width = Integer
097: .parseInt(GraphicViewer.this .size.getText());
098: } catch (NumberFormatException nan) {
099: // well lets just leave width alone
100: }
101: fire(selectionEvent); // everything worked
102: } catch (Throwable t) {
103: //meh
104: } finally {
105: GraphicViewer.this .name
106: .setEnabled(GraphicViewer.this .enabled);
107: GraphicViewer.this .size
108: .setEnabled(GraphicViewer.this .enabled);
109: }
110: }
111:
112: };
113:
114: Listener sync = new Listener();
115: private SelectionListener listener;
116:
117: /**
118: * Accepts a listener that will be notified when content changes.
119: * @param listener1
120: */
121: public void addListener(SelectionListener listener1) {
122: this .listener = listener1;
123: }
124:
125: /**
126: * Remove listener.
127: * @param listener1
128: */
129: public void removeListener(SelectionListener listener1) {
130: if (this .listener == listener1)
131: this .listener = null;
132: }
133:
134: /**
135: * TODO summary sentence for fire ...
136: *
137: * @param event
138: */
139: protected void fire(SelectionEvent event) {
140: if (this .listener == null)
141: return;
142: this .listener.widgetSelected(event);
143: }
144:
145: /**
146: * TODO summary sentence for createControl ...
147: *
148: * @param parent
149: * @param klisten
150: * @param build
151: * @return Generated composite
152: */
153: public Composite createControl(Composite parent,
154: KeyListener klisten, StyleBuilder build) {
155: Composite part = AbstractSimpleConfigurator.subpart(parent,
156: Messages.SimpleStyleConfigurator_point_label);
157:
158: this .on = new Button(part, SWT.CHECK);
159: //this.on.addSelectionListener( this.sync );
160:
161: this .size = new Combo(part, SWT.DROP_DOWN);
162: this .size.setItems(new String[] {
163: "1", "2", "3", "5", "10", "15" }); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
164: this .size.setTextLimit(2);
165: this .size.addKeyListener(klisten);
166: this .size.setToolTipText(Messages.GraphicViewer_size_tooltip);
167:
168: this .name = new Combo(part, SWT.DROP_DOWN);
169: this .name.setItems(build.getWellKnownMarkNames());
170: this .name.setTextLimit(9);
171: this .name.addKeyListener(klisten);
172: this .name.setToolTipText(Messages.GraphicViewer_name_tooltip);
173: return part;
174: }
175:
176: /**
177: * TODO summary sentence for getGraphic ...
178: *
179: * @param filll
180: * @param stroke
181: * @param build
182: * @return Graphic defined by this model
183: */
184: public Graphic getGraphic(Fill filll, Stroke stroke,
185: StyleBuilder build) {
186: if (!this .enabled) {
187: Mark mark = null;
188: if (this .type == null) {
189: build.createMark("square", null, null); //$NON-NLS-1$
190: } else {
191: mark = build.createMark(this .type, (Fill) null,
192: (Stroke) null);
193: }
194: return build.createGraphic(null, mark, null);
195: }
196: Mark mark = build.createMark(this .type, filll, stroke);
197: Graphic graphic = build.createGraphic(null, mark, null);
198: graphic.setSize(build.literalExpression(this .width));
199: return graphic;
200: }
201:
202: /**
203: * TODO summary sentence for setGraphic ...
204: *
205: * @param graphic
206: * @param mode
207: * @param enabled
208: */
209: public void setGraphic(Graphic graphic2, Mode mode,
210: Color defaultColor) {
211:
212: boolean enabled = true;
213: Graphic graphic = graphic2;
214: if (graphic == null) {
215: StyleBuilder builder = new StyleBuilder();
216: graphic = builder.createGraphic(null, builder.createMark(
217: StyleBuilder.MARK_SQUARE, defaultColor), null);
218: enabled = false;
219: }
220: if (graphic == null || graphic.getMarks() == null
221: || graphic.getMarks().length == 0)
222: setMark(null, mode);
223: else
224: setMark(graphic.getMarks()[0], mode);
225: this .enabled = this .enabled && enabled;
226: }
227:
228: private void setMark(Mark mark, Mode mode) {
229: listen(false);
230: try {
231: this .enabled = (mode == Mode.POINT && mark != null);
232: this .width = SLD.size(mark);
233: this .type = SLD.wellKnownName(mark);
234:
235: // Stroke is used in line, point and polygon
236: this .on.setEnabled(mode == Mode.POINT);
237:
238: String text = MessageFormat.format(
239: "{0,number,#0}", this .width); //$NON-NLS-1$
240: if (text != null) {
241: this .size.setText(text);
242: this .size.select(this .size.indexOf(text));
243: }
244:
245: if (this .type != null) {
246: this .name.setText(this .type);
247: this .name.select(this .name.indexOf(text));
248: }
249:
250: this .on.setSelection(this .enabled);
251: this .size.setEnabled(this .enabled);
252: this .name.setEnabled(this .enabled);
253: } finally {
254: listen(true); // listen to user now
255: }
256: }
257:
258: void listen(boolean listen) {
259: if (listen) {
260: this.on.addSelectionListener(this.sync);
261: this.size.addSelectionListener(this.sync);
262: this.size.addModifyListener(this.sync);
263: this.name.addSelectionListener(this.sync);
264: this.name.addModifyListener(this.sync);
265: } else {
266: this.on.removeSelectionListener(this.sync);
267: this.size.removeSelectionListener(this.sync);
268: this.size.removeModifyListener(this.sync);
269: this.name.removeSelectionListener(this.sync);
270: this.name.removeModifyListener(this.sync);
271: }
272: }
273: }
|