svn-document-layout / trunk / org.gvsig.app.document.layout2.app / org.gvsig.app.document.layout2.app.mainplugin / src / main / java / org / gvsig / app / project / documents / layout / fframes / FFrameView.java @ 213
History | View | Annotate | Download (42.6 KB)
1 | 5 | jldominguez | /* gvSIG. Geographic Information System of the Valencian Government
|
---|---|---|---|
2 | *
|
||
3 | * Copyright (C) 2007-2008 Infrastructures and Transports Department
|
||
4 | * of the Valencian Government (CIT)
|
||
5 | *
|
||
6 | * This program is free software; you can redistribute it and/or
|
||
7 | * modify it under the terms of the GNU General Public License
|
||
8 | * as published by the Free Software Foundation; either version 2
|
||
9 | * of the License, or (at your option) any later version.
|
||
10 | *
|
||
11 | * This program 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
|
||
14 | * GNU General Public License for more details.
|
||
15 | *
|
||
16 | * You should have received a copy of the GNU General Public License
|
||
17 | * along with this program; if not, write to the Free Software
|
||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||
19 | * MA 02110-1301, USA.
|
||
20 | *
|
||
21 | */
|
||
22 | package org.gvsig.app.project.documents.layout.fframes; |
||
23 | |||
24 | 93 | jldominguez | import java.awt.BasicStroke; |
25 | 5 | jldominguez | import java.awt.Color; |
26 | import java.awt.Dimension; |
||
27 | 93 | jldominguez | import java.awt.Font; |
28 | 5 | jldominguez | import java.awt.Graphics2D; |
29 | import java.awt.Point; |
||
30 | import java.awt.Rectangle; |
||
31 | import java.awt.geom.AffineTransform; |
||
32 | import java.awt.geom.Point2D; |
||
33 | import java.awt.geom.Rectangle2D; |
||
34 | import java.awt.image.BufferedImage; |
||
35 | |||
36 | import org.cresques.cts.IProjection; |
||
37 | import org.gvsig.andami.PluginServices; |
||
38 | import org.gvsig.andami.messages.NotificationManager; |
||
39 | 140 | cmartinez | import org.gvsig.andami.ui.mdiFrame.NewStatusBar; |
40 | 5 | jldominguez | import org.gvsig.app.project.Project; |
41 | 147 | cmartinez | import org.gvsig.app.project.ProjectManager; |
42 | import org.gvsig.app.project.documents.Document; |
||
43 | 5 | jldominguez | import org.gvsig.app.project.documents.layout.DefaultLayoutNotification; |
44 | 110 | jldominguez | import org.gvsig.app.project.documents.layout.FLayoutFunctions; |
45 | 5 | jldominguez | import org.gvsig.app.project.documents.layout.FLayoutUtilities; |
46 | import org.gvsig.app.project.documents.layout.LayoutNotification; |
||
47 | 168 | cmartinez | import org.gvsig.app.project.documents.layout.TocModelChangedNotification; |
48 | 5 | jldominguez | import org.gvsig.app.project.documents.view.ViewDocument; |
49 | import org.gvsig.compat.print.PrintAttributes; |
||
50 | import org.gvsig.fmap.dal.exception.ReadException; |
||
51 | import org.gvsig.fmap.geom.Geometry; |
||
52 | 181 | cmartinez | import org.gvsig.fmap.geom.Geometry.SUBTYPES; |
53 | import org.gvsig.fmap.geom.GeometryLocator; |
||
54 | import org.gvsig.fmap.geom.GeometryManager; |
||
55 | import org.gvsig.fmap.geom.exception.CreateEnvelopeException; |
||
56 | 5 | jldominguez | import org.gvsig.fmap.geom.primitive.Envelope; |
57 | import org.gvsig.fmap.mapcontext.MapContext; |
||
58 | import org.gvsig.fmap.mapcontext.MapContextException; |
||
59 | import org.gvsig.fmap.mapcontext.ViewPort; |
||
60 | 146 | cmartinez | import org.gvsig.fmap.mapcontext.events.AtomicEvent; |
61 | 5 | jldominguez | import org.gvsig.fmap.mapcontext.events.ColorEvent; |
62 | import org.gvsig.fmap.mapcontext.events.ExtentEvent; |
||
63 | 176 | cmartinez | import org.gvsig.fmap.mapcontext.events.FMapEvent; |
64 | 5 | jldominguez | import org.gvsig.fmap.mapcontext.events.ProjectionEvent; |
65 | 146 | cmartinez | import org.gvsig.fmap.mapcontext.events.listeners.AtomicEventListener; |
66 | 5 | jldominguez | import org.gvsig.fmap.mapcontext.events.listeners.ViewPortListener; |
67 | 142 | cmartinez | import org.gvsig.fmap.mapcontext.layers.CancelationException; |
68 | import org.gvsig.fmap.mapcontext.layers.LayerCollectionEvent; |
||
69 | import org.gvsig.fmap.mapcontext.layers.LayerCollectionListener; |
||
70 | 168 | cmartinez | import org.gvsig.fmap.mapcontext.layers.LayerEvent; |
71 | 142 | cmartinez | import org.gvsig.fmap.mapcontext.layers.LayerPositionEvent; |
72 | 5 | jldominguez | import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendChangedEvent; |
73 | import org.gvsig.fmap.mapcontext.rendering.legend.events.listeners.LegendListener; |
||
74 | 93 | jldominguez | import org.gvsig.gui.beans.Messages; |
75 | 5 | jldominguez | import org.gvsig.tools.ToolsLocator; |
76 | import org.gvsig.tools.dynobject.DynStruct; |
||
77 | import org.gvsig.tools.persistence.PersistenceManager; |
||
78 | import org.gvsig.tools.persistence.PersistentState; |
||
79 | import org.gvsig.tools.persistence.exception.PersistenceException; |
||
80 | 143 | cmartinez | import org.slf4j.Logger; |
81 | import org.slf4j.LoggerFactory; |
||
82 | 5 | jldominguez | |
83 | /**
|
||
84 | 176 | cmartinez | * FFrame used for embedding a View in the Layout. The View is not actually
|
85 | * inserted on the Layout, but it is used together with the MapContext
|
||
86 | * in order do draw an image which is then painted on the FFrame. Therefore,
|
||
87 | * no MapControl is used in current implementation, but a similar behavior
|
||
88 | * is simulated by the FFrameView. The original MapContext is cloned when
|
||
89 | * assigned to the FFrameView, which is then used for drawing.
|
||
90 | 5 | jldominguez | *
|
91 | 176 | cmartinez | * The FFrameView and the associated View can be synchronized, depending
|
92 | * on the values of {@link #getTypeScale()} and {@link #getLinked()}.
|
||
93 | *
|
||
94 | * The main synchronization logic is kept on two internal classes:
|
||
95 | * {@link OwnMapContextListener} and {@link ViewDocListener}. The first one
|
||
96 | * listens for events on the FFrameView and synchronizes the View accordingly.
|
||
97 | * The second one listens for events on the View and synchronizes the FFrameView
|
||
98 | * accordingly. There synchronization process is flagged using
|
||
99 | 182 | cmartinez | * {@link #b_updating} and {@link #b_updating}, in order
|
100 | 181 | cmartinez | * to avoid incurring on infinite synchronization loops.
|
101 | 176 | cmartinez | *
|
102 | 5 | jldominguez | * @author Vicente Caballero Navarro
|
103 | 176 | cmartinez | * @author Cesar Martinez Izquierdo
|
104 | 5 | jldominguez | */
|
105 | 142 | cmartinez | public class FFrameView extends FFrame implements IFFrameUseProject, IFFrameUseFMap { |
106 | 5 | jldominguez | |
107 | public static final String PERSISTENCE_DEFINITION_NAME = "FFrameView"; |
||
108 | |||
109 | private static final String MODE_FIELD = "mode"; |
||
110 | private static final String TYPESCALE_FIELD = "typeScale"; |
||
111 | private static final String QUALITY_FIELD = "quality"; |
||
112 | private static final String BLINKED_FIELD = "bLinked"; |
||
113 | private static final String MAPUNITS_FIELD = "mapUnits"; |
||
114 | private static final String SCALE_FIELD = "scale"; |
||
115 | private static final String VIEW_FIELD = "view"; |
||
116 | private static final String ENVELOPE_FIELD = "envelope"; |
||
117 | private static final String SHOWGRID_FIELD = "showGrid"; |
||
118 | private static final String GRID_FIELD = "gridview"; |
||
119 | 176 | cmartinez | private static final String HAS_TOC = "hasToc"; |
120 | 143 | cmartinez | // following fields are unused - should be deleted?
|
121 | private static final String EXTENSION_FIELD = "extension"; |
||
122 | 5 | jldominguez | |
123 | private static final Logger logger = LoggerFactory |
||
124 | .getLogger(FFrameView.class); |
||
125 | public static final int PRESENTATION = 0; |
||
126 | public static final int DRAFT = 1; |
||
127 | protected int mode; |
||
128 | protected int typeScale = AUTOMATICO; |
||
129 | protected int quality = PRESENTATION; |
||
130 | protected boolean linked = true; |
||
131 | protected ViewDocument viewDocument = null; |
||
132 | protected MapContext mapContext = null; |
||
133 | protected int mapUnits = 1; // Meters. |
||
134 | |||
135 | 64 | jldominguez | protected BufferedImage m_image = null; |
136 | protected AffineTransform at = null; |
||
137 | 5 | jldominguez | protected Project project = null; |
138 | 64 | jldominguez | protected double scaleAnt; |
139 | protected Point origin; |
||
140 | protected Point2D p1; |
||
141 | protected Point2D p2; |
||
142 | protected IFFrame grid;
|
||
143 | protected boolean showGrid = false; |
||
144 | 5 | jldominguez | |
145 | 182 | cmartinez | private boolean b_updating = false; |
146 | 147 | cmartinez | protected boolean b_validCache = false; |
147 | 181 | cmartinez | protected boolean b_drawing = false; |
148 | 144 | cmartinez | protected ViewDocListener viewDocListener;
|
149 | protected OwnMapContextListener ownMapContextListener;
|
||
150 | 202 | cmartinez | private boolean b_hasToc = true; |
151 | 181 | cmartinez | protected static final GeometryManager geomManager = GeometryLocator.getGeometryManager(); |
152 | |||
153 | 176 | cmartinez | /**
|
154 | 182 | cmartinez | * When we load a FFrameview from project, it will receive a wrong
|
155 | * extentChanged event the first time the View is painted, so we must
|
||
156 | * ignore this first event.
|
||
157 | 176 | cmartinez | */
|
158 | private boolean b_frameInitialized = true; |
||
159 | 142 | cmartinez | |
160 | 145 | cmartinez | |
161 | 5 | jldominguez | /**
|
162 | * Creates a new FFrameView object.
|
||
163 | */
|
||
164 | public FFrameView() {
|
||
165 | num++; |
||
166 | 144 | cmartinez | createListeners(); |
167 | 5 | jldominguez | } |
168 | 144 | cmartinez | |
169 | protected void createListeners() { |
||
170 | viewDocListener = new ViewDocListener();
|
||
171 | ownMapContextListener = new OwnMapContextListener();
|
||
172 | } |
||
173 | 5 | jldominguez | |
174 | /**
|
||
175 | 176 | cmartinez | * Returns a description of the FFrame
|
176 | 5 | jldominguez | *
|
177 | 176 | cmartinez | * @return Description.
|
178 | 5 | jldominguez | */
|
179 | public String toString() { |
||
180 | if (getView() == null) { |
||
181 | return "FFrameView " + num + ": " + "Vacio"; |
||
182 | } |
||
183 | |||
184 | return "FFrameView " + num + ": " + getView().getName(); |
||
185 | } |
||
186 | |||
187 | /**
|
||
188 | 176 | cmartinez | * Sets the scale of the MapContext contained in this FFrameView
|
189 | 5 | jldominguez | *
|
190 | 176 | cmartinez | * @param d Scale to be set
|
191 | 5 | jldominguez | */
|
192 | public void setScale(double d) { |
||
193 | 142 | cmartinez | if (getMapContext()!=null) { |
194 | getMapContext().setScaleView((long) d);
|
||
195 | } |
||
196 | 5 | jldominguez | } |
197 | |||
198 | /**
|
||
199 | 176 | cmartinez | * Sets a new Envelope on the MapContext contained in
|
200 | * this FFrameView
|
||
201 | 5 | jldominguez | *
|
202 | 176 | cmartinez | * @param r Envelope to be set
|
203 | 5 | jldominguez | */
|
204 | public void setNewEnvelope(Envelope r) { |
||
205 | 142 | cmartinez | getMapContext().getViewPort().setEnvelope(r); |
206 | updateScaleCtrl(); |
||
207 | 5 | jldominguez | } |
208 | 141 | cmartinez | |
209 | /**
|
||
210 | * Calculates the resolution (measured on dots per inch, DPI) to be
|
||
211 | * considered to draw the FFrameView on screen. It is calculated by
|
||
212 | * dividing the width (in pixels) of the FFrame divided by the width
|
||
213 | * in inches of the paper.
|
||
214 | */
|
||
215 | protected double getDrawPaperDPI() { |
||
216 | 213 | cmartinez | AffineTransform at = null; |
217 | if (getLayoutContext()!=null) { |
||
218 | at = getLayoutContext().getAT(); |
||
219 | } |
||
220 | return (2.54*getBoundingBox(at).width)/getBoundBox().width; |
||
221 | 141 | cmartinez | } |
222 | 5 | jldominguez | |
223 | /**
|
||
224 | 176 | cmartinez | * Returns the MapContext contained in this FFrameView, which is
|
225 | * usually a clone of the associated View. This MapContext
|
||
226 | * may be synchronized with the View one, depending on the
|
||
227 | * scale type that has been set (see {{@link #getTypeScale()}.
|
||
228 | 5 | jldominguez | *
|
229 | 176 | cmartinez | * @return The mapContext object
|
230 | 5 | jldominguez | */
|
231 | public MapContext getMapContext() {
|
||
232 | return mapContext;
|
||
233 | } |
||
234 | |||
235 | /**
|
||
236 | 176 | cmartinez | * Sets the quality of the visualization of the FFrame on screen.
|
237 | * Valid values include {@link #DRAFT} and {@link #PRESENTATION}.
|
||
238 | * Draft will disable the frame normal drawing, which will be
|
||
239 | * replaced by an empty rectangle only showing the name of the
|
||
240 | * frame.
|
||
241 | 5 | jldominguez | *
|
242 | 176 | cmartinez | * @param q Integer representing the quality.
|
243 | 5 | jldominguez | */
|
244 | public void setQuality(int q) { |
||
245 | quality = q; |
||
246 | } |
||
247 | |||
248 | /**
|
||
249 | 176 | cmartinez | * Gets the quality of the visualization of the FFrame on screen.
|
250 | * Valid values include {@link #DRAFT} and {@link #PRESENTATION}.
|
||
251 | * Draft will disable the frame normal drawing, which will be
|
||
252 | * replaced by an empty rectangle only showing the name of the
|
||
253 | * frame.
|
||
254 | 5 | jldominguez | *
|
255 | 176 | cmartinez | * @param q The selected quality
|
256 | 5 | jldominguez | */
|
257 | public int getQuality() { |
||
258 | return quality;
|
||
259 | } |
||
260 | |||
261 | 176 | cmartinez | /**
|
262 | * Sets the MapContext associated with this FFrameView, which will
|
||
263 | * be used to clone the layers and synchronize the FFrameView with
|
||
264 | * the associated View
|
||
265 | *
|
||
266 | * @param viewMapContext
|
||
267 | */
|
||
268 | 142 | cmartinez | public void setViewMapContext(MapContext viewMapContext) { |
269 | if (mapContext!=null) { |
||
270 | clearOwnListeners(mapContext); |
||
271 | } |
||
272 | try {
|
||
273 | if (linked){
|
||
274 | mapContext = |
||
275 | viewMapContext.createNewFMap( |
||
276 | (ViewPort) viewMapContext.getViewPort().clone()); |
||
277 | } |
||
278 | else {
|
||
279 | mapContext = viewMapContext.cloneFMap(); |
||
280 | mapContext.setViewPort((ViewPort) viewMapContext |
||
281 | .getViewPort().clone()); |
||
282 | } |
||
283 | ViewPort newViewPort = getMapContext().getViewPort(); |
||
284 | 213 | cmartinez | AffineTransform at;
|
285 | if (getLayoutContext()!=null) { |
||
286 | at = getLayoutContext().getAT(); |
||
287 | } |
||
288 | else {
|
||
289 | at = null;
|
||
290 | } |
||
291 | newViewPort.setImageSize(new Dimension((int) getBoundingBox(at).width, |
||
292 | (int) getBoundingBox(at).height));
|
||
293 | 142 | cmartinez | newViewPort.setDPI(getDrawPaperDPI()); |
294 | setListeners(); |
||
295 | updateScaleCtrl(); |
||
296 | 147 | cmartinez | setTocModel(); |
297 | 142 | cmartinez | } catch (CloneNotSupportedException e1) { |
298 | NotificationManager.addError("Excepci?n :", e1);
|
||
299 | } |
||
300 | |||
301 | } |
||
302 | 176 | cmartinez | |
303 | 5 | jldominguez | /**
|
304 | 176 | cmartinez | * Sets the View associated with this FFrameView, which will
|
305 | * be used to clone the MapContext and the layers. It will
|
||
306 | * also used to synchronize the FFrameView with
|
||
307 | * the associated View, depending on the selected scle type
|
||
308 | 5 | jldominguez | *
|
309 | 176 | cmartinez | * @param viewMapContext
|
310 | 5 | jldominguez | */
|
311 | 56 | jldominguez | public void setView(ViewDocument dvd) { |
312 | 202 | cmartinez | ViewDocument oldDoc = viewDocument; |
313 | 143 | cmartinez | if (oldDoc!=null && oldDoc.getMapContext()!=null) { |
314 | clearViewListeners(oldDoc.getMapContext()); |
||
315 | } |
||
316 | 56 | jldominguez | viewDocument = dvd; |
317 | 142 | cmartinez | if (dvd!=null) { |
318 | setViewMapContext(dvd.getMapContext()); |
||
319 | 5 | jldominguez | } |
320 | } |
||
321 | |||
322 | /**
|
||
323 | 176 | cmartinez | * Gets the associated View
|
324 | 5 | jldominguez | *
|
325 | 176 | cmartinez | * @return The associated view
|
326 | * @see {@link #setView(ViewDocument)}
|
||
327 | 5 | jldominguez | */
|
328 | public ViewDocument getView() {
|
||
329 | return viewDocument;
|
||
330 | } |
||
331 | |||
332 | /**
|
||
333 | 141 | cmartinez | * Draws the FFrameView on the provided Graphics, according to the
|
334 | * provided affine transform and the visible rectangle.
|
||
335 | 5 | jldominguez | *
|
336 | 141 | cmartinez | * @param g Graphics2D
|
337 | * @param at Affine transform to translate sheet coordinates (in cm)
|
||
338 | * to screen coordinates (in pixels)
|
||
339 | * @param visibleLayoutDocRect visible rectangle
|
||
340 | * @param imgBase Image used to speed up the drawing process
|
||
341 | 5 | jldominguez | */
|
342 | 141 | cmartinez | public void draw(Graphics2D g, AffineTransform at, Rectangle2D visibleLayoutDocRect, BufferedImage imgBase) { |
343 | Rectangle2D.Double fframeViewRect = getBoundingBox(at);
|
||
344 | Rectangle originalClip = preDraw(g, fframeViewRect);
|
||
345 | if (intersects(visibleLayoutDocRect, fframeViewRect)) {
|
||
346 | 5 | jldominguez | if (getMapContext() == null) { |
347 | drawEmpty(g); |
||
348 | 93 | jldominguez | } else {
|
349 | if (FLayoutUtilities.hasEditingLayers(getView())) {
|
||
350 | |||
351 | /*
|
||
352 | * We are not drawing if any layer is in editing mode
|
||
353 | */
|
||
354 | 110 | jldominguez | drawMessage(g, Messages.getText( |
355 | "_Cannot_draw_view_if_layers_in_editing_mode"));
|
||
356 | 93 | jldominguez | |
357 | 5 | jldominguez | } else {
|
358 | 93 | jldominguez | if (getQuality() == PRESENTATION) {
|
359 | 110 | jldominguez | try {
|
360 | 141 | cmartinez | drawPresentation(g, at, fframeViewRect, visibleLayoutDocRect, imgBase); |
361 | 110 | jldominguez | } catch (Exception exc) { |
362 | drawMessage(g, FLayoutFunctions.getLastMessage(exc)); |
||
363 | } |
||
364 | |||
365 | 93 | jldominguez | } else {
|
366 | drawDraft(g); |
||
367 | } |
||
368 | } |
||
369 | 176 | cmartinez | updateScaleCtrl(); // we need to update the scale whenever the window gets activated
|
370 | 5 | jldominguez | } |
371 | } |
||
372 | 141 | cmartinez | postDraw(g, fframeViewRect, visibleLayoutDocRect, imgBase, originalClip, at); |
373 | 5 | jldominguez | if (showGrid && grid != null) { |
374 | 141 | cmartinez | grid.draw(g, at, visibleLayoutDocRect, imgBase); |
375 | 5 | jldominguez | } |
376 | } |
||
377 | |||
378 | 110 | jldominguez | private void drawMessage(Graphics2D g, String msg) { |
379 | 93 | jldominguez | |
380 | Rectangle2D r = getBoundingBox(null); |
||
381 | g.setColor(Color.lightGray);
|
||
382 | g.fillRect((int) r.getX(), (int) r.getY(), (int) r.getWidth(), |
||
383 | (int) r.getHeight());
|
||
384 | g.setColor(Color.darkGray);
|
||
385 | g.setStroke(new BasicStroke(2)); |
||
386 | g.drawRect((int) r.getX(), (int) r.getY(), (int) r.getWidth(), |
||
387 | (int) r.getHeight());
|
||
388 | g.setColor(Color.black);
|
||
389 | |||
390 | int scale = (int) (r.getWidth() / 24); |
||
391 | Font f = new Font("SansSerif", Font.PLAIN, scale); |
||
392 | g.setFont(f); |
||
393 | |||
394 | 110 | jldominguez | g.drawString(msg, (int) (r.getCenterX() - ((msg.length() * scale) / 4)), |
395 | 93 | jldominguez | (int) (r.getCenterY()));
|
396 | } |
||
397 | |||
398 | 181 | cmartinez | protected Envelope getVisibleEnvelope(Rectangle2D.Double fframeViewRect, |
399 | Rectangle2D.Double visiblefframeViewRect) {
|
||
400 | Envelope oldEnv = getMapContext().getViewPort().getAdjustedEnvelope(); |
||
401 | double widthFactor = ((int)visiblefframeViewRect.width) / fframeViewRect.width; |
||
402 | double heightFactor = ((int)visiblefframeViewRect.height) / fframeViewRect.height; |
||
403 | |||
404 | double newWidth = oldEnv.getLength(0)*widthFactor; |
||
405 | double newHeight = oldEnv.getLength(1)*heightFactor; |
||
406 | |||
407 | double translateX = visiblefframeViewRect.x - fframeViewRect.x;
|
||
408 | double translateY = visiblefframeViewRect.y - fframeViewRect.y;
|
||
409 | double translateFactorX = translateX / fframeViewRect.width;
|
||
410 | double translateFactorY = translateY / fframeViewRect.height;
|
||
411 | |||
412 | double newX = oldEnv.getMinimum(0) + translateFactorX*oldEnv.getLength(0); |
||
413 | double newMaxY = oldEnv.getMaximum(1) - translateFactorY*oldEnv.getLength(1); |
||
414 | double newMaxX = newX + newWidth;
|
||
415 | double newY = newMaxY - newHeight;
|
||
416 | |||
417 | Envelope newEnv = null;
|
||
418 | try {
|
||
419 | newEnv = geomManager.createEnvelope(newX, newY, newMaxX, newMaxY, SUBTYPES.GEOM2D); |
||
420 | } catch (CreateEnvelopeException e) {
|
||
421 | logger.error("Error calculating visible extent", e);
|
||
422 | } |
||
423 | return newEnv;
|
||
424 | |||
425 | } |
||
426 | |||
427 | 110 | jldominguez | protected void drawPresentation( |
428 | Graphics2D g,
|
||
429 | AffineTransform affineTransform,
|
||
430 | 141 | cmartinez | Rectangle2D.Double fframeViewRect,
|
431 | Rectangle2D visibleLayoutDocRect,
|
||
432 | 110 | jldominguez | BufferedImage imgBase) throws Exception { |
433 | |||
434 | 181 | cmartinez | b_drawing = true;
|
435 | Rectangle2D.Double visiblefframeViewRect = new Rectangle2D.Double(); |
||
436 | Rectangle2D.Double.intersect(fframeViewRect, visibleLayoutDocRect, visiblefframeViewRect);
|
||
437 | if (visiblefframeViewRect.width<=0 || visiblefframeViewRect.height<=0) { |
||
438 | b_drawing = false;
|
||
439 | return;
|
||
440 | } |
||
441 | int drawWidth = (int)visiblefframeViewRect.width; |
||
442 | int drawHeight = (int)visiblefframeViewRect.height; |
||
443 | |||
444 | Envelope oldEnvelope = getMapContext().getViewPort().getEnvelope(); |
||
445 | if (!visiblefframeViewRect.equals(fframeViewRect)) {
|
||
446 | // if visible area is smaller than the fframe, we will only draw this area,
|
||
447 | // so we need to tell the ViewPort the image size and extent for drawing,
|
||
448 | // and restore the real extent after drawing
|
||
449 | Envelope newEnvelope = getVisibleEnvelope(fframeViewRect, visiblefframeViewRect); |
||
450 | // image size must be set before the envelope, as it has influence on the adjustedExtent
|
||
451 | getMapContext().getViewPort().setImageSize(new Dimension(drawWidth, drawHeight)); |
||
452 | getMapContext().getViewPort().setEnvelope(newEnvelope); |
||
453 | } |
||
454 | |||
455 | // map origin should be calculated using the full fframeview, as the visible one position will be relative
|
||
456 | Point mapOrigin = new Point((int)fframeViewRect.getMinX(), (int)fframeViewRect.getMaxY()); |
||
457 | |||
458 | 147 | cmartinez | // paint the MapContext on m_image, if not already cached
|
459 | 176 | cmartinez | createImage(affineTransform, drawWidth, drawHeight, mapOrigin); |
460 | 144 | cmartinez | |
461 | 147 | cmartinez | //Draw the created image
|
462 | 181 | cmartinez | drawImage(g, m_image, visiblefframeViewRect); |
463 | 147 | cmartinez | |
464 | 181 | cmartinez | if (!visiblefframeViewRect.equals(fframeViewRect)) {
|
465 | // restore real envelope and image size
|
||
466 | getMapContext().getViewPort().setImageSize(new Dimension((int)fframeViewRect.width, (int) fframeViewRect.height)); |
||
467 | getMapContext().getViewPort().setEnvelope(oldEnvelope); |
||
468 | } |
||
469 | |||
470 | 147 | cmartinez | scaleAnt = affineTransform.getScaleX(); |
471 | 181 | cmartinez | origin = mapOrigin; |
472 | b_drawing = false;
|
||
473 | 147 | cmartinez | } |
474 | |||
475 | 176 | cmartinez | protected void createImage(AffineTransform affineTransform, |
476 | 147 | cmartinez | int width, int height, Point mapOrigin) throws ReadException, MapContextException { |
477 | ViewPort viewPort = this.getMapContext().getViewPort();
|
||
478 | |||
479 | 144 | cmartinez | //If the image has to be created...
|
480 | 142 | cmartinez | if (origin == null || |
481 | !origin.equals(mapOrigin) || |
||
482 | affineTransform.getScaleX() != scaleAnt || |
||
483 | m_image == null ||
|
||
484 | 144 | cmartinez | !b_validCache) { |
485 | 39 | jldominguez | |
486 | 147 | cmartinez | viewPort.setDPI(getDrawPaperDPI()); |
487 | 167 | cmartinez | viewPort.setImageSize(new Dimension(width, height)); |
488 | 147 | cmartinez | |
489 | 5 | jldominguez | m_image = |
490 | 141 | cmartinez | new BufferedImage( |
491 | 147 | cmartinez | width, |
492 | height, |
||
493 | 141 | cmartinez | BufferedImage.TYPE_INT_ARGB);
|
494 | 39 | jldominguez | |
495 | 142 | cmartinez | Graphics2D gimg = (Graphics2D) m_image.createGraphics(); |
496 | getMapContext().draw(m_image, gimg, getScale()); |
||
497 | gimg.dispose(); |
||
498 | b_validCache = true;
|
||
499 | 5 | jldominguez | } |
500 | |||
501 | 147 | cmartinez | } |
502 | |||
503 | protected void drawImage(Graphics2D g, BufferedImage image, |
||
504 | Rectangle2D.Double visibleRectangle) {
|
||
505 | |||
506 | Color theBackColor = getMapContext().getViewPort().getBackColor();
|
||
507 | 5 | jldominguez | if (theBackColor != null) { |
508 | g.setColor(theBackColor); |
||
509 | 147 | cmartinez | g.fillRect((int) visibleRectangle.x, (int) visibleRectangle.y, |
510 | (int)visibleRectangle.width,
|
||
511 | (int)visibleRectangle.height);
|
||
512 | 5 | jldominguez | } |
513 | 141 | cmartinez | g.drawImage(m_image, |
514 | 147 | cmartinez | (int) visibleRectangle.x,
|
515 | (int) visibleRectangle.y,
|
||
516 | null);
|
||
517 | 5 | jldominguez | } |
518 | 39 | jldominguez | |
519 | 141 | cmartinez | protected Rectangle preDraw(Graphics2D g, Rectangle2D.Double fframeViewRect){ |
520 | 5 | jldominguez | Rectangle originalClip = null; |
521 | if (g.getClipBounds() != null) { |
||
522 | originalClip = (Rectangle) g.getClipBounds().clone();
|
||
523 | } |
||
524 | if (getRotation() != 0) { |
||
525 | 141 | cmartinez | g.rotate(Math.toRadians(getRotation()), fframeViewRect.getCenterX(), fframeViewRect.getCenterY()
|
526 | + (fframeViewRect.height / 2));
|
||
527 | 181 | cmartinez | } |
528 | 141 | cmartinez | g.clipRect((int) fframeViewRect.getMinX(), (int) fframeViewRect.getMinY(), |
529 | (int) fframeViewRect.getWidth(), (int) fframeViewRect.getHeight()); |
||
530 | 5 | jldominguez | return originalClip;
|
531 | } |
||
532 | |||
533 | 141 | cmartinez | protected void postDraw(Graphics2D g, Rectangle2D.Double fframeViewRect, Rectangle2D visibleLayoutDocRect, BufferedImage imgBase, |
534 | 5 | jldominguez | Rectangle originalClip, AffineTransform at){ |
535 | if (getRotation() != 0) { |
||
536 | 141 | cmartinez | g.rotate(Math.toRadians(-getRotation()), fframeViewRect.getCenterX(), fframeViewRect.getCenterY());
|
537 | 5 | jldominguez | } |
538 | if (getMapContext() != null) { |
||
539 | setATMap(getMapContext().getViewPort().getAffineTransform()); |
||
540 | } |
||
541 | if (originalClip != null) { |
||
542 | g.setClip(originalClip.x, originalClip.y, originalClip.width, originalClip.height); |
||
543 | } |
||
544 | } |
||
545 | |||
546 | public void print(Graphics2D g, AffineTransform at, Geometry geom, |
||
547 | PrintAttributes printAttributes) { |
||
548 | Rectangle2D.Double rectangleLayout = getBoundingBox(at);
|
||
549 | |||
550 | Rectangle originalClip = preDraw(g, rectangleLayout);
|
||
551 | print(g, at, printAttributes); |
||
552 | postDraw(g, rectangleLayout, null, null, originalClip, at); |
||
553 | if (showGrid && grid != null) { |
||
554 | grid.print(g, at, geom, printAttributes); |
||
555 | } |
||
556 | } |
||
557 | |||
558 | 65 | jldominguez | protected void print(Graphics2D g, AffineTransform at, PrintAttributes printAttributes) { |
559 | 5 | jldominguez | Rectangle2D.Double layoutRectangle = getBoundingBox(at);
|
560 | 142 | cmartinez | |
561 | // FIXME: should we clone the mapcontext and viewport before printing ??
|
||
562 | // otherwise we will probably have unexpected results if the user modifies
|
||
563 | // the layout while printing
|
||
564 | 5 | jldominguez | ViewPort viewPort = this.getMapContext().getViewPort();
|
565 | |||
566 | 57 | jldominguez | Point2D old_offset = viewPort.getOffset();
|
567 | Dimension old_imgsize = viewPort.getImageSize();
|
||
568 | |||
569 | 5 | jldominguez | viewPort.setOffset(new Point2D.Double(layoutRectangle.x, layoutRectangle.y)); |
570 | viewPort.setImageSize(new Dimension((int) layoutRectangle.width, (int) layoutRectangle.height)); |
||
571 | |||
572 | //Draw the backgroung color of the map
|
||
573 | Color theBackColor = viewPort.getBackColor();
|
||
574 | if (theBackColor != null) { |
||
575 | g.setColor(theBackColor); |
||
576 | g.fillRect((int) layoutRectangle.x, (int) layoutRectangle.y, viewPort |
||
577 | .getImageWidth(), viewPort |
||
578 | .getImageHeight()); |
||
579 | } |
||
580 | |||
581 | //Print the map
|
||
582 | try {
|
||
583 | this.getMapContext().print(g, getScale(), printAttributes);
|
||
584 | } catch (ReadException e) {
|
||
585 | NotificationManager.addError(e.getMessage(), e); |
||
586 | } catch (MapContextException e) {
|
||
587 | NotificationManager.addError(e.getMessage(), e); |
||
588 | 57 | jldominguez | } |
589 | |||
590 | // Restore offset, imgsize
|
||
591 | viewPort.setOffset(old_offset); |
||
592 | viewPort.setImageSize(old_imgsize); |
||
593 | 5 | jldominguez | } |
594 | |||
595 | /**
|
||
596 | * Rellena la unidad de medida en la que est? la vista.
|
||
597 | *
|
||
598 | * @param i
|
||
599 | * entero que representa la unidad de medida de la vista.
|
||
600 | */
|
||
601 | public void setMapUnits(int i) { |
||
602 | mapUnits = i; |
||
603 | } |
||
604 | |||
605 | /**
|
||
606 | * Obtiene la unidad de medida en la que est? la vista.
|
||
607 | *
|
||
608 | * @return Unidad de medida.
|
||
609 | */
|
||
610 | public int getMapUnits() { |
||
611 | return mapUnits;
|
||
612 | } |
||
613 | |||
614 | /**
|
||
615 | * Devuelve la escala seg?n el tipo de escala que se haya seleccionado al
|
||
616 | * a?adida la vista.
|
||
617 | *
|
||
618 | * @return escala.
|
||
619 | */
|
||
620 | public long getScale() { |
||
621 | 142 | cmartinez | return (long) getMapContext().getScaleView(); |
622 | 5 | jldominguez | } |
623 | |||
624 | /**
|
||
625 | * Seleccionar si la vista esta relacionada o no con la original.
|
||
626 | *
|
||
627 | * @param b
|
||
628 | * true si est? ligada y false si no lo est?.
|
||
629 | */
|
||
630 | public void setLinked(boolean b) { |
||
631 | linked = b; |
||
632 | 142 | cmartinez | resetListeners(); |
633 | 5 | jldominguez | } |
634 | |||
635 | /**
|
||
636 | * Devuelve si est? ligada o no el FFrameView con la vista.
|
||
637 | *
|
||
638 | * @return True si la vista est? ligada.
|
||
639 | */
|
||
640 | public boolean getLinked() { |
||
641 | return linked;
|
||
642 | } |
||
643 | |||
644 | /**
|
||
645 | 142 | cmartinez | * Devuelve el tipo de escala que est? seleccionada AUTOMATICO o
|
646 | 5 | jldominguez | * MANUAL.
|
647 | *
|
||
648 | * @return entero que representa el tipo seleccionado.
|
||
649 | */
|
||
650 | public int getTypeScale() { |
||
651 | return typeScale;
|
||
652 | } |
||
653 | |||
654 | /**
|
||
655 | * Rellenar el tipo de escala que se desea.
|
||
656 | *
|
||
657 | * @param i
|
||
658 | * entero que representa el tipo de escala.
|
||
659 | */
|
||
660 | public void setTypeScale(int i) { |
||
661 | typeScale = i; |
||
662 | 142 | cmartinez | resetListeners(); |
663 | 5 | jldominguez | } |
664 | |||
665 | /**
|
||
666 | * Inserta la imagen para repintar el FFrameView.
|
||
667 | *
|
||
668 | * @param bi
|
||
669 | * Imagen para repintar.
|
||
670 | */
|
||
671 | public void setBufferedImage(BufferedImage bi) { |
||
672 | m_image = bi; |
||
673 | } |
||
674 | |||
675 | /**
|
||
676 | * Devuelve la imagen para repintar.
|
||
677 | *
|
||
678 | * @return Imagen para repintar.
|
||
679 | */
|
||
680 | public BufferedImage getBufferedImage() { |
||
681 | return m_image;
|
||
682 | } |
||
683 | |||
684 | /**
|
||
685 | * Devuelve la MAtriz de transformaci?n utilizada por la FFrameView.
|
||
686 | *
|
||
687 | * @return MAtriz de transformaci?n.
|
||
688 | */
|
||
689 | public AffineTransform getATMap() { |
||
690 | return at;
|
||
691 | } |
||
692 | |||
693 | /**
|
||
694 | * Inserta la matriz de transformaci?n.
|
||
695 | *
|
||
696 | * @param transform
|
||
697 | * Matriz de transformaci?n.
|
||
698 | */
|
||
699 | public void setATMap(AffineTransform transform) { |
||
700 | at = transform; |
||
701 | } |
||
702 | |||
703 | /**
|
||
704 | * Inserta el proyecto.
|
||
705 | *
|
||
706 | * @param p
|
||
707 | * Proyecto.
|
||
708 | */
|
||
709 | public void setProject(Project p) { |
||
710 | project = p; |
||
711 | } |
||
712 | |||
713 | /**
|
||
714 | * @see org.gvsig.app.project.documents.layout.fframes.IFFrame#getNameFFrame()
|
||
715 | */
|
||
716 | public String getNameFFrame() { |
||
717 | return PluginServices.getText(this, "Vista") + num; |
||
718 | } |
||
719 | |||
720 | public String getName() { |
||
721 | return PERSISTENCE_DEFINITION_NAME;
|
||
722 | } |
||
723 | |||
724 | /**
|
||
725 | * DOCUMENT ME!
|
||
726 | *
|
||
727 | * @param arg0
|
||
728 | * DOCUMENT ME!
|
||
729 | *
|
||
730 | * @return DOCUMENT ME!
|
||
731 | */
|
||
732 | public boolean compare(Object arg0) { |
||
733 | if (!(arg0 instanceof FFrameView)) { |
||
734 | return false; |
||
735 | } |
||
736 | |||
737 | if (!this.getName().equals(((FFrameView) arg0).getName())) { |
||
738 | return false; |
||
739 | } |
||
740 | |||
741 | if (Math.abs(this.getBoundBox().getWidth() |
||
742 | - (((FFrameView) arg0).getBoundBox().getWidth())) > 0.05) {
|
||
743 | return false; |
||
744 | } |
||
745 | if (Math.abs(this.getBoundBox().getHeight() |
||
746 | - (((FFrameView) arg0).getBoundBox().getHeight())) > 0.05) {
|
||
747 | return false; |
||
748 | } |
||
749 | |||
750 | if (!this.toString().equals(((FFrameView) arg0).toString())) { |
||
751 | return false; |
||
752 | } |
||
753 | |||
754 | if (this.getMapContext() != null |
||
755 | && !this.getMapContext()
|
||
756 | .equals(((FFrameView) arg0).getMapContext())) { |
||
757 | return false; |
||
758 | } |
||
759 | |||
760 | if (this.getRotation() != ((FFrameView) arg0).getRotation()) { |
||
761 | return false; |
||
762 | } |
||
763 | return true; |
||
764 | } |
||
765 | 140 | cmartinez | |
766 | public void updateScaleCtrl() { |
||
767 | NewStatusBar statusbar = PluginServices.getMainFrame().getStatusBar(); |
||
768 | MapContext mapContext = this.getMapContext();
|
||
769 | 146 | cmartinez | if (mapContext==null) { |
770 | return;
|
||
771 | } |
||
772 | 140 | cmartinez | statusbar.setMessage("units",
|
773 | PluginServices.getText(this, mapContext.getDistanceName()));
|
||
774 | statusbar.setControlValue("layout-view-change-scale",
|
||
775 | 142 | cmartinez | String.valueOf(getMapContext().getScaleView()));
|
776 | 140 | cmartinez | IProjection proj = mapContext.getViewPort().getProjection(); |
777 | if (proj != null) { |
||
778 | statusbar.setMessage("projection", proj.getAbrev());
|
||
779 | } else {
|
||
780 | statusbar.setMessage("projection", ""); |
||
781 | } |
||
782 | } |
||
783 | 5 | jldominguez | |
784 | public void fullExtent() throws ReadException { |
||
785 | setNewEnvelope(getMapContext().getFullEnvelope()); |
||
786 | } |
||
787 | |||
788 | public void setPointsToZoom(Point2D px1, Point2D px2) { |
||
789 | p1 = px1; |
||
790 | p2 = px2; |
||
791 | } |
||
792 | |||
793 | public void movePoints(Point2D px1, Point2D px2) { |
||
794 | double difX = -px2.getX() + px1.getX();
|
||
795 | double difY = -px2.getY() + px1.getY();
|
||
796 | if (p1 != null) { |
||
797 | p1.setLocation(p1.getX() + difX, p1.getY() + difY); |
||
798 | p2.setLocation(p2.getX() + difX, p2.getY() + difY); |
||
799 | } |
||
800 | } |
||
801 | |||
802 | 43 | jldominguez | /**
|
803 | * This method deals with places where this fframeview and the cloned
|
||
804 | * fframeview (frame) are registered as listeners. The goal should be
|
||
805 | * leaving the cloned instance (frame) as listener in the same way
|
||
806 | * that 'this' instance is doing.
|
||
807 | */
|
||
808 | protected void cloneActions(FFrameView frame) { |
||
809 | 5 | jldominguez | } |
810 | |||
811 | public Object clone() throws CloneNotSupportedException { |
||
812 | 147 | cmartinez | Document d = ProjectManager.getInstance().getCurrentProject().getDocuments().get(0); |
813 | 5 | jldominguez | FFrameView frame = (FFrameView) super.clone();
|
814 | 147 | cmartinez | frame.createListeners(); // necessary to create the listeners within the right scope
|
815 | 182 | cmartinez | frame.setView(this.getView());
|
816 | 5 | jldominguez | |
817 | if (grid != null) { |
||
818 | FFrameGrid newGrid = (FFrameGrid) this.grid.clone();
|
||
819 | newGrid.setFFrameDependence(frame); |
||
820 | frame.setGrid(newGrid); |
||
821 | } |
||
822 | cloneActions(frame); |
||
823 | return frame;
|
||
824 | } |
||
825 | |||
826 | public void setGrid(IFFrame grid) { |
||
827 | this.grid = grid;
|
||
828 | this.grid.setRotation(this.getRotation()); |
||
829 | } |
||
830 | |||
831 | public IFFrame getGrid() {
|
||
832 | return this.grid; |
||
833 | } |
||
834 | |||
835 | public void setRotation(double rotation) { |
||
836 | super.setRotation(rotation);
|
||
837 | if (grid != null) { |
||
838 | grid.setRotation(rotation); |
||
839 | } |
||
840 | } |
||
841 | |||
842 | public void showGrid(boolean b) { |
||
843 | showGrid = b; |
||
844 | } |
||
845 | |||
846 | public boolean isShowGrid() { |
||
847 | return showGrid;
|
||
848 | } |
||
849 | |||
850 | public void refreshOriginalExtent() { |
||
851 | } |
||
852 | |||
853 | public static void registerPersistent() { |
||
854 | PersistenceManager manager = ToolsLocator.getPersistenceManager(); |
||
855 | 176 | cmartinez | if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) { |
856 | 5 | jldominguez | DynStruct definition = |
857 | manager.addDefinition(FFrameView.class, |
||
858 | PERSISTENCE_DEFINITION_NAME, |
||
859 | 167 | cmartinez | "FFrameView persistence definition", null, null); |
860 | 5 | jldominguez | definition.extend(manager |
861 | .getDefinition(FFrame.PERSISTENCE_DEFINITION_NAME)); |
||
862 | |||
863 | definition.addDynFieldInt(MODE_FIELD).setMandatory(true);
|
||
864 | definition.addDynFieldInt(TYPESCALE_FIELD).setMandatory(true);
|
||
865 | 143 | cmartinez | definition.addDynFieldInt(EXTENSION_FIELD).setMandatory(false);
|
866 | 5 | jldominguez | definition.addDynFieldInt(QUALITY_FIELD).setMandatory(true);
|
867 | definition.addDynFieldBoolean(BLINKED_FIELD).setMandatory(true);
|
||
868 | definition.addDynFieldInt(MAPUNITS_FIELD).setMandatory(true);
|
||
869 | 142 | cmartinez | definition.addDynFieldDouble(SCALE_FIELD).setMandatory(false);
|
870 | 5 | jldominguez | definition.addDynFieldObject(VIEW_FIELD) |
871 | .setClassOfValue(ViewDocument.class).setMandatory(false);
|
||
872 | definition.addDynFieldObject(ENVELOPE_FIELD) |
||
873 | .setClassOfValue(Envelope.class).setMandatory(false);
|
||
874 | definition.addDynFieldBoolean(SHOWGRID_FIELD).setMandatory(true);
|
||
875 | definition.addDynFieldObject(GRID_FIELD) |
||
876 | .setClassOfValue(IFFrame.class).setMandatory(false);
|
||
877 | 145 | cmartinez | definition.addDynFieldBoolean(HAS_TOC).setMandatory(false);
|
878 | 5 | jldominguez | } |
879 | } |
||
880 | |||
881 | @Override
|
||
882 | public void loadFromState(PersistentState state) |
||
883 | throws PersistenceException {
|
||
884 | super.loadFromState(state);
|
||
885 | 176 | cmartinez | b_frameInitialized = false;
|
886 | 5 | jldominguez | mode = state.getInt(MODE_FIELD); |
887 | typeScale = state.getInt(TYPESCALE_FIELD); |
||
888 | quality = state.getInt(QUALITY_FIELD); |
||
889 | linked = state.getBoolean(BLINKED_FIELD); |
||
890 | 142 | cmartinez | mapUnits = state.getInt(MAPUNITS_FIELD);; |
891 | 5 | jldominguez | viewDocument = (ViewDocument) state.get(VIEW_FIELD); |
892 | 168 | cmartinez | if (state.hasValue(HAS_TOC)) {
|
893 | this.b_hasToc = state.getBoolean(HAS_TOC);
|
||
894 | } |
||
895 | if (viewDocument!=null) { |
||
896 | this.setView(viewDocument);
|
||
897 | // it is crucial to don't persist the MapContext and get a cloned one from the View instead,
|
||
898 | // as the cloned instance is different from the one created using persistence. In particular,
|
||
899 | // the cloned one will share the EventBuffer with the original one, while persistence would
|
||
900 | // create 2 separate EventBuffers, which will then have a very stange behaviour
|
||
901 | } |
||
902 | if (getMapContext()!=null) { |
||
903 | double mapScale = state.getDouble(SCALE_FIELD);
|
||
904 | 182 | cmartinez | getMapContext().setScaleView((long)mapScale);
|
905 | 168 | cmartinez | getMapContext().getViewPort().setEnvelope( |
906 | (Envelope) state.get(ENVELOPE_FIELD)); |
||
907 | if (this.getLayoutContext()!=null) { |
||
908 | this.getLayoutContext().setTocModel(getMapContext());
|
||
909 | } |
||
910 | 5 | jldominguez | |
911 | } |
||
912 | showGrid = state.getBoolean(SHOWGRID_FIELD); |
||
913 | grid = (IFFrame) state.get(GRID_FIELD); |
||
914 | } |
||
915 | |||
916 | @Override
|
||
917 | public void saveToState(PersistentState state) throws PersistenceException { |
||
918 | super.saveToState(state);
|
||
919 | state.set(MODE_FIELD, mode); |
||
920 | state.set(TYPESCALE_FIELD, typeScale); |
||
921 | state.set(QUALITY_FIELD, quality); |
||
922 | state.set(BLINKED_FIELD, linked); |
||
923 | state.set(MAPUNITS_FIELD, mapUnits); |
||
924 | state.set(VIEW_FIELD, viewDocument); |
||
925 | 147 | cmartinez | state.set(HAS_TOC, b_hasToc); |
926 | 5 | jldominguez | |
927 | if (getMapContext() != null |
||
928 | && getMapContext().getViewPort().getEnvelope() != null) {
|
||
929 | state.set(ENVELOPE_FIELD, getMapContext().getViewPort() |
||
930 | .getEnvelope()); |
||
931 | 145 | cmartinez | state.set(SCALE_FIELD, (double)getMapContext().getScaleView());
|
932 | 5 | jldominguez | } |
933 | |||
934 | state.set(SHOWGRID_FIELD, showGrid); |
||
935 | state.set(GRID_FIELD, grid); |
||
936 | } |
||
937 | |||
938 | @Override
|
||
939 | 142 | cmartinez | public void setBoundBox(Rectangle2D r) { |
940 | super.setBoundBox(r);
|
||
941 | if (getMapContext()!=null) { |
||
942 | 213 | cmartinez | AffineTransform at = this.getLayoutContext().getAT(); |
943 | 142 | cmartinez | getMapContext().getViewPort().setImageSize( |
944 | 213 | cmartinez | new Dimension((int)getBoundingBox(at).getWidth(), (int)getBoundingBox(at).getHeight())); |
945 | 142 | cmartinez | getMapContext().getViewPort().setDPI(getDrawPaperDPI()); |
946 | updateScaleCtrl(); |
||
947 | // FIXME: what should we do here? should we invalidate the cache?
|
||
948 | // should we also trigger a Layout redraw?
|
||
949 | refresh(); |
||
950 | } |
||
951 | 5 | jldominguez | } |
952 | 72 | jldominguez | |
953 | /**
|
||
954 | 176 | cmartinez | * Gets the rotation of the frame
|
955 | 72 | jldominguez | *
|
956 | 176 | cmartinez | * @return Rotation in degrees
|
957 | 72 | jldominguez | */
|
958 | public double getMapRotation() { |
||
959 | return 0; |
||
960 | } |
||
961 | 142 | cmartinez | |
962 | protected void invalidateLayout() { |
||
963 | b_validCache = false;
|
||
964 | 147 | cmartinez | if (getLayoutContext()!=null) { |
965 | getLayoutContext().notifAllObservers(); |
||
966 | } |
||
967 | 142 | cmartinez | observers.notifyObservers(this,
|
968 | 146 | cmartinez | new DefaultLayoutNotification(LayoutNotification.LAYOUT_REFRESH));
|
969 | 142 | cmartinez | } |
970 | 147 | cmartinez | |
971 | protected void invalidateToc() { |
||
972 | if (getLayoutContext()!=null) { |
||
973 | 168 | cmartinez | getLayoutContext().notifyTocUpdated(TocModelChangedNotification.Type.MODEL_CHANGED); |
974 | 147 | cmartinez | } |
975 | } |
||
976 | 144 | cmartinez | |
977 | public void refresh() { |
||
978 | // FIXME: what should we do here? do we really need to invalidate cache??
|
||
979 | b_validCache = false;
|
||
980 | } |
||
981 | 142 | cmartinez | |
982 | 144 | cmartinez | protected void resetListeners() { |
983 | if (this.getMapContext()!=null) { |
||
984 | clearOwnListeners(this.getMapContext());
|
||
985 | } |
||
986 | if (this.getView()!=null && this.getView().getMapContext()!=null) { |
||
987 | clearViewListeners(this.getView().getMapContext());
|
||
988 | } |
||
989 | setListeners(); |
||
990 | } |
||
991 | |||
992 | protected void setListeners() { |
||
993 | if (getView()!=null) { |
||
994 | if (linked) {
|
||
995 | getView().getMapContext().addLayerListener(viewDocListener); |
||
996 | getView().getMapContext().getLayers().addLayerCollectionListener(viewDocListener); |
||
997 | 146 | cmartinez | getView().getMapContext().addAtomicEventListener(viewDocListener); |
998 | 144 | cmartinez | } |
999 | if (getTypeScale()==IFFrameUseFMap.AUTOMATICO) {
|
||
1000 | getView().getMapContext().getViewPort().addViewPortListener(viewDocListener); |
||
1001 | } |
||
1002 | } |
||
1003 | if (getMapContext()!=null) { |
||
1004 | getMapContext().addLayerListener(ownMapContextListener); |
||
1005 | getMapContext().getLayers().addLayerCollectionListener(ownMapContextListener); |
||
1006 | getMapContext().getViewPort().addViewPortListener(ownMapContextListener); |
||
1007 | } |
||
1008 | } |
||
1009 | protected void clearOwnListeners(MapContext mapContext) { |
||
1010 | mapContext.removeLayerListener(ownMapContextListener); |
||
1011 | mapContext.getViewPort().removeViewPortListener(ownMapContextListener); |
||
1012 | mapContext.getLayers().removeLayerCollectionListener(ownMapContextListener); |
||
1013 | } |
||
1014 | protected void clearViewListeners(MapContext mapContext) { |
||
1015 | mapContext.removeLayerListener(viewDocListener); |
||
1016 | mapContext.getViewPort().removeViewPortListener(viewDocListener); |
||
1017 | mapContext.getLayers().removeLayerCollectionListener(viewDocListener); |
||
1018 | 181 | cmartinez | mapContext.removeAtomicEventListener(viewDocListener); |
1019 | 144 | cmartinez | } |
1020 | |||
1021 | /*
|
||
1022 | * (non-Javadoc)
|
||
1023 | * @see org.gvsig.tools.dispose.Disposable#dispose()
|
||
1024 | */
|
||
1025 | public void dispose() { |
||
1026 | try {
|
||
1027 | if (this.getMapContext()!=null) { |
||
1028 | clearOwnListeners(this.getMapContext());
|
||
1029 | } |
||
1030 | if (this.getView()!=null && this.getView().getMapContext()!=null) { |
||
1031 | clearViewListeners(this.getView().getMapContext());
|
||
1032 | } |
||
1033 | } |
||
1034 | catch (Exception ex) {} |
||
1035 | this.viewDocument = null; |
||
1036 | this.mapContext = null; |
||
1037 | } |
||
1038 | 142 | cmartinez | |
1039 | 167 | cmartinez | public void frameRemoved() { |
1040 | 144 | cmartinez | if (mapContext!=null) { |
1041 | clearOwnListeners(mapContext); |
||
1042 | } |
||
1043 | if (this.getView()!=null && this.getView().getMapContext()!=null) { |
||
1044 | clearViewListeners(this.getView().getMapContext());
|
||
1045 | } |
||
1046 | 147 | cmartinez | if (b_hasToc && getLayoutContext()!=null) { |
1047 | getLayoutContext().setTocModel(null);
|
||
1048 | 145 | cmartinez | } |
1049 | 167 | cmartinez | m_image = null; // FIXME: we could instead move it to a LRU cache to keep the last N images |
1050 | 144 | cmartinez | } |
1051 | |||
1052 | 167 | cmartinez | public void frameAdded() { |
1053 | 145 | cmartinez | setListeners(); |
1054 | 182 | cmartinez | setTocModel(); |
1055 | 145 | cmartinez | updateScaleCtrl(); |
1056 | } |
||
1057 | |||
1058 | 147 | cmartinez | public void setHasToc(boolean hasToc) { |
1059 | this.b_hasToc = hasToc;
|
||
1060 | setTocModel(); |
||
1061 | } |
||
1062 | |||
1063 | protected void setTocModel() { |
||
1064 | if (getLayoutContext()!=null) { |
||
1065 | if (b_hasToc && getMapContext()!=null) { |
||
1066 | getLayoutContext().setTocModel(getMapContext()); |
||
1067 | } |
||
1068 | else {
|
||
1069 | getLayoutContext().setTocModel(null);
|
||
1070 | } |
||
1071 | 144 | cmartinez | } |
1072 | } |
||
1073 | |||
1074 | 145 | cmartinez | @Override
|
1075 | protected void doSetSelected(int selectedStatus) { |
||
1076 | 147 | cmartinez | boolean oldSelectedStatus = isSelected();
|
1077 | 145 | cmartinez | super.doSetSelected(selectedStatus);
|
1078 | 147 | cmartinez | if (!oldSelectedStatus && isSelected()) { // changed from not selected to selected |
1079 | setTocModel(); |
||
1080 | updateScaleCtrl(); |
||
1081 | } |
||
1082 | 144 | cmartinez | } |
1083 | |||
1084 | private class ViewDocListener |
||
1085 | 146 | cmartinez | implements ViewPortListener, LegendListener, LayerCollectionListener, AtomicEventListener {
|
1086 | 144 | cmartinez | |
1087 | 142 | cmartinez | public void extentChanged(ExtentEvent e) { |
1088 | 182 | cmartinez | if (!b_updating && getTypeScale()==AUTOMATICO) {
|
1089 | 176 | cmartinez | if (!b_frameInitialized) {
|
1090 | b_frameInitialized = true;
|
||
1091 | return;
|
||
1092 | } |
||
1093 | 142 | cmartinez | if (getMapContext()!=null) { |
1094 | 182 | cmartinez | b_updating = true;
|
1095 | 142 | cmartinez | getMapContext().getViewPort().setEnvelope(e.getNewExtent()); |
1096 | updateScaleCtrl(); |
||
1097 | invalidateLayout(); |
||
1098 | 182 | cmartinez | b_updating = false;
|
1099 | 142 | cmartinez | } |
1100 | } |
||
1101 | } |
||
1102 | |||
1103 | public void backColorChanged(ColorEvent e) { |
||
1104 | 182 | cmartinez | if (!b_updating && linked) {
|
1105 | 142 | cmartinez | if (getMapContext()!=null) { |
1106 | 182 | cmartinez | b_updating = true;
|
1107 | 142 | cmartinez | mapContext.getViewPort().setBackColor(e.getNewColor()); |
1108 | invalidateLayout(); |
||
1109 | 182 | cmartinez | b_updating = true;
|
1110 | 142 | cmartinez | } |
1111 | } |
||
1112 | } |
||
1113 | |||
1114 | public void projectionChanged(ProjectionEvent e) { |
||
1115 | 182 | cmartinez | if (!b_updating && getTypeScale()==AUTOMATICO) {
|
1116 | 142 | cmartinez | if (getMapContext()!=null) { |
1117 | 182 | cmartinez | b_updating = true;
|
1118 | 142 | cmartinez | getMapContext().getViewPort().setProjection(e.getNewProjection()); |
1119 | invalidateLayout(); |
||
1120 | // FIXME: force also a view redraw someway??
|
||
1121 | 182 | cmartinez | b_updating = false;
|
1122 | 142 | cmartinez | } |
1123 | } |
||
1124 | } |
||
1125 | |||
1126 | public void conditionalRedraw() { |
||
1127 | 182 | cmartinez | if (!b_updating && linked) {
|
1128 | b_updating = true;
|
||
1129 | 142 | cmartinez | invalidateLayout(); |
1130 | // the view should also receive the event and update automatically
|
||
1131 | 182 | cmartinez | b_updating = false;
|
1132 | 142 | cmartinez | } |
1133 | } |
||
1134 | |||
1135 | public void legendChanged(LegendChangedEvent e) { |
||
1136 | conditionalRedraw(); |
||
1137 | 147 | cmartinez | invalidateToc(); |
1138 | 142 | cmartinez | } |
1139 | |||
1140 | public void layerAdded(LayerCollectionEvent e) { |
||
1141 | conditionalRedraw(); |
||
1142 | 147 | cmartinez | invalidateToc(); |
1143 | 142 | cmartinez | } |
1144 | |||
1145 | public void layerMoved(LayerPositionEvent e) { |
||
1146 | conditionalRedraw(); |
||
1147 | 147 | cmartinez | invalidateToc(); |
1148 | 142 | cmartinez | } |
1149 | |||
1150 | public void layerRemoved(LayerCollectionEvent e) { |
||
1151 | conditionalRedraw(); |
||
1152 | 147 | cmartinez | invalidateToc(); |
1153 | 142 | cmartinez | } |
1154 | |||
1155 | public void layerAdding(LayerCollectionEvent e) |
||
1156 | throws CancelationException {
|
||
1157 | // nothing needed
|
||
1158 | } |
||
1159 | |||
1160 | public void layerMoving(LayerPositionEvent e) |
||
1161 | throws CancelationException {
|
||
1162 | // nothing needed
|
||
1163 | } |
||
1164 | |||
1165 | public void layerRemoving(LayerCollectionEvent e) |
||
1166 | throws CancelationException {
|
||
1167 | // nothing needed
|
||
1168 | } |
||
1169 | |||
1170 | public void visibilityChanged(LayerCollectionEvent e) |
||
1171 | throws CancelationException {
|
||
1172 | 176 | cmartinez | // AtomicEvent is catching visibility changes instead of this one,
|
1173 | // as this event is not being received. Maybe is only triggered if the
|
||
1174 | 168 | cmartinez | // visibility of the whole group changes??
|
1175 | 142 | cmartinez | conditionalRedraw(); |
1176 | 147 | cmartinez | invalidateToc(); |
1177 | 142 | cmartinez | } |
1178 | 146 | cmartinez | |
1179 | public void atomicEvent(AtomicEvent e) { |
||
1180 | 176 | cmartinez | boolean needRedraw = false; |
1181 | // not all the events require a fframeview redraw
|
||
1182 | for (int i=e.getLayerEvents().length-1; i>=0; i--) { |
||
1183 | FMapEvent at = e.getEvent(i); |
||
1184 | if (at instanceof LayerEvent) { |
||
1185 | if (at.getEventType()==LayerEvent.DRAW_VALUES_CHANGED) {
|
||
1186 | needRedraw = true;
|
||
1187 | break;
|
||
1188 | } |
||
1189 | } |
||
1190 | } |
||
1191 | if (needRedraw) {
|
||
1192 | conditionalRedraw(); |
||
1193 | } |
||
1194 | 147 | cmartinez | invalidateToc(); |
1195 | 146 | cmartinez | } |
1196 | 144 | cmartinez | } |
1197 | 142 | cmartinez | |
1198 | 144 | cmartinez | private class OwnMapContextListener |
1199 | 168 | cmartinez | implements ViewPortListener, LegendListener, LayerCollectionListener {
|
1200 | 144 | cmartinez | |
1201 | 142 | cmartinez | public void extentChanged(ExtentEvent e) { |
1202 | 182 | cmartinez | if (!b_drawing && !b_updating && (getTypeScale() == AUTOMATICO)) {
|
1203 | 142 | cmartinez | if (getView()!=null) { |
1204 | 182 | cmartinez | b_updating = true;
|
1205 | 142 | cmartinez | getView().getMapContext().getViewPort().setEnvelope(e.getNewExtent()); |
1206 | updateScaleCtrl(); |
||
1207 | invalidateLayout(); |
||
1208 | 182 | cmartinez | b_updating = false;
|
1209 | 142 | cmartinez | } |
1210 | } |
||
1211 | } |
||
1212 | |||
1213 | public void backColorChanged(ColorEvent e) { |
||
1214 | 202 | cmartinez | if (!b_updating) {
|
1215 | 142 | cmartinez | if (getView()!=null) { |
1216 | 182 | cmartinez | b_updating = true;
|
1217 | 142 | cmartinez | getView().getMapContext().getViewPort().setBackColor(e.getNewColor()); |
1218 | invalidateLayout(); |
||
1219 | 182 | cmartinez | b_updating = false;
|
1220 | 142 | cmartinez | } |
1221 | } |
||
1222 | } |
||
1223 | |||
1224 | public void projectionChanged(ProjectionEvent e) { |
||
1225 | 182 | cmartinez | if (!b_updating && (getTypeScale() == AUTOMATICO)) {
|
1226 | 142 | cmartinez | if (getView()!=null) { |
1227 | 182 | cmartinez | b_updating = true;
|
1228 | 142 | cmartinez | getView().getMapContext().getViewPort().setProjection(e.getNewProjection()); |
1229 | invalidateLayout(); |
||
1230 | // FIXME: force also a view redraw someway??
|
||
1231 | 182 | cmartinez | b_updating = false;
|
1232 | 142 | cmartinez | } |
1233 | } |
||
1234 | } |
||
1235 | |||
1236 | public void conditionalRedraw() { |
||
1237 | 202 | cmartinez | if (!b_updating) {
|
1238 | 182 | cmartinez | b_updating = true;
|
1239 | 142 | cmartinez | invalidateLayout(); |
1240 | // the view should also receive the event and update automatically
|
||
1241 | 182 | cmartinez | b_updating = false;
|
1242 | 144 | cmartinez | } |
1243 | 142 | cmartinez | } |
1244 | 144 | cmartinez | |
1245 | 142 | cmartinez | public void legendChanged(final LegendChangedEvent e) { |
1246 | conditionalRedraw(); |
||
1247 | 168 | cmartinez | invalidateToc(); |
1248 | 142 | cmartinez | } |
1249 | |||
1250 | public void layerAdded(final LayerCollectionEvent e) { |
||
1251 | 213 | cmartinez | // necessary to set an envelope when the first layer is added
|
1252 | if (!b_updating && getMapContext().getViewPort().getEnvelope()==null) { |
||
1253 | try {
|
||
1254 | b_updating = true;
|
||
1255 | fullExtent(); |
||
1256 | |||
1257 | } catch (ReadException e1) {
|
||
1258 | } finally {
|
||
1259 | b_updating = false;
|
||
1260 | } |
||
1261 | } |
||
1262 | 142 | cmartinez | conditionalRedraw(); |
1263 | 168 | cmartinez | invalidateToc(); |
1264 | 142 | cmartinez | } |
1265 | 144 | cmartinez | |
1266 | 142 | cmartinez | public void layerMoved(final LayerPositionEvent e) { |
1267 | conditionalRedraw(); |
||
1268 | 168 | cmartinez | invalidateToc(); |
1269 | 142 | cmartinez | } |
1270 | 144 | cmartinez | |
1271 | 142 | cmartinez | public void layerRemoved(final LayerCollectionEvent e) { |
1272 | conditionalRedraw(); |
||
1273 | 168 | cmartinez | invalidateToc(); |
1274 | 142 | cmartinez | } |
1275 | |||
1276 | public void layerAdding(LayerCollectionEvent e) |
||
1277 | throws CancelationException {
|
||
1278 | // nothing neededO
|
||
1279 | 144 | cmartinez | |
1280 | 142 | cmartinez | } |
1281 | |||
1282 | public void layerMoving(LayerPositionEvent e) |
||
1283 | throws CancelationException {
|
||
1284 | // nothing needed
|
||
1285 | 144 | cmartinez | |
1286 | 142 | cmartinez | } |
1287 | |||
1288 | public void layerRemoving(LayerCollectionEvent e) |
||
1289 | throws CancelationException {
|
||
1290 | // nothing needed
|
||
1291 | 144 | cmartinez | |
1292 | 142 | cmartinez | } |
1293 | |||
1294 | public void visibilityChanged(LayerCollectionEvent e) |
||
1295 | throws CancelationException {
|
||
1296 | conditionalRedraw(); |
||
1297 | } |
||
1298 | |||
1299 | } |
||
1300 | 5 | jldominguez | } |