Revision 37374

View differences:

tags/v2_0_0_Build_2041/libraries/libFMap_controls/src-test/org/gvsig/fmap/mapcontrol/tools/AreaListenerTest.java
1
package org.gvsig.fmap.mapcontrol.tools;
2

  
3
import java.awt.geom.Point2D;
4

  
5
import org.cresques.cts.IProjection;
6
import org.gvsig.fmap.crs.CRSFactory;
7
import org.gvsig.fmap.mapcontext.MapContext;
8
import org.gvsig.fmap.mapcontext.ViewPort;
9
import org.gvsig.fmap.mapcontrol.MapControl;
10
import org.gvsig.tools.junit.AbstractLibraryAutoInitTestCase;
11

  
12

  
13
public class AreaListenerTest extends AbstractLibraryAutoInitTestCase {
14
	private IProjection projectionUTM = CRSFactory.getCRS("EPSG:23030");
15
	private IProjection projectionGeo = CRSFactory.getCRS("EPSG:4230");
16
		
17
	@Override
18
	protected void doSetUp() throws Exception {
19
		// Nothing to do	
20
	}
21

  
22
	public void test1() {
23
		AreaListenerImpl areaListenerUTM=new AreaListenerImpl(newMapControlUTM());
24
		AreaListenerImpl areaListenerGeo=new AreaListenerImpl(newMapControlGeo());
25
		Double[] xsUTM=new Double[] {new Double(731292),new Double(731901),new Double(730138)};
26
		Double[] ysUTM=new Double[] {new Double(4351223),new Double(4350768),new Double(4349232)};
27
		double areaUTM=areaListenerUTM.returnCoordsArea(xsUTM,ysUTM,new Point2D.Double(730138,4349232));
28
		Double[] xsGeo=new Double[] {new Double(-0.31888183),new Double(-0.31173131),new Double(-0.33268401)};
29
		Double[] ysGeo=new Double[] {new Double(39.27871741),new Double(39.27464327),new Double(39.26117368)};
30
		double areaGeo=areaListenerGeo.returnGeoCArea(xsGeo,ysGeo,new Point2D.Double(-0.33268401,39.26117368));
31
		assertTrue("Area UTM igual a Geo",areaUTM<(areaGeo+1000)&& areaUTM>(areaGeo-1000));
32
	}
33
	private MapControl newMapControlUTM() {
34
		ViewPort vp = new ViewPort(projectionUTM);
35
		MapControl mc=new MapControl();
36
		mc.setMapContext(new MapContext(vp));
37
		return mc;
38
	}
39
	private MapControl newMapControlGeo() {
40
		ViewPort vp = new ViewPort(projectionGeo);
41
		MapControl mc=new MapControl();
42
		mc.setMapContext(new MapContext(vp));
43
		return mc;
44
	}
45
}
tags/v2_0_0_Build_2041/libraries/libFMap_controls/src/org/gvsig/app/gui/JComboBoxUnits.java
1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *  Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib??ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *      +34 963862235
28
 *   gvsig@gva.es
29
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41
package org.gvsig.app.gui;
42

  
43
import org.gvsig.fmap.mapcontext.MapContext;
44
import org.gvsig.i18n.Messages;
45
import org.gvsig.utils.swing.JComboBox;
46

  
47

  
48
/**
49
 * <p>Class representing a JComboBox with the measure units handled by the application.
50
 * It takes values from Attributes.NAMES and Attributes.CHANGE static fields. So, to
51
 * add more measure units, you must edit Attributes class and change will be automatically
52
 * reflected in the combo box.</p>
53
 *
54
 * <p>The internatiolanization of the field is automatically handled by the system</p>
55
 * @author jaume dominguez faus - jaume.dominguez@iver.es
56
 */
57
public class JComboBoxUnits extends JComboBox {
58
	private static final long serialVersionUID = 8015263853737441433L;
59

  
60
	/**
61
	 * Creates a new instance of JUnitComboBox including "pixel" units and
62
	 * setting them as automatically pre-selected.
63
	 */
64
	public JComboBoxUnits() {
65
		this(true);
66
	}
67

  
68
	/**
69
	 *
70
	 * Creates a new instance of JUnitComboBox. If includePixel is true
71
	 * then pixel units are included in the list and they are automatically
72
	 * pre-selected. Otherwise, meters are preselected.
73
	 *
74
	 */
75
	public JComboBoxUnits(boolean includePixel) {
76
		super();
77
		String[] names=MapContext.getDistanceNames();
78

  
79
		for (int i = 0; i < names.length; i++) {
80
			super.addItem(Messages.getText(names[i]));
81
		}
82
		if (includePixel) {
83
			super.addItem(Messages.getText("pixels"));
84
			setSelectedItem(Messages.getText("pixels"));
85
		} else {
86
			setSelectedIndex(1);
87
		}
88
		setMaximumRowCount(10);
89
	}
90

  
91

  
92
	/**
93
	 * Returns the conversion factor from the <b>unit selected in the combo box</b>
94
	 * to <b>meters</b> or <b>0</b> if pixels have been selected as the size unit.
95
	 * @return
96
	 */
97
	public double getUnitConversionFactor() {
98
			double unitFactor;
99
			try {
100
				unitFactor = MapContext.getDistanceTrans2Meter()[getSelectedIndex()];
101
			} catch (ArrayIndexOutOfBoundsException aioobEx) { //jijiji
102
				unitFactor = 0; // which represents size in pixel
103
			}
104
			return unitFactor;
105

  
106
	}
107

  
108
	/**
109
	 * the use of this method is not allowed in this combo box.
110
	 * @deprecated
111
	 */
112
	public void addItem(Object anObject) {
113
		throw new Error("Operation not allowed");
114
	}
115

  
116
	/**
117
	 * the use of this method is not allowed for this combo box.
118
	 * @deprecated
119
	 */
120
	public void removeAllItems() {
121
		throw new Error("Operation not allowed");
122
	}
123

  
124
	public int getSelectedUnitIndex() {
125
		int i = getSelectedIndex();
126
		if (i>MapContext.getDistanceNames().length-1)
127
			return -1;
128
		else return i;
129
	}
130

  
131
	public void setSelectedUnitIndex(int unitIndex) {
132
		if (unitIndex == -1) {
133
			setSelectedIndex(getItemCount()-1);
134
		} else {
135
			setSelectedIndex(unitIndex);
136
		}
137
	}
138

  
139

  
140

  
141
}
0 142

  
tags/v2_0_0_Build_2041/libraries/libFMap_controls/src/org/gvsig/fmap/mapcontrol/MapControl.java
1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *  Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib??ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *      +34 963862235
28
 *   gvsig@gva.es
29
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41
package org.gvsig.fmap.mapcontrol;
42

  
43
import java.awt.Color;
44
import java.awt.Cursor;
45
import java.awt.Dimension;
46
import java.awt.Graphics;
47
import java.awt.Graphics2D;
48
import java.awt.Image;
49
import java.awt.Point;
50
import java.awt.Toolkit;
51
import java.awt.event.ActionEvent;
52
import java.awt.event.ActionListener;
53
import java.awt.event.ComponentEvent;
54
import java.awt.event.ComponentListener;
55
import java.awt.event.MouseEvent;
56
import java.awt.event.MouseListener;
57
import java.awt.event.MouseMotionListener;
58
import java.awt.event.MouseWheelEvent;
59
import java.awt.event.MouseWheelListener;
60
import java.awt.geom.Point2D;
61
import java.awt.image.BufferedImage;
62
import java.awt.image.MemoryImageSource;
63
import java.util.ArrayList;
64
import java.util.Comparator;
65
import java.util.HashMap;
66
import java.util.List;
67
import java.util.Set;
68
import java.util.TreeMap;
69
import java.util.prefs.Preferences;
70

  
71
import javax.swing.JComponent;
72
import javax.swing.SwingUtilities;
73
import javax.swing.Timer;
74

  
75
import org.cresques.cts.IProjection;
76
import org.slf4j.Logger;
77
import org.slf4j.LoggerFactory;
78

  
79
import org.gvsig.fmap.crs.CRSFactory;
80
import org.gvsig.fmap.dal.DataStoreNotification;
81
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
82
import org.gvsig.fmap.geom.Geometry;
83
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
84
import org.gvsig.fmap.geom.GeometryLocator;
85
import org.gvsig.fmap.geom.GeometryManager;
86
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
87
import org.gvsig.fmap.geom.primitive.Envelope;
88
import org.gvsig.fmap.geom.util.Converter;
89
import org.gvsig.fmap.mapcontext.MapContext;
90
import org.gvsig.fmap.mapcontext.ViewPort;
91
import org.gvsig.fmap.mapcontext.events.AtomicEvent;
92
import org.gvsig.fmap.mapcontext.events.listeners.AtomicEventListener;
93
import org.gvsig.fmap.mapcontext.layers.FLayers;
94
import org.gvsig.fmap.mapcontext.layers.LayerCollectionEvent;
95
import org.gvsig.fmap.mapcontext.layers.LayerEvent;
96
import org.gvsig.fmap.mapcontext.layers.SpatialCache;
97
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
98
import org.gvsig.fmap.mapcontext.layers.vectorial.GraphicLayer;
99
import org.gvsig.fmap.mapcontrol.tools.BehaviorException;
100
import org.gvsig.fmap.mapcontrol.tools.CompoundBehavior;
101
import org.gvsig.fmap.mapcontrol.tools.Behavior.Behavior;
102
import org.gvsig.fmap.mapcontrol.tools.Listeners.ToolListener;
103
import org.gvsig.fmap.mapcontrol.tools.grid.Grid;
104
import org.gvsig.fmap.mapcontrol.tools.snapping.snappers.ISnapper;
105
import org.gvsig.fmap.mapcontrol.tools.snapping.snappers.ISnapperGeometriesVectorial;
106
import org.gvsig.fmap.mapcontrol.tools.snapping.snappers.ISnapperRaster;
107
import org.gvsig.fmap.mapcontrol.tools.snapping.snappers.ISnapperVectorial;
108
import org.gvsig.tools.observer.Observable;
109
import org.gvsig.tools.observer.Observer;
110
import org.gvsig.tools.task.Cancellable;
111
import org.gvsig.utils.exceptionHandling.ExceptionHandlingSupport;
112
import org.gvsig.utils.exceptionHandling.ExceptionListener;
113

  
114
/**
115
 * <p>
116
 * A component that includes a {@link MapContext MapContext} with support for
117
 * use it as a particular {@link Behavior Behavior}.
118
 * </p>
119
 * 
120
 * <p>
121
 * A developer can register a set of <code>Behavior</code>, but only one (that
122
 * can be a composition of several) of them can be active. The active one
123
 * defines the way to work and access with its <code>MapContext</code>'s layers.
124
 * The active behavior, in combination with the appropriate {@link ToolListener
125
 * ToolListener} will allow user work with a particular <i>tool</i>.
126
 * </p>
127
 * 
128
 * <p>
129
 * All mouse events produced on this component will be delegated to the current
130
 * active behavior, the <i>currentMapTool</i>.
131
 * </p>
132
 * 
133
 * <p>
134
 * <b>Drawing process:</b>
135
 * </p>
136
 * 
137
 * <p>
138
 * Uses a double buffer for the drawing process of <code>MapContext</code>'s
139
 * information.
140
 * </p>
141
 * 
142
 * <p>
143
 * If the double buffer wasn't created, creates a new one.
144
 * </p>
145
 * 
146
 * <p>
147
 * Paints the component according the following algorithm: <br>
148
 * &nbsp If <i>status</i> is <i>UPDATED</i>:<br>
149
 * &nbsp &nbsp If there is a <i>double buffer</i>:<br>
150
 * &nbsp &nbsp &nbsp If there is a <i>behavior</i> for managing the
151
 * <code>MapControl</code> instance, delegates the drawing process to that
152
 * behavior, calling: <code><i>behavior_instance</i>.paintComponent(g)</code>.<br>
153
 * &nbsp &nbsp &nbsp Else, repaints the current graphical information quickly
154
 * calling: <code>g.drawImage(image,0,0,null)</code>.<br>
155
 * &nbsp Else, (<i>status</i> is <i>OUTDATED</i>, or <i>ONLY_GRAPHICS</i>):
156
 * executes a quickly repaint of the previous information calling
157
 * <code>g.drawImage(image,0,0,null)</code>, and creates a <i>painting
158
 * request</i> to delegate the heavy drawing process to the {@link Drawer2
159
 * Drawer2}'s worker thread, according the <i>SingleWorketThread</i> pattern,
160
 * starting a timer to update (invoking <code>repaint()</code>) the view every
161
 * delay of <code>1000 / drawFrameRate</code> ms. during that heavy drawing
162
 * process, and if its enabled <code>drawAnimationEnabled</code>. The
163
 * <i>painting request</i> once is being attended, invokes
164
 * <code>MapContext</code> to draw the layers:
165
 * <code>mapContext.draw(image, g, cancel,mapContext.getScaleView());</code>
166
 * <br>
167
 * <p>
168
 * Some notes:
169
 * <ul>
170
 * <li>The painting process can be cancelled calling {@link #cancelDrawing()
171
 * #cancelDrawing()}.</li>
172
 * <li>At last resort, the particular implementation of each layer in a
173
 * <code>MapControl</code>'s <code>MapContrext</code> will be that one which
174
 * will draw the graphical information, and, if supports, which could cancel its
175
 * drawing subprocess.</li>
176
 * <li>It's possible to force repaint all layers, calling
177
 * {@link #drawMap(boolean doClear) #drawMap(boolean)}.</li>
178
 * <li>It's possible repaint only the dirty layers, calling
179
 * {@link #rePaintDirtyLayers() #rePaintDirtyLayers()}.</li>
180
 * <li>It's possible repaint only the {@link GraphicLayer GraphicLayer}, calling
181
 * {@link #drawGraphics() #drawGraphics()}.</li>
182
 * </ul>
183
 * </p>
184
 * 
185
 * <p>
186
 * <b>Tools:</b>
187
 * </p>
188
 * 
189
 * <p>
190
 * A developer can:
191
 * <ul>
192
 * <li>Register each tool as:
193
 * <ul>
194
 * <li>A single behavior: {@link #addBehavior(String, Behavior)
195
 * #addMapTool(String, Behavior)}.</li>
196
 * <li>Or, a compound behavior: {@link #addBehavior(String, Behavior)
197
 * #addMapTool(String, Behavior)}.</li>
198
 * </ul>
199
 * </li>
200
 * <li>Get the current active tool: {@link #getCurrentMapTool()
201
 * #getCurrentMapTool()}.</li>
202
 * <li>Get the current active tool name: {@link #getCurrentTool()
203
 * #getCurrentTool()}.</li>
204
 * <li>Get a registered tool: {@link #getMapTool(String) #getMapTool(String)}.</li>
205
 * <li>Get the name of all tools registered: {@link #getMapToolsKeySet()
206
 * #getMapToolsKeySet()}.</li>
207
 * <li>Get all tools registered, including the name they were registered:
208
 * {@link #getNamesMapTools() #getNamesMapTools()}.</li>
209
 * <li>Determine if has a tool registered: {@link #hasTool(String)
210
 * #hasTool(String)}.</li>
211
 * <li>Set as an active tool, one of the registered: {@link #setTool(String)
212
 * #setTool(String)}.</li>
213
 * <li>Set as active tool, the previous used: {@link #setPrevTool()
214
 * #setPrevTool()}.</li>
215
 * <li>Set the current tool: {@link #setCurrentMapTool(Behavior)
216
 * #setCurrentMapTool(Behavior)}.</li>
217
 * <li>Change the draw frame rate: {@link #setDrawFrameRate(int)
218
 * #setDrawFrameRate(int)} and {@link #applyFrameRate() #applyFrameRate()}.</li>
219
 * <li>Get the draw frame rate: {@link #getDrawFrameRate() #getDrawFrameRate()}.
220
 * </li>
221
 * <li>Determine if will repaint this component each time timer finishes:
222
 * {@link #isDrawAnimationEnabled() #isDrawAnimationEnabled()}.</li>
223
 * <li>Change if will repaint this component each time timer finishes:
224
 * {@link #setDrawAnimationEnabled(boolean) #setDrawAnimationEnabled(boolean)}.</li>
225
 * <li>Get the shared object that determines if a drawing process must be
226
 * cancelled or can continue: {@link #getCanceldraw() #getCanceldraw()}.</li>
227
 * <li>Get the combined tool: {@link #getCombinedTool() #getCombinedTool()}.</li>
228
 * <li>Set a combined tool: {@link #setCombinedTool(Behavior)
229
 * #setCombinedTool(Behavior)}.</li>
230
 * <li>Remove the combined tool: {@link #removeCombinedTool()
231
 * #removeCombinedTool()}.</li>
232
 * </ul>
233
 * </p>
234
 * 
235
 * <p>
236
 * <b>Exception listener:</b>
237
 * </p>
238
 * 
239
 * <p>
240
 * Adding an <code>ExceptionListener</code>, can get notification about any
241
 * exception produced:
242
 * <ul>
243
 * <li>Attending a <i>painting request</i>.</li>
244
 * <li>Working with the active tool.</li>
245
 * <li>Applying a <i>zoom in</i> or <i>zoom out</i> operation.</li>
246
 * </ul>
247
 * </p>
248
 * 
249
 * <p>
250
 * <b>Other:</b>
251
 * </p>
252
 * 
253
 * <p>
254
 * Other useful capabilities of <code>MapControl</code>:
255
 * <ul>
256
 * <li>Cancel the current drawing process (notifying it also to the inner
257
 * <code>MapContext</code> instance and its layers): {@link #cancelDrawing()
258
 * #cancelDrawing()}.</li>
259
 * <li>Applying a <i>zoom in</i> operation centered at mouse position (without a
260
 * <code>ToolListener</code>): {@link #zoomIn() #zoomIn()}.</li>
261
 * <li>Applying a <i>zoom out</i> operation centered at mouse position (without
262
 * a <code>ToolListener</code>): {@link #zoomOut() #zoomOut()}.</li>
263
 * </ul>
264
 * </p>
265
 * 
266
 * @see CancelDraw
267
 * @see Drawer
268
 * @see MapContextListener
269
 * @see MapToolListener
270
 * 
271
 * @author Fernando Gonz?lez Cort?s
272
 * @author Pablo Piqueras Bartolom? (pablo.piqueras@iver.es)
273
 */
274
public class MapControl extends JComponent implements ComponentListener,
275
    Observer {
276

  
277
    protected static final GeometryManager geomManager =
278
        GeometryLocator.getGeometryManager();
279
    protected static final Logger logger =
280
        LoggerFactory.getLogger(GeometryManager.class);
281

  
282
    /**
283
     * <p>
284
     * One of the possible status of <code>MapControl</code>. Determines that
285
     * all visible information has been drawn and its updated.
286
     * </p>
287
     */
288
    public static final int ACTUALIZADO = 0;
289

  
290
    /**
291
     * <p>
292
     * One of the possible status of <code>MapControl</code>. Determines that
293
     * not all visible information has been drawn or isn't updated.
294
     * </p>
295
     */
296
    public static final int DESACTUALIZADO = 1;
297

  
298
    /**
299
     * <p>
300
     * One of the possible status of <code>MapControl</code>. Determines that
301
     * only the graphical layer must be drawn / updated.
302
     * </p>
303
     */
304
    public static final int ONLY_GRAPHICS = 2;
305

  
306
    /**
307
     * <p>
308
     * Determines if the drawer can update this <code>MapControl</code> instance
309
     * when the timer launches an event.
310
     * </p>
311
     */
312
    private static boolean drawAnimationEnabled = true;
313

  
314
    /**
315
     * <p>
316
     * Inner model with the layers, event support for drawing them, and the
317
     * <code>ViewPort</code> with information to adapt to the bounds available
318
     * in <i>image coordinates</i>.
319
     * </p>
320
     * 
321
     * @see #getMapContext()
322
     * @see #setMapContext(MapContext)
323
     */
324
    private MapContext mapContext = null;
325

  
326
    /**
327
     * <p>
328
     * All registered <code>Behavior</code> that can define a way to work with
329
     * this <code>MapControl</code>.
330
     * </p>
331
     * 
332
     * <p>
333
     * Only one of them can be active at a given moment.
334
     * </p>
335
     * 
336
     * @see #addBehavior(String, Behavior)
337
     * @see #addBehavior(String, Behavior[])
338
     * @see #getMapTool(String)
339
     * @see #getMapToolsKeySet()
340
     * @see #getNamesMapTools()
341
     */
342
    protected HashMap namesMapTools = new HashMap();
343

  
344
    /**
345
     * <p>
346
     * Active {@link Behavior Behavior} that will generate events according a
347
     * criterion, and then, with a {@link ToolListener ToolListener} associated,
348
     * will simulate to user that works with this component as a particular
349
     * tool.
350
     * </p>
351
     * 
352
     * @see #getCurrentMapTool()
353
     * @see #getCurrentTool()
354
     * @see #setTool(String)
355
     */
356
    protected Behavior currentMapTool = null;
357

  
358
    /**
359
     * <p>
360
     * Determines which's the current drawn status of this component:
361
     * <ul>
362
     * <li><b>OUTDATED</b>: all visible information has been drawn or isn't
363
     * updated.</li>
364
     * <li><b>UTDATED</b>: all visible information has been drawn and its
365
     * updated.</li>
366
     * <li><b>ONLY_GRAPHICS</b>: only the graphical layer must be drawn /
367
     * updated.</li>
368
     * </ul>
369
     * </p>
370
     * 
371
     * <p>
372
     * The <code>MapControl</code> drawing process will consider the value of
373
     * this parameter to decide which elements will be updated or drawn.
374
     * </p>
375
     */
376
    private int status = DESACTUALIZADO;
377

  
378
    /**
379
     * <p>
380
     * Image with a buffer to accelerate the draw the changes of the graphical
381
     * items in this component.
382
     * </p>
383
     * 
384
     * <p>
385
     * Firstly, information will be drawn in the buffer, and, when is outright
386
     * drawn, that information will be displayed. Meanwhile, the previous image
387
     * can be kept showed.
388
     * </p>
389
     * 
390
     * @see BufferedImage
391
     * 
392
     * @see #getImage()
393
     */
394
    private BufferedImage image = null;
395

  
396
    /**
397
     * <p>
398
     * Name of the tool used currently to interact with this component.
399
     * </p>
400
     * 
401
     * @see #getCurrentTool()
402
     * @see #setTool(String)
403
     */
404
    protected String currentTool;
405

  
406
    /**
407
     * <p>
408
     * Object to store the flag that notifies a drawing thread task and
409
     * <code>MapContext</code>'s layers, that must be canceled or can continue
410
     * with the process.
411
     * </p>
412
     * 
413
     * @see #cancelDrawing()
414
     */
415
    private CancelDraw canceldraw;
416

  
417
    // private boolean isCancelled = true;
418

  
419
    /**
420
     * <p>
421
     * Fires an action events after a specified delay.
422
     * </p>
423
     * 
424
     * <p>
425
     * <code>MapControl</code> will use the timer to update its visible
426
     * graphical information during a drawing process, or allowing to cancel
427
     * that process.
428
     * </p>
429
     * 
430
     * <p>
431
     * This is very useful to pretend faster interactivity to user when
432
     * <code>MapControl</code> has lots of layers, and / or layers with heavy
433
     * graphical elements, that need a long time to finish drawing all its data.
434
     * </p>
435
     */
436
    private Timer timer;
437

  
438
    /**
439
     * <p>
440
     * Reference to the {@link ViewPort ViewPort} of the {@link MapContext
441
     * MapContext} of this component.
442
     * </p>
443
     * 
444
     * <p>
445
     * The view port once is created an instance of <code>MapControl</code>, is
446
     * obtained from the <i>EPSG:23030</i> projection, that's the default
447
     * projection for this component.
448
     * </p>
449
     * 
450
     * <p>
451
     * After, the view port will change adapting itself according the current
452
     * projection and the extent.
453
     * </p>
454
     * 
455
     * @see #getViewPort()
456
     * 
457
     * @see ViewPort
458
     */
459
    protected ViewPort vp;
460

  
461
    /**
462
     * <p>
463
     * Manager of all <code>MapControl</code> painting requests.
464
     * </p>
465
     */
466
    private Drawer drawer;
467

  
468
    /**
469
     * <p>
470
     * Listener of all kind of mouse events produced in this component.
471
     * </p>
472
     * 
473
     * <p>
474
     * Delegates each mouse event to the current map tool.
475
     * </p>
476
     * 
477
     * @see #addBehavior(String, Behavior)
478
     * @see #addBehavior(String, Behavior[])
479
     * @see #getMapTool(String)
480
     * @see #getMapToolsKeySet()
481
     * @see #getNamesMapTools()
482
     * @see #setTool(String)
483
     */
484
    protected MapToolListener mapToolListener = new MapToolListener();
485

  
486
    /**
487
     * <p>
488
     * Listener of all events produced in a this component's
489
     * <code>MapContext</code> object during an atomic period of time.
490
     * </p>
491
     */
492
    private MapContextListener mapContextListener = new MapContextListener();
493

  
494
    /**
495
     * <p>
496
     * Group of <code>ExceptionListener</code> that, in whatever moment could be
497
     * notified a Throwable Java error or exception.
498
     * </p>
499
     * 
500
     * @see #addExceptionListener(ExceptionListener)
501
     * @see #removeExceptionListener(ExceptionListener)
502
     */
503
    private ExceptionHandlingSupport exceptionHandlingSupport =
504
        new ExceptionHandlingSupport();
505

  
506
    /**
507
     * <p>
508
     * Name of the previous tool used.
509
     * </p>
510
     */
511
    protected String prevTool;
512

  
513
    /**
514
     * <p>
515
     * Tool that will be used combined with the current tool of this
516
     * <code>MapControl</code>.
517
     * </p>
518
     */
519
    private Behavior combinedTool = null;
520

  
521
    /**
522
     * Optional grid that could be applied on the <code>MapControl</code>'s view
523
     * port.
524
     * 
525
     * @see #getGrid()
526
     * @see #setAdjustGrid(boolean)
527
     */
528
    private Grid cadgrid = new Grid();
529
    /**
530
     * Represents the cursor's point selected in <i>screen coordinates</i>.
531
     * 
532
     * @see ViewPort#fromMapPoint(Point2D)
533
     */
534
    private Point2D adjustedPoint;
535
    /**
536
     * <p>
537
     * Determines if the position of the snap of the mouse's cursor on the
538
     * <code>MapControl</code> is within the area around a control point of a
539
     * geometry.
540
     * </p>
541
     * 
542
     * <p>
543
     * The area is calculated as a circle centered at the control point and with
544
     * radius the pixels tolerance defined in the preferences.
545
     * </p>
546
     */
547
    private boolean bForceCoord = false;
548

  
549
    /**
550
     * Kind of geometry drawn to identify the kind of control point selected by
551
     * the cursor's mouse.
552
     */
553
    private ISnapper usedSnap = null;
554

  
555
    /**
556
     * Determines if the snap tools are enabled or disabled.
557
     * 
558
     * @see #isRefentEnabled()
559
     * @see #setRefentEnabled(boolean)
560
     */
561
    private boolean bRefent = true;
562

  
563
    /**
564
     * Stores the 2D map coordinates of the last point added.
565
     */
566
    private double[] previousPoint = null;
567

  
568
    protected static MapControlManager mapControlManager =
569
        MapControlLocator.getMapControlManager();
570

  
571
    private static TreeMap selected = new TreeMap(new Comparator() {
572

  
573
        public int compare(Object o1, Object o2) {
574
            if (o1.getClass().equals(o2.getClass()))
575
                return 0;
576
            if (((ISnapper) o1).getPriority() > ((ISnapper) o2).getPriority())
577
                return 1;
578
            else
579
                return -1;
580
        }
581

  
582
    });
583

  
584
    /**
585
     * Represents the cursor's point selected in <i>map coordinates</i>.
586
     * 
587
     * @see MapControl#toMapPoint
588
     */
589
    private Point2D mapAdjustedPoint;
590

  
591
    /**
592
     * Renderer used to draw the layers.
593
     */
594
    private MapControlDrawer mapControlDrawer = null;
595
	private Cursor transparentCursor;
596

  
597
    /**
598
     * <p>
599
     * Creates a new <code>MapControl</code> instance with the following
600
     * characteristics:
601
     * <ul>
602
     * <li><i>Name</i>: MapControl .</li>
603
     * <li>Disables the double buffer of <code>JComponent</code> .</li>
604
     * <li>Sets opaque <i>(see {@link JComponent#setOpaque(boolean)} )</i>.</li>
605
     * <li>Sets its status to <code>OUTDATED</code> .</li>
606
     * <li>Creates a new {@link CancelDraw CancelDraw} object to notify
607
     * <code>MapContext</code>'s layers if can continue processing the drawn or
608
     * must cancel it.</li>
609
     * <li>Creates a new {@link MapContext MapContext} with a new
610
     * {@link ViewPort ViewPort} in the projection <i>"EPSG:23030"</i> .</li>
611
     * <li>Creates a new {@link CommandListener CommandListener} for edition
612
     * operations.</li>
613
     * <li>Creates a new {@link MapToolListener MapToolListener}, and associates
614
     * it as a listener of whatever kind of mouse events produced in this
615
     * component.</li>
616
     * <li>Creates a new {@link Drawer2 Drawer2} for managing the painting
617
     * requests.</li>
618
     * <li>Creates a new timer that will invoke refresh this component
619
     * <code>drawFrameRate</code> per second, when is running a drawing process,
620
     * and its enabled <code>drawAnimationEnabled</code>.</li>
621
     * </ul>
622
     * </p>
623
     */
624
    public MapControl() {
625
        this.setName("MapControl");
626
        Toolkit toolkit = Toolkit.getDefaultToolkit();
627
        Image imageTransparentCursor = toolkit.createImage(new MemoryImageSource(16, 16, new int[16 * 16], 0,16));
628
        transparentCursor =
629
            toolkit.createCustomCursor(imageTransparentCursor, new Point(0, 0), "invisiblecursor");
630

  
631
        setDoubleBuffered(false);
632
        setOpaque(true);
633
        status = DESACTUALIZADO;
634

  
635
        // Clase usada para cancelar el dibujado
636
        canceldraw = new CancelDraw();
637

  
638
        // Modelo de datos y ventana del mismo
639
        // TODO: Cuando creamos un mapControl, deber?amos asignar
640
        // la projecci?n por defecto con la que vayamos a trabajar.
641
        // 23030 es el c?digo EPSG del UTM30 elipsoide ED50
642
        vp = new ViewPort(CRSFactory.getCRS("EPSG:23030"));
643
        setMapContext(new MapContext(vp));
644

  
645
        // eventos
646
        this.addComponentListener(this);
647
        this.addMouseListener(mapToolListener);
648
        this.addMouseMotionListener(mapToolListener);
649
        this.addMouseWheelListener(mapToolListener);
650

  
651
        this.drawer = new Drawer();
652
        // Timer para mostrar el redibujado mientras se dibuja
653
        timer =
654
            new Timer(1000 / MapContext.getDrawFrameRate(),
655
                new ActionListener() {
656

  
657
                    public void actionPerformed(ActionEvent e) {
658

  
659
                        if (drawAnimationEnabled) {
660
                            MapControl.this.repaint();
661
                        }
662
                    }
663
                });
664
        initializeGrid();
665
    }
666

  
667
    /**
668
     * <p>
669
     * Sets a <code>MapContext</code> to this component.
670
     * </p>
671
     * 
672
     * <p>
673
     * The <code>MapContext</code> has the <i>model</i>, and most of the
674
     * <i>view</i>, and <i>control</i> logic of the layers of this component,
675
     * including a {@link ViewPort ViewPort} to adapt the information to the
676
     * projection, and to display it in the available area.
677
     * </p>
678
     * 
679
     * <p>
680
     * If <code>model</code> hadn't a <code>ViewPort</code>, assigns the current
681
     * one to it, otherwise, use its <code>ViewPort</code>.
682
     * </p>
683
     * 
684
     * <p>
685
     * After assigning the <code>MapContext</code> and <code>ViewPort</code>,
686
     * sets the same {@link MapContextListener MapContextListener} that was
687
     * using, and changes the <i>status</i> to <code>OUTDATED</code>.
688
     * </p>
689
     * 
690
     * @param model
691
     *            this component's <code>MapContext</code>, that includes the
692
     *            <code>ViewPort</code>.
693
     * 
694
     * @see MapContext
695
     * 
696
     * @see #getMapContext()
697
     */
698
    public void setMapContext(MapContext model) {
699
        if (mapContext != null) {
700
            mapContext.removeAtomicEventListener(mapContextListener);
701
            mapContext.dispose();
702
        }
703

  
704
        mapContext = model;
705

  
706
        if (mapContext.getViewPort() == null) {
707
            mapContext.setViewPort(vp);
708
        } else {
709
            vp = mapContext.getViewPort();
710
            cadgrid.setViewPort(vp);
711
        }
712

  
713
        mapContext.addAtomicEventListener(mapContextListener);
714

  
715
        status = DESACTUALIZADO;
716
    }
717

  
718
    /**
719
     * @return the mapControlDrawer
720
     */
721
    public MapControlDrawer getMapControlDrawer() {
722
        return mapControlDrawer;
723
    }
724

  
725
    /**
726
     * @param mapControlDrawer
727
     *            the mapControlDrawer to set
728
     */
729
    public void setMapControlDrawer(MapControlDrawer mapControlDrawer) {
730
        this.mapControlDrawer = mapControlDrawer;
731
        this.mapControlDrawer.setViewPort(vp);
732
    }
733

  
734
    /**
735
     * <p>
736
     * Gets this component's {@link MapContext MapContext} projection.
737
     * </p>
738
     * 
739
     * @return this component's {@link MapContext MapContext} projection
740
     * 
741
     * @see MapContext#getProjection()
742
     * @see MapControl#setProjection(IProjection)
743
     */
744
    public IProjection getProjection() {
745
        return getMapContext().getProjection();
746
    }
747

  
748
    /**
749
     * <p>
750
     * Sets the projection to this component's {@link MapContext MapContext}.
751
     * </p>
752
     * 
753
     * @param proj
754
     *            the kind of projection to this component's {@link MapContext
755
     *            MapContext}
756
     * 
757
     * @see MapContext#setProjection(IProjection)
758
     * @see MapControl#getProjection()
759
     */
760
    public void setProjection(IProjection proj) {
761
        getMapContext().setProjection(proj);
762
    }
763

  
764
    /**
765
     * <p>
766
     * Gets this component's <code>MapContext</code>, with the <i>model</i>, and
767
     * most of the <i>view</i>, and <i>control</i> logic of the layers of this
768
     * component, including a {@link ViewPort ViewPort} to adapt the information
769
     * to the projection, and display it in the available area.
770
     * </p>
771
     * 
772
     * @return this component's <code>MapContext</code>, that includes the
773
     *         <code>ViewPort</code> used to project the
774
     *         graphical information, and display it in the available area
775
     * 
776
     * @see MapContext
777
     * 
778
     * @see MapControl#setMapContext(MapContext)
779
     */
780
    public MapContext getMapContext() {
781
        return mapContext;
782
    }
783

  
784
    /**
785
     * <p>
786
     * Registers a new behavior to this component.
787
     * </p>
788
     * 
789
     * <p>
790
     * According the nature of the {@link Behavior Behavior}, different events
791
     * will be generated. Those events can be caught by a particular
792
     * {@link ToolListener ToolListener}, allowing user to interact with this
793
     * <code>MapControl</code> object as a <i>tool</i>.
794
     * </p>
795
     * 
796
     * @param name
797
     *            name to identify the behavior to add
798
     * @param tool
799
     *            the behavior to add
800
     * 
801
     * @see #addBehavior(String, Behavior[])
802
     * @see #getNamesMapTools()
803
     * @see #getMapToolsKeySet()
804
     * @see #hasTool(String)
805
     */
806
    public void addBehavior(String name, Behavior tool) {
807
        namesMapTools.put(name, tool);
808
        tool.setMapControl(this);
809
    }
810

  
811
    /**
812
     * <p>
813
     * Registers a new behavior to this component as a {@link CompoundBehavior
814
     * CompoundBehavior} made up of <code>tools</code>.
815
     * </p>
816
     * 
817
     * <p>
818
     * According the nature of the behaviors registered, different events will
819
     * be generated. Those events can be caught by a particular
820
     * {@link ToolListener ToolListener}, allowing user to interact with this
821
     * <code>MapControl</code> object as a <i>tool</i>.
822
     * </p>
823
     * 
824
     * @param name
825
     *            name to identify the compound behavior to add
826
     * @param tools
827
     *            the compound behavior to add
828
     * 
829
     * @see #addBehavior(String, Behavior)
830
     * @see #getNamesMapTools()
831
     * @see #getMapToolsKeySet()
832
     * @see #hasTool(String)
833
     */
834
    public void addBehavior(String name, Behavior[] tools) {
835
        CompoundBehavior tool = new CompoundBehavior(tools);
836
        addBehavior(name, tool);
837
    }
838

  
839
    /**
840
     * <p>
841
     * Gets the <code>Behavior</code> registered in this component, identified
842
     * by <code>name</code>.
843
     * </p>
844
     * 
845
     * @param name
846
     *            name of a registered behavior
847
     * 
848
     * @return tool the registered behavior in this component as
849
     *         <code>name</code>, or <code>null</code> if
850
     *         no one has that identifier
851
     * 
852
     * @see #addBehavior(String, Behavior)
853
     * @see #addBehavior(String, Behavior[])
854
     * @see #hasTool(String)
855
     */
856
    public Behavior getMapTool(String name) {
857
        return (Behavior) namesMapTools.get(name);
858
    }
859

  
860
    /**
861
     * <p>
862
     * Returns a set view of the keys that identified the tools registered.
863
     * </p>
864
     * 
865
     * @return a set view of the keys that identified the tools registered
866
     * 
867
     * @see HashMap#keySet()
868
     * 
869
     * @see #getNamesMapTools()
870
     * @see #addBehavior(String, Behavior)
871
     * @see #addBehavior(String, Behavior[])
872
     */
873
    public Set getMapToolsKeySet() {
874
        return namesMapTools.keySet();
875
    }
876

  
877
    /**
878
     * <p>
879
     * Returns <code>true</code> if this component contains a tool identified by
880
     * <code>toolName</code>.
881
     * </p>
882
     * 
883
     * @param toolName
884
     *            identifier of the tool
885
     * 
886
     * @return <code>true</code> if this component contains a tool identified by
887
     *         <code>toolName</code>; otherwise <code>false</code>
888
     * 
889
     * @see #addBehavior(String, Behavior)
890
     * @see #addBehavior(String, Behavior[])
891
     */
892
    public boolean hasTool(String toolName) {
893
        return namesMapTools.containsKey(toolName);
894
    }
895

  
896
    /**
897
     * <p>
898
     * Sets as current active <code>Behavior</code> associated to this
899
     * component, that one which is registered and identified by
900
     * <code>toolName</code>.
901
     * </p>
902
     * 
903
     * <p>
904
     * Changing the current active behavior for this <code>MapControl</code>,
905
     * implies also updating the previous <i>behavior</i> tool, and the current
906
     * cursor.
907
     * </p>
908
     * 
909
     * @param toolName
910
     *            name of a registered behavior
911
     * 
912
     * @see #getCurrentMapTool()
913
     * @see #getCurrentTool()
914
     */
915
    public void setTool(String toolName) {
916
        prevTool = getCurrentTool();
917
        Behavior mapTool = (Behavior) namesMapTools.get(toolName);
918
        currentMapTool = mapTool;
919
        currentTool = toolName;
920

  
921
        if (combinedTool != null) {
922
            if (mapTool instanceof CompoundBehavior) {
923
                ((CompoundBehavior) mapTool).addMapBehavior(combinedTool, true);
924
            } else {
925
                currentMapTool =
926
                    new CompoundBehavior(new Behavior[] { currentMapTool });
927
                ((CompoundBehavior) currentMapTool).addMapBehavior(
928
                    combinedTool, true);
929
            }
930
        }
931

  
932
        // this.setCursor(mapTool.getCursor());
933
    }
934

  
935
    /**
936
     * <p>
937
     * Gets as current active <code>Behavior</code> associated to this
938
     * component, that one which is registered and identified by
939
     * <code>toolName</code>.
940
     * </p>
941
     * 
942
     * <p>
943
     * Changing the current active behavior for this <code>MapControl</code>,
944
     * implies also updating the previous <i>behavior</i> tool, and the current
945
     * cursor.
946
     * </p>
947
     * 
948
     * @param toolName
949
     *            name of a registered behavior
950
     * 
951
     * @see #getCurrentTool()
952
     * @see #setTool(String)
953
     */
954
    public Behavior getCurrentMapTool() {
955
        return currentMapTool;
956
    }
957

  
958
    /**
959
     * <p>
960
     * Returns the name of the current selected tool on this MapControl
961
     * </p>
962
     * 
963
     * @return the name of the current's behavior tool associated to this
964
     *         component
965
     * 
966
     * @see #getCurrentMapTool()
967
     * @see #setTool(String)
968
     */
969
    public String getCurrentTool() {
970
        return currentTool;
971
    }
972

  
973
    /**
974
     * <p>
975
     * Determines that current drawing process of <code>MapControl</code>'s
976
     * <code>MapContext</code>'s data must be canceled.
977
     * </p>
978
     * 
979
     * <p>
980
     * It has no effects if now isn't drawing that graphical information.
981
     * </p>
982
     * 
983
     * <p>
984
     * At last resort, the particular implementation of each layer in this
985
     * <code>MapControl</code>'s <code>MapContrext</code> will be that one which
986
     * will draw the graphical information, and, if supports, which could cancel
987
     * its drawing subprocess.
988
     * </p>
989
     */
990
    public void cancelDrawing() {
991
        /*
992
         * if (drawer != null) {
993
         * if (!drawer.isAlive()) {
994
         * return;
995
         * }
996
         * }
997
         */
998
        canceldraw.setCanceled(true);
999

  
1000
        /*
1001
         * while (!isCancelled) {
1002
         * if (!drawer.isAlive()) {
1003
         * // Si hemos llegado aqu? con un thread vivo, seguramente
1004
         * // no estamos actualizados.
1005
         * 
1006
         * break;
1007
         * }
1008
         * 
1009
         * }
1010
         * canceldraw.setCancel(false);
1011
         * isCancelled = false;
1012
         * drawerAlive = false;
1013
         */
1014
    }
1015

  
1016
    /**
1017
     * <p>
1018
     * Creates a {@link BufferedImage BufferedImage} image if there was no
1019
     * buffered image, or if its viewport's image height or width is different
1020
     * from this component's size. Once has created a double-buffer, fills it
1021
     * with the vieport's background color, or with <i>white</i> if it had no
1022
     * background color.
1023
     * </p>
1024
     * 
1025
     * <p>
1026
     * If no double-buffered existed, creates a {@link BufferedImage
1027
     * BufferedImage} with the size of this component, and as an image with
1028
     * 8-bit RGBA color components packed into integer pixels. That image has a
1029
     * <code>DirectColorModel</code> with alpha. The color data in that image is
1030
     * considered not to be premultiplied with alpha.
1031
     * </p>
1032
     * 
1033
     * <p>
1034
     * Once has created and filled the new inner <code>MapControl</code>'s
1035
     * double-buffer, changes the status to <code>OUTDATED</code>.
1036
     * </p>
1037
     * 
1038
     * @return <code>true</code> if has created and filled a new double-buffer
1039
     *         for this <code>MapControl</code> instance; otherwise
1040
     *         <code>false</code>
1041
     */
1042
    private boolean adaptToImageSize() {
1043
        if ((image == null) || (vp.getImageWidth() != this.getWidth())
1044
            || (vp.getImageHeight() != this.getHeight())) {
1045
            image =
1046
                new BufferedImage(this.getWidth(), this.getHeight(),
1047
                    BufferedImage.TYPE_INT_ARGB);
1048
            // ESTILO MAC
1049
            // image = GraphicsEnvironment.getLocalGraphicsEnvironment()
1050
            // .getDefaultScreenDevice().getDefaultConfiguration()
1051
            // .createCompatibleImage(this.getWidth(), this.getHeight());
1052
            vp.setImageSize(new Dimension(getWidth(), getHeight()));
1053
            getMapContext().getViewPort().refreshExtent();
1054

  
1055
            Graphics gTemp = image.createGraphics();
1056
            Color theBackColor = vp.getBackColor();
1057
            if (theBackColor == null) {
1058
                gTemp.setColor(Color.WHITE);
1059
            } else {
1060
                gTemp.setColor(theBackColor);
1061
            }
1062

  
1063
            gTemp.fillRect(0, 0, getWidth(), getHeight());
1064
            gTemp.dispose();
1065
            status = DESACTUALIZADO;
1066
            // g.drawImage(image,0,0,null);
1067
            return true;
1068
        }
1069
        return false;
1070
    }
1071

  
1072
    /**
1073
     * <p>
1074
     * Paints the graphical information of this component using a double buffer.
1075
     * </p>
1076
     * 
1077
     * <p>
1078
     * If the double buffer wasn't created, creates a new one.
1079
     * </p>
1080
     * 
1081
     * <p>
1082
     * Paints the component according the following algorithm: <br>
1083
     * &nbsp If <i>status</i> is <i>UPDATED</i>:<br>
1084
     * &nbsp &nbsp If there is no <i>double buffer</i>:<br>
1085
     * &nbsp &nbsp &nbsp If there is a <i>behavior</i> for managing the
1086
     * <code>MapControl</code> instance, delegates the drawing process to that
1087
     * behavior, calling:
1088
     * <code><i>behavior_instance</i>.paintComponent(g)</code> &nbsp .<br>
1089
     * &nbsp &nbsp &nbsp Else, repaints the current graphical information
1090
     * quickly calling: <code>g.drawImage(image,0,0,null)</code> &nbsp .<br>
1091
     * &nbsp Else, (<i>status</i> is <i>OUTDATED</i>, or <i>ONLY_GRAPHICS</i>):
1092
     * executes a quickly repaint of the previous information calling
1093
     * <code>g.drawImage(image,0,0,null)</code>, and creates a <i>painting
1094
     * request</i> to delegate the heavy drawing process to the {@link Drawer2
1095
     * Drawer2}'s worker thread, according the <i>SingleWorketThread</i>
1096
     * pattern, starting a timer to update (invoking <code>repaint()</code> that
1097
     * comprises invoke this method) the view every delay of 360 ms. during the
1098
     * the process drawing.
1099
     * </p>
1100
     * 
1101
     * @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
1102
     * @see Drawer2
1103
     */
1104
    protected void paintComponent(Graphics g) {
1105
        adaptToImageSize();
1106

  
1107
        try {
1108
            mapControlDrawer.startDrawing(this);
1109
        } catch (InterruptedException e) {
1110
            logger.error("Error locking the MapControlDrawer", e);
1111
        }
1112
        mapControlDrawer.setGraphics(g);
1113
        mapControlDrawer.stopDrawing(this);
1114
        mapControlDrawer.setViewPort(getMapContext().getViewPort());
1115

  
1116
        if (status == ACTUALIZADO) {
1117
            /*
1118
             * Si hay un behaviour y la imagen es distinta de null se delega el
1119
             * dibujado
1120
             * en dicho behaviour
1121
             */
1122
            if (image != null) {
1123
                if (currentMapTool != null) {
1124
                    currentMapTool.paintComponent(mapControlDrawer);
1125
                } else {
1126
                    mapControlDrawer.drawImage(image, 0, 0);
1127
                }
1128
            }
1129
        } else
1130
            if ((status == DESACTUALIZADO) || (status == ONLY_GRAPHICS)) {
1131

  
1132
                mapControlDrawer.drawImage(image, 0, 0);
1133

  
1134
                drawer.put(new PaintingRequest());
1135
                timer.start();
1136
            }
1137
        cadgrid.drawGrid(mapControlDrawer);
1138
        drawCursor();
1139
    }
1140

  
1141
    /**
1142
     * <p>
1143
     * Gets the {@link BufferedImage BufferedImage} used to accelerate the draw
1144
     * of new ''frames'' with changes, or new graphical items in this component.
1145
     * </p>
1146
     * 
1147
     * @return double buffered image used by this component to accelerate the
1148
     *         draw of its graphical information, or <code>null</code> if isn't
1149
     *         already created
1150
     * 
1151
     * @see BufferedImage
1152
     */
1153
    public BufferedImage getImage() {
1154
        return image;
1155
    }
1156

  
1157
    /**
1158
     * <p>
1159
     * Forces repaint all visible graphical information in this component.
1160
     * </p>
1161
     * 
1162
     * <p>
1163
     * If <code>doClear == true</code>, before repainting, clears the background
1164
     * color, with the inner viewport's background color.
1165
     * </p>
1166
     * 
1167
     * @param doClear
1168
     *            <code>true</code> if needs clearing the background color
1169
     *            before drawing the map
1170
     * 
1171
     * @see #cancelDrawing()
1172
     * @see FLayers#setDirty(boolean)
1173
     */
1174
    public void drawMap(boolean doClear) {
1175
        cancelDrawing();
1176
        // System.out.println("drawMap con doClear=" + doClear);
1177
        status = DESACTUALIZADO;
1178
        if (doClear) {
1179
            // image = null; // Se usa para el PAN
1180
            if (image != null) {
1181
                Graphics2D g = image.createGraphics();
1182
                Color theBackColor = vp.getBackColor();
1183
                if (theBackColor == null) {
1184
                    g.setColor(Color.WHITE);
1185
                } else {
1186
                    g.setColor(theBackColor);
1187
                }
1188
                g.fillRect(0, 0, vp.getImageWidth(), vp.getImageHeight());
1189
                g.dispose();
1190
            }
1191
        }
1192
        repaint();
1193
    }
1194

  
1195
    /**
1196
     * <p>
1197
     * Cancels any current drawing process, changing the status to
1198
     * <code>OUTDATED</code>, and forcing repaint only the layers dirty.
1199
     * </p>
1200
     * 
1201
     * @see #cancelDrawing()
1202
     */
1203
    public void rePaintDirtyLayers() {
1204
        cancelDrawing();
1205
        status = DESACTUALIZADO;
1206
        repaint();
1207
    }
1208

  
1209
    /**
1210
     * <p>
1211
     * Cancels any current drawing process, changing the status to
1212
     * <code>ONLY_GRAPHICS</code>, and forcing repaint only the graphical layer
1213
     * of the <code>MapContext</code>.
1214
     * </p>
1215
     */
1216
    public void drawGraphics() {
1217
        status = ONLY_GRAPHICS;
1218
        repaint();
1219
    }
1220

  
1221
    /**
1222
     * @see java.awt.event.ComponentListener#componentHidden(java.awt.event.ComponentEvent)
1223
     */
1224
    public void componentHidden(ComponentEvent e) {
1225
    }
1226

  
1227
    /**
1228
     * @see java.awt.event.ComponentListener#componentMoved(java.awt.event.ComponentEvent)
1229
     */
1230
    public void componentMoved(ComponentEvent e) {
1231
    }
1232

  
1233
    /**
1234
     * @see java.awt.event.ComponentListener#componentResized(java.awt.event.ComponentEvent)
1235
     */
1236
    public void componentResized(ComponentEvent e) {
1237
        /*
1238
         * image = new BufferedImage(this.getWidth(), this.getHeight(),
1239
         * BufferedImage.TYPE_INT_ARGB);
1240
         * Graphics gTemp = image.createGraphics();
1241
         * gTemp.setColor(vp.getBackColor());
1242
         * gTemp.fillRect(0,0,getWidth(), getHeight());
1243
         * System.out.println("MapControl resized");
1244
         * // image = null;
1245
         * vp.setImageSize(new Dimension(getWidth(), getHeight()));
1246
         * getMapContext().getViewPort().setScale();
1247
         */
1248
        // drawMap(true);
1249
    }
1250

  
1251
    /**
1252
     * @see java.awt.event.ComponentListener#componentShown(java.awt.event.ComponentEvent)
1253
     */
1254
    public void componentShown(ComponentEvent e) {
1255
    }
1256

  
1257
    /**
1258
     * @see ExceptionHandlingSupport#addExceptionListener(ExceptionListener)
1259
     */
1260
    public void addExceptionListener(ExceptionListener o) {
1261
        exceptionHandlingSupport.addExceptionListener(o);
1262
    }
1263

  
1264
    /**
1265
     * @see ExceptionHandlingSupport#removeExceptionListener(ExceptionListener)
1266
     */
1267
    public boolean removeExceptionListener(ExceptionListener o) {
1268
        return exceptionHandlingSupport.removeExceptionListener(o);
1269
    }
1270

  
1271
    /**
1272
     * @see ExceptionHandlingSupport#throwException(Throwable)
1273
     */
1274
    protected void throwException(Throwable t) {
1275
        exceptionHandlingSupport.throwException(t);
1276
    }
1277

  
1278
    /**
1279
     * <p>
1280
     * Represents each <code>MapControl</code>'s data painting request.
1281
     * </p>
1282
     * 
1283
     * <p>
1284
     * The request will be attended by a <code>Drawer2</code>, which will hold
1285
     * it since the <code>Drawer2</code>'s worker takes it, or arrives a new
1286
     * painting request, which will replace it.
1287
     * </p>
1288
     */
1289
    private class PaintingRequest {
1290

  
1291
        /**
1292
         * <p>
1293
         * Creates a new <code>PaintingRequest
1294
         * </p>
1295
         * instance.</p>
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff