/[schmitzm]/trunk/src/skrueger/geotools/XMapPane.java
ViewVC logotype

Annotation of /trunk/src/skrueger/geotools/XMapPane.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 445 - (hide annotations)
Wed Oct 7 13:17:02 2009 UTC (15 years, 4 months ago) by alfonx
Original Path: branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/JMapPane.java
File size: 34504 byte(s)
* GP: * Do not allow NaN values in zoom back/forward Envelopes
* Extra check against unlimited while loop in JMapPane.bestAllowedMapArea
1 mojays 2 /*
2     * GeoTools - OpenSource mapping toolkit
3     * http://geotools.org
4     * (C) 2002-2006, GeoTools Project Managment Committee (PMC)
5     *
6     * This library is free software; you can redistribute it and/or
7     * modify it under the terms of the GNU Lesser General Public
8     * License as published by the Free Software Foundation;
9     * version 2.1 of the License.
10     *
11     * This library is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14     * Lesser General Public License for more details.
15     */
16 alfonx 388 package gtmig.org.geotools.swing;
17 mojays 2
18     /**
19     * <b>Xulu:<br>
20 mojays 114 * Code taken from gt-2.4.5 to make some changes (marked with {@code xulu}),
21 mojays 2 * which can not be realized in a subclass:</b>
22     * <ul>
23     * <li>{@link #getMapArea()} declared as {@code final}<li>
24     * <li>some variables declared as {@code protected}</li>
25     * <li>minimal/maximal zoom scale</li>
26     * <li>zoom in and zoom out via mouse click realized by setMapArea(..)</li>
27     * </ul>
28     * <br><br>
29     * A simple map container that is a JPanel with a map in. provides simple
30     * pan,zoom, highlight and selection The mappane stores an image of the map
31     * (drawn from the context) and an image of the slected feature(s) to speed up
32     * rendering of the highlights. Thus the whole map is only redrawn when the bbox
33     * changes, selection is only redrawn when the selected feature changes.
34     *
35     *
36     * @author Ian Turton
37     *
38     */
39    
40     import java.awt.Color;
41     import java.awt.Cursor;
42     import java.awt.Graphics;
43     import java.awt.Graphics2D;
44     import java.awt.LayoutManager;
45     import java.awt.Rectangle;
46     import java.awt.event.InputEvent;
47     import java.awt.event.MouseEvent;
48     import java.awt.event.MouseListener;
49     import java.awt.event.MouseMotionListener;
50     import java.awt.image.BufferedImage;
51     import java.beans.PropertyChangeEvent;
52     import java.beans.PropertyChangeListener;
53     import java.io.IOException;
54     import java.util.Date;
55     import java.util.HashMap;
56     import java.util.Map;
57    
58     import javax.swing.JPanel;
59    
60     import org.apache.log4j.Logger;
61     import org.geotools.map.MapContext;
62     import org.geotools.map.event.MapLayerListEvent;
63     import org.geotools.map.event.MapLayerListListener;
64     import org.geotools.renderer.GTRenderer;
65 alfonx 336 import org.geotools.renderer.label.LabelCacheImpl;
66 mojays 2 import org.geotools.renderer.lite.LabelCache;
67     import org.geotools.renderer.lite.StreamingRenderer;
68 alfonx 348 import org.geotools.renderer.shape.ShapefileRenderer;
69 mojays 2 import org.opengis.filter.FilterFactory2;
70     import org.opengis.referencing.crs.CoordinateReferenceSystem;
71    
72 mojays 436 import schmitzm.geotools.JTSUtil;
73 mojays 2 import schmitzm.swing.SwingUtil;
74    
75     import com.vividsolutions.jts.geom.Coordinate;
76     import com.vividsolutions.jts.geom.Envelope;
77     import com.vividsolutions.jts.geom.GeometryFactory;
78    
79     public class JMapPane extends JPanel implements MouseListener,
80 alfonx 336 MouseMotionListener, PropertyChangeListener, MapLayerListListener {
81 alfonx 144 private static Logger LOGGER = Logger.getLogger(JMapPane.class.getName());
82 alfonx 153
83 alfonx 144 private static final long serialVersionUID = -8647971481359690499L;
84 mojays 2
85 alfonx 144 public static final int Reset = 0;
86 mojays 2
87 alfonx 144 public static final int ZoomIn = 1;
88 mojays 2
89 alfonx 144 public static final int ZoomOut = 2;
90 mojays 2
91 alfonx 144 public static final int Pan = 3;
92 mojays 2
93 alfonx 144 public static final int Select = 4;
94 mojays 2
95 alfonx 144 /**
96     * what renders the map
97     */
98     GTRenderer renderer;
99 mojays 2
100 alfonx 144 /**
101     * the map context to render
102     */
103     MapContext context;
104 mojays 2
105 alfonx 144 /**
106     * the area of the map to draw
107     */
108     protected Envelope mapArea;
109 mojays 2
110 alfonx 144 /**
111     * the size of the pane last time we drew
112     */
113     protected Rectangle oldRect = null;
114 mojays 2
115 alfonx 144 /**
116     * the last map area drawn.
117     */
118     protected Envelope oldMapArea = null;
119 mojays 2
120 alfonx 144 /**
121     * the base image of the map
122     */
123     protected BufferedImage baseImage, panningImage;
124 mojays 2
125 alfonx 144 /**
126     * a factory for filters
127     */
128     FilterFactory2 ff;
129 mojays 2
130 alfonx 144 /**
131     * a factory for geometries
132     */
133     GeometryFactory gf = new GeometryFactory(); // FactoryFinder.getGeometryFactory(null);
134 mojays 2
135 alfonx 144 private int state = ZoomIn;
136 mojays 2
137 alfonx 144 /**
138     * how far to zoom in or out
139     */
140     private double zoomFactor = 2.0;
141 mojays 2
142 alfonx 144 boolean changed = true;
143 mojays 2
144 alfonx 336 LabelCache labelCache = new LabelCacheImpl();
145 mojays 2
146 alfonx 144 protected boolean reset = false;
147 mojays 2
148 alfonx 144 int startX;
149 mojays 2
150 alfonx 144 int startY;
151 mojays 2
152 alfonx 414 /**
153     * If not <code>null</code>, the {@link JMapPane} will not allow to zoom/pan
154     * out of that area
155     **/
156     private Envelope maxExtend = null;
157    
158     // /**
159     // * Is max. 1 or 0 of the 2 axised allowed to extend the maxExtend? If
160     // * <code>true</code> the extends has to be fully inside maxExtend
161     // **/
162     // boolean maxExtendForceMode = true;
163    
164 alfonx 144 private boolean clickable;
165 mojays 2
166 alfonx 144 int lastX;
167 mojays 2
168 alfonx 144 int lastY;
169 mojays 2
170 alfonx 144 private Double maxZoomScale = Double.MIN_VALUE;
171     private Double minZoomScale = Double.MAX_VALUE;
172 mojays 2
173 alfonx 144 /**
174     * Wenn true, dann wurde PANNING via mouseDraged-Events begonnen. Dieses
175     * Flag wird benutzt um nur einmal den passenden Cursor nur einmal zu
176     * setzen.
177     */
178 mojays 2 private boolean panning_started = false;
179    
180 alfonx 144 public JMapPane() {
181     this(null, true, null, null);
182     }
183 mojays 2
184 alfonx 144 /**
185     * create a basic JMapPane
186     *
187     * @param render
188     * - how to draw the map
189     * @param context
190     * - the map context to display
191     */
192 alfonx 307 public JMapPane(final GTRenderer render, final MapContext context) {
193 alfonx 144 this(null, true, render, context);
194     }
195 mojays 2
196 alfonx 144 /**
197     * full constructor extending JPanel
198     *
199     * @param layout
200     * - layout (probably shouldn't be set)
201     * @param isDoubleBuffered
202     * - a Swing thing I don't really understand
203     * @param render
204     * - what to draw the map with
205     * @param context
206     * - what to draw
207     */
208 alfonx 307 public JMapPane(final LayoutManager layout, final boolean isDoubleBuffered,
209     final GTRenderer render, final MapContext context) {
210 alfonx 144 super(layout, isDoubleBuffered);
211 mojays 2
212 alfonx 144 ff = (FilterFactory2) org.geotools.factory.CommonFactoryFinder
213     .getFilterFactory(null);
214     setRenderer(render);
215 mojays 2
216 alfonx 144 setContext(context);
217 mojays 2
218 alfonx 144 this.addMouseListener(this);
219     this.addMouseMotionListener(this);
220     setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
221     }
222 mojays 2
223 alfonx 144 /**
224     * get the renderer
225     */
226     public GTRenderer getRenderer() {
227     return renderer;
228     }
229 mojays 2
230 alfonx 307 public void setRenderer(final GTRenderer renderer) {
231 alfonx 414 Map<Object, Object> hints = new HashMap<Object, Object>();
232    
233 alfonx 307 this.renderer = renderer;
234 alfonx 414
235     if (renderer instanceof StreamingRenderer
236     || renderer instanceof ShapefileRenderer) {
237 alfonx 144 hints = renderer.getRendererHints();
238     if (hints == null) {
239 alfonx 414 hints = new HashMap<Object, Object>();
240 alfonx 144 }
241     if (hints.containsKey(StreamingRenderer.LABEL_CACHE_KEY)) {
242     labelCache = (LabelCache) hints
243     .get(StreamingRenderer.LABEL_CACHE_KEY);
244     } else {
245     hints.put(StreamingRenderer.LABEL_CACHE_KEY, labelCache);
246     }
247 alfonx 307
248     hints.put("memoryPreloadingEnabled", Boolean.TRUE);
249 alfonx 414
250 alfonx 144 renderer.setRendererHints(hints);
251     }
252 mojays 2
253 alfonx 144 if (this.context != null) {
254     this.renderer.setContext(this.context);
255     }
256     }
257 mojays 2
258 alfonx 144 public MapContext getContext() {
259     return context;
260     }
261 mojays 2
262 alfonx 307 public void setContext(final MapContext context) {
263 alfonx 144 if (this.context != null) {
264     this.context.removeMapLayerListListener(this);
265     }
266 mojays 2
267 alfonx 144 this.context = context;
268 mojays 2
269 alfonx 144 if (context != null) {
270     this.context.addMapLayerListListener(this);
271     }
272 mojays 2
273 alfonx 144 if (renderer != null) {
274     renderer.setContext(this.context);
275     }
276     }
277 mojays 2
278 alfonx 144 public Envelope getMapArea() {
279     return mapArea;
280     }
281 mojays 2
282 alfonx 307 public void setMapArea(final Envelope mapArea) {
283 alfonx 144 this.mapArea = mapArea;
284     }
285 mojays 2
286 alfonx 144 public int getState() {
287     return state;
288     }
289 mojays 2
290 alfonx 307 public void setState(final int state) {
291 alfonx 144 this.state = state;
292 mojays 2
293 alfonx 144 // System.out.println("State: " + state);
294     }
295 mojays 2
296 alfonx 144 public double getZoomFactor() {
297     return zoomFactor;
298     }
299 mojays 2
300 alfonx 307 public void setZoomFactor(final double zoomFactor) {
301 alfonx 144 this.zoomFactor = zoomFactor;
302     }
303 mojays 2
304 alfonx 307 protected void paintComponent(final Graphics g) {
305 alfonx 144 super.paintComponent(g);
306 mojays 2
307 alfonx 144 if ((renderer == null) || (mapArea == null)) {
308     return;
309     }
310 mojays 2
311 alfonx 307 final Rectangle r = getBounds();
312     final Rectangle dr = new Rectangle(r.width, r.height);
313 mojays 2
314 alfonx 144 if (!r.equals(oldRect) || reset) {
315     if (!r.equals(oldRect) && (mapArea == null)) {
316     try {
317     mapArea = context.getLayerBounds();
318 alfonx 307 } catch (final IOException e) {
319 alfonx 336 LOGGER.warn("context.getLayerBounds()", e);
320 alfonx 144 }
321     }
322 mojays 2
323 alfonx 144 if (mapArea != null) {
324     /* either the viewer size has changed or we've done a reset */
325     changed = true; /* note we need to redraw */
326     reset = false; /* forget about the reset */
327     oldRect = r; /* store what the current size is */
328 mojays 2
329 alfonx 418 mapArea = fixAspectRatio(r, mapArea, false);
330 alfonx 144 }
331     }
332 mojays 2
333 alfonx 144 if (!mapArea.equals(oldMapArea)) { /* did the map extent change? */
334     changed = true;
335     oldMapArea = mapArea;
336     // when we tell the context that the bounds have changed WMSLayers
337     // can refresh them selves
338     context.setAreaOfInterest(mapArea, context
339     .getCoordinateReferenceSystem());
340     }
341 mojays 2
342 alfonx 414 if (changed) { /* if the map changed then redraw */
343 alfonx 144 changed = false;
344     baseImage = new BufferedImage(dr.width, dr.height,
345     BufferedImage.TYPE_INT_ARGB);
346 mojays 2
347 alfonx 307 final Graphics2D ig = baseImage.createGraphics();
348 alfonx 144 /* System.out.println("rendering"); */
349 alfonx 414 if (renderer.getContext() != null)
350 alfonx 307 renderer.setContext(context);
351 alfonx 144 labelCache.clear(); // work around anoying labelcache bug
352 mojays 2
353 alfonx 144 // draw the map
354     renderer.paint((Graphics2D) ig, dr, mapArea);
355 mojays 2
356 alfonx 167 // TODO nur machen, wenn panning beginnt
357 alfonx 144 panningImage = new BufferedImage(dr.width, dr.height,
358     BufferedImage.TYPE_INT_RGB);
359 mojays 2
360 alfonx 144 }
361 mojays 2
362 alfonx 144 ((Graphics2D) g).drawImage(baseImage, 0, 0, this);
363     }
364 mojays 2
365 alfonx 418 /**
366     * Returns an {@link Envelope} that has the same aspect ratio as the given rectangle
367     * @param grow
368     * If <code>true</code>, than the area will be enlarged to match
369     * the aspect ratio. If <code>false</code>, it will only shrink.
370     */
371     private Envelope fixAspectRatio(final Rectangle r, final Envelope mapArea,
372     boolean grow) {
373 alfonx 431
374     if (mapArea == null) {
375     LOGGER.warn("mapArea has been null in method fixAspectRatio, returning an unmodified ");
376     }
377 mojays 2
378 alfonx 307 final double mapWidth = mapArea.getWidth(); /* get the extent of the map */
379     final double mapHeight = mapArea.getHeight();
380     final double scaleX = r.getWidth() / mapArea.getWidth(); /*
381 alfonx 414 * calculate the
382     * new scale
383     */
384 mojays 2
385 alfonx 307 final double scaleY = r.getHeight() / mapArea.getHeight();
386 alfonx 144 double scale = 1.0; // stupid compiler!
387 mojays 2
388 alfonx 418 if ((grow && scaleX < scaleY) || (!grow && scaleX > scaleY)) {
389 alfonx 144 scale = scaleX;
390     } else {
391     scale = scaleY;
392     }
393 mojays 2
394 alfonx 144 /* calculate the difference in width and height of the new extent */
395 alfonx 307 final double deltaX = /* Math.abs */((r.getWidth() / scale) - mapWidth);
396     final double deltaY = /* Math.abs */((r.getHeight() / scale) - mapHeight);
397 mojays 2
398 alfonx 144 /*
399     * System.out.println("delta x " + deltaX);
400     * System.out.println("delta y " + deltaY);
401     */
402 mojays 2
403 alfonx 144 /* create the new extent */
404 alfonx 414 final Coordinate ll = new Coordinate(
405     mapArea.getMinX() - (deltaX / 2.0), mapArea.getMinY()
406     - (deltaY / 2.0));
407     final Coordinate ur = new Coordinate(
408     mapArea.getMaxX() + (deltaX / 2.0), mapArea.getMaxY()
409     + (deltaY / 2.0));
410 mojays 2
411 alfonx 144 return new Envelope(ll, ur);
412     }
413 mojays 2
414 alfonx 307 public void mouseClicked(final MouseEvent e) {
415 alfonx 414 if (mapArea == null)
416     return;
417 alfonx 144 // System.out.println("before area "+mapArea+"\nw:"+mapArea.getWidth()+"
418     // h:"+mapArea.getHeight());
419 alfonx 307 final Rectangle bounds = this.getBounds();
420     final double x = (double) (e.getX());
421     final double y = (double) (e.getY());
422     final double width = mapArea.getWidth();
423     final double height = mapArea.getHeight();
424 alfonx 144 // xulu.sc
425     // double width2 = mapArea.getWidth() / 2.0;
426     // double height2 = mapArea.getHeight() / 2.0;
427 alfonx 307 final double width2 = width / 2.0;
428     final double height2 = height / 2.0;
429 alfonx 144 // xulu.ec
430 alfonx 414 final double mapX = ((x * width) / (double) bounds.width)
431     + mapArea.getMinX();
432 alfonx 307 final double mapY = (((bounds.getHeight() - y) * height) / (double) bounds.height)
433 alfonx 144 + mapArea.getMinY();
434 mojays 2
435 alfonx 144 /*
436     * System.out.println(""+x+"->"+mapX);
437     * System.out.println(""+y+"->"+mapY);
438     */
439 mojays 2
440 alfonx 144 /*
441     * Coordinate ll = new Coordinate(mapArea.getMinX(), mapArea.getMinY());
442     * Coordinate ur = new Coordinate(mapArea.getMaxX(), mapArea.getMaxY());
443     */
444     double zlevel = 1.0;
445 mojays 2
446 alfonx 144 switch (state) {
447     case Pan:
448     zlevel = 1.0;
449     // xulu.sc SK: return here.. a mouselistener is managing the PANNING
450     // break;
451     return;
452     // xulu.ec
453     case ZoomIn:
454     zlevel = zoomFactor;
455 mojays 2
456 alfonx 144 break;
457 mojays 2
458 alfonx 144 case ZoomOut:
459     zlevel = 1.0 / zoomFactor;
460 mojays 2
461 alfonx 144 break;
462 alfonx 414 //
463     // case Select:
464     // doSelection(mapX, mapY, selectionLayer);
465     //
466     // return;
467 mojays 2
468 alfonx 144 default:
469     return;
470     }
471 mojays 2
472 alfonx 307 final Coordinate ll = new Coordinate(mapX - (width2 / zlevel), mapY
473 alfonx 144 - (height2 / zlevel));
474 alfonx 307 final Coordinate ur = new Coordinate(mapX + (width2 / zlevel), mapY
475 alfonx 144 + (height2 / zlevel));
476     // xulu.sc SK: Check for min/max scale
477     // mapArea = new Envelope(ll, ur);
478     final Envelope newMapArea = new Envelope(ll, ur);
479     setMapArea(bestAllowedMapArea(newMapArea));
480     // xulu.ec
481 mojays 2
482 alfonx 144 // sk.ec
483 mojays 2
484 alfonx 144 // System.out.println("after area "+mapArea+"\nw:"+mapArea.getWidth()+"
485     // h:"+mapArea.getHeight());
486     repaint();
487     }
488 mojays 2
489 alfonx 307 public void mouseEntered(final MouseEvent e) {
490 alfonx 144 }
491 mojays 2
492 alfonx 307 public void mouseExited(final MouseEvent e) {
493 alfonx 144 }
494 mojays 2
495 alfonx 307 public void mousePressed(final MouseEvent e) {
496 alfonx 144 startX = e.getX();
497     startY = e.getY();
498     lastX = 0;
499     lastY = 0;
500     }
501 mojays 2
502 alfonx 307 public void mouseReleased(final MouseEvent e) {
503     final int endX = e.getX();
504     final int endY = e.getY();
505 mojays 2
506 alfonx 144 processDrag(startX, startY, endX, endY, e);
507     lastX = 0;
508     lastY = 0;
509 mojays 2
510 alfonx 144 /**
511     * Es wird nicht (mehr) gepannt!
512     */
513     panning_started = false;
514     }
515 mojays 2
516 alfonx 307 public void mouseDragged(final MouseEvent e) {
517     final Graphics graphics = this.getGraphics();
518     final int x = e.getX();
519     final int y = e.getY();
520 mojays 2
521 alfonx 144 if ((state == JMapPane.Pan)
522     || ((e.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) != 0)) {
523     /**
524     * SK: Der Cursor wird auf PANNING gesetzt.
525     */
526     if (panning_started == false) {
527     panning_started = true;
528     setCursor(SwingUtil.PANNING_CURSOR);
529     }
530 mojays 2
531 alfonx 144 // move the image with the mouse
532     if ((lastX > 0) && (lastY > 0)) {
533 alfonx 307 final int dx = lastX - startX;
534     final int dy = lastY - startY;
535 alfonx 144 // System.out.println("translate "+dx+","+dy);
536     final Graphics2D g2 = panningImage.createGraphics();
537     g2.setBackground(new Color(240, 240, 240)); // TODO richtige
538 alfonx 414 // farbe? am besten
539     // vom L&F die
540     // hintergrundfarbe
541     // auslesen...
542    
543 mojays 2 g2.clearRect(0, 0, this.getWidth(), this.getHeight());
544     g2.drawImage(baseImage, dx, dy, this);
545 alfonx 144 graphics.drawImage(panningImage, 0, 0, this);
546     }
547 mojays 2
548 alfonx 144 lastX = x;
549     lastY = y;
550     } else
551 mojays 2
552 alfonx 144 if ((state == JMapPane.ZoomIn) || (state == JMapPane.ZoomOut)) {
553 mojays 2
554 alfonx 144 graphics.setXORMode(Color.WHITE);
555 mojays 2
556 alfonx 144 if ((lastX > 0) && (lastY > 0)) {
557     drawRectangle(graphics);
558     }
559 mojays 2
560 alfonx 144 // draw new box
561     lastX = x;
562     lastY = y;
563     drawRectangle(graphics);
564 alfonx 414 }
565     // else if (state == JMapPane.Select && selectionLayer != null) {
566     //
567     // // construct a new bbox filter
568     // final Rectangle bounds = this.getBounds();
569     //
570     // final double mapWidth = mapArea.getWidth();
571     // final double mapHeight = mapArea.getHeight();
572     //
573     // final double x1 = ((this.startX * mapWidth) / (double) bounds.width)
574     // + mapArea.getMinX();
575     // final double y1 = (((bounds.getHeight() - this.startY) * mapHeight) /
576     // (double) bounds.height)
577     // + mapArea.getMinY();
578     // final double x2 = ((x * mapWidth) / (double) bounds.width)
579     // + mapArea.getMinX();
580     // final double y2 = (((bounds.getHeight() - y) * mapHeight) / (double)
581     // bounds.height)
582     // + mapArea.getMinY();
583     // final double left = Math.min(x1, x2);
584     // final double right = Math.max(x1, x2);
585     // final double bottom = Math.min(y1, y2);
586     // final double top = Math.max(y1, y2);
587     //
588     // String name = selectionLayer.getFeatureSource().getSchema()
589     // .getDefaultGeometry().getName();
590     //
591     // if (name == "") {
592     // name = "the_geom";
593     // }
594     // final Filter bb = ff.bbox(ff.property(name), left, bottom, right,
595     // top,
596     // getContext().getCoordinateReferenceSystem().toString());
597     // if (selectionManager != null) {
598     // selectionManager.selectionChanged(this, bb);
599     // }
600     //
601     // graphics.setXORMode(Color.green);
602     //
603     // /*
604     // * if ((lastX > 0) && (lastY > 0)) { drawRectangle(graphics); }
605     // */
606     //
607     // // draw new box
608     // lastX = x;
609     // lastY = y;
610     // drawRectangle(graphics);
611     // }
612 mojays 2
613 alfonx 144 }
614 mojays 2
615 alfonx 144 // sk.cs
616     // private void processDrag(int x1, int y1, int x2, int y2) {
617     // sk.ce
618     protected void processDrag(final int x1, final int y1, final int x2,
619 alfonx 307 final int y2, final MouseEvent e) {
620 mojays 2
621 alfonx 431
622 alfonx 144 /****
623 alfonx 431 * If no layers exist, we ignore the drag.
624 alfonx 144 */
625 alfonx 431 if (context.getLayerCount() <= 0) {
626 alfonx 144 return;
627 alfonx 431 }
628    
629 alfonx 144 // System.out.println("processing drag from " + x1 + "," + y1 + " -> "
630     // + x2 + "," + y2);
631     if ((x1 == x2) && (y1 == y2)) {
632     if (isClickable()) {
633     mouseClicked(new MouseEvent(this, 0, new Date().getTime(), 0,
634     x1, y1, y2, false));
635     }
636 mojays 2
637 alfonx 144 return;
638     }
639 mojays 2
640 alfonx 307 final Rectangle bounds = this.getBounds();
641 mojays 2
642 alfonx 307 final double mapWidth = mapArea.getWidth();
643     final double mapHeight = mapArea.getHeight();
644 mojays 2
645 alfonx 307 final double startX = ((x1 * mapWidth) / (double) bounds.width)
646 alfonx 144 + mapArea.getMinX();
647 alfonx 307 final double startY = (((bounds.getHeight() - y1) * mapHeight) / (double) bounds.height)
648 alfonx 144 + mapArea.getMinY();
649 alfonx 307 final double endX = ((x2 * mapWidth) / (double) bounds.width)
650 alfonx 144 + mapArea.getMinX();
651 alfonx 307 final double endY = (((bounds.getHeight() - y2) * mapHeight) / (double) bounds.height)
652 alfonx 144 + mapArea.getMinY();
653 mojays 2
654 alfonx 144 if ((state == JMapPane.Pan) || (e.getButton() == MouseEvent.BUTTON3)) {
655     // move the image with the mouse
656     // calculate X offsets from start point to the end Point
657 alfonx 307 final double deltaX1 = endX - startX;
658 mojays 2
659 alfonx 144 // System.out.println("deltaX " + deltaX1);
660     // new edges
661 alfonx 307 final double left = mapArea.getMinX() - deltaX1;
662     final double right = mapArea.getMaxX() - deltaX1;
663 mojays 2
664 alfonx 144 // now for Y
665 alfonx 307 final double deltaY1 = endY - startY;
666 mojays 2
667 alfonx 144 // System.out.println("deltaY " + deltaY1);
668 alfonx 307 final double bottom = mapArea.getMinY() - deltaY1;
669     final double top = mapArea.getMaxY() - deltaY1;
670     final Coordinate ll = new Coordinate(left, bottom);
671     final Coordinate ur = new Coordinate(right, top);
672 alfonx 144 // xulu.sc
673     // mapArea = fixAspectRatio(this.getBounds(), new Envelope(ll, ur));
674 alfonx 431
675    
676 alfonx 418 setMapArea(bestAllowedMapArea(new Envelope(ll, ur)));
677 alfonx 144 // xulu.ec
678     } else if (state == JMapPane.ZoomIn) {
679 mojays 2
680 alfonx 144 // Zu kleine Flächen sollen nicht gezoomt werden.
681     // sk.bc
682     if ((Math.abs(x1 - x2) * Math.abs(y2 - y1)) < 150)
683     return;
684     // sk.ec
685 mojays 2
686 alfonx 144 drawRectangle(this.getGraphics());
687     // make the dragged rectangle (in map coords) the new BBOX
688 alfonx 307 final double left = Math.min(startX, endX);
689     final double right = Math.max(startX, endX);
690     final double bottom = Math.min(startY, endY);
691     final double top = Math.max(startY, endY);
692     final Coordinate ll = new Coordinate(left, bottom);
693     final Coordinate ur = new Coordinate(right, top);
694 alfonx 144 // xulu.sc
695 mojays 2
696 alfonx 144 // mapArea = fixAspectRatio(this.getBounds(), new Envelope(ll, ur));
697     setMapArea(bestAllowedMapArea(new Envelope(ll, ur)));
698 mojays 2
699 alfonx 144 // sk.sc
700 alfonx 414 // {
701     // // SK tries to paint a preview of the zoom ;-9 aha.... well
702     // Graphics2D graphics = (Graphics2D) JMapPane.this.getGraphics();
703     // graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
704     // RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
705     // graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
706     // RenderingHints.VALUE_ANTIALIAS_OFF);
707     // graphics.setRenderingHint(RenderingHints.KEY_RENDERING,
708     // RenderingHints.VALUE_RENDER_SPEED);
709     // graphics.drawImage(baseImage, 0, 0, JMapPane.this.getWidth(),
710     // JMapPane.this.getHeight(), x1, y1, x2, y2, null);
711     // }
712 alfonx 144 // xulu.ec
713     } else if (state == JMapPane.ZoomOut) {
714     drawRectangle(this.getGraphics());
715 mojays 2
716 alfonx 144 // make the dragged rectangle in screen coords the new map size?
717 alfonx 307 final double left = Math.min(startX, endX);
718     final double right = Math.max(startX, endX);
719     final double bottom = Math.min(startY, endY);
720     final double top = Math.max(startY, endY);
721     final double nWidth = (mapWidth * mapWidth) / (right - left);
722     final double nHeight = (mapHeight * mapHeight) / (top - bottom);
723     final double deltaX1 = left - mapArea.getMinX();
724     final double nDeltaX1 = (deltaX1 * nWidth) / mapWidth;
725     final double deltaY1 = bottom - mapArea.getMinY();
726     final double nDeltaY1 = (deltaY1 * nHeight) / mapHeight;
727     final Coordinate ll = new Coordinate(mapArea.getMinX() - nDeltaX1,
728 alfonx 144 mapArea.getMinY() - nDeltaY1);
729 alfonx 307 final double deltaX2 = mapArea.getMaxX() - right;
730     final double nDeltaX2 = (deltaX2 * nWidth) / mapWidth;
731     final double deltaY2 = mapArea.getMaxY() - top;
732     final double nDeltaY2 = (deltaY2 * nHeight) / mapHeight;
733     final Coordinate ur = new Coordinate(mapArea.getMaxX() + nDeltaX2,
734 alfonx 144 mapArea.getMaxY() + nDeltaY2);
735     // xulu.sc
736     // mapArea = fixAspectRatio(this.getBounds(), new Envelope(ll, ur));
737     setMapArea(bestAllowedMapArea(new Envelope(ll, ur)));
738 mojays 2
739 alfonx 144 // xulu.ec
740 alfonx 414 }
741     // else if (state == JMapPane.Select && selectionLayer != null) {
742     // final double left = Math.min(startX, endX);
743     // final double right = Math.max(startX, endX);
744     // final double bottom = Math.min(startY, endY);
745     // final double top = Math.max(startY, endY);
746     //
747     // String name = selectionLayer.getFeatureSource().getSchema()
748     // .getDefaultGeometry().getLocalName();
749     //
750     // if (name == "") {
751     // name = "the_geom";
752     // }
753     // final Filter bb = ff.bbox(ff.property(name), left, bottom, right,
754     // top,
755     // getContext().getCoordinateReferenceSystem().toString());
756     // // System.out.println(bb.toString());
757     // if (selectionManager != null) {
758     // selectionManager.selectionChanged(this, bb);
759     // }
760     // /*
761     // * FeatureCollection fc; selection = null; try { fc =
762     // * selectionLayer.getFeatureSource().getFeatures(bb); selection =
763     // * fc; } catch (IOException e) { e.printStackTrace(); }
764     // */
765     // }
766 mojays 2
767 alfonx 144 // xulu.so
768     // setMapArea(mapArea);
769     // xulu.eo
770     repaint();
771     }
772 mojays 2
773 alfonx 144 private boolean isClickable() {
774     return clickable;
775     }
776 mojays 2
777 alfonx 414 //
778     // private org.geotools.styling.Style setupStyle(final int type, final Color
779     // color) {
780     // final StyleFactory sf = org.geotools.factory.CommonFactoryFinder
781     // .getStyleFactory(null);
782     // final StyleBuilder sb = new StyleBuilder();
783     //
784     // org.geotools.styling.Style s = sf.createStyle();
785     // s.setTitle("selection");
786     //
787     // // TODO parameterise the color
788     // final PolygonSymbolizer ps = sb.createPolygonSymbolizer(color);
789     // ps.setStroke(sb.createStroke(color));
790     //
791     // final LineSymbolizer ls = sb.createLineSymbolizer(color);
792     // final Graphic h = sb.createGraphic();
793     // h.setMarks(new Mark[] { sb.createMark("square", color) });
794     //
795     // final PointSymbolizer pts = sb.createPointSymbolizer(h);
796     //
797     // // Rule r = sb.createRule(new Symbolizer[]{ps,ls,pts});
798     // switch (type) {
799     // case POLYGON:
800     // s = sb.createStyle(ps);
801     //
802     // break;
803     //
804     // case POINT:
805     // s = sb.createStyle(pts);
806     //
807     // break;
808     //
809     // case LINE:
810     // s = sb.createStyle(ls);
811     // }
812     //
813     // return s;
814     // }
815 mojays 2
816 alfonx 307 public void propertyChange(final PropertyChangeEvent evt) {
817     final String prop = evt.getPropertyName();
818 mojays 2
819 alfonx 144 if (prop.equalsIgnoreCase("crs")) {
820     context.setAreaOfInterest(context.getAreaOfInterest(),
821     (CoordinateReferenceSystem) evt.getNewValue());
822     }
823     }
824 mojays 2
825 alfonx 144 public boolean isReset() {
826     return reset;
827     }
828 mojays 2
829 alfonx 307 public void setReset(final boolean reset) {
830 alfonx 144 this.reset = reset;
831     }
832 mojays 2
833 alfonx 307 public void layerAdded(final MapLayerListEvent event) {
834 alfonx 144 changed = true;
835 mojays 2
836 alfonx 144 if (context.getLayers().length == 1) { // the first one
837 mojays 2
838 alfonx 144 try {
839     // xulu.sc
840     // mapArea = context.getLayerBounds();
841     mapArea = context.getAreaOfInterest();
842     if (mapArea == null)
843     mapArea = context.getLayerBounds();
844     // xulu.ec
845 alfonx 307 } catch (final IOException e) {
846 alfonx 144 // TODO Auto-generated catch block
847     e.printStackTrace();
848     }
849 mojays 2
850 alfonx 144 reset = true;
851     }
852 mojays 2
853 alfonx 144 repaint();
854     }
855 mojays 2
856 alfonx 307 public void layerRemoved(final MapLayerListEvent event) {
857 alfonx 144 changed = true;
858     repaint();
859     }
860 mojays 2
861 alfonx 307 public void layerChanged(final MapLayerListEvent event) {
862 alfonx 144 changed = true;
863     // System.out.println("layer changed - repaint");
864     repaint();
865     }
866 mojays 2
867 alfonx 307 public void layerMoved(final MapLayerListEvent event) {
868 alfonx 144 changed = true;
869     repaint();
870     }
871 mojays 2
872 alfonx 307 protected void drawRectangle(final Graphics graphics) {
873 alfonx 144 // undraw last box/draw new box
874 alfonx 307 final int left = Math.min(startX, lastX);
875     final int right = Math.max(startX, lastX);
876     final int top = Math.max(startY, lastY);
877     final int bottom = Math.min(startY, lastY);
878     final int width = right - left;
879     final int height = top - bottom;
880 alfonx 144 // System.out.println("drawing rect("+left+","+bottom+","+ width+","+
881     // height+")");
882     graphics.drawRect(left, bottom, width, height);
883     }
884 mojays 2
885 alfonx 144 /**
886     * if clickable is set to true then a single click on the map pane will zoom
887     * or pan the map.
888     *
889     * @param clickable
890     */
891 alfonx 307 public void setClickable(final boolean clickable) {
892 alfonx 144 this.clickable = clickable;
893     }
894 mojays 2
895 alfonx 307 public void mouseMoved(final MouseEvent e) {
896 alfonx 144 }
897    
898     // xulu.sn
899 alfonx 76 /**
900     * Korrigiert den {@link Envelope} aka {@code mapArea} auf die beste
901     * erlaubte Flaeche damit die Massstabsbeschaenkungen noch eingehalten
902     * werden, FALLS der uebergeben Envelope nicht schon gueltig sein sollte.<br/>
903     * Since 21. April 09: Before thecalculation starts, the aspect ratio is
904     * corrected. This change implies, that setMapArea() will most of the time
905     * not allow setting to a wrong aspectRatio.
906     *
907     * @author <a href="mailto:[email protected]">Stefan Alfons
908     * Kr&uuml;ger</a>
909     */
910     public Envelope bestAllowedMapArea(Envelope env) {
911     if (getWidth() == 0)
912     return env;
913     if (env == null)
914     return env;
915 mojays 2
916 alfonx 414 Envelope newArea = null;
917    
918 alfonx 76 /**
919 alfonx 144 * Correct the aspect Ratio before we check the rest. Otherwise we might
920     * easily fail.
921 alfonx 76 */
922 alfonx 418 env = fixAspectRatio(this.getBounds(), env, false);
923 mojays 2
924 alfonx 307 final double scale = env.getWidth() / getWidth();
925     final double centerX = env.getMinX() + env.getWidth() / 2.;
926     final double centerY = env.getMinY() + env.getHeight() / 2.;
927 alfonx 414 double newWidth2 = 0;
928     double newHeight2 = 0;
929 alfonx 76 if (scale < getMaxZoomScale()) {
930     // ****************************************************************************
931     // Wir zoomen weiter rein als erlaubt => Anpassen des envelope
932     // ****************************************************************************
933     newWidth2 = getMaxZoomScale() * getWidth() / 2.;
934     newHeight2 = getMaxZoomScale() * getHeight() / 2.;
935     } else if (scale > getMinZoomScale()) {
936     // ****************************************************************************
937     // Wir zoomen weiter raus als erlaubt => Anpassen des envelope
938     // ****************************************************************************
939     newWidth2 = getMinZoomScale() * getWidth() / 2.;
940     newHeight2 = getMinZoomScale() * getHeight() / 2.;
941     } else {
942     // ****************************************************************************
943     // Die mapArea / der Envelope ist ist gueltig! Keine Aenderungen
944     // ****************************************************************************
945 alfonx 414 newArea = env;
946 alfonx 76 }
947 mojays 2
948 alfonx 414 if (newArea == null) {
949 mojays 2
950 alfonx 414 final Coordinate ll = new Coordinate(centerX - newWidth2, centerY
951     - newHeight2);
952     final Coordinate ur = new Coordinate(centerX + newWidth2, centerY
953     + newHeight2);
954    
955     newArea = new Envelope(ll, ur);
956     }
957    
958 alfonx 418 Envelope maxAllowedExtend = getMaxExtend();
959 alfonx 445 while (maxAllowedExtend != null && !maxAllowedExtend.contains(newArea) && newArea != null && !newArea.isNull() && !Double.isNaN(newArea.getMinX()) && !Double.isNaN(newArea.getMaxX()) && !Double.isNaN(newArea.getMinY()) && !Double.isNaN(newArea.getMaxY()) ) {
960 alfonx 418 /*
961     * If a maxExtend is set, we have to honour that...
962     */
963 alfonx 414
964 alfonx 418 // Exceeds top? Move down and maybe cut
965     if (newArea.getMaxY() > maxAllowedExtend.getMaxY()) {
966     double divY = newArea.getMaxY() - maxAllowedExtend.getMaxY();
967 mojays 436 // LOGGER.debug("Moving area down by " + divY);
968 alfonx 414
969 alfonx 418 newArea = new Envelope(new Coordinate(newArea.getMinX(),
970     newArea.getMinY() - divY), new Coordinate(newArea
971     .getMaxX(), newArea.getMaxY() - divY));
972 alfonx 414
973 alfonx 418 if (newArea.getMinY() < maxAllowedExtend.getMinY()) {
974 mojays 436 // LOGGER.debug("Now it exeeds the bottom border.. cut!");
975 alfonx 418 // And cut the bottom if it moved out of the area
976 alfonx 414 newArea = new Envelope(new Coordinate(newArea.getMinX(),
977 alfonx 418 maxAllowedExtend.getMinY()), new Coordinate(newArea
978     .getMaxX(), newArea.getMaxY()));
979 alfonx 414
980 mojays 436 // LOGGER.debug("and fix aspect ratio");
981 alfonx 414
982 alfonx 418 newArea = fixAspectRatio(this.getBounds(), newArea, false);
983 alfonx 414 }
984 alfonx 418 }
985 alfonx 414
986 alfonx 418 // Exceeds bottom? Move up and maybe cut
987     if (newArea.getMinY() < maxAllowedExtend.getMinY()) {
988     double divY = newArea.getMinY() - maxAllowedExtend.getMinY();
989 mojays 436 // LOGGER.debug("Moving area up by " + divY);
990 alfonx 414
991 alfonx 418 newArea = new Envelope(new Coordinate(newArea.getMinX(),
992     newArea.getMinY() - divY), new Coordinate(newArea
993     .getMaxX(), newArea.getMaxY() - divY));
994    
995     if (newArea.getMaxY() > maxAllowedExtend.getMaxY()) {
996 alfonx 438 // LOGGER.debug("Now it exeeds the top border.. cut!");
997 alfonx 418 // And cut the bottom if it moved out of the area
998 alfonx 414 newArea = new Envelope(new Coordinate(newArea.getMinX(),
999 alfonx 418 newArea.getMinY()), new Coordinate(newArea
1000     .getMaxX(), maxAllowedExtend.getMaxY()));
1001 alfonx 414
1002 alfonx 438 // LOGGER.debug("and fix aspect ratio");
1003 alfonx 414
1004 alfonx 418 newArea = fixAspectRatio(this.getBounds(), newArea, false);
1005 alfonx 414 }
1006 alfonx 418 }
1007 alfonx 414
1008 alfonx 418 // Exceeds to the right? move and maybe cut
1009     if (newArea.getMaxX() > maxAllowedExtend.getMaxX()) {
1010 alfonx 414
1011 alfonx 418 // Move left..
1012     double divX = newArea.getMaxX() - maxAllowedExtend.getMaxX();
1013 mojays 436 // LOGGER.debug("Moving area left by " + divX);
1014 alfonx 414
1015 alfonx 418 newArea = new Envelope(new Coordinate(newArea.getMinX() - divX,
1016     newArea.getMinY()), new Coordinate(newArea.getMaxX()
1017     - divX, newArea.getMaxY()));
1018 alfonx 414
1019 alfonx 418 if (newArea.getMinX() < maxAllowedExtend.getMinX()) {
1020 alfonx 438 // LOGGER.debug("Now it exeeds the left border.. cut!");
1021 alfonx 418 // And cut the left if it moved out of the area
1022 alfonx 420 newArea = new Envelope(new Coordinate(maxAllowedExtend.getMinX(),
1023 alfonx 418 newArea.getMinY()), new Coordinate(newArea
1024     .getMaxX(), newArea.getMaxY()));
1025 alfonx 414
1026 alfonx 438 // LOGGER.debug("and fix aspect ratio");
1027 alfonx 414
1028 alfonx 418 newArea = fixAspectRatio(this.getBounds(), newArea, false);
1029 alfonx 414 }
1030 alfonx 418 }
1031 alfonx 414
1032 alfonx 418 // Exceeds to the left? move and maybe cut
1033     if (newArea.getMinX() < maxAllowedExtend.getMinX()) {
1034 alfonx 414
1035 alfonx 418 // Move right..
1036     double divX = newArea.getMinX() - maxAllowedExtend.getMinX();
1037 mojays 436 // LOGGER.debug("Moving area right by " + divX);
1038 alfonx 414
1039 alfonx 418 newArea = new Envelope(new Coordinate(newArea.getMinX() - divX,
1040     newArea.getMinY()), new Coordinate(newArea.getMaxX()
1041     - divX, newArea.getMaxY()));
1042 alfonx 414
1043 alfonx 418 if (newArea.getMaxX() > maxAllowedExtend.getMaxX()) {
1044 alfonx 438 // LOGGER.debug("Now it exeeds the right border.. cut!");
1045 alfonx 418 // And cut the left if it moved out of the area
1046     newArea = new Envelope(new Coordinate(newArea.getMinX(),
1047     newArea.getMinY()), new Coordinate(maxAllowedExtend
1048     .getMaxX(), newArea.getMaxY()));
1049 alfonx 414
1050 alfonx 438 // LOGGER.debug("and fix aspect ratio");
1051 alfonx 414
1052 alfonx 418 newArea = fixAspectRatio(this.getBounds(), newArea, false);
1053 alfonx 414 }
1054     }
1055    
1056     }
1057    
1058     return newArea;
1059 alfonx 76 }
1060    
1061 alfonx 144 /**
1062     * Retuns the minimum allowed zoom scale. This is the bigger number value of
1063     * the two. Defaults to {@link Double}.MAX_VALUE
1064     *
1065     * @author <a href="mailto:[email protected]">Stefan Alfons
1066     * Kr&uuml;ger</a>
1067     */
1068     public Double getMinZoomScale() {
1069     return minZoomScale;
1070     }
1071 mojays 2
1072 alfonx 144 /**
1073     * Retuns the maximum allowed zoom scale. This is the smaller number value
1074     * of the two. Defaults to {@link Double}.MIN_VALUE
1075     *
1076     * @author <a href="mailto:[email protected]">Stefan Alfons
1077     * Kr&uuml;ger</a>
1078     */
1079     public Double getMaxZoomScale() {
1080     return maxZoomScale;
1081     }
1082 mojays 2
1083 alfonx 144 /**
1084     * Set the maximum allowed zoom scale. This is the smaller number value of
1085     * the two.
1086     *
1087     * @author <a href="mailto:[email protected]">Stefan Alfons
1088     * Kr&uuml;ger</a>
1089     */
1090 alfonx 307 public void setMaxZoomScale(final Double maxZoomScale) {
1091 alfonx 144 this.maxZoomScale = maxZoomScale;
1092     }
1093 mojays 2
1094 alfonx 144 /**
1095     * Set the minimum (nearest) allowed zoom scale. This is the bigger number
1096     * value of the two.
1097     *
1098     * @author <a href="mailto:[email protected]">Stefan Alfons
1099     * Kr&uuml;ger</a>
1100     */
1101 alfonx 307 public void setMinZoomScale(final Double minZoomScale) {
1102 alfonx 144 this.minZoomScale = minZoomScale;
1103     }
1104 mojays 2
1105 alfonx 414 /**
1106     * Defines an evelope of the viwable area. The JMapPane will never show
1107     * anything outside of this extend.
1108     *
1109     * @param maxExtend
1110     * <code>null</code> to not have this restriction.
1111     */
1112     public void setMaxExtend(Envelope maxExtend) {
1113     this.maxExtend = maxExtend;
1114     }
1115    
1116     /**
1117     * Returns the evelope of the viewable area. The JMapPane will never show
1118 alfonx 418 * anything outside of this extend. If this has been set to
1119     * <code>null</code> via {@link #setMaxExtend(Envelope)}, it tries to return
1120     * quickly the context's bounds. It it takes to long to determine the
1121     * context bounds, <code>null</code> is returned.
1122 alfonx 414 *
1123     * @param maxExtend
1124     * <code>null</code> to not have this restriction.
1125     */
1126    
1127     public Envelope getMaxExtend() {
1128 alfonx 418 if (maxExtend == null) {
1129     try {
1130 mojays 436 return fixAspectRatio(
1131     this.getBounds(),
1132     // Kartenbereich um 10% vergroessern
1133     JTSUtil.expandEnvelope(context.getLayerBounds(), 0.1),
1134     true
1135     );
1136 alfonx 418 } catch (IOException e) {
1137 mojays 436 LOGGER.warn(
1138 alfonx 418 "maxExtend == null; faild to getLayerBounds of context",
1139     e);
1140     }
1141     }
1142 alfonx 414 return maxExtend;
1143     }
1144    
1145 mojays 2 }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26