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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26