/[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 307 - (show annotations)
Thu Aug 20 13:49:50 2009 UTC (15 years, 6 months ago) by alfonx
Original Path: trunk/src/org/geotools/gui/swing/JMapPane.java
File size: 39495 byte(s)
* GP-Feature: Futher patched our Shapefilerender (= TransitionRenderer in SCHMITZM) to also support spatial quad tree index from JARs. It used a "isLocal" method that only checked for file:// protocoll, and not for jar://... protocoll
* GP-Bugfix: Fixed a problem with .cpg files.. they have been set to the system default when saving the atlas.
* The rendering of vectors should generally be faster now... especially in exported atlases
* Organized-IMports
* Better handling of calls to SingleInstanceListener.newActivation: the splashscreen is now shown and the windows brought to front.
* AV-Feature: After switching from/to anti-aliased rendering, the waiting cursor appears above the map correctly now.
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.feature.FeatureCollection;
62 import org.geotools.filter.IllegalFilterException;
63 import org.geotools.gui.swing.event.HighlightChangeListener;
64 import org.geotools.gui.swing.event.HighlightChangedEvent;
65 import org.geotools.gui.swing.event.SelectionChangeListener;
66 import org.geotools.gui.swing.event.SelectionChangedEvent;
67 import org.geotools.map.DefaultMapContext;
68 import org.geotools.map.MapContext;
69 import org.geotools.map.MapLayer;
70 import org.geotools.map.event.MapLayerListEvent;
71 import org.geotools.map.event.MapLayerListListener;
72 import org.geotools.referencing.crs.DefaultGeographicCRS;
73 import org.geotools.renderer.GTRenderer;
74 import org.geotools.renderer.lite.LabelCache;
75 import org.geotools.renderer.lite.LabelCacheDefault;
76 import org.geotools.renderer.lite.StreamingRenderer;
77 import org.geotools.renderer.shape.TransitionShapefileRenderer;
78 import org.geotools.styling.Graphic;
79 import org.geotools.styling.LineSymbolizer;
80 import org.geotools.styling.Mark;
81 import org.geotools.styling.PointSymbolizer;
82 import org.geotools.styling.PolygonSymbolizer;
83 import org.geotools.styling.Style;
84 import org.geotools.styling.StyleBuilder;
85 import org.geotools.styling.StyleFactory;
86 import org.opengis.filter.Filter;
87 import org.opengis.filter.FilterFactory2;
88 import org.opengis.referencing.crs.CoordinateReferenceSystem;
89
90 import schmitzm.swing.SwingUtil;
91
92 import com.vividsolutions.jts.geom.Coordinate;
93 import com.vividsolutions.jts.geom.Envelope;
94 import com.vividsolutions.jts.geom.Geometry;
95 import com.vividsolutions.jts.geom.GeometryFactory;
96
97 public class JMapPane extends JPanel implements MouseListener,
98 MouseMotionListener, HighlightChangeListener, SelectionChangeListener,
99 PropertyChangeListener, MapLayerListListener {
100 private static Logger LOGGER = Logger.getLogger(JMapPane.class.getName());
101
102 private static final long serialVersionUID = -8647971481359690499L;
103
104 public static final int Reset = 0;
105
106 public static final int ZoomIn = 1;
107
108 public static final int ZoomOut = 2;
109
110 public static final int Pan = 3;
111
112 public static final int Select = 4;
113
114 private static final int POLYGON = 0;
115
116 private static final int LINE = 1;
117
118 private static final int POINT = 2;
119
120 /**
121 * what renders the map
122 */
123 GTRenderer renderer;
124
125 private GTRenderer highlightRenderer, selectionRenderer;
126
127 /**
128 * the map context to render
129 */
130 MapContext context;
131
132 private MapContext selectionContext;
133
134 /**
135 * the area of the map to draw
136 */
137 // xulu.sc
138 // Envelope mapArea;
139 protected Envelope mapArea;
140 // xulu.ec
141
142 /**
143 * the size of the pane last time we drew
144 */
145 // xulu.sc
146 // private Rectangle oldRect = null;
147 protected Rectangle oldRect = null;
148 // xulu.ec
149
150 /**
151 * the last map area drawn.
152 */
153 // xulu.sc
154 // private Envelope oldMapArea = null;
155 protected Envelope oldMapArea = null;
156 // xulu.ec
157
158 /**
159 * the base image of the map
160 */
161 protected BufferedImage baseImage, panningImage;
162 // SK: private BufferedImage baseImage, panningImage;
163
164 /**
165 * image of selection
166 */
167 private BufferedImage selectImage;
168
169 /**
170 * style for selected items
171 */
172 private Style selectionStyle;
173
174 /**
175 * layer that selection works on
176 */
177 private MapLayer selectionLayer;
178
179 /**
180 * layer that highlight works on
181 */
182 private MapLayer highlightLayer;
183
184 /**
185 * the object which manages highlighting
186 */
187 private HighlightManager highlightManager;
188
189 /**
190 * is highlighting on or off
191 */
192 private boolean highlight = true;
193
194 /**
195 * a factory for filters
196 */
197 FilterFactory2 ff;
198
199 /**
200 * a factory for geometries
201 */
202 GeometryFactory gf = new GeometryFactory(); // FactoryFinder.getGeometryFactory(null);
203
204 /**
205 * the collections of features to be selected or highlighted
206 */
207 FeatureCollection selection;
208
209 /**
210 * the collections of features to be selected or highlighted
211 */
212 FeatureCollection highlightFeature;
213
214 private int state = ZoomIn;
215
216 /**
217 * how far to zoom in or out
218 */
219 private double zoomFactor = 2.0;
220
221 Style lineHighlightStyle;
222
223 Style pointHighlightStyle;
224
225 Style polygonHighlightStyle;
226
227 Style polygonSelectionStyle;
228
229 Style pointSelectionStyle;
230
231 Style lineSelectionStyle;
232
233 boolean changed = true;
234
235 LabelCache labelCache = new LabelCacheDefault();
236
237 // xulu.sc
238 // private boolean reset = false;
239 protected boolean reset = false;
240 // xulu.ec
241
242 int startX;
243
244 int startY;
245
246 private boolean clickable;
247
248 int lastX;
249
250 int lastY;
251
252 private SelectionManager selectionManager;
253 // xulu.sn
254 private Double maxZoomScale = Double.MIN_VALUE;
255 private Double minZoomScale = Double.MAX_VALUE;
256 // xulu.en
257
258 // sk.sn
259 /**
260 * Wenn true, dann wurde PANNING via mouseDraged-Events begonnen. Dieses
261 * Flag wird benutzt um nur einmal den passenden Cursor nur einmal zu
262 * setzen.
263 */
264 private boolean panning_started = false;
265
266 // sk.en
267
268 public JMapPane() {
269 this(null, true, null, null);
270 }
271
272 /**
273 * create a basic JMapPane
274 *
275 * @param render
276 * - how to draw the map
277 * @param context
278 * - the map context to display
279 */
280 public JMapPane(final GTRenderer render, final MapContext context) {
281 this(null, true, render, context);
282 }
283
284 /**
285 * full constructor extending JPanel
286 *
287 * @param layout
288 * - layout (probably shouldn't be set)
289 * @param isDoubleBuffered
290 * - a Swing thing I don't really understand
291 * @param render
292 * - what to draw the map with
293 * @param context
294 * - what to draw
295 */
296 public JMapPane(final LayoutManager layout, final boolean isDoubleBuffered,
297 final GTRenderer render, final MapContext context) {
298 super(layout, isDoubleBuffered);
299
300 ff = (FilterFactory2) org.geotools.factory.CommonFactoryFinder
301 .getFilterFactory(null);
302 setRenderer(render);
303
304 setContext(context);
305
306 this.addMouseListener(this);
307 this.addMouseMotionListener(this);
308 setHighlightManager(new HighlightManager(highlightLayer));
309 setSelectionManager(new SelectionManager(selectionLayer));
310 lineHighlightStyle = setupStyle(LINE, Color.red);
311
312 pointHighlightStyle = setupStyle(POINT, Color.red);
313
314 polygonHighlightStyle = setupStyle(POLYGON, Color.red);
315
316 polygonSelectionStyle = setupStyle(POLYGON, Color.cyan);
317
318 pointSelectionStyle = setupStyle(POINT, Color.cyan);
319
320 lineSelectionStyle = setupStyle(LINE, Color.cyan);
321 setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
322 }
323
324 /**
325 * get the renderer
326 */
327 public GTRenderer getRenderer() {
328 return renderer;
329 }
330
331 public void setRenderer(final GTRenderer renderer) {
332 Map hints = new HashMap();
333
334 this.renderer = renderer;
335
336 if (renderer instanceof StreamingRenderer || renderer instanceof TransitionShapefileRenderer) {
337 hints = renderer.getRendererHints();
338 if (hints == null) {
339 hints = new HashMap();
340 }
341 if (hints.containsKey(StreamingRenderer.LABEL_CACHE_KEY)) {
342 labelCache = (LabelCache) hints
343 .get(StreamingRenderer.LABEL_CACHE_KEY);
344 } else {
345 hints.put(StreamingRenderer.LABEL_CACHE_KEY, labelCache);
346 }
347
348 hints.put("memoryPreloadingEnabled", Boolean.TRUE);
349
350 renderer.setRendererHints(hints);
351 }
352
353 // this.highlightRenderer = new StreamingRenderer();
354 // this.selectionRenderer = new StreamingRenderer();
355
356 // highlightRenderer.setRendererHints(hints);
357 // selectionRenderer.setRendererHints(hints);
358
359 // renderer.setRendererHints(hints);
360
361 if (this.context != null) {
362 this.renderer.setContext(this.context);
363 }
364 }
365
366 public MapContext getContext() {
367 return context;
368 }
369
370 public void setContext(final MapContext context) {
371 if (this.context != null) {
372 this.context.removeMapLayerListListener(this);
373 }
374
375 this.context = context;
376
377 if (context != null) {
378 this.context.addMapLayerListListener(this);
379 }
380
381 if (renderer != null) {
382 renderer.setContext(this.context);
383 }
384 }
385
386 public Envelope getMapArea() {
387 return mapArea;
388 }
389
390 public void setMapArea(final Envelope mapArea) {
391 this.mapArea = mapArea;
392 }
393
394 public int getState() {
395 return state;
396 }
397
398 public void setState(final int state) {
399 this.state = state;
400
401 // System.out.println("State: " + state);
402 }
403
404 public double getZoomFactor() {
405 return zoomFactor;
406 }
407
408 public void setZoomFactor(final double zoomFactor) {
409 this.zoomFactor = zoomFactor;
410 }
411
412 public MapLayer getSelectionLayer() {
413 return selectionLayer;
414 }
415
416 public void setSelectionLayer(final MapLayer selectionLayer) {
417 this.selectionLayer = selectionLayer;
418 if (selectionManager != null) {
419 selectionManager.setSelectionLayer(selectionLayer);
420 }
421 }
422
423 public boolean isHighlight() {
424 return highlight;
425 }
426
427 public void setHighlight(final boolean highlight) {
428 this.highlight = highlight;
429 }
430
431 public MapLayer getHighlightLayer() {
432 return highlightLayer;
433 }
434
435 public void setHighlightLayer(final MapLayer highlightLayer) {
436 this.highlightLayer = highlightLayer;
437
438 if (highlightManager != null) {
439 highlightManager.setHighlightLayer(highlightLayer);
440 }
441 }
442
443 public HighlightManager getHighlightManager() {
444 return highlightManager;
445 }
446
447 public void setHighlightManager(final HighlightManager highlightManager) {
448 this.highlightManager = highlightManager;
449 this.highlightManager.addHighlightChangeListener(this);
450 this.addMouseMotionListener(this.highlightManager);
451 }
452
453 public Style getLineHighlightStyle() {
454 return lineHighlightStyle;
455 }
456
457 public void setLineHighlightStyle(final Style lineHighlightStyle) {
458 this.lineHighlightStyle = lineHighlightStyle;
459 }
460
461 public Style getLineSelectionStyle() {
462 return lineSelectionStyle;
463 }
464
465 public void setLineSelectionStyle(final Style lineSelectionStyle) {
466 this.lineSelectionStyle = lineSelectionStyle;
467 }
468
469 public Style getPointHighlightStyle() {
470 return pointHighlightStyle;
471 }
472
473 public void setPointHighlightStyle(final Style pointHighlightStyle) {
474 this.pointHighlightStyle = pointHighlightStyle;
475 }
476
477 public Style getPointSelectionStyle() {
478 return pointSelectionStyle;
479 }
480
481 public void setPointSelectionStyle(final Style pointSelectionStyle) {
482 this.pointSelectionStyle = pointSelectionStyle;
483 }
484
485 public Style getPolygonHighlightStyle() {
486 return polygonHighlightStyle;
487 }
488
489 public void setPolygonHighlightStyle(final Style polygonHighlightStyle) {
490 this.polygonHighlightStyle = polygonHighlightStyle;
491 }
492
493 public Style getPolygonSelectionStyle() {
494 return polygonSelectionStyle;
495 }
496
497 public void setPolygonSelectionStyle(final Style polygonSelectionStyle) {
498 this.polygonSelectionStyle = polygonSelectionStyle;
499 }
500
501 protected void paintComponent(final Graphics g) {
502 super.paintComponent(g);
503
504 if ((renderer == null) || (mapArea == null)) {
505 return;
506 }
507
508 final Rectangle r = getBounds();
509 final Rectangle dr = new Rectangle(r.width, r.height);
510
511 if (!r.equals(oldRect) || reset) {
512 if (!r.equals(oldRect) && (mapArea == null)) {
513 try {
514 mapArea = context.getLayerBounds();
515 } catch (final IOException e) {
516 // TODO Auto-generated catch block
517 e.printStackTrace();
518 }
519 }
520
521 if (mapArea != null) {
522 /* either the viewer size has changed or we've done a reset */
523 changed = true; /* note we need to redraw */
524 reset = false; /* forget about the reset */
525 oldRect = r; /* store what the current size is */
526
527 mapArea = fixAspectRatio(r, mapArea);
528 }
529 }
530
531 if (!mapArea.equals(oldMapArea)) { /* did the map extent change? */
532 changed = true;
533 oldMapArea = mapArea;
534 // when we tell the context that the bounds have changed WMSLayers
535 // can refresh them selves
536 context.setAreaOfInterest(mapArea, context
537 .getCoordinateReferenceSystem());
538 }
539
540 if (changed ) { /* if the map changed then redraw */
541 changed = false;
542 baseImage = new BufferedImage(dr.width, dr.height,
543 BufferedImage.TYPE_INT_ARGB);
544
545 final Graphics2D ig = baseImage.createGraphics();
546 /* System.out.println("rendering"); */
547 if (renderer.getContext() != null)
548 renderer.setContext(context);
549 labelCache.clear(); // work around anoying labelcache bug
550
551 // draw the map
552 renderer.paint((Graphics2D) ig, dr, mapArea);
553
554 // TODO nur machen, wenn panning beginnt
555 panningImage = new BufferedImage(dr.width, dr.height,
556 BufferedImage.TYPE_INT_RGB);
557
558 }
559
560 ((Graphics2D) g).drawImage(baseImage, 0, 0, this);
561
562 if ((selection != null) && (selection.size() > 0)) {
563 // paint selection
564
565 String type = selectionLayer.getFeatureSource().getSchema()
566 .getDefaultGeometry().getType().getName();
567 /* String type = selection.getDefaultGeometry().getGeometryType(); */
568 /* System.out.println(type); */
569 if (type == null)
570 type = "polygon";
571
572 /* String type = "point"; */
573
574 if (type.toLowerCase().endsWith("polygon")) {
575 selectionStyle = polygonSelectionStyle;
576 } else if (type.toLowerCase().endsWith("point")) {
577 selectionStyle = pointSelectionStyle;
578 } else if (type.toLowerCase().endsWith("line")) {
579 selectionStyle = lineSelectionStyle;
580 }
581
582 selectionContext = new DefaultMapContext(DefaultGeographicCRS.WGS84);
583
584 selectionContext.addLayer(selection, selectionStyle);
585 selectionRenderer.setContext(selectionContext);
586
587 selectImage = new BufferedImage(dr.width, dr.height,
588 BufferedImage.TYPE_INT_ARGB);
589
590 final Graphics2D ig = selectImage.createGraphics();
591 /* System.out.println("rendering selection"); */
592 selectionRenderer.paint((Graphics2D) ig, dr, mapArea);
593
594 ((Graphics2D) g).drawImage(selectImage, 0, 0, this);
595 }
596
597 if (highlight && (highlightFeature != null)
598 && (highlightFeature.size() > 0)) {
599 /*
600 * String type = selection.getDefaultGeometry().getGeometryType();
601 * System.out.println(type); if(type==null) type="polygon";
602 */
603 String type = highlightLayer.getFeatureSource().getSchema()
604 .getDefaultGeometry().getType().getName();
605 /* String type = selection.getDefaultGeometry().getGeometryType(); */
606 // System.out.println(type);
607 if (type == null)
608 type = "polygon";
609
610 /* String type = "point"; */
611 Style highlightStyle = null;
612 if (type.toLowerCase().endsWith("polygon")) {
613 highlightStyle = polygonHighlightStyle;
614 } else if (type.toLowerCase().endsWith("point")) {
615 highlightStyle = pointHighlightStyle;
616 } else if (type.toLowerCase().endsWith("line")) {
617 highlightStyle = lineHighlightStyle;
618 }
619
620 final MapContext highlightContext = new DefaultMapContext(
621 DefaultGeographicCRS.WGS84);
622
623 highlightContext.addLayer(highlightFeature, highlightStyle);
624 highlightRenderer.setContext(highlightContext);
625
626 /* System.out.println("rendering highlight"); */
627 highlightRenderer.paint((Graphics2D) g, dr, mapArea);
628 }
629 }
630
631 private Envelope fixAspectRatio(final Rectangle r, final Envelope mapArea) {
632
633 final double mapWidth = mapArea.getWidth(); /* get the extent of the map */
634 final double mapHeight = mapArea.getHeight();
635 final double scaleX = r.getWidth() / mapArea.getWidth(); /*
636 * calculate the new
637 * scale
638 */
639
640 final double scaleY = r.getHeight() / mapArea.getHeight();
641 double scale = 1.0; // stupid compiler!
642
643 if (scaleX < scaleY) { /* pick the smaller scale */
644 scale = scaleX;
645 } else {
646 scale = scaleY;
647 }
648
649 /* calculate the difference in width and height of the new extent */
650 final double deltaX = /* Math.abs */((r.getWidth() / scale) - mapWidth);
651 final double deltaY = /* Math.abs */((r.getHeight() / scale) - mapHeight);
652
653 /*
654 * System.out.println("delta x " + deltaX);
655 * System.out.println("delta y " + deltaY);
656 */
657
658 /* create the new extent */
659 final Coordinate ll = new Coordinate(mapArea.getMinX() - (deltaX / 2.0),
660 mapArea.getMinY() - (deltaY / 2.0));
661 final Coordinate ur = new Coordinate(mapArea.getMaxX() + (deltaX / 2.0),
662 mapArea.getMaxY() + (deltaY / 2.0));
663
664 return new Envelope(ll, ur);
665 }
666
667 public void doSelection(final double x, final double y, final MapLayer layer) {
668
669 final Geometry geometry = gf.createPoint(new Coordinate(x, y));
670
671 // org.opengis.geometry.Geometry geometry = new Point();
672
673 findFeature(geometry, layer);
674
675 }
676
677 /**
678 * @param geometry
679 * - a geometry to construct the filter with
680 * @param i
681 * - the index of the layer to search
682 * @throws IndexOutOfBoundsException
683 */
684 private void findFeature(final Geometry geometry, final MapLayer layer)
685 throws IndexOutOfBoundsException {
686 org.opengis.filter.spatial.BinarySpatialOperator f = null;
687
688 if ((context == null) || (layer == null)) {
689 return;
690 }
691
692 try {
693 String name = layer.getFeatureSource().getSchema()
694 .getDefaultGeometry().getLocalName();
695
696 if (name == "") {
697 name = "the_geom";
698 }
699
700 try {
701 f = ff.contains(ff.property(name), ff.literal(geometry));
702 if (selectionManager != null) {
703 // System.out.println("selection changed");
704 selectionManager.selectionChanged(this, f);
705
706 }
707 } catch (final IllegalFilterException e) {
708 // TODO Auto-generated catch block
709 e.printStackTrace();
710 }
711
712 /*
713 * // f.addLeftGeometry(ff.property(name)); //
714 * System.out.println("looking with " + f); FeatureCollection fc =
715 * layer.getFeatureSource().getFeatures(f);
716 *
717 *
718 *
719 * if (fcol == null) { fcol = fc;
720 *
721 * // here we should set the defaultgeom type } else {
722 * fcol.addAll(fc); }
723 */
724
725 /*
726 * GeometryAttributeType gat =
727 * layer.getFeatureSource().getSchema().getDefaultGeometry();
728 * fcol.setDefaultGeometry((Geometry)gat.createDefaultValue());
729 */
730
731 /*
732 * Iterator fi = fc.iterator(); while (fi.hasNext()) { Feature feat
733 * = (Feature) fi.next(); System.out.println("selected " +
734 * feat.getAttribute("STATE_NAME")); }
735 */
736 } catch (final IllegalFilterException e) {
737 // TODO Auto-generated catch block
738 e.printStackTrace();
739 }
740 return;
741 }
742
743 public void mouseClicked(final MouseEvent e) {
744 if (mapArea == null) return;
745 // System.out.println("before area "+mapArea+"\nw:"+mapArea.getWidth()+"
746 // h:"+mapArea.getHeight());
747 final Rectangle bounds = this.getBounds();
748 final double x = (double) (e.getX());
749 final double y = (double) (e.getY());
750 final double width = mapArea.getWidth();
751 final double height = mapArea.getHeight();
752 // xulu.sc
753 // double width2 = mapArea.getWidth() / 2.0;
754 // double height2 = mapArea.getHeight() / 2.0;
755 final double width2 = width / 2.0;
756 final double height2 = height / 2.0;
757 // xulu.ec
758 final double mapX = ((x * width) / (double) bounds.width) + mapArea.getMinX();
759 final double mapY = (((bounds.getHeight() - y) * height) / (double) bounds.height)
760 + mapArea.getMinY();
761
762 /*
763 * System.out.println(""+x+"->"+mapX);
764 * System.out.println(""+y+"->"+mapY);
765 */
766
767 /*
768 * Coordinate ll = new Coordinate(mapArea.getMinX(), mapArea.getMinY());
769 * Coordinate ur = new Coordinate(mapArea.getMaxX(), mapArea.getMaxY());
770 */
771 double zlevel = 1.0;
772
773 switch (state) {
774 case Pan:
775 zlevel = 1.0;
776 // xulu.sc SK: return here.. a mouselistener is managing the PANNING
777 // break;
778 return;
779 // xulu.ec
780 case ZoomIn:
781 zlevel = zoomFactor;
782
783 break;
784
785 case ZoomOut:
786 zlevel = 1.0 / zoomFactor;
787
788 break;
789
790 case Select:
791 doSelection(mapX, mapY, selectionLayer);
792
793 return;
794
795 default:
796 return;
797 }
798
799 final Coordinate ll = new Coordinate(mapX - (width2 / zlevel), mapY
800 - (height2 / zlevel));
801 final Coordinate ur = new Coordinate(mapX + (width2 / zlevel), mapY
802 + (height2 / zlevel));
803 // xulu.sc SK: Check for min/max scale
804 // mapArea = new Envelope(ll, ur);
805 final Envelope newMapArea = new Envelope(ll, ur);
806 setMapArea(bestAllowedMapArea(newMapArea));
807 // xulu.ec
808
809 // sk.ec
810
811 // System.out.println("after area "+mapArea+"\nw:"+mapArea.getWidth()+"
812 // h:"+mapArea.getHeight());
813 repaint();
814 }
815
816 public void mouseEntered(final MouseEvent e) {
817 }
818
819 public void mouseExited(final MouseEvent e) {
820 }
821
822 public void mousePressed(final MouseEvent e) {
823 startX = e.getX();
824 startY = e.getY();
825 lastX = 0;
826 lastY = 0;
827 }
828
829 public void mouseReleased(final MouseEvent e) {
830 final int endX = e.getX();
831 final int endY = e.getY();
832
833 processDrag(startX, startY, endX, endY, e);
834 lastX = 0;
835 lastY = 0;
836
837 /**
838 * Es wird nicht (mehr) gepannt!
839 */
840 panning_started = false;
841 }
842
843 public void mouseDragged(final MouseEvent e) {
844 final Graphics graphics = this.getGraphics();
845 final int x = e.getX();
846 final int y = e.getY();
847
848 if ((state == JMapPane.Pan)
849 || ((e.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) != 0)) {
850 /**
851 * SK: Der Cursor wird auf PANNING gesetzt.
852 */
853 if (panning_started == false) {
854 panning_started = true;
855 setCursor(SwingUtil.PANNING_CURSOR);
856 }
857
858 // move the image with the mouse
859 if ((lastX > 0) && (lastY > 0)) {
860 final int dx = lastX - startX;
861 final int dy = lastY - startY;
862 // System.out.println("translate "+dx+","+dy);
863 final Graphics2D g2 = panningImage.createGraphics();
864 g2.setBackground(new Color(240, 240, 240)); // TODO richtige
865 // farbe? am besten
866 // vom L&F die
867 // hintergrundfarbe
868 // auslesen...
869
870 g2.clearRect(0, 0, this.getWidth(), this.getHeight());
871 g2.drawImage(baseImage, dx, dy, this);
872 graphics.drawImage(panningImage, 0, 0, this);
873 }
874
875 lastX = x;
876 lastY = y;
877 } else
878
879 if ((state == JMapPane.ZoomIn) || (state == JMapPane.ZoomOut)) {
880
881 graphics.setXORMode(Color.WHITE);
882
883 if ((lastX > 0) && (lastY > 0)) {
884 drawRectangle(graphics);
885 }
886
887 // draw new box
888 lastX = x;
889 lastY = y;
890 drawRectangle(graphics);
891 } else if (state == JMapPane.Select && selectionLayer != null) {
892
893 // construct a new bbox filter
894 final Rectangle bounds = this.getBounds();
895
896 final double mapWidth = mapArea.getWidth();
897 final double mapHeight = mapArea.getHeight();
898
899 final double x1 = ((this.startX * mapWidth) / (double) bounds.width)
900 + mapArea.getMinX();
901 final double y1 = (((bounds.getHeight() - this.startY) * mapHeight) / (double) bounds.height)
902 + mapArea.getMinY();
903 final double x2 = ((x * mapWidth) / (double) bounds.width)
904 + mapArea.getMinX();
905 final double y2 = (((bounds.getHeight() - y) * mapHeight) / (double) bounds.height)
906 + mapArea.getMinY();
907 final double left = Math.min(x1, x2);
908 final double right = Math.max(x1, x2);
909 final double bottom = Math.min(y1, y2);
910 final double top = Math.max(y1, y2);
911
912 String name = selectionLayer.getFeatureSource().getSchema()
913 .getDefaultGeometry().getName();
914
915 if (name == "") {
916 name = "the_geom";
917 }
918 final Filter bb = ff.bbox(ff.property(name), left, bottom, right, top,
919 getContext().getCoordinateReferenceSystem().toString());
920 if (selectionManager != null) {
921 selectionManager.selectionChanged(this, bb);
922 }
923
924 graphics.setXORMode(Color.green);
925
926 /*
927 * if ((lastX > 0) && (lastY > 0)) { drawRectangle(graphics); }
928 */
929
930 // draw new box
931 lastX = x;
932 lastY = y;
933 drawRectangle(graphics);
934 }
935
936 }
937
938 // sk.cs
939 // private void processDrag(int x1, int y1, int x2, int y2) {
940 // sk.ce
941 protected void processDrag(final int x1, final int y1, final int x2,
942 final int y2, final MouseEvent e) {
943
944 /****
945 * If no layer is availabe we dont want a NullPointerException
946 */
947 if (mapArea == null)
948 return;
949
950 // System.out.println("processing drag from " + x1 + "," + y1 + " -> "
951 // + x2 + "," + y2);
952 if ((x1 == x2) && (y1 == y2)) {
953 if (isClickable()) {
954 mouseClicked(new MouseEvent(this, 0, new Date().getTime(), 0,
955 x1, y1, y2, false));
956 }
957
958 return;
959 }
960
961 final Rectangle bounds = this.getBounds();
962
963 final double mapWidth = mapArea.getWidth();
964 final double mapHeight = mapArea.getHeight();
965
966 final double startX = ((x1 * mapWidth) / (double) bounds.width)
967 + mapArea.getMinX();
968 final double startY = (((bounds.getHeight() - y1) * mapHeight) / (double) bounds.height)
969 + mapArea.getMinY();
970 final double endX = ((x2 * mapWidth) / (double) bounds.width)
971 + mapArea.getMinX();
972 final double endY = (((bounds.getHeight() - y2) * mapHeight) / (double) bounds.height)
973 + mapArea.getMinY();
974
975 if ((state == JMapPane.Pan) || (e.getButton() == MouseEvent.BUTTON3)) {
976 // move the image with the mouse
977 // calculate X offsets from start point to the end Point
978 final double deltaX1 = endX - startX;
979
980 // System.out.println("deltaX " + deltaX1);
981 // new edges
982 final double left = mapArea.getMinX() - deltaX1;
983 final double right = mapArea.getMaxX() - deltaX1;
984
985 // now for Y
986 final double deltaY1 = endY - startY;
987
988 // System.out.println("deltaY " + deltaY1);
989 final double bottom = mapArea.getMinY() - deltaY1;
990 final double top = mapArea.getMaxY() - deltaY1;
991 final Coordinate ll = new Coordinate(left, bottom);
992 final Coordinate ur = new Coordinate(right, top);
993 // xulu.sc
994 // mapArea = fixAspectRatio(this.getBounds(), new Envelope(ll, ur));
995 setMapArea(fixAspectRatio(this.getBounds(), new Envelope(ll, ur)));
996 // xulu.ec
997 } else if (state == JMapPane.ZoomIn) {
998
999 // Zu kleine Flächen sollen nicht gezoomt werden.
1000 // sk.bc
1001 if ((Math.abs(x1 - x2) * Math.abs(y2 - y1)) < 150)
1002 return;
1003 // sk.ec
1004
1005 drawRectangle(this.getGraphics());
1006 // make the dragged rectangle (in map coords) the new BBOX
1007 final double left = Math.min(startX, endX);
1008 final double right = Math.max(startX, endX);
1009 final double bottom = Math.min(startY, endY);
1010 final double top = Math.max(startY, endY);
1011 final Coordinate ll = new Coordinate(left, bottom);
1012 final Coordinate ur = new Coordinate(right, top);
1013 // xulu.sc
1014
1015 // mapArea = fixAspectRatio(this.getBounds(), new Envelope(ll, ur));
1016 setMapArea(bestAllowedMapArea(new Envelope(ll, ur)));
1017
1018 // sk.sc
1019 // {
1020 // // SK tries to paint a preview of the zoom ;-9 aha.... well
1021 // Graphics2D graphics = (Graphics2D) JMapPane.this.getGraphics();
1022 // graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
1023 // RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
1024 // graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
1025 // RenderingHints.VALUE_ANTIALIAS_OFF);
1026 // graphics.setRenderingHint(RenderingHints.KEY_RENDERING,
1027 // RenderingHints.VALUE_RENDER_SPEED);
1028 // graphics.drawImage(baseImage, 0, 0, JMapPane.this.getWidth(),
1029 // JMapPane.this.getHeight(), x1, y1, x2, y2, null);
1030 // }
1031 // xulu.ec
1032 } else if (state == JMapPane.ZoomOut) {
1033 drawRectangle(this.getGraphics());
1034
1035 // make the dragged rectangle in screen coords the new map size?
1036 final double left = Math.min(startX, endX);
1037 final double right = Math.max(startX, endX);
1038 final double bottom = Math.min(startY, endY);
1039 final double top = Math.max(startY, endY);
1040 final double nWidth = (mapWidth * mapWidth) / (right - left);
1041 final double nHeight = (mapHeight * mapHeight) / (top - bottom);
1042 final double deltaX1 = left - mapArea.getMinX();
1043 final double nDeltaX1 = (deltaX1 * nWidth) / mapWidth;
1044 final double deltaY1 = bottom - mapArea.getMinY();
1045 final double nDeltaY1 = (deltaY1 * nHeight) / mapHeight;
1046 final Coordinate ll = new Coordinate(mapArea.getMinX() - nDeltaX1,
1047 mapArea.getMinY() - nDeltaY1);
1048 final double deltaX2 = mapArea.getMaxX() - right;
1049 final double nDeltaX2 = (deltaX2 * nWidth) / mapWidth;
1050 final double deltaY2 = mapArea.getMaxY() - top;
1051 final double nDeltaY2 = (deltaY2 * nHeight) / mapHeight;
1052 final Coordinate ur = new Coordinate(mapArea.getMaxX() + nDeltaX2,
1053 mapArea.getMaxY() + nDeltaY2);
1054 // xulu.sc
1055 // mapArea = fixAspectRatio(this.getBounds(), new Envelope(ll, ur));
1056 setMapArea(bestAllowedMapArea(new Envelope(ll, ur)));
1057
1058 // xulu.ec
1059 } else if (state == JMapPane.Select && selectionLayer != null) {
1060 final double left = Math.min(startX, endX);
1061 final double right = Math.max(startX, endX);
1062 final double bottom = Math.min(startY, endY);
1063 final double top = Math.max(startY, endY);
1064
1065 String name = selectionLayer.getFeatureSource().getSchema()
1066 .getDefaultGeometry().getLocalName();
1067
1068 if (name == "") {
1069 name = "the_geom";
1070 }
1071 final Filter bb = ff.bbox(ff.property(name), left, bottom, right, top,
1072 getContext().getCoordinateReferenceSystem().toString());
1073 // System.out.println(bb.toString());
1074 if (selectionManager != null) {
1075 selectionManager.selectionChanged(this, bb);
1076 }
1077 /*
1078 * FeatureCollection fc; selection = null; try { fc =
1079 * selectionLayer.getFeatureSource().getFeatures(bb); selection =
1080 * fc; } catch (IOException e) { e.printStackTrace(); }
1081 */
1082 }
1083
1084 // xulu.so
1085 // setMapArea(mapArea);
1086 // xulu.eo
1087 repaint();
1088 }
1089
1090 private boolean isClickable() {
1091 return clickable;
1092 }
1093
1094 private org.geotools.styling.Style setupStyle(final int type, final Color color) {
1095 final StyleFactory sf = org.geotools.factory.CommonFactoryFinder
1096 .getStyleFactory(null);
1097 final StyleBuilder sb = new StyleBuilder();
1098
1099 org.geotools.styling.Style s = sf.createStyle();
1100 s.setTitle("selection");
1101
1102 // TODO parameterise the color
1103 final PolygonSymbolizer ps = sb.createPolygonSymbolizer(color);
1104 ps.setStroke(sb.createStroke(color));
1105
1106 final LineSymbolizer ls = sb.createLineSymbolizer(color);
1107 final Graphic h = sb.createGraphic();
1108 h.setMarks(new Mark[] { sb.createMark("square", color) });
1109
1110 final PointSymbolizer pts = sb.createPointSymbolizer(h);
1111
1112 // Rule r = sb.createRule(new Symbolizer[]{ps,ls,pts});
1113 switch (type) {
1114 case POLYGON:
1115 s = sb.createStyle(ps);
1116
1117 break;
1118
1119 case POINT:
1120 s = sb.createStyle(pts);
1121
1122 break;
1123
1124 case LINE:
1125 s = sb.createStyle(ls);
1126 }
1127
1128 return s;
1129 }
1130
1131 public void highlightChanged(final HighlightChangedEvent e) {
1132 final org.opengis.filter.Filter f = e.getFilter();
1133
1134 try {
1135 highlightFeature = highlightLayer.getFeatureSource().getFeatures(f);
1136 } catch (final IOException e1) {
1137 // TODO Auto-generated catch block
1138 e1.printStackTrace();
1139 }
1140
1141 repaint();
1142 }
1143
1144 public void propertyChange(final PropertyChangeEvent evt) {
1145 final String prop = evt.getPropertyName();
1146
1147 if (prop.equalsIgnoreCase("crs")) {
1148 context.setAreaOfInterest(context.getAreaOfInterest(),
1149 (CoordinateReferenceSystem) evt.getNewValue());
1150 }
1151 }
1152
1153 public boolean isReset() {
1154 return reset;
1155 }
1156
1157 public void setReset(final boolean reset) {
1158 this.reset = reset;
1159 }
1160
1161 public void layerAdded(final MapLayerListEvent event) {
1162 changed = true;
1163
1164 if (context.getLayers().length == 1) { // the first one
1165
1166 try {
1167 // xulu.sc
1168 // mapArea = context.getLayerBounds();
1169 mapArea = context.getAreaOfInterest();
1170 if (mapArea == null)
1171 mapArea = context.getLayerBounds();
1172 // xulu.ec
1173 } catch (final IOException e) {
1174 // TODO Auto-generated catch block
1175 e.printStackTrace();
1176 }
1177
1178 reset = true;
1179 }
1180
1181 repaint();
1182 }
1183
1184 public void layerRemoved(final MapLayerListEvent event) {
1185 changed = true;
1186 repaint();
1187 }
1188
1189 public void layerChanged(final MapLayerListEvent event) {
1190 changed = true;
1191 // System.out.println("layer changed - repaint");
1192 repaint();
1193 }
1194
1195 public void layerMoved(final MapLayerListEvent event) {
1196 changed = true;
1197 repaint();
1198 }
1199
1200 protected void drawRectangle(final Graphics graphics) {
1201 // undraw last box/draw new box
1202 final int left = Math.min(startX, lastX);
1203 final int right = Math.max(startX, lastX);
1204 final int top = Math.max(startY, lastY);
1205 final int bottom = Math.min(startY, lastY);
1206 final int width = right - left;
1207 final int height = top - bottom;
1208 // System.out.println("drawing rect("+left+","+bottom+","+ width+","+
1209 // height+")");
1210 graphics.drawRect(left, bottom, width, height);
1211 }
1212
1213 /**
1214 * if clickable is set to true then a single click on the map pane will zoom
1215 * or pan the map.
1216 *
1217 * @param clickable
1218 */
1219 public void setClickable(final boolean clickable) {
1220 this.clickable = clickable;
1221 }
1222
1223 public void mouseMoved(final MouseEvent e) {
1224 }
1225
1226 public FeatureCollection getSelection() {
1227 return selection;
1228 }
1229
1230 public void setSelection(final FeatureCollection selection) {
1231 this.selection = selection;
1232 repaint();
1233 }
1234
1235 /*
1236 * (non-Javadoc)
1237 *
1238 * @see
1239 * org.geotools.gui.swing.event.SelectionChangeListener#selectionChanged
1240 * (org.geotools.gui.swing.event.SelectionChangedEvent)
1241 */
1242 public void selectionChanged(final SelectionChangedEvent e) {
1243
1244 try {
1245 selection = selectionLayer.getFeatureSource().getFeatures(
1246 e.getFilter());
1247 repaint();
1248 } catch (final IOException e1) {
1249 e1.printStackTrace();
1250 }
1251 }
1252
1253 public SelectionManager getSelectionManager() {
1254 return selectionManager;
1255 }
1256
1257 public void setSelectionManager(final SelectionManager selectionManager) {
1258 this.selectionManager = selectionManager;
1259 this.selectionManager.addSelectionChangeListener(this);
1260
1261 }
1262
1263 // xulu.sn
1264 /**
1265 * Korrigiert den {@link Envelope} aka {@code mapArea} auf die beste
1266 * erlaubte Flaeche damit die Massstabsbeschaenkungen noch eingehalten
1267 * werden, FALLS der uebergeben Envelope nicht schon gueltig sein sollte.<br/>
1268 * Since 21. April 09: Before thecalculation starts, the aspect ratio is
1269 * corrected. This change implies, that setMapArea() will most of the time
1270 * not allow setting to a wrong aspectRatio.
1271 *
1272 * @author <a href="mailto:[email protected]">Stefan Alfons
1273 * Kr&uuml;ger</a>
1274 */
1275 public Envelope bestAllowedMapArea(Envelope env) {
1276 if (getWidth() == 0)
1277 return env;
1278 if (env == null)
1279 return env;
1280
1281 /**
1282 * Correct the aspect Ratio before we check the rest. Otherwise we might
1283 * easily fail.
1284 */
1285 env = fixAspectRatio(this.getBounds(), env);
1286
1287 final double scale = env.getWidth() / getWidth();
1288 final double centerX = env.getMinX() + env.getWidth() / 2.;
1289 final double centerY = env.getMinY() + env.getHeight() / 2.;
1290 double newWidth2;
1291 double newHeight2;
1292 if (scale < getMaxZoomScale()) {
1293 // ****************************************************************************
1294 // Wir zoomen weiter rein als erlaubt => Anpassen des envelope
1295 // ****************************************************************************
1296 newWidth2 = getMaxZoomScale() * getWidth() / 2.;
1297 newHeight2 = getMaxZoomScale() * getHeight() / 2.;
1298 } else if (scale > getMinZoomScale()) {
1299 // ****************************************************************************
1300 // Wir zoomen weiter raus als erlaubt => Anpassen des envelope
1301 // ****************************************************************************
1302 newWidth2 = getMinZoomScale() * getWidth() / 2.;
1303 newHeight2 = getMinZoomScale() * getHeight() / 2.;
1304 } else {
1305 // ****************************************************************************
1306 // Die mapArea / der Envelope ist ist gueltig! Keine Aenderungen
1307 // ****************************************************************************
1308 return env;
1309 }
1310
1311 final Coordinate ll = new Coordinate(centerX - newWidth2, centerY
1312 - newHeight2);
1313 final Coordinate ur = new Coordinate(centerX + newWidth2, centerY
1314 + newHeight2);
1315
1316 return new Envelope(ll, ur);
1317 }
1318
1319 /**
1320 * Retuns the minimum allowed zoom scale. This is the bigger number value of
1321 * the two. Defaults to {@link Double}.MAX_VALUE
1322 *
1323 * @author <a href="mailto:[email protected]">Stefan Alfons
1324 * Kr&uuml;ger</a>
1325 */
1326 public Double getMinZoomScale() {
1327 return minZoomScale;
1328 }
1329
1330 /**
1331 * Retuns the maximum allowed zoom scale. This is the smaller number value
1332 * of the two. Defaults to {@link Double}.MIN_VALUE
1333 *
1334 * @author <a href="mailto:[email protected]">Stefan Alfons
1335 * Kr&uuml;ger</a>
1336 */
1337 public Double getMaxZoomScale() {
1338 return maxZoomScale;
1339 }
1340
1341 /**
1342 * Set the maximum allowed zoom scale. This is the smaller number value of
1343 * the two.
1344 *
1345 * @author <a href="mailto:[email protected]">Stefan Alfons
1346 * Kr&uuml;ger</a>
1347 */
1348 public void setMaxZoomScale(final Double maxZoomScale) {
1349 // System.out.println("setting max scale to "+maxZoomScale);
1350 this.maxZoomScale = maxZoomScale;
1351 }
1352
1353 /**
1354 * Set the minimum (nearest) allowed zoom scale. This is the bigger number
1355 * value of the two.
1356 *
1357 * @author <a href="mailto:[email protected]">Stefan Alfons
1358 * Kr&uuml;ger</a>
1359 */
1360 public void setMinZoomScale(final Double minZoomScale) {
1361 this.minZoomScale = minZoomScale;
1362 }
1363 // xulu.en
1364
1365 }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26