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 net.refractions.udig.style.sld.AbstractSimpleConfigurator;
018: import net.refractions.udig.style.sld.SLDPlugin;
019: import net.refractions.udig.style.sld.internal.Messages;
020:
021: import org.eclipse.swt.SWT;
022: import org.eclipse.swt.events.KeyListener;
023: import org.eclipse.swt.events.ModifyEvent;
024: import org.eclipse.swt.events.ModifyListener;
025: import org.eclipse.swt.events.SelectionEvent;
026: import org.eclipse.swt.events.SelectionListener;
027: import org.eclipse.swt.widgets.Button;
028: import org.eclipse.swt.widgets.Combo;
029: import org.eclipse.swt.widgets.Composite;
030:
031: /**
032: * Allows editing/viewing of a scale. Used to build the min/max scale editors for a rule.
033: * <p>
034: * Here is the pretty picture: <pre><code>
035: * +-+ +-------------+
036: * Scale:|x| | 90% \/|
037: * +-+ +-------------+
038: * </code></pre>
039: * </p>
040: * <p>
041: * Workflow:
042: * <ol>
043: * <li>createControl( parent ) - set up controls
044: * <li>setFill( stroke, mode ) - provide content from SimpleStyleConfigurator/SimpleRasterConfigurator
045: * <ol>
046: * <li> scale values got from rules
047: * <li> values copied into controls
048: * <li> controls enabled based on mode & fields
049: * </ol>
050: * <li>Listener.widgetSelected/modifyText - User performs an "edit"
051: * <li>Listener.sync( SelectionEvent ) - update fields with values of controls
052: * <li>fire( SelectionSevent ) - notify SimpleStyleConfigurator/SimpleRasterConfigurator of change
053: * <li>getScale( ) - returns the specified scale
054: * </ul>
055: * </p>
056: * @author Andrea Aime
057: * @since 1.1
058: */
059: public class ScaleViewer {
060: public static final int MIN = 0;
061: public static final int MAX = 1;
062:
063: boolean enabled;
064: double scale;
065: int type;
066:
067: Button on;
068: Combo scaleEditor;
069:
070: private class Listener implements SelectionListener, ModifyListener {
071: public void widgetSelected(SelectionEvent e) {
072: sync(e);
073: };
074:
075: public void widgetDefaultSelected(SelectionEvent e) {
076: sync(e);
077: };
078:
079: public void modifyText(ModifyEvent e) {
080: sync(AbstractSimpleConfigurator.selectionEvent(e));
081: };
082:
083: private void sync(SelectionEvent selectionEvent) {
084: try {
085: ScaleViewer.this .enabled = ScaleViewer.this .on
086: .getSelection();
087: String ptext = ScaleViewer.this .scaleEditor.getText();
088: ScaleViewer.this .scale = Double.parseDouble(ptext);
089: SLDPlugin.trace(
090: "scale: " + ScaleViewer.this .scale, null); //$NON-NLS-1$
091: fire(selectionEvent); // everything worked
092: } catch (Throwable t) {
093: SLDPlugin.trace("Scale sync failure", t); //$NON-NLS-1$
094: } finally {
095: ScaleViewer.this .scaleEditor
096: .setEnabled(ScaleViewer.this .enabled);
097: }
098: }
099:
100: };
101:
102: Listener sync = new Listener();
103: private SelectionListener listener;
104:
105: public ScaleViewer(int type) {
106: if (type != MIN && type != MAX)
107: throw new IllegalArgumentException(
108: "Type should be either MIN or MAX"); //$NON-NLS-1$
109: this .type = type;
110: this .scale = type == MIN ? 0 : Double.MAX_VALUE;
111: }
112:
113: /**
114: * Accepts a listener that will be notified when content changes.
115: * @param listener1
116: */
117: public void addListener(SelectionListener listener1) {
118: this .listener = listener1;
119: }
120:
121: /**
122: * Remove listener.
123: * @param listener1
124: */
125: public void removeListener(SelectionListener listener1) {
126: if (this .listener == listener1)
127: this .listener = null;
128: }
129:
130: /**
131: * TODO summary sentence for fire ...
132: *
133: * @param event
134: */
135: protected void fire(SelectionEvent event) {
136: if (this .listener == null)
137: return;
138: this .listener.widgetSelected(event);
139: }
140:
141: /**
142: * TODO summary sentence for createControl ...
143: *
144: * @param parent
145: * @param kListener
146: * @return Generated composite
147: */
148: public Composite createControl(Composite parent,
149: KeyListener kListener) {
150: String labelId = type == MIN ? Messages.SimpleStyleConfigurator_minscaleden_label
151: : Messages.SimpleStyleConfigurator_maxscaleden_label;
152: Composite part = AbstractSimpleConfigurator.subpart(parent,
153: labelId);
154:
155: this .on = new Button(part, SWT.CHECK);
156: this .on.addSelectionListener(this .sync);
157:
158: this .scaleEditor = new Combo(part, SWT.DROP_DOWN);
159: this .scaleEditor
160: .setItems(new String[] {
161: "100", "1000", "10000", "100000", "1000000", "10000000" }); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
162: this .scaleEditor.setTextLimit(10);
163: this .scaleEditor.addKeyListener(kListener);
164: String tooltip = type == MIN ? Messages.ScaleViewer_minscaleden_tooltip
165: : Messages.ScaleViewer_maxscaleden_tooltip;
166: this .scaleEditor.setToolTipText(tooltip);
167: return part;
168: }
169:
170: /**
171: * Gets the scale denominator chosen by the user, or the default value for this type if none was selected.
172: * Default values are 0 for MIN type, {@linkplain Double#MAX_VALUE} for the MAX type
173: * @param build
174: *
175: * @return Fill defined by this model
176: */
177: public double getScale() {
178: if (!this .enabled)
179: return type == MIN ? 0 : Double.MAX_VALUE;
180: else
181: return scale;
182: }
183:
184: /**
185: * Sets the scale denominator, or disables the component if the provided scale is not a positive number
186: * @param scale
187: */
188: public void setScale(double scale2, long defaultScale) {
189: listen(false);
190:
191: this .scale = scale2;
192: this .enabled = true;
193: if (Double.isNaN(scale) || Double.isInfinite(scale)
194: || scale <= Double.MIN_VALUE
195: || scale >= Double.MAX_VALUE) {
196: this .scale = defaultScale;
197: this .enabled = false;
198: }
199:
200: scaleEditor.setText(Double.toString(scale));
201: this .on.setSelection(this .enabled);
202: this .scaleEditor.setEnabled(this .enabled);
203: listen(true);
204: }
205:
206: void listen(boolean listen) {
207: if (listen) {
208: this .on.addSelectionListener(this .sync);
209: this .scaleEditor.addSelectionListener(this .sync);
210: this .scaleEditor.addModifyListener(this .sync);
211: } else {
212: this .on.removeSelectionListener(this .sync);
213: this .scaleEditor.removeSelectionListener(this .sync);
214: this .scaleEditor.removeModifyListener(this .sync);
215: }
216: }
217:
218: public boolean isEnabled() {
219: return enabled;
220: }
221:
222: }
|