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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26