Revision 23645 branches/v2_0_0_prep/libraries/libFMap_mapcontrol/src/org/gvsig/fmap/mapcontrol/MapControl.java

View differences:

MapControl.java
41 41
package org.gvsig.fmap.mapcontrol;
42 42

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

  
61 69
import javax.swing.JComponent;
62 70
import javax.swing.Timer;
......
66 74
import org.gvsig.fmap.data.DefaultDataStoreNotification;
67 75
import org.gvsig.fmap.geom.primitive.DefaultEnvelope;
68 76
import org.gvsig.fmap.geom.primitive.Envelope;
77
import org.gvsig.fmap.geom.util.Converter;
69 78
import org.gvsig.fmap.mapcontext.MapContext;
70 79
import org.gvsig.fmap.mapcontext.ViewPort;
71 80
import org.gvsig.fmap.mapcontext.events.AtomicEvent;
......
74 83
import org.gvsig.fmap.mapcontext.layers.GraphicLayer;
75 84
import org.gvsig.fmap.mapcontext.layers.LayerCollectionEvent;
76 85
import org.gvsig.fmap.mapcontext.layers.LayerEvent;
86
import org.gvsig.fmap.mapcontext.layers.SpatialCache;
87
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
77 88
import org.gvsig.fmap.mapcontrol.tools.BehaviorException;
78 89
import org.gvsig.fmap.mapcontrol.tools.CompoundBehavior;
79 90
import org.gvsig.fmap.mapcontrol.tools.Behavior.Behavior;
80 91
import org.gvsig.fmap.mapcontrol.tools.Listeners.ToolListener;
92
import org.gvsig.fmap.mapcontrol.tools.grid.Grid;
93
import org.gvsig.fmap.mapcontrol.tools.snapping.GeometriesSnappingVisitor;
94
import org.gvsig.fmap.mapcontrol.tools.snapping.SnappingVisitor;
95
import org.gvsig.fmap.mapcontrol.tools.snapping.snappers.ISnapper;
96
import org.gvsig.fmap.mapcontrol.tools.snapping.snappers.ISnapperGeometriesVectorial;
97
import org.gvsig.fmap.mapcontrol.tools.snapping.snappers.ISnapperRaster;
98
import org.gvsig.fmap.mapcontrol.tools.snapping.snappers.ISnapperVectorial;
81 99
import org.gvsig.tools.observer.Observable;
82 100
import org.gvsig.tools.observer.Observer;
83 101

  
......
368 386
     * We need this to avoid not wanted refresh. REMEMBER TO SET TO TRUE!!
369 387
     */
370 388
    // private boolean paintEnabled = false;
389
	/**
390
	 * Edition preferences.
391
	 */
392
	private static Preferences prefs = Preferences.userRoot().node( "cadtooladapter" );
393
	/**
394
	 * Optional grid that could be applied on the <code>MapControl</code>'s view port.
395
	 *
396
	 * @see #getGrid()
397
	 * @see #setAdjustGrid(boolean)
398
	 */
399
	private Grid cadgrid = new Grid();
400
	/**
401
	 * Represents the cursor's point selected in <i>screen coordinates</i>.
402
	 *
403
	 * @see ViewPort#fromMapPoint(Point2D)
404
	 */
405
	private Point2D adjustedPoint;
406
	/**
407
	 * <p>Determines if the position of the snap of the mouse's cursor on the <code>MapControl</code>
408
	 * is within the area around a control point of a geometry.</p>
409
	 *
410
	 * <p>The area is calculated as a circle centered at the control point and with radius the pixels tolerance
411
	 *  defined in the preferences.</p>
412
	 */
413
	private boolean bForceCoord = false;
414
	/**
415
	 * Kind of geometry drawn to identify the kind of control point selected by the cursor's mouse.
416
	 */
417
	private ISnapper usedSnap = null;
418
	/**
419
	 * A light yellow color for the tool tip text box associated to the point indicated by the mouse's cursor.
420
	 */
421
	private Color theTipColor = new Color(255, 255, 155);
371 422

  
372 423
	/**
424
	 * Determines if the snap tools are enabled or disabled.
425
	 *
426
	 * @see #isRefentEnabled()
427
	 * @see #setRefentEnabled(boolean)
428
	 */
429
	private boolean bRefent = true;
430

  
431
	/**
432
	 * Stores the 2D map coordinates of the last point added.
433
	 */
434
	private double[] previousPoint = null;
435

  
436
	private static HashMap selected = new HashMap();
437

  
438
	private static int tolerance=4;
439
	/**
440
	 * Represents the cursor's point selected in <i>map coordinates</i>.
441
	 *
442
	 * @see MapControl#toMapPoint
443
	 */
444
	private Point2D mapAdjustedPoint;
445

  
446
	/**
373 447
	 * <p>Creates a new <code>MapControl</code> instance with the following characteristics:
374 448
	 * <ul>
375 449
	 *  <li><i>Name</i>: MapControl .</li>
......
419 493
						}
420 494
					}
421 495
				});
496
		initializeGrid();
422 497
	}
423 498

  
424 499
	/**
......
450 525
			mapContext.setViewPort(vp);
451 526
		} else {
452 527
			vp = mapContext.getViewPort();
453

  
528
			cadgrid.setViewPort(vp);
454 529
			// vp.setImageSize(new Dimension(getWidth(), getHeight()));
455 530
			//System.err.println("Viewport en setMapContext:" + vp);
456 531
		}
......
615 690
			}
616 691
		}
617 692

  
618
		this.setCursor(mapTool.getCursor());
693
//		this.setCursor(mapTool.getCursor());
619 694
	}
620 695

  
621 696
	/**
......
822 897

  
823 898
			// status = ACTUALIZADO;
824 899
		}
900
		cadgrid.drawGrid(g);
901
		drawCursor(g);
825 902
	}
826 903

  
827 904
	/**
......
1062 1139
                }
1063 1140

  
1064 1141

  
1142

  
1065 1143
                // status = FAST_PAINT;
1066 1144
              //  drawerAlive = false;
1067 1145
                timer.stop();
......
1434 1512
		 * @see Behavior#mouseEntered(MouseEvent)
1435 1513
		 */
1436 1514
		public void mouseEntered(MouseEvent e) {
1515
			clearMouseImage();
1437 1516
			try {
1438 1517
				if (currentMapTool != null) {
1439 1518
					currentMapTool.mouseEntered(e);
......
1559 1638
		 * @see Behavior#mouseDragged(MouseEvent)
1560 1639
		 */
1561 1640
		public void mouseDragged(MouseEvent e) {
1641
			calculateSnapPoint(e.getPoint());
1562 1642
			try {
1563 1643
				if (currentMapTool != null) {
1564 1644
					currentMapTool.mouseDragged(e);
......
1566 1646
			} catch (BehaviorException t) {
1567 1647
				throwException(t);
1568 1648
			}
1649
			repaint();
1569 1650
		}
1570 1651

  
1571 1652
		/**
......
1573 1654
		 * @see Behavior#mouseMoved(MouseEvent)
1574 1655
		 */
1575 1656
		public void mouseMoved(MouseEvent e) {
1657
			calculateSnapPoint(e.getPoint());
1576 1658
			try {
1577 1659
				if (currentMapTool != null) {
1578 1660
					currentMapTool.mouseMoved(e);
......
1580 1662
			} catch (BehaviorException t) {
1581 1663
				throwException(t);
1582 1664
			}
1665
			repaint();
1583 1666
		}
1584 1667
	}
1585 1668

  
......
1928 2011
			repaint();
1929 2012
		}
1930 2013
	}
2014
	/**
2015
	 * <p>Updates the grid on the <code>ViewPort</code> of the associated <code>MapControl</code>
2016
	 *  object according the values in the {@link com.iver.cit.gvsig.gui.cad.CADToolAdapter.prefs.Preferences com.iver.cit.gvsig.gui.cad.CADToolAdapter.prefs.Preferences}.</p>
2017
	 *
2018
	 * <p>The preferences are:
2019
	 *  <ul>
2020
	 *   <li>Show/hide the grid.</li>
2021
	 *   <li>Adjust or not the grid.</li>
2022
	 *   <li>Horizontal ( X ) line separation.</li>
2023
	 *   <li>Vertical ( Y ) line separation.</li>
2024
	 *  </ul>
2025
	 * </p>
2026
	 */
2027
	public void initializeGrid(){
2028
		boolean showGrid = prefs.getBoolean("grid.showgrid",cadgrid.isShowGrid());
2029
		boolean adjustGrid = prefs.getBoolean("grid.adjustgrid",cadgrid.isAdjustGrid());
2030

  
2031
		double dx = prefs.getDouble("grid.distancex",cadgrid.getGridSizeX());
2032
		double dy = prefs.getDouble("grid.distancey",cadgrid.getGridSizeY());
2033

  
2034
		setGridVisibility(showGrid);
2035
		setAdjustGrid(adjustGrid);
2036
		cadgrid.setGridSizeX(dx);
2037
		cadgrid.setGridSizeY(dy);
2038
	}
2039

  
2040
	public void setAdjustGrid(boolean adjustGrid) {
2041
		cadgrid.setAdjustGrid(adjustGrid);
2042
	}
2043

  
2044
	public void setGridVisibility(boolean showGrid) {
2045
		cadgrid.setShowGrid(showGrid);
2046
		cadgrid.setViewPort(getViewPort());
2047
		this.repaint();
2048
	}
2049
	/**
2050
	 * <p>Draws a 31x31 pixels cross round the mouse's cursor with an small geometry centered:
2051
	 *  <ul>
2052
	 *   <li><i>an square centered</i>: if isn't over a <i>control point</i>.
2053
	 *   <li><i>an small geometry centered according to the kind of control point</i>: if it's over a control
2054
	 *    point. In this case, the small geometry is drawn by a {@link ISnapper ISnapper} type object.<br>
2055
	 *    On the other hand, a light-yellowed background tool tip text with the type of <i>control point</i> will
2056
	 *     be displayed.</li>
2057
	 * </p>
2058
	 *
2059
	 * @param g <code>MapControl</code>'s graphics where the data will be drawn
2060
	 */
2061
	private void drawCursor(Graphics g) {
2062
		Image cursor=getCurrentMapTool().getImageCursor();
2063

  
2064

  
2065

  
2066
		g.setColor(Color.black);
2067
		Point2D p = adjustedPoint;
2068

  
2069
		if (p == null) {
2070
			cadgrid.setViewPort(vp);
2071
			return;
2072
		}
2073
		g.drawImage(cursor, (int)p.getX()-16, (int)p.getY()-16, this);
2074
//		int size1 = 15;
2075
//		int size2 = 3;
2076
//		g.drawLine((int) (p.getX() - size1), (int) (p.getY()),
2077
//				(int) (p.getX() + size1), (int) (p.getY()));
2078
//		g.drawLine((int) (p.getX()), (int) (p.getY() - size1),
2079
//				(int) (p.getX()), (int) (p.getY() + size1));
2080
//
2081
//		// getMapControl().setToolTipText(null);
2082
//		if (adjustedPoint != null) {
2083
//			if (bForceCoord) {
2084
//				/* g.setColor(Color.ORANGE);
2085
//				g.drawRect((int) (adjustedPoint.getX() - 6),
2086
//						(int) (adjustedPoint.getY() - 6), 12, 12);
2087
//				g.drawRect((int) (adjustedPoint.getX() - 3),
2088
//						(int) (adjustedPoint.getY() - 3), 6, 6);
2089
//				g.setColor(Color.MAGENTA);
2090
//				g.drawRect((int) (adjustedPoint.getX() - 4),
2091
//						(int) (adjustedPoint.getY() - 4), 8, 8); */
2092
//				if (usedSnap != null)
2093
//				{
2094
//					usedSnap.draw(g, adjustedPoint);
2095
//
2096
//					Graphics2D g2 = (Graphics2D) g;
2097
//			        FontMetrics metrics = g2.getFontMetrics();
2098
//			        int w = metrics.stringWidth(usedSnap.getToolTipText()) + 5;
2099
//			        int h = metrics.getMaxAscent() + 5;
2100
//			        int x = (int)p.getX()+9;
2101
//			        int y = (int)p.getY()- 7;
2102
//
2103
//			        g2.setColor(theTipColor );
2104
//			        g2.fillRect(x, y-h, w, h);
2105
//			        g2.setColor(Color.BLACK);
2106
//			        g2.drawRect(x, y-h, w, h);
2107
//					g2.drawString(usedSnap.getToolTipText(), x+3, y-3);
2108
//
2109
//
2110
//					// getMapControl().setToolTipText(usedSnap.getToolTipText());
2111
//				}
2112
//
2113
//				bForceCoord = false;
2114
//			} else {
2115
//				g.drawRect((int) (p.getX() - size2), (int) (p.getY() - size2),
2116
//						(int) (size2 * 2), (int) (size2 * 2));
2117
//			}
2118
//		}
2119
//		repaint();
2120
	}
2121
	/**
2122
	 * Hides the mouse's cursor.
2123
	 */
2124
	private void clearMouseImage() {
2125
		int[] pixels = new int[16 * 16];
2126
		Image image = Toolkit.getDefaultToolkit().createImage(
2127
				new MemoryImageSource(16, 16, pixels, 0, 16));
2128
		Cursor transparentCursor = Toolkit.getDefaultToolkit()
2129
				.createCustomCursor(image, new Point(0, 0), "invisiblecursor");
2130

  
2131
		setCursor(transparentCursor);
2132
	}
2133
	/**
2134
	 * <p>Adjusts the <code>point</code> to the grid if its enabled, and
2135
	 *  sets <code>mapHandlerAdjustedPoint</code> with that new value.</p>
2136
	 *
2137
	 * <p>The value returned is the distance between those points: the original and
2138
	 *  the adjusted one.</p>
2139
	 *
2140
	 * @param point point to adjust
2141
	 * @param mapHandlerAdjustedPoint <code>point</code> adjusted
2142
	 *
2143
	 * @return distance from <code>point</code> to the adjusted one. If there is no
2144
	 *  adjustment, returns <code>Double.MAX_VALUE</code>.
2145
	 */
2146
	private double adjustToHandler(Point2D point,
2147
			Point2D mapHandlerAdjustedPoint) {
2148

  
2149
		if (!isRefentEnabled())
2150
			return Double.MAX_VALUE;
2151

  
2152
//		ILayerEdited aux = CADExtension.getEditionManager().getActiveLayerEdited();
2153
//		if (!(aux instanceof VectorialLayerEdited))
2154
//			return Double.MAX_VALUE;
2155
//		VectorialLayerEdited vle = (VectorialLayerEdited) aux;
2156

  
2157
		ArrayList layersToSnap = getMapContext().getLayersToSnap();
2158

  
2159
		ArrayList snappers=new ArrayList(selected.keySet());
2160

  
2161
		double mapTolerance = vp.toMapDistance(MapControl.tolerance);
2162
		double minDist = mapTolerance;
2163
//		double rw = getMapControl().getViewPort().toMapDistance(5);
2164
		Point2D mapPoint = point;
2165
		double middleTol=mapTolerance * 0.5;
2166
		org.gvsig.fmap.geom.primitive.Envelope r = new DefaultEnvelope(mapPoint.getX() - middleTol,
2167
				mapPoint.getY() - middleTol,
2168
				mapPoint.getX() + middleTol,
2169
				mapPoint.getY() + middleTol);
2170

  
2171
		com.vividsolutions.jts.geom.Envelope e = Converter.convertEnvelopeToJTS(r);
2172

  
2173
		usedSnap = null;
2174
		Point2D lastPoint = null;
2175
		if (previousPoint != null)
2176
		{
2177
			lastPoint = new Point2D.Double(previousPoint[0], previousPoint[1]);
2178
		}
2179
		for (int j = 0; j < layersToSnap.size(); j++)
2180
		{
2181
			FLyrVect lyrVect = (FLyrVect) layersToSnap.get(j);
2182
			SpatialCache cache = lyrVect.getSpatialCache();
2183
			if (lyrVect.isVisible())
2184
			{
2185
				// La lista de snappers est? siempre ordenada por prioridad. Los de mayor
2186
				// prioridad est?n primero.
2187
				for (int i = 0; i < snappers.size(); i++)
2188
				{
2189
					ISnapper theSnapper = (ISnapper) snappers.get(i);
2190

  
2191
					if (usedSnap != null)
2192
					{
2193
						// Si ya tenemos un snap y es de alta prioridad, cogemos ese. (A no ser que en otra capa encontremos un snapper mejor)
2194
						if (theSnapper.getPriority() < usedSnap.getPriority())
2195
							break;
2196
					}
2197
					SnappingVisitor snapVisitor = null;
2198
					Point2D theSnappedPoint = null;
2199

  
2200
					if (theSnapper instanceof ISnapperVectorial)
2201
					{
2202
						if (theSnapper instanceof ISnapperGeometriesVectorial) {
2203
							snapVisitor=new GeometriesSnappingVisitor((ISnapperGeometriesVectorial) theSnapper,point,mapTolerance,lastPoint);
2204
						}else {
2205
							snapVisitor = new SnappingVisitor((ISnapperVectorial) theSnapper, point, mapTolerance, lastPoint);
2206
						}
2207
						// System.out.println("Cache size = " + cache.size());
2208
						cache.query(e, snapVisitor);
2209
						theSnappedPoint = snapVisitor.getSnapPoint();
2210

  
2211
					}
2212
					if (theSnapper instanceof ISnapperRaster)
2213
					{
2214
						ISnapperRaster snapRaster = (ISnapperRaster) theSnapper;
2215
						theSnappedPoint = snapRaster.getSnapPoint(this, point, mapTolerance, lastPoint);
2216
					}
2217

  
2218

  
2219
					if (theSnappedPoint != null) {
2220
						double distAux = theSnappedPoint.distance(point);
2221
						if (minDist > distAux)
2222
						{
2223
							minDist = distAux;
2224
							usedSnap = theSnapper;
2225
							mapHandlerAdjustedPoint.setLocation(theSnappedPoint);
2226
						}
2227
					}
2228
				}
2229
			} // visible
2230
		}
2231
		if (usedSnap != null)
2232
			return minDist;
2233
		return Double.MAX_VALUE;
2234

  
2235
	}
2236
	/**
2237
	 * Determines if snap tools are enabled or disabled.
2238
	 *
2239
	 * @return <code>true</code> to enable the snap tools; <code>false</code> to disable them
2240
	 *
2241
	 * @see #setRefentEnabled(boolean)
2242
	 */
2243
	public boolean isRefentEnabled()
2244
	{
2245
		return bRefent;
2246
	}
2247
	public void initializeSnapping() {
2248
		ArrayList snappers=getMapContext().getSnappers();
2249
        for (int n = 0; n < snappers.size(); n++) {
2250
            ISnapper snp = (ISnapper) snappers.get(n);
2251
            String nameClass=snp.getClass().getName();
2252
            nameClass=nameClass.substring(nameClass.lastIndexOf('.'));
2253
            boolean select = prefs.getBoolean("snapper_activated" + nameClass, false);
2254
            if (select)
2255
            	selected.put(snp, new Boolean(select));
2256
            int priority = prefs.getInt("snapper_priority" + nameClass,3);
2257
            snp.setPriority(priority);
2258
        }
2259
//        applySnappers = prefs.getBoolean("apply-snappers",true);
2260
//        snapConfig.setApplySnappers(applySnappers);
2261
//        snapConfig.selectSnappers(selected);
2262

  
2263
    }
2264
	/**
2265
	 * <p>Tries to find the nearest geometry or grid control point by the position of the current snap tool.</p>
2266
	 *
2267
	 * <p>Prioritizes the grid control points than the geometries ones.</p>
2268
	 *
2269
	 * <p>If finds any near, stores the <i>map</i> and <i>pixel</i> coordinates for the snap, and enables
2270
	 *  the <code>bForceCoord</code> attribute for the next draw of the mouse's cursor.</p>
2271
	 *
2272
	 * @param point current mouse 2D position
2273
	 */
2274
	public Point2D calculateSnapPoint(Point point) {
2275
		// Se comprueba el ajuste a rejilla
2276

  
2277
		Point2D gridAdjustedPoint = vp.toMapPoint(
2278
				point);
2279
		double minDistance = Double.MAX_VALUE;
2280
//		CADTool ct = (CADTool) cadToolStack.peek();
2281
//		if (ct instanceof SelectionCADTool
2282
//				&& ((SelectionCADTool) ct).getStatus().equals(
2283
//						"Selection.FirstPoint")) {
2284
//			mapAdjustedPoint = gridAdjustedPoint;
2285
//			adjustedPoint = (Point2D) point.clone();
2286
//		} else {
2287

  
2288
			minDistance = cadgrid.adjustToGrid(gridAdjustedPoint);
2289
			if (minDistance < Double.MAX_VALUE) {
2290
				adjustedPoint = vp.fromMapPoint(
2291
						gridAdjustedPoint);
2292
				mapAdjustedPoint = gridAdjustedPoint;
2293
			} else {
2294
				mapAdjustedPoint = null;
2295
			}
2296
//		}
2297
		Point2D handlerAdjustedPoint = null;
2298

  
2299
		// Se comprueba el ajuste a los handlers
2300
		if (mapAdjustedPoint != null) {
2301
			handlerAdjustedPoint = (Point2D) mapAdjustedPoint.clone(); // getMapControl().getViewPort().toMapPoint(point);
2302
		} else {
2303
			handlerAdjustedPoint = vp.toMapPoint(
2304
					point);
2305
		}
2306

  
2307
		Point2D mapPoint = new Point2D.Double();
2308
		double distance = adjustToHandler(handlerAdjustedPoint, mapPoint);
2309

  
2310
		if (distance < minDistance) {
2311
			bForceCoord = true;
2312
			adjustedPoint = vp.fromMapPoint(mapPoint);
2313
			mapAdjustedPoint = mapPoint;
2314
			minDistance = distance;
2315
		}
2316

  
2317
		// Si no hay ajuste
2318
		if (minDistance == Double.MAX_VALUE) {
2319
			adjustedPoint = point;
2320
			mapAdjustedPoint = null;
2321
		}
2322
		return mapAdjustedPoint;
2323
	}
2324
	/**
2325
	 * Sets the snap tools enabled or disabled.
2326
	 *
2327
	 * @param activated <code>true</code> to enable the snap tools; <code>false</code> to disable them
2328
	 *
2329
	 * @see #isRefentEnabled()
2330
	 */
2331
	public void setRefentEnabled(boolean activated) {
2332
		bRefent = activated;
2333
	}
2334

  
2335
	public Grid getGrid() {
2336
		return cadgrid;
2337
	}
2338

  
2339
	public static HashMap getSelectedSnapppers() {
2340
		return selected;
2341
	}
2342

  
1931 2343
}

Also available in: Unified diff