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 @ 226

History | View | Annotate | Download (42.6 KB)

1
/* 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
import java.awt.BasicStroke;
25
import java.awt.Color;
26
import java.awt.Dimension;
27
import java.awt.Font;
28
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
import org.gvsig.andami.ui.mdiFrame.NewStatusBar;
40
import org.gvsig.app.project.Project;
41
import org.gvsig.app.project.ProjectManager;
42
import org.gvsig.app.project.documents.Document;
43
import org.gvsig.app.project.documents.layout.DefaultLayoutNotification;
44
import org.gvsig.app.project.documents.layout.FLayoutFunctions;
45
import org.gvsig.app.project.documents.layout.FLayoutUtilities;
46
import org.gvsig.app.project.documents.layout.LayoutNotification;
47
import org.gvsig.app.project.documents.layout.TocModelChangedNotification;
48
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
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
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
import org.gvsig.fmap.mapcontext.events.AtomicEvent;
61
import org.gvsig.fmap.mapcontext.events.ColorEvent;
62
import org.gvsig.fmap.mapcontext.events.ExtentEvent;
63
import org.gvsig.fmap.mapcontext.events.FMapEvent;
64
import org.gvsig.fmap.mapcontext.events.ProjectionEvent;
65
import org.gvsig.fmap.mapcontext.events.listeners.AtomicEventListener;
66
import org.gvsig.fmap.mapcontext.events.listeners.ViewPortListener;
67
import org.gvsig.fmap.mapcontext.layers.CancelationException;
68
import org.gvsig.fmap.mapcontext.layers.LayerCollectionEvent;
69
import org.gvsig.fmap.mapcontext.layers.LayerCollectionListener;
70
import org.gvsig.fmap.mapcontext.layers.LayerEvent;
71
import org.gvsig.fmap.mapcontext.layers.LayerPositionEvent;
72
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendChangedEvent;
73
import org.gvsig.fmap.mapcontext.rendering.legend.events.listeners.LegendListener;
74
import org.gvsig.gui.beans.Messages;
75
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
import org.slf4j.Logger;
81
import org.slf4j.LoggerFactory;
82

    
83
/**
84
 * 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
 * 
91
 * 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
 * {@link #b_updating} and {@link #b_updating}, in order
100
 * to avoid incurring on infinite synchronization loops. 
101
 * 
102
 * @author Vicente Caballero Navarro
103
 * @author Cesar Martinez Izquierdo
104
 */
105
public class FFrameView extends FFrame implements IFFrameUseProject, IFFrameUseFMap {
106

    
107
    public static final String PERSISTENCE_DEFINITION_NAME = "FFrameView";
108

    
109
    private static final String QUALITY_FIELD = "quality";
110
    private static final String MAPUNITS_FIELD = "mapUnits";
111
    private static final String SCALE_FIELD = "scale";
112
    private static final String VIEW_FIELD = "view";
113
    private static final String ENVELOPE_FIELD = "envelope";
114
    private static final String SHOWGRID_FIELD = "showGrid";
115
    private static final String GRID_FIELD = "gridview";
116
    private static final String HAS_TOC = "hasToc";
117
    private static final String LAYER_SYNC_FIELD = "layerSync";
118
    private static final String EXTENT_SYNC_FIELD = "extentSync";
119
    // following fields are unused - they are kept for backward-compatibility 
120
    private static final String EXTENSION_FIELD = "extension";
121
    private static final String BLINKED_FIELD = "bLinked";
122
    private static final String MODE_FIELD = "mode";
123
    private static final String TYPESCALE_FIELD = "typeScale";
124
    private static final String MAPCONTEXT_FIELD = "mapContext";
125
    private static final String VIEWING_FIELD = "viewing";
126

    
127
    private static final Logger logger = LoggerFactory
128
        .getLogger(FFrameView.class);
129
    public static final int PRESENTATION = 0;
130
    public static final int DRAFT = 1;
131
    protected boolean syncLayers = true;
132
    protected boolean syncExtents = true;
133
    protected int quality = PRESENTATION;
134
    protected ViewDocument viewDocument = null;
135
    protected MapContext mapContext = null;
136
    protected int mapUnits = 1; // Meters.
137

    
138
    protected BufferedImage m_image = null;
139
    protected AffineTransform at = null;
140
    protected Project project = null;
141
    protected double scaleAnt;
142
    protected Point origin;
143
    protected Point2D p1;
144
    protected Point2D p2;
145
    protected IFFrame grid;
146
    protected boolean showGrid = false;
147

    
148
        private boolean b_updating = false;
149
        protected boolean b_validCache = false;
150
        protected boolean b_drawing = false;
151
        protected ViewDocListener viewDocListener;
152
        protected OwnMapContextListener ownMapContextListener;
153
        private boolean b_hasToc = true;
154
    protected static final GeometryManager geomManager = GeometryLocator.getGeometryManager();
155

    
156
        /**
157
         * When we load a FFrameview from project, it will receive a wrong
158
         * extentChanged event the first time the View is painted, so we must
159
         * ignore this first event. 
160
         */
161
        private boolean b_frameInitialized = true;
162

    
163
        protected AffineTransform originalGraphicsAt = null;
164
        protected Rectangle originalClip = null;
165

    
166

    
167
    /**
168
     * Creates a new FFrameView object.
169
     */
170
    public FFrameView() {
171
        num++;
172
        createListeners();
173
    }
174
    
175
    protected void createListeners() {
176
            viewDocListener = new ViewDocListener();
177
            ownMapContextListener = new OwnMapContextListener();
178
    }
179

    
180
    /**
181
     * Returns a description of the FFrame
182
     * 
183
     * @return Description.
184
     */
185
    public String toString() {
186
        if (getView() == null) {
187
            return "FFrameView " + num + ": " + "Vacio";
188
        }
189

    
190
        return "FFrameView " + num + ": " + getView().getName();
191
    }
192

    
193
    /**
194
     * Sets the scale of the MapContext contained in this FFrameView
195
     * 
196
     * @param d Scale to be set
197
     */
198
    public void setScale(double d) {
199
            if (getMapContext()!=null) {
200
                    getMapContext().setScaleView((long) d);
201
            }
202
    }
203

    
204
    /**
205
     * Sets a new Envelope on the MapContext contained in
206
     * this FFrameView
207
     * 
208
     * @param r Envelope to be set
209
     */
210
    public void setNewEnvelope(Envelope r) {
211
            getMapContext().getViewPort().setEnvelope(r);
212
            updateScaleCtrl();
213
    }
214
    
215
    /**
216
     * Calculates the resolution (measured on dots per inch, DPI) to be
217
     * considered to draw the FFrameView on screen. It is calculated by
218
     * dividing the width (in pixels) of the FFrame divided by the width
219
     * in inches of the paper.
220
     */
221
    protected double getDrawPaperDPI() {
222
            AffineTransform at = null;
223
            if (getLayoutContext()!=null) {
224
                    at = getLayoutContext().getAT();
225
            }
226
            return (2.54*getBoundingBox(at).width)/getBoundBox().width;        
227
    }
228

    
229
    /**
230
     * Returns the MapContext contained in this FFrameView, which is
231
     * usually a clone of the associated View. This MapContext
232
     * may be synchronized with the View one, depending on the
233
     * scale type that has been set (see {{@link #getTypeScale()}.
234
     * 
235
     * @return The mapContext object
236
     */
237
    public MapContext getMapContext() {
238
        return mapContext;
239
    }
240

    
241
    /**
242
     * Sets the quality of the visualization of the FFrame on screen.
243
     * Valid values include {@link #DRAFT} and {@link #PRESENTATION}.
244
     * Draft will disable the frame normal drawing, which will be
245
     * replaced by an empty rectangle only showing the name of the
246
     * frame.  
247
     * 
248
     * @param q Integer representing the quality.
249
     */
250
    public void setQuality(int q) {
251
        quality = q;
252
    }
253

    
254
    /**
255
     * Gets the quality of the visualization of the FFrame on screen.
256
     * Valid values include {@link #DRAFT} and {@link #PRESENTATION}.
257
     * Draft will disable the frame normal drawing, which will be
258
     * replaced by an empty rectangle only showing the name of the
259
     * frame.  
260
     * 
261
     * @param q The selected quality
262
     */
263
    public int getQuality() {
264
        return quality;
265
    }
266

    
267
    /**
268
     * Sets the MapContext associated with this FFrameView, which will
269
     * be used to clone the layers and synchronize the FFrameView with
270
     * the associated View 
271
     * 
272
     * @param viewMapContext
273
     */
274
    public void setViewMapContext(MapContext viewMapContext) {
275
            if (mapContext!=null) {
276
                    clearOwnListeners(mapContext);
277
            }
278
            try {
279
                    if (syncLayers){
280
                            mapContext =
281
                                            viewMapContext.createNewFMap(
282
                                                            (ViewPort) viewMapContext.getViewPort().clone());
283
                    }
284
                    else {
285
                            mapContext = viewMapContext.cloneFMap();
286
                            mapContext.setViewPort((ViewPort) viewMapContext
287
                                            .getViewPort().clone());
288
                    }
289
                    ViewPort newViewPort = getMapContext().getViewPort();
290
                    AffineTransform at;
291
                    if (getLayoutContext()!=null) {
292
                            at = getLayoutContext().getAT();
293
                    }
294
                    else {
295
                            at = null;
296
                    }
297
                    newViewPort.setImageSize(new Dimension((int) getBoundingBox(at).width,
298
                                    (int) getBoundingBox(at).height));
299
                    newViewPort.setDPI(getDrawPaperDPI());
300
                    setListeners();
301
                    updateScaleCtrl();
302
                    setTocModel();
303
            } catch (CloneNotSupportedException e1) {
304
                    NotificationManager.addError("Excepci?n :", e1);
305
            }
306

    
307
    }
308

    
309
    /**
310
     * Sets the View associated with this FFrameView, which will
311
     * be used to clone the MapContext and the layers. It will
312
     * also used to synchronize the FFrameView with
313
     * the associated View, depending on the selected scle type 
314
     * 
315
     * @param viewMapContext
316
     */
317
    public void setView(ViewDocument dvd) {
318
            ViewDocument oldDoc = viewDocument;
319
            if (oldDoc!=null && oldDoc.getMapContext()!=null) {
320
                    clearViewListeners(oldDoc.getMapContext());
321
            }
322
        viewDocument = dvd;
323
        if (dvd!=null) {
324
            setViewMapContext(dvd.getMapContext());
325
        }
326
    }
327

    
328
    /**
329
     * Gets the associated View
330
     * 
331
     * @return The associated view
332
     * @see {@link #setView(ViewDocument)}
333
     */
334
    public ViewDocument getView() {
335
        return viewDocument;
336
    }
337

    
338
    /**
339
     * Draws the FFrameView on the provided Graphics, according to the
340
     * provided affine transform and the visible rectangle.
341
     * 
342
     * @param g Graphics2D
343
     * @param at Affine transform to translate sheet coordinates (in cm)
344
     *                                 to screen coordinates (in pixels)
345
     * @param visibleLayoutDocRect visible rectangle
346
     * @param imgBase Image used to speed up the drawing process
347
     */
348
    public void draw(Graphics2D g, AffineTransform at, Rectangle2D visibleLayoutDocRect, BufferedImage imgBase) {
349
        Rectangle2D.Double fframeViewRect = getBoundingBox(at);  
350
        preDraw(g, fframeViewRect);    
351
        if (intersects(visibleLayoutDocRect, fframeViewRect)) {
352
            if (getMapContext() == null) {
353
                drawEmpty(g);
354
            } else {
355
                if (FLayoutUtilities.hasEditingLayers(getView())) {
356
                    
357
                    /*
358
                     * We are not drawing if any layer is in editing mode
359
                     */
360
                    drawMessage(g, Messages.getText(
361
                        "_Cannot_draw_view_if_layers_in_editing_mode"));
362
                    
363
                } else {
364
                    if (getQuality() == PRESENTATION) {
365
                        try {
366
                            drawPresentation(g, at, fframeViewRect, visibleLayoutDocRect, imgBase);
367
                        } catch (Exception exc) {
368
                            drawMessage(g, FLayoutFunctions.getLastMessage(exc));
369
                        }
370
                        
371
                    } else {
372
                        drawDraft(g);
373
                    }               
374
                }
375
                updateScaleCtrl(); // we need to update the scale whenever the window gets activated
376
            }
377
        }
378
        postDraw(g, fframeViewRect, visibleLayoutDocRect, imgBase, at); 
379
        if (showGrid && grid != null) {           
380
            grid.draw(g, at, visibleLayoutDocRect, imgBase);
381
        }    
382
    }
383
    
384
    private void drawMessage(Graphics2D g, String msg) {
385
        
386
        Rectangle2D r = getBoundingBox(null);
387
        g.setColor(Color.lightGray);
388
        g.fillRect((int) r.getX(), (int) r.getY(), (int) r.getWidth(),
389
            (int) r.getHeight());
390
        g.setColor(Color.darkGray);
391
        g.setStroke(new BasicStroke(2));
392
        g.drawRect((int) r.getX(), (int) r.getY(), (int) r.getWidth(),
393
            (int) r.getHeight());
394
        g.setColor(Color.black);
395

    
396
        int scale = (int) (r.getWidth() / 24);
397
        Font f = new Font("SansSerif", Font.PLAIN, scale);
398
        g.setFont(f);
399

    
400
        g.drawString(msg, (int) (r.getCenterX() - ((msg.length() * scale) / 4)),
401
            (int) (r.getCenterY()));        
402
    }
403

    
404
    protected Envelope getVisibleEnvelope(Rectangle2D.Double fframeViewRect,
405
            Rectangle2D.Double visiblefframeViewRect) {
406
            Envelope oldEnv = getMapContext().getViewPort().getAdjustedEnvelope();
407
            double widthFactor = ((int)visiblefframeViewRect.width) / fframeViewRect.width;
408
            double heightFactor = ((int)visiblefframeViewRect.height) / fframeViewRect.height;
409
            
410
            double newWidth = oldEnv.getLength(0)*widthFactor;
411
            double newHeight = oldEnv.getLength(1)*heightFactor;
412
        
413
        double translateX = visiblefframeViewRect.x - fframeViewRect.x;
414
        double translateY = visiblefframeViewRect.y - fframeViewRect.y;
415
        double translateFactorX = translateX / fframeViewRect.width;
416
        double translateFactorY = translateY / fframeViewRect.height;
417
        
418
        double newX = oldEnv.getMinimum(0) + translateFactorX*oldEnv.getLength(0);
419
        double newMaxY =  oldEnv.getMaximum(1) - translateFactorY*oldEnv.getLength(1);
420
        double newMaxX = newX + newWidth;
421
        double newY = newMaxY - newHeight;
422

    
423
        Envelope newEnv = null;
424
                try {
425
                        newEnv = geomManager.createEnvelope(newX, newY, newMaxX, newMaxY, SUBTYPES.GEOM2D);
426
                } catch (CreateEnvelopeException e) {
427
                        logger.error("Error calculating visible extent", e);
428
                }
429
        return newEnv;
430
                    
431
    }
432
    
433
    protected void drawPresentation(
434
        Graphics2D g,
435
        AffineTransform affineTransform,
436
        Rectangle2D.Double fframeViewRect,
437
        Rectangle2D visibleLayoutDocRect,
438
        BufferedImage imgBase) throws Exception {
439
        
440
            b_drawing = true;
441
            Rectangle2D.Double visiblefframeViewRect = new Rectangle2D.Double();
442
            Rectangle2D.Double.intersect(fframeViewRect, visibleLayoutDocRect, visiblefframeViewRect);
443
        if (visiblefframeViewRect.width<=0 || visiblefframeViewRect.height<=0) {
444
                b_drawing = false;
445
                return;
446
        }
447
            int drawWidth = (int)visiblefframeViewRect.width;
448
            int drawHeight = (int)visiblefframeViewRect.height;
449

    
450
        Envelope oldEnvelope = getMapContext().getViewPort().getEnvelope();
451
        if (!visiblefframeViewRect.equals(fframeViewRect)) {
452
                // if visible area is smaller than the fframe, we will only draw this area,
453
                // so we need to tell the ViewPort the image size and extent for drawing,
454
                // and restore the real extent after drawing
455
                Envelope newEnvelope = getVisibleEnvelope(fframeViewRect, visiblefframeViewRect);
456
                // image size must be set before the envelope, as it has influence on the adjustedExtent
457
                getMapContext().getViewPort().setImageSize(new Dimension(drawWidth, drawHeight));
458
                getMapContext().getViewPort().setEnvelope(newEnvelope);
459
        }
460
        
461
        // map origin should be calculated using the full fframeview, as the visible one position will be relative
462
        Point mapOrigin = new Point((int)fframeViewRect.getMinX(), (int)fframeViewRect.getMaxY());
463

    
464
        // paint the MapContext on m_image, if not already cached
465
        createImage(affineTransform, drawWidth, drawHeight, mapOrigin);
466

    
467
        //Draw the created image
468
        drawImage(g, m_image, visiblefframeViewRect);
469
        
470
        if (!visiblefframeViewRect.equals(fframeViewRect)) {
471
                // restore real envelope and image size
472
                getMapContext().getViewPort().setImageSize(new Dimension((int)fframeViewRect.width, (int) fframeViewRect.height));
473
                getMapContext().getViewPort().setEnvelope(oldEnvelope);
474
        }
475
        
476
        scaleAnt = affineTransform.getScaleX();
477
        origin = mapOrigin;
478
        b_drawing = false;
479
    }
480
    
481
    protected void createImage(AffineTransform affineTransform,
482
                    int width, int height, Point mapOrigin) throws ReadException, MapContextException {
483
            ViewPort viewPort = this.getMapContext().getViewPort();
484

    
485
        //If the image has to be created...
486
            if (origin == null ||
487
                            !origin.equals(mapOrigin) ||
488
                            affineTransform.getScaleX() != scaleAnt ||
489
                            m_image == null ||
490
                            !b_validCache) { 
491

    
492
                    viewPort.setDPI(getDrawPaperDPI());
493
                viewPort.setImageSize(new Dimension(width, height)); 
494
            
495
            m_image =
496
                    new BufferedImage(
497
                                    width,
498
                                    height,
499
                                    BufferedImage.TYPE_INT_ARGB);
500

    
501
            Graphics2D gimg = (Graphics2D) m_image.createGraphics();
502
            getMapContext().draw(m_image, gimg, getScale());
503
            gimg.dispose();
504
            b_validCache = true;
505
        } 
506

    
507
    }
508
    
509
    protected void drawImage(Graphics2D g, BufferedImage image,
510
                    Rectangle2D.Double visibleRectangle) {
511

    
512
            Color theBackColor = getMapContext().getViewPort().getBackColor();
513
        if (theBackColor != null) {
514
            g.setColor(theBackColor);
515
            g.fillRect((int) visibleRectangle.x, (int) visibleRectangle.y,
516
                            (int)visibleRectangle.width,
517
                            (int)visibleRectangle.height);
518
        }
519
        g.drawImage(m_image, 
520
                        (int) visibleRectangle.x,
521
                        (int) visibleRectangle.y,
522
                        null);            
523
    }
524

    
525
    protected void preDraw(Graphics2D g, Rectangle2D.Double fframeViewRect){
526
            originalGraphicsAt = (AffineTransform) g.getTransform().clone();
527
        if (g.getClipBounds() != null) {
528
            originalClip = (Rectangle) g.getClipBounds().clone();
529
        }
530
        if (getRotation() != 0) {
531
            g.rotate(Math.toRadians(getRotation()), fframeViewRect.getCenterX(), fframeViewRect.getCenterY());
532
        }
533
        g.clipRect((int) fframeViewRect.getMinX(), (int) fframeViewRect.getMinY(),
534
            (int) fframeViewRect.getWidth(), (int) fframeViewRect.getHeight());
535
    }
536
    
537
    protected void postDraw(Graphics2D g, Rectangle2D.Double fframeViewRect, Rectangle2D visibleLayoutDocRect, BufferedImage imgBase, 
538
        AffineTransform at){
539
            g.setTransform(originalGraphicsAt);
540
        if (getMapContext() != null) {
541
            setATMap(getMapContext().getViewPort().getAffineTransform());
542
        }
543
        if (originalGraphicsAt != null) {
544
            g.setClip(originalClip.x, originalClip.y, originalClip.width, originalClip.height);
545
        }            
546
    }
547

    
548
    public void print(Graphics2D g, AffineTransform at, Geometry geom,
549
        PrintAttributes printAttributes) {
550
        Rectangle2D.Double rectangleLayout = getBoundingBox(at);  
551
        
552
        preDraw(g, rectangleLayout);
553
        print(g, at, printAttributes);
554
        postDraw(g, rectangleLayout, null, null, at);
555
        if (showGrid && grid != null) {
556
            grid.print(g, at, geom, printAttributes);
557
        }    
558
    }
559

    
560
    protected void print(Graphics2D g, AffineTransform at, PrintAttributes printAttributes) {
561
        Rectangle2D.Double layoutRectangle = getBoundingBox(at);
562
        
563
        // FIXME: should we clone the mapcontext and viewport before printing ??
564
        // otherwise we will probably have unexpected results if the user modifies
565
        // the layout while printing
566
        ViewPort viewPort = this.getMapContext().getViewPort();
567
        
568
        Point2D old_offset = viewPort.getOffset();
569
        Dimension old_imgsize = viewPort.getImageSize();
570
        
571
        viewPort.setOffset(new Point2D.Double(layoutRectangle.x, layoutRectangle.y));
572
        viewPort.setImageSize(new Dimension((int) layoutRectangle.width, (int) layoutRectangle.height));
573

    
574
        //Draw the backgroung color of the map
575
        Color theBackColor = viewPort.getBackColor();
576
        if (theBackColor != null) {
577
            g.setColor(theBackColor);
578
            g.fillRect((int) layoutRectangle.x, (int) layoutRectangle.y, viewPort
579
                    .getImageWidth(), viewPort
580
                    .getImageHeight());
581
        }        
582
        
583
        //Print the map
584
        try {
585
            this.getMapContext().print(g, getScale(), printAttributes);
586
        } catch (ReadException e) {
587
            NotificationManager.addError(e.getMessage(), e);
588
        } catch (MapContextException e) {
589
            NotificationManager.addError(e.getMessage(), e);
590
        }      
591
        
592
        // Restore offset, imgsize
593
        viewPort.setOffset(old_offset);
594
        viewPort.setImageSize(old_imgsize);
595
    }
596

    
597
    /**
598
     * Rellena la unidad de medida en la que est? la vista.
599
     * 
600
     * @param i
601
     *            entero que representa la unidad de medida de la vista.
602
     */
603
    public void setMapUnits(int i) {
604
        mapUnits = i;
605
    }
606

    
607
    /**
608
     * Obtiene la unidad de medida en la que est? la vista.
609
     * 
610
     * @return Unidad de medida.
611
     */
612
    public int getMapUnits() {
613
        return mapUnits;
614
    }
615

    
616
    /**
617
     * Devuelve la escala seg?n el tipo de escala que se haya seleccionado al
618
     * a?adida la vista.
619
     * 
620
     * @return escala.
621
     */
622
    public long getScale() {
623
            return (long) getMapContext().getScaleView();
624
    }
625

    
626
    /**
627
     * Inserta la imagen para repintar el FFrameView.
628
     * 
629
     * @param bi
630
     *            Imagen para repintar.
631
     */
632
    public void setBufferedImage(BufferedImage bi) {
633
        m_image = bi;
634
    }
635

    
636
    /**
637
     * Devuelve la imagen para repintar.
638
     * 
639
     * @return Imagen para repintar.
640
     */
641
    public BufferedImage getBufferedImage() {
642
        return m_image;
643
    }
644

    
645
    /**
646
     * Devuelve la MAtriz de transformaci?n utilizada por la FFrameView.
647
     * 
648
     * @return MAtriz de transformaci?n.
649
     */
650
    public AffineTransform getATMap() {
651
        return at;
652
    }
653

    
654
    /**
655
     * Inserta la matriz de transformaci?n.
656
     * 
657
     * @param transform
658
     *            Matriz de transformaci?n.
659
     */
660
    public void setATMap(AffineTransform transform) {
661
        at = transform;
662
    }
663

    
664
    /**
665
     * Inserta el proyecto.
666
     * 
667
     * @param p
668
     *            Proyecto.
669
     */
670
    public void setProject(Project p) {
671
        project = p;
672
    }
673

    
674
    /**
675
     * @see org.gvsig.app.project.documents.layout.fframes.IFFrame#getNameFFrame()
676
     */
677
    public String getNameFFrame() {
678
        return PluginServices.getText(this, "Vista") + num;
679
    }
680

    
681
    public String getName() {
682
        return PERSISTENCE_DEFINITION_NAME;
683
    }
684

    
685
    /**
686
     * DOCUMENT ME!
687
     * 
688
     * @param arg0
689
     *            DOCUMENT ME!
690
     * 
691
     * @return DOCUMENT ME!
692
     */
693
    public boolean compare(Object arg0) {
694
        if (!(arg0 instanceof FFrameView)) {
695
            return false;
696
        }
697

    
698
        if (!this.getName().equals(((FFrameView) arg0).getName())) {
699
            return false;
700
        }
701

    
702
        if (Math.abs(this.getBoundBox().getWidth()
703
            - (((FFrameView) arg0).getBoundBox().getWidth())) > 0.05) {
704
            return false;
705
        }
706
        if (Math.abs(this.getBoundBox().getHeight()
707
            - (((FFrameView) arg0).getBoundBox().getHeight())) > 0.05) {
708
            return false;
709
        }
710

    
711
        if (!this.toString().equals(((FFrameView) arg0).toString())) {
712
            return false;
713
        }
714

    
715
        if (this.getMapContext() != null
716
            && !this.getMapContext()
717
                .equals(((FFrameView) arg0).getMapContext())) {
718
            return false;
719
        }
720

    
721
        if (this.getRotation() != ((FFrameView) arg0).getRotation()) {
722
            return false;
723
        }
724
        return true;
725
    }
726
    
727
    public void updateScaleCtrl() {
728
            NewStatusBar statusbar = PluginServices.getMainFrame().getStatusBar();
729
            MapContext mapContext = this.getMapContext();
730
            if (mapContext==null) {
731
                    return;
732
            }
733
            statusbar.setMessage("units",
734
                            PluginServices.getText(this, mapContext.getDistanceName()));
735
            statusbar.setControlValue("layout-view-change-scale",
736
                            String.valueOf(getMapContext().getScaleView()));
737
            IProjection proj = mapContext.getViewPort().getProjection();
738
            if (proj != null) {
739
                    statusbar.setMessage("projection", proj.getAbrev());
740
            } else {
741
                    statusbar.setMessage("projection", "");
742
            }
743
    }
744

    
745
    public void fullExtent() throws ReadException {
746
        setNewEnvelope(getMapContext().getFullEnvelope());
747
    }
748

    
749
    public void setPointsToZoom(Point2D px1, Point2D px2) {
750
        p1 = px1;
751
        p2 = px2;
752
    }
753

    
754
    public void movePoints(Point2D px1, Point2D px2) {
755
        double difX = -px2.getX() + px1.getX();
756
        double difY = -px2.getY() + px1.getY();
757
        if (p1 != null) {
758
            p1.setLocation(p1.getX() + difX, p1.getY() + difY);
759
            p2.setLocation(p2.getX() + difX, p2.getY() + difY);
760
        }
761
    }
762

    
763
    /**
764
     * This method deals with places where this fframeview and the cloned
765
     * fframeview (frame) are registered as listeners. The goal should be
766
     * leaving the cloned instance (frame) as listener in the same way
767
     * that 'this' instance is doing.
768
     */
769
    protected void cloneActions(FFrameView frame) {
770
    }
771

    
772
    public Object clone() throws CloneNotSupportedException {
773
            Document d = ProjectManager.getInstance().getCurrentProject().getDocuments().get(0);
774
        FFrameView frame = (FFrameView) super.clone();
775
        frame.createListeners(); // necessary to create the listeners within the right scope
776
        frame.setView(this.getView());
777

    
778
        if (grid != null) {
779
            FFrameGrid newGrid = (FFrameGrid) this.grid.clone();
780
            newGrid.setFFrameDependence(frame);
781
            frame.setGrid(newGrid);
782
        }
783
        cloneActions(frame);
784
        return frame;
785
    }
786

    
787
    public void setGrid(IFFrame grid) {
788
        this.grid = grid;
789
        this.grid.setRotation(this.getRotation());
790
    }
791

    
792
    public IFFrame getGrid() {
793
        return this.grid;
794
    }
795

    
796
    public void setRotation(double rotation) {
797
        super.setRotation(rotation);
798
        if (grid != null) {
799
            grid.setRotation(rotation);
800
        }
801
    }
802

    
803
    public void showGrid(boolean b) {
804
        showGrid = b;
805
    }
806

    
807
    public boolean isShowGrid() {
808
        return showGrid;
809
    }
810

    
811
    public void refreshOriginalExtent() {
812
    }
813

    
814
    public static void registerPersistent() {
815
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
816
        if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) {          
817
            DynStruct definition =
818
                manager.addDefinition(FFrameView.class,
819
                    PERSISTENCE_DEFINITION_NAME,
820
                    "FFrameView persistence definition", null, null); 
821
            definition.extend(manager
822
                .getDefinition(FFrame.PERSISTENCE_DEFINITION_NAME));
823

    
824
            definition.addDynFieldInt(EXTENSION_FIELD).setMandatory(false);
825
            definition.addDynFieldInt(QUALITY_FIELD).setMandatory(true);
826
            definition.addDynFieldInt(MAPUNITS_FIELD).setMandatory(true);
827
            definition.addDynFieldDouble(SCALE_FIELD).setMandatory(false);
828
            definition.addDynFieldObject(VIEW_FIELD)
829
                .setClassOfValue(ViewDocument.class).setMandatory(false);
830
            definition.addDynFieldObject(ENVELOPE_FIELD)
831
                .setClassOfValue(Envelope.class).setMandatory(false);
832
            definition.addDynFieldBoolean(SHOWGRID_FIELD).setMandatory(true);
833
            definition.addDynFieldObject(GRID_FIELD)
834
                .setClassOfValue(IFFrame.class).setMandatory(false);
835
            definition.addDynFieldBoolean(HAS_TOC).setMandatory(false);
836
            // unused fields, kept for backward compatibility
837
            definition.addDynFieldInt(MODE_FIELD).setMandatory(false);
838
            definition.addDynFieldInt(TYPESCALE_FIELD).setMandatory(false);
839
            definition.addDynFieldBoolean(BLINKED_FIELD).setMandatory(false);
840
            definition.addDynFieldObject(MAPCONTEXT_FIELD)
841
            .setClassOfValue(MapContext.class).setMandatory(false);
842
            definition.addDynFieldInt(VIEWING_FIELD).setMandatory(false);
843
        }
844
    }
845

    
846
    @Override
847
    public void loadFromState(PersistentState state)
848
        throws PersistenceException {
849
        super.loadFromState(state);
850
        b_frameInitialized = false;
851
        if (state.hasValue(EXTENT_SYNC_FIELD)) {
852
                syncExtents = state.getBoolean(EXTENT_SYNC_FIELD);
853
        }
854
        else {
855
                syncExtents = true;
856
        }
857
        if (state.hasValue(LAYER_SYNC_FIELD)) {
858
                syncLayers = state.getBoolean(LAYER_SYNC_FIELD);
859
        }
860
        else {
861
                syncLayers = true;
862
        }
863
        quality = state.getInt(QUALITY_FIELD);
864
        syncLayers = state.getBoolean(BLINKED_FIELD);
865
        mapUnits = state.getInt(MAPUNITS_FIELD);;
866
        viewDocument = (ViewDocument) state.get(VIEW_FIELD);
867
        if (state.hasValue(HAS_TOC)) {
868
                this.b_hasToc = state.getBoolean(HAS_TOC);
869
        }        
870
        if (viewDocument!=null) {
871
                this.setView(viewDocument);
872
                // it is crucial to don't persist the MapContext and get a cloned one from the View instead,
873
                // as the cloned instance is different from the one created using persistence. In particular,
874
                // the cloned one will share the EventBuffer with the original one, while persistence would
875
                // create 2 separate EventBuffers, which will then have a very stange behaviour
876
        }
877
        if (getMapContext()!=null) {
878
                double mapScale = state.getDouble(SCALE_FIELD);
879
                getMapContext().setScaleView((long)mapScale);
880
                getMapContext().getViewPort().setEnvelope(
881
                (Envelope) state.get(ENVELOPE_FIELD));
882
                if (this.getLayoutContext()!=null) {
883
                        this.getLayoutContext().setTocModel(getMapContext());
884
                }
885

    
886
        }
887
        showGrid = state.getBoolean(SHOWGRID_FIELD);
888
        grid = (IFFrame) state.get(GRID_FIELD);
889
    }
890

    
891
    @Override
892
    public void saveToState(PersistentState state) throws PersistenceException {
893
        super.saveToState(state);
894
        state.set(EXTENT_SYNC_FIELD, syncExtents);
895
        state.set(LAYER_SYNC_FIELD, syncLayers);
896
        state.set(QUALITY_FIELD, quality);
897
        state.set(MAPUNITS_FIELD, mapUnits);
898
        state.set(VIEW_FIELD, viewDocument);
899
        state.set(HAS_TOC, b_hasToc);
900

    
901
        if (getMapContext() != null
902
            && getMapContext().getViewPort().getEnvelope() != null) {
903
            state.set(ENVELOPE_FIELD, getMapContext().getViewPort()
904
                .getEnvelope());
905
            state.set(SCALE_FIELD, (double)getMapContext().getScaleView());
906
        }
907

    
908
        state.set(SHOWGRID_FIELD, showGrid);
909
        state.set(GRID_FIELD, grid);
910
    }
911
    
912
    @Override
913
    public void setBoundBox(Rectangle2D r) {
914
            super.setBoundBox(r);
915
            if (getMapContext()!=null) {
916
                    AffineTransform at = this.getLayoutContext().getAT();
917
                    getMapContext().getViewPort().setImageSize(
918
                                    new Dimension((int)getBoundingBox(at).getWidth(), (int)getBoundingBox(at).getHeight()));
919
                    getMapContext().getViewPort().setDPI(getDrawPaperDPI());
920
                    updateScaleCtrl();
921
                    // FIXME: what should we do here? should we invalidate the cache?
922
                    // should we also trigger a Layout redraw?
923
                    refresh();
924
            }
925
    }   
926

    
927
    /**
928
     * Gets the rotation of the frame
929
     * 
930
     * @return Rotation in degrees
931
     */
932
    public double getMapRotation() {
933
        return 0;
934
    }
935
    
936
        protected void invalidateLayout() {
937
                b_validCache = false;
938
                if (getLayoutContext()!=null) {
939
                        getLayoutContext().notifAllObservers();
940
                }
941
        observers.notifyObservers(this, 
942
                new DefaultLayoutNotification(LayoutNotification.LAYOUT_REFRESH));
943
        }
944
        
945
        protected void invalidateToc() {
946
                if (getLayoutContext()!=null) {
947
                        getLayoutContext().notifyTocUpdated(TocModelChangedNotification.Type.MODEL_CHANGED);
948
                }
949
        }
950

    
951
        public void refresh() {
952
        // FIXME: what should we do here? do we really need to invalidate cache??
953
            b_validCache = false;                
954
        }
955
    
956
    protected void resetListeners() {
957
                if (this.getMapContext()!=null) {
958
                        clearOwnListeners(this.getMapContext());
959
                }
960
                if (this.getView()!=null && this.getView().getMapContext()!=null) {
961
                        clearViewListeners(this.getView().getMapContext());
962
                }
963
            setListeners();
964
    }
965
    
966
    protected void setListeners() {
967
            if (getView()!=null) {
968
                    if (syncLayers) {
969
                            getView().getMapContext().addLayerListener(viewDocListener);
970
                            getView().getMapContext().getLayers().addLayerCollectionListener(viewDocListener);
971
                            getView().getMapContext().addAtomicEventListener(viewDocListener);
972
                    }
973
                    if (getExtentSynced()) {
974
                            getView().getMapContext().getViewPort().addViewPortListener(viewDocListener);
975
                    }
976
            }
977
            if (getMapContext()!=null) {
978
                    getMapContext().addLayerListener(ownMapContextListener);
979
                    getMapContext().getLayers().addLayerCollectionListener(ownMapContextListener);
980
                    getMapContext().getViewPort().addViewPortListener(ownMapContextListener);
981
            }
982
    }
983
    protected void clearOwnListeners(MapContext mapContext) {
984
            mapContext.removeLayerListener(ownMapContextListener);
985
            mapContext.getViewPort().removeViewPortListener(ownMapContextListener);
986
            mapContext.getLayers().removeLayerCollectionListener(ownMapContextListener);
987
    }
988
    protected void clearViewListeners(MapContext mapContext) {
989
            mapContext.removeLayerListener(viewDocListener);
990
            mapContext.getViewPort().removeViewPortListener(viewDocListener);
991
            mapContext.getLayers().removeLayerCollectionListener(viewDocListener);
992
            mapContext.removeAtomicEventListener(viewDocListener);
993
    }
994
    
995
    /*
996
     * (non-Javadoc)
997
     * @see org.gvsig.tools.dispose.Disposable#dispose()
998
     */
999
        public void dispose() {
1000
                try {
1001
                        if (this.getMapContext()!=null) {
1002
                                clearOwnListeners(this.getMapContext());
1003
                        }
1004
                        if (this.getView()!=null && this.getView().getMapContext()!=null) {
1005
                                clearViewListeners(this.getView().getMapContext());
1006
                        }
1007
                }
1008
                catch (Exception ex) {}
1009
                this.viewDocument = null;
1010
                this.mapContext = null;
1011
        }
1012

    
1013
        public void frameRemoved() {
1014
                if (mapContext!=null) {
1015
                        clearOwnListeners(mapContext);
1016
                }
1017
                if (this.getView()!=null && this.getView().getMapContext()!=null) {
1018
                        clearViewListeners(this.getView().getMapContext());
1019
                }
1020
                if (b_hasToc && getLayoutContext()!=null) {
1021
                        getLayoutContext().setTocModel(null);
1022
                }
1023
                m_image = null; // FIXME: we could instead move it to a LRU cache to keep the last N images
1024
        }
1025

    
1026
        public void frameAdded() {
1027
                setListeners();
1028
                setTocModel();
1029
                updateScaleCtrl();
1030
        }
1031
        
1032
        public void setHasToc(boolean hasToc) {
1033
                this.b_hasToc = hasToc;
1034
                setTocModel();
1035
        }
1036
        
1037
        protected void setTocModel() {
1038
                if (getLayoutContext()!=null) {
1039
                        if (b_hasToc && getMapContext()!=null) {
1040
                                getLayoutContext().setTocModel(getMapContext());
1041
                        }
1042
                        else {
1043
                                getLayoutContext().setTocModel(null);
1044
                        }
1045
                }
1046
        }
1047
        
1048
        @Override
1049
        protected void doSetSelected(int selectedStatus) {
1050
                boolean oldSelectedStatus = isSelected();
1051
                super.doSetSelected(selectedStatus);
1052
                if (!oldSelectedStatus && isSelected()) { // changed from not selected to selected
1053
                        setTocModel();
1054
                        updateScaleCtrl();
1055
                }
1056
        }
1057
        
1058
        public boolean getLayerSynced() {
1059
                return syncLayers;
1060
        }
1061

    
1062
        public void setLayerSynced(boolean synced) {
1063
        syncLayers = synced;
1064
        resetListeners();
1065
        }
1066

    
1067
        public boolean getExtentSynced() {
1068
                return syncExtents;
1069
        }
1070

    
1071
        public void setExtentSynced(boolean synced) {
1072
                syncExtents = synced;
1073
        resetListeners();
1074
        }
1075

    
1076
        private class ViewDocListener
1077
        implements ViewPortListener, LegendListener, LayerCollectionListener, AtomicEventListener {
1078

    
1079
                public void extentChanged(ExtentEvent e) {
1080
                        if (!b_updating && getExtentSynced()) {
1081
                                if (!b_frameInitialized) {
1082
                                        b_frameInitialized = true;
1083
                                        return;
1084
                                }
1085
                                if (getMapContext()!=null) {
1086
                                        b_updating = true;
1087
                                        getMapContext().getViewPort().setEnvelope(e.getNewExtent());
1088
                                        updateScaleCtrl();
1089
                                        invalidateLayout();
1090
                                        b_updating = false;
1091
                                }
1092
                        }                        
1093
                }
1094

    
1095
                public void backColorChanged(ColorEvent e) {
1096
                        if (!b_updating && syncLayers) {
1097
                                if (getMapContext()!=null) {
1098
                                        b_updating = true;
1099
                                        mapContext.getViewPort().setBackColor(e.getNewColor());
1100
                                        invalidateLayout();
1101
                                        b_updating = true;
1102
                                }
1103
                        }
1104
                }
1105

    
1106
                public void projectionChanged(ProjectionEvent e) {
1107
                        if (!b_updating && getExtentSynced()) {
1108
                                if (getMapContext()!=null) {
1109
                                        b_updating = true;
1110
                                        getMapContext().getViewPort().setProjection(e.getNewProjection());
1111
                                        invalidateLayout();
1112
                                        // FIXME: force also a view redraw someway??
1113
                                        b_updating = false;
1114
                                }
1115
                        }
1116
                }
1117

    
1118
                public void conditionalRedraw() {
1119
                        if (!b_updating && syncLayers) {
1120
                                b_updating = true;
1121
                                invalidateLayout();
1122
                                // the view should also receive the event and update automatically
1123
                                b_updating = false;
1124
                        }                        
1125
                }
1126

    
1127
                public void legendChanged(LegendChangedEvent e) {
1128
                        conditionalRedraw();
1129
                        invalidateToc();
1130
                }
1131

    
1132
                public void layerAdded(LayerCollectionEvent e) {
1133
                        conditionalRedraw();
1134
                        invalidateToc();
1135
                }
1136

    
1137
                public void layerMoved(LayerPositionEvent e) {
1138
                        conditionalRedraw();
1139
                        invalidateToc();
1140
                }
1141

    
1142
                public void layerRemoved(LayerCollectionEvent e) {
1143
                        conditionalRedraw();
1144
                        invalidateToc();
1145
                }
1146

    
1147
                public void layerAdding(LayerCollectionEvent e)
1148
                                throws CancelationException {
1149
                        // nothing needed
1150
                }
1151

    
1152
                public void layerMoving(LayerPositionEvent e)
1153
                                throws CancelationException {
1154
                        // nothing needed
1155
                }
1156

    
1157
                public void layerRemoving(LayerCollectionEvent e)
1158
                                throws CancelationException {
1159
                        // nothing needed
1160
                }
1161

    
1162
                public void visibilityChanged(LayerCollectionEvent e)
1163
                                throws CancelationException {
1164
                        // AtomicEvent is catching visibility changes instead of this one,
1165
                        // as this event is not being received. Maybe is only triggered if the
1166
                        // visibility of the whole group changes??
1167
                        conditionalRedraw();
1168
                        invalidateToc();
1169
                }
1170

    
1171
                public void atomicEvent(AtomicEvent e) {
1172
                        boolean needRedraw = false;
1173
                        // not all the events require a fframeview redraw
1174
                        for (int i=e.getLayerEvents().length-1; i>=0; i--) {
1175
                                FMapEvent at = e.getEvent(i);
1176
                                if (at instanceof LayerEvent) {
1177
                                        if (at.getEventType()==LayerEvent.DRAW_VALUES_CHANGED) {
1178
                                                needRedraw = true;
1179
                                                break;
1180
                                        }
1181
                                }
1182
                        }
1183
                        if (needRedraw) {
1184
                                conditionalRedraw();
1185
                        }
1186
                        invalidateToc();
1187
                }
1188
        }
1189

    
1190
        private class OwnMapContextListener
1191
                implements ViewPortListener, LegendListener, LayerCollectionListener {
1192

    
1193
                public void extentChanged(ExtentEvent e) {
1194
                        if (!b_drawing && !b_updating) {
1195
                                if (getView()!=null) {
1196
                                        b_updating = true;
1197
                                        if (getExtentSynced()){
1198
                                                getView().getMapContext().getViewPort().setEnvelope(e.getNewExtent());
1199
                                        }
1200
                                        updateScaleCtrl();
1201
                                        invalidateLayout();
1202
                                        b_updating = false;
1203
                                }
1204
                        }                        
1205
                }
1206

    
1207
                public void backColorChanged(ColorEvent e) {
1208
                        if (!b_updating) {
1209
                                if (getView()!=null) {
1210
                                        b_updating = true;
1211
                                        if (getLayerSynced()) {
1212
                                                getView().getMapContext().getViewPort().setBackColor(e.getNewColor());
1213
                                        }
1214
                                        invalidateLayout();
1215
                                        b_updating = false;
1216
                                }
1217
                        }
1218
                }
1219

    
1220
                public void projectionChanged(ProjectionEvent e) {
1221
                        if (!b_updating && getExtentSynced()) {
1222
                                if (getView()!=null) {
1223
                                        b_updating = true;
1224
                                        if (getLayerSynced()) {
1225
                                                getView().getMapContext().getViewPort().setProjection(e.getNewProjection());
1226
                                        }
1227
                                        invalidateLayout();
1228
                                        // FIXME: force also a view redraw someway??
1229
                                        b_updating = false;
1230
                                }
1231
                        }
1232
                }
1233

    
1234
                public void conditionalRedraw() {
1235
                        if (!b_updating) {
1236
                                b_updating = true;
1237
                                invalidateLayout();
1238
                                // the view should also receive the event and update automatically
1239
                                b_updating = false;
1240
                        }
1241
                }
1242

    
1243
                public void legendChanged(final LegendChangedEvent e) {
1244
                        conditionalRedraw();
1245
                        invalidateToc();
1246
                }
1247

    
1248
                public void layerAdded(final LayerCollectionEvent e) {
1249
                        // necessary to set an envelope when the first layer is added
1250
                        if (!b_updating && getMapContext().getViewPort().getEnvelope()==null) {
1251
                                try {
1252
                                        b_updating = true;
1253
                                        fullExtent();
1254
                                        
1255
                                } catch (ReadException e1) {
1256
                                } finally {
1257
                                        b_updating = false;
1258
                                }
1259
                        }
1260
                        conditionalRedraw();
1261
                        invalidateToc();
1262
                }
1263

    
1264
                public void layerMoved(final LayerPositionEvent e) {
1265
                        conditionalRedraw();
1266
                        invalidateToc();
1267
                }
1268

    
1269
                public void layerRemoved(final LayerCollectionEvent e) {
1270
                        conditionalRedraw();
1271
                        invalidateToc();
1272
                }
1273

    
1274
                public void layerAdding(LayerCollectionEvent e)
1275
                                throws CancelationException {
1276
                        // nothing neededO
1277

    
1278
                }
1279

    
1280
                public void layerMoving(LayerPositionEvent e)
1281
                                throws CancelationException {
1282
                        // nothing needed
1283

    
1284
                }
1285

    
1286
                public void layerRemoving(LayerCollectionEvent e)
1287
                                throws CancelationException {
1288
                        // nothing needed
1289

    
1290
                }
1291

    
1292
                public void visibilityChanged(LayerCollectionEvent e)
1293
                                throws CancelationException {
1294
                        conditionalRedraw();
1295
                }
1296
        }
1297
}