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

History | View | Annotate | Download (42.9 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

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

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

    
187
        return "FFrameView " + num + ": " + getView().getName();
188
    }
189

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

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

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

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

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

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

    
304
    }
305

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

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

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

    
393
        int scale = (int) (r.getWidth() / 24);
394
        Font f = new Font("SansSerif", Font.PLAIN, scale);
395
        g.setFont(f);
396

    
397
        g.drawString(msg, (int) (r.getCenterX() - ((msg.length() * scale) / 4)),
398
            (int) (r.getCenterY()));        
399
    }
400

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

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

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

    
461
        // paint the MapContext on m_image, if not already cached
462
        createImage(affineTransform, drawWidth, drawHeight, mapOrigin);
463

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

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

    
489
                    viewPort.setDPI(getDrawPaperDPI());
490
                viewPort.setImageSize(new Dimension(width, height)); 
491
            
492
            m_image =
493
                    new BufferedImage(
494
                                    width,
495
                                    height,
496
                                    BufferedImage.TYPE_INT_ARGB);
497

    
498
            Graphics2D gimg = (Graphics2D) m_image.createGraphics();
499
            getMapContext().draw(m_image, gimg, getScale());
500
            gimg.dispose();
501
            b_validCache = true;
502
        } 
503

    
504
    }
505
    
506
    protected void drawImage(Graphics2D g, BufferedImage image,
507
                    Rectangle2D.Double visibleRectangle) {
508

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
794
    public IFFrame getGrid() {
795
        return this.grid;
796
    }
797

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

    
805
    public void showGrid(boolean b) {
806
        showGrid = b;
807
    }
808

    
809
    public boolean isShowGrid() {
810
        return showGrid;
811
    }
812

    
813
    public void refreshOriginalExtent() {
814
    }
815

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

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

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

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

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

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

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

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

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

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

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

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

    
1069
        public boolean getExtentSynced() {
1070
                return syncExtents;
1071
        }
1072

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

    
1078
        private class ViewDocListener
1079
        implements ViewPortListener, LegendListener, LayerCollectionListener, AtomicEventListener {
1080

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

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

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

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

    
1129
                public void legendChanged(LegendChangedEvent e) {
1130
                        conditionalRedraw();
1131
                        invalidateToc();
1132
                }
1133

    
1134
                public void layerAdded(LayerCollectionEvent e) {
1135
                        conditionalRedraw();
1136
                        invalidateToc();
1137
                }
1138

    
1139
                public void layerMoved(LayerPositionEvent e) {
1140
                        conditionalRedraw();
1141
                        invalidateToc();
1142
                }
1143

    
1144
                public void layerRemoved(LayerCollectionEvent e) {
1145
                        conditionalRedraw();
1146
                        invalidateToc();
1147
                }
1148

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

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

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

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

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

    
1192
        private class OwnMapContextListener
1193
                implements ViewPortListener, LegendListener, LayerCollectionListener {
1194

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

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

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

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

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

    
1250
                public void layerAdded(final LayerCollectionEvent e) {
1251
                        // 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
                        conditionalRedraw();
1263
                        invalidateToc();
1264
                }
1265

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

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

    
1276
                public void layerAdding(LayerCollectionEvent e)
1277
                                throws CancelationException {
1278
                        // nothing neededO
1279

    
1280
                }
1281

    
1282
                public void layerMoving(LayerPositionEvent e)
1283
                                throws CancelationException {
1284
                        // nothing needed
1285

    
1286
                }
1287

    
1288
                public void layerRemoving(LayerCollectionEvent e)
1289
                                throws CancelationException {
1290
                        // nothing needed
1291

    
1292
                }
1293

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