Statistics
| Revision:

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
}