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

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.Area;
33
import java.awt.geom.NoninvertibleTransformException;
34
import java.awt.geom.Point2D;
35
import java.awt.geom.Rectangle2D;
36
import java.awt.image.BufferedImage;
37

    
38
import org.cresques.cts.IProjection;
39
import org.gvsig.andami.PluginServices;
40
import org.gvsig.andami.messages.NotificationManager;
41
import org.gvsig.andami.ui.mdiFrame.NewStatusBar;
42
import org.gvsig.app.project.Project;
43
import org.gvsig.app.project.ProjectManager;
44
import org.gvsig.app.project.documents.Document;
45
import org.gvsig.app.project.documents.layout.DefaultLayoutNotification;
46
import org.gvsig.app.project.documents.layout.FLayoutFunctions;
47
import org.gvsig.app.project.documents.layout.FLayoutUtilities;
48
import org.gvsig.app.project.documents.layout.LayoutNotification;
49
import org.gvsig.app.project.documents.layout.TocModelChangedNotification;
50
import org.gvsig.app.project.documents.view.ViewDocument;
51
import org.gvsig.compat.print.PrintAttributes;
52
import org.gvsig.fmap.dal.exception.ReadException;
53
import org.gvsig.fmap.geom.Geometry;
54
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
55
import org.gvsig.fmap.geom.GeometryLocator;
56
import org.gvsig.fmap.geom.GeometryManager;
57
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
58
import org.gvsig.fmap.geom.primitive.Envelope;
59
import org.gvsig.fmap.mapcontext.MapContext;
60
import org.gvsig.fmap.mapcontext.MapContextException;
61
import org.gvsig.fmap.mapcontext.ViewPort;
62
import org.gvsig.fmap.mapcontext.events.AtomicEvent;
63
import org.gvsig.fmap.mapcontext.events.ColorEvent;
64
import org.gvsig.fmap.mapcontext.events.ExtentEvent;
65
import org.gvsig.fmap.mapcontext.events.FMapEvent;
66
import org.gvsig.fmap.mapcontext.events.ProjectionEvent;
67
import org.gvsig.fmap.mapcontext.events.listeners.AtomicEventListener;
68
import org.gvsig.fmap.mapcontext.events.listeners.ViewPortListener;
69
import org.gvsig.fmap.mapcontext.layers.CancelationException;
70
import org.gvsig.fmap.mapcontext.layers.LayerCollectionEvent;
71
import org.gvsig.fmap.mapcontext.layers.LayerCollectionListener;
72
import org.gvsig.fmap.mapcontext.layers.LayerEvent;
73
import org.gvsig.fmap.mapcontext.layers.LayerPositionEvent;
74
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendChangedEvent;
75
import org.gvsig.fmap.mapcontext.rendering.legend.events.listeners.LegendListener;
76
import org.gvsig.gui.beans.Messages;
77
import org.gvsig.tools.ToolsLocator;
78
import org.gvsig.tools.dynobject.DynStruct;
79
import org.gvsig.tools.persistence.PersistenceManager;
80
import org.gvsig.tools.persistence.PersistentState;
81
import org.gvsig.tools.persistence.exception.PersistenceException;
82
import org.slf4j.Logger;
83
import org.slf4j.LoggerFactory;
84

    
85
/**
86
 * FFrame used for embedding a View in the Layout. The View is not actually
87
 * inserted on the Layout, but it is used together with the MapContext
88
 * in order do draw an image which is then painted on the FFrame. Therefore,
89
 * no MapControl is used in current implementation, but a similar behavior
90
 * is simulated by the FFrameView. The original MapContext is cloned when
91
 * assigned to the FFrameView, which is then used for drawing.
92
 * 
93
 * The FFrameView and the associated View can be synchronized, depending
94
 * on the values of {@link #getTypeScale()} and {@link #getLinked()}.
95
 * 
96
 * The main synchronization logic is kept on two internal classes: 
97
 * {@link OwnMapContextListener} and {@link ViewDocListener}. The first one
98
 * listens for events on the FFrameView and synchronizes the View accordingly.
99
 * The second one listens for events on the View and synchronizes the FFrameView
100
 * accordingly. There synchronization process is flagged using
101
 * {@link #b_updating} and {@link #b_updating}, in order
102
 * to avoid incurring on infinite synchronization loops. 
103
 * 
104
 * @author Vicente Caballero Navarro
105
 * @author Cesar Martinez Izquierdo
106
 */
107
public class FFrameView extends FFrame implements IFFrameUseProject, IFFrameUseFMap {
108

    
109
    public static final String PERSISTENCE_DEFINITION_NAME = "FFrameView";
110

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

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

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

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

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

    
165
        protected AffineTransform originalGraphicsAT = null;
166
        protected Rectangle originalClip = null;
167

    
168

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

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

    
192
        return "FFrameView " + num + ": " + getView().getName();
193
    }
194

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

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

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

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

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

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

    
309
    }
310

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

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

    
340
    /**
341
     * Draws the FFrameView on the provided Graphics, according to the
342
     * provided affine transform and the visible rectangle.
343
     * 
344
     * @param g Graphics2D
345
     * @param at Affine transform to translate sheet coordinates (in cm)
346
     *                                 to screen coordinates (in pixels)
347
     * @param visibleLayoutDocRect visible rectangle
348
     * @param imgBase Image used to speed up the drawing process
349
     */
350
    public void draw(Graphics2D g, AffineTransform at, Rectangle2D visibleLayoutDocRect, BufferedImage imgBase) {
351
        Rectangle2D.Double fframeViewRect = getBoundingBox(at);
352
        Rectangle2D.Double visibleArea = (Rectangle2D.Double) getVisibleRect(visibleLayoutDocRect, fframeViewRect);
353
        if (visibleArea==null) {
354
                return;
355
        }
356
        preDraw(g, fframeViewRect, visibleArea);
357
        if (getMapContext() == null) {
358
                drawEmpty(g);
359
        } else {
360
                if (FLayoutUtilities.hasEditingLayers(getView())) {
361

    
362
                        /*
363
                         * We are not drawing if any layer is in editing mode
364
                         */
365
                        drawMessage(g, Messages.getText(
366
                                        "_Cannot_draw_view_if_layers_in_editing_mode"));
367

    
368
                } else {
369
                        if (getQuality() == PRESENTATION) {
370
                                try {
371
                                        drawPresentation(g, at, fframeViewRect, visibleArea, imgBase);
372
                                } catch (Exception exc) {
373
                                        drawMessage(g, FLayoutFunctions.getLastMessage(exc));
374
                                }
375

    
376
                        } else {
377
                                drawDraft(g);
378
                        }               
379
                }
380
                updateScaleCtrl(); // we need to update the scale whenever the window gets activated
381
        }
382
        postDraw(g, fframeViewRect, at); 
383
        if (showGrid && grid != null) {           
384
            grid.draw(g, at, visibleLayoutDocRect, imgBase);
385
        }    
386
    }
387
    
388
    private void drawMessage(Graphics2D g, String msg) {
389
        
390
        Rectangle2D r = getBoundingBox(null);
391
        g.setColor(Color.lightGray);
392
        g.fillRect((int) r.getX(), (int) r.getY(), (int) r.getWidth(),
393
            (int) r.getHeight());
394
        g.setColor(Color.darkGray);
395
        g.setStroke(new BasicStroke(2));
396
        g.drawRect((int) r.getX(), (int) r.getY(), (int) r.getWidth(),
397
            (int) r.getHeight());
398
        g.setColor(Color.black);
399

    
400
        int scale = (int) (r.getWidth() / 24);
401
        Font f = new Font("SansSerif", Font.PLAIN, scale);
402
        g.setFont(f);
403

    
404
        g.drawString(msg, (int) (r.getCenterX() - ((msg.length() * scale) / 4)),
405
            (int) (r.getCenterY()));        
406
    }
407

    
408
    /**
409
     * Gets the visible envelope, in map coordinates
410
     * 
411
     * @param fframeViewRect Rectangle defining the bounding box of the
412
     * FFrameView, in screen coordinates
413
     * @param visiblefframeViewRect Rectangle defining the bounding box
414
     * of the visible area of the fframeView, in screen coordinates
415
     * @return
416
     */
417
    protected Envelope getVisibleEnvelope(Rectangle2D.Double fframeViewRect,
418
            Rectangle2D.Double visiblefframeViewRect) {
419
            Envelope oldEnv = getMapContext().getViewPort().getAdjustedEnvelope();
420
            double widthFactor = ((int)visiblefframeViewRect.width) / fframeViewRect.width;
421
            double heightFactor = ((int)visiblefframeViewRect.height) / fframeViewRect.height;
422
            
423
            double newWidth = oldEnv.getLength(0)*widthFactor;
424
            double newHeight = oldEnv.getLength(1)*heightFactor;
425
        
426
        double translateX = visiblefframeViewRect.x - fframeViewRect.x;
427
        double translateY = visiblefframeViewRect.y - fframeViewRect.y;
428
        double translateFactorX = translateX / fframeViewRect.width;
429
        double translateFactorY = translateY / fframeViewRect.height;
430
        
431
        double newX = oldEnv.getMinimum(0) + translateFactorX*oldEnv.getLength(0);
432
        double newMaxY =  oldEnv.getMaximum(1) - translateFactorY*oldEnv.getLength(1);
433
        double newMaxX = newX + newWidth;
434
        double newY = newMaxY - newHeight;
435

    
436
        Envelope newEnv = null;
437
                try {
438
                        newEnv = geomManager.createEnvelope(newX, newY, newMaxX, newMaxY, SUBTYPES.GEOM2D);
439
                } catch (CreateEnvelopeException e) {
440
                        logger.error("Error calculating visible extent", e);
441
                }
442
        return newEnv;
443
                    
444
    }
445
    
446
    protected void drawPresentation(
447
        Graphics2D g,
448
        AffineTransform affineTransform,
449
        Rectangle2D.Double fframeViewRect,
450
        Rectangle2D.Double visibleRect,
451
        BufferedImage imgBase) throws Exception {
452
            
453
            b_drawing = true;
454
            int drawWidth = (int)visibleRect.width;
455
            int drawHeight = (int)visibleRect.height;
456

    
457
            Envelope oldEnvelope = null;
458
        if (!visibleRect.equals(fframeViewRect)) {
459
                // if visible area is smaller than the fframe, we will only draw this area,
460
                // so we need to tell the ViewPort the image size and extent for drawing,
461
                // and restore the real extent after drawing
462
            oldEnvelope = getMapContext().getViewPort().getEnvelope();
463
            if (oldEnvelope==null) {
464
                    return;
465
            }
466
                Envelope newEnvelope = getVisibleEnvelope(fframeViewRect, visibleRect);
467
                // image size must be set before the envelope, as it has influence on the adjustedExtent
468
                getMapContext().getViewPort().setImageSize(new Dimension(drawWidth, drawHeight));
469
                getMapContext().getViewPort().setEnvelope(newEnvelope);
470
        }
471
        
472
        // map origin should be calculated using the full fframeview, as the visible position will be relative
473
        Point mapOrigin = new Point((int)fframeViewRect.getMinX(), (int)fframeViewRect.getMaxY());
474

    
475
        // paint the MapContext on m_image, if not already cached
476
        createImage(affineTransform, drawWidth, drawHeight, mapOrigin);
477

    
478
        //Draw the created image
479
        drawImage(g, m_image, visibleRect);
480
        
481
        if (oldEnvelope!=null) {
482
                // restore real envelope and image size
483
                getMapContext().getViewPort().setImageSize(new Dimension((int)fframeViewRect.width, (int) fframeViewRect.height));
484
                getMapContext().getViewPort().setEnvelope(oldEnvelope);
485
        }
486
        
487
        scaleAnt = affineTransform.getScaleX();
488
        origin = mapOrigin;
489
        b_drawing = false;
490
    }
491
    
492
    protected void createImage(AffineTransform affineTransform,
493
                    int width, int height, Point mapOrigin) throws ReadException, MapContextException {
494
            ViewPort viewPort = this.getMapContext().getViewPort();
495

    
496
        //If the image has to be created...
497
            if (origin == null ||
498
                            !origin.equals(mapOrigin) ||
499
                            affineTransform.getScaleX() != scaleAnt ||
500
                            m_image == null ||
501
                            !b_validCache) { 
502

    
503
                    viewPort.setDPI(getDrawPaperDPI());
504
                viewPort.setImageSize(new Dimension(width, height)); 
505
            
506
            m_image =
507
                    new BufferedImage(
508
                                    width,
509
                                    height,
510
                                    BufferedImage.TYPE_INT_ARGB);
511

    
512
            Graphics2D gimg = (Graphics2D) m_image.createGraphics();
513
            getMapContext().draw(m_image, gimg, getScale());
514
            gimg.dispose();
515
            b_validCache = true;
516
        } 
517

    
518
    }
519
    
520
    protected void drawImage(Graphics2D g, BufferedImage image,
521
                    Rectangle2D.Double visibleRectangle) {
522

    
523
            Color theBackColor = getMapContext().getViewPort().getBackColor();
524
        if (theBackColor != null) {
525
            g.setColor(theBackColor);
526
            g.fillRect((int) visibleRectangle.x, (int) visibleRectangle.y,
527
                            (int)visibleRectangle.width,
528
                            (int)visibleRectangle.height);
529
        }
530
        g.drawImage(m_image, 
531
                        (int) visibleRectangle.x,
532
                        (int) visibleRectangle.y,
533
                        null);            
534
    }
535

    
536
    protected void preDraw(Graphics2D g, Rectangle2D.Double fframeViewRect, Rectangle2D.Double visibleRect){
537
            originalGraphicsAT = (AffineTransform) g.getTransform().clone();
538
            
539
        if (g.getClipBounds() != null) {
540
            originalClip = (Rectangle) g.getClipBounds().clone();
541
        }
542
        AffineTransform rotationAT = getRotationAT();
543
        if (rotationAT!=null) {
544
                g.transform(rotationAT);
545
        }
546
        g.setClip((int) visibleRect.getMinX(), (int) visibleRect.getMinY(),
547
            (int) visibleRect.getWidth(), (int) visibleRect.getHeight());
548
    }
549
    
550
    protected void postDraw(Graphics2D g, Rectangle2D.Double fframeViewRect, AffineTransform at){
551
            g.setTransform(originalGraphicsAT);
552
        if (getMapContext() != null) {
553
            setATMap(getMapContext().getViewPort().getAffineTransform());
554
        }
555
        if (originalClip != null) {
556
            g.setClip(originalClip.x, originalClip.y, originalClip.width, originalClip.height);
557
        }            
558
    }
559

    
560
    public void print(Graphics2D g, AffineTransform at, Geometry geom,
561
        PrintAttributes printAttributes) {
562
        Rectangle2D.Double rectangleLayout = getBoundingBox(at);  
563
        
564
        preDraw(g, rectangleLayout, rectangleLayout);
565
        print(g, at, printAttributes);
566
        postDraw(g, rectangleLayout, at);
567
        if (showGrid && grid != null) {
568
            grid.print(g, at, geom, printAttributes);
569
        }    
570
    }
571

    
572
    protected void print(Graphics2D g, AffineTransform at, PrintAttributes printAttributes) {
573
        Rectangle2D.Double layoutRectangle = getBoundingBox(at);
574
        
575
        // FIXME: should we clone the mapcontext and viewport before printing ??
576
        // otherwise we will probably have unexpected results if the user modifies
577
        // the layout while printing
578
        ViewPort viewPort = this.getMapContext().getViewPort();
579
        
580
        Point2D old_offset = viewPort.getOffset();
581
        Dimension old_imgsize = viewPort.getImageSize();
582
        
583
        viewPort.setOffset(new Point2D.Double(layoutRectangle.x, layoutRectangle.y));
584
        viewPort.setImageSize(new Dimension((int) layoutRectangle.width, (int) layoutRectangle.height));
585

    
586
        //Draw the backgroung color of the map
587
        Color theBackColor = viewPort.getBackColor();
588
        if (theBackColor != null) {
589
            g.setColor(theBackColor);
590
            g.fillRect((int) layoutRectangle.x, (int) layoutRectangle.y, viewPort
591
                    .getImageWidth(), viewPort
592
                    .getImageHeight());
593
        }        
594
        
595
        //Print the map
596
        try {
597
            this.getMapContext().print(g, getScale(), printAttributes);
598
        } catch (ReadException e) {
599
            NotificationManager.addError(e.getMessage(), e);
600
        } catch (MapContextException e) {
601
            NotificationManager.addError(e.getMessage(), e);
602
        }      
603
        
604
        // Restore offset, imgsize
605
        viewPort.setOffset(old_offset);
606
        viewPort.setImageSize(old_imgsize);
607
    }
608

    
609
    /**
610
     * Rellena la unidad de medida en la que est? la vista.
611
     * 
612
     * @param i
613
     *            entero que representa la unidad de medida de la vista.
614
     */
615
    public void setMapUnits(int i) {
616
        mapUnits = i;
617
    }
618

    
619
    /**
620
     * Obtiene la unidad de medida en la que est? la vista.
621
     * 
622
     * @return Unidad de medida.
623
     */
624
    public int getMapUnits() {
625
        return mapUnits;
626
    }
627

    
628
    /**
629
     * Devuelve la escala seg?n el tipo de escala que se haya seleccionado al
630
     * a?adida la vista.
631
     * 
632
     * @return escala.
633
     */
634
    public long getScale() {
635
            return (long) getMapContext().getScaleView();
636
    }
637

    
638
    /**
639
     * Inserta la imagen para repintar el FFrameView.
640
     * 
641
     * @param bi
642
     *            Imagen para repintar.
643
     */
644
    public void setBufferedImage(BufferedImage bi) {
645
        m_image = bi;
646
    }
647

    
648
    /**
649
     * Devuelve la imagen para repintar.
650
     * 
651
     * @return Imagen para repintar.
652
     */
653
    public BufferedImage getBufferedImage() {
654
        return m_image;
655
    }
656

    
657
    /**
658
     * Devuelve la MAtriz de transformaci?n utilizada por la FFrameView.
659
     * 
660
     * @return MAtriz de transformaci?n.
661
     */
662
    public AffineTransform getATMap() {
663
        return mapAT;
664
    }
665

    
666
    /**
667
     * Inserta la matriz de transformaci?n.
668
     * 
669
     * @param transform
670
     *            Matriz de transformaci?n.
671
     */
672
    public void setATMap(AffineTransform transform) {
673
        mapAT = transform;
674
    }
675

    
676
    /**
677
     * Inserta el proyecto.
678
     * 
679
     * @param p
680
     *            Proyecto.
681
     */
682
    public void setProject(Project p) {
683
        project = p;
684
    }
685

    
686
    /**
687
     * @see org.gvsig.app.project.documents.layout.fframes.IFFrame#getNameFFrame()
688
     */
689
    public String getNameFFrame() {
690
        return PluginServices.getText(this, "Vista") + num;
691
    }
692

    
693
    public String getName() {
694
        return PERSISTENCE_DEFINITION_NAME;
695
    }
696

    
697
    /**
698
     * DOCUMENT ME!
699
     * 
700
     * @param arg0
701
     *            DOCUMENT ME!
702
     * 
703
     * @return DOCUMENT ME!
704
     */
705
    public boolean compare(Object arg0) {
706
        if (!(arg0 instanceof FFrameView)) {
707
            return false;
708
        }
709

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

    
714
        if (Math.abs(this.getBoundBox().getWidth()
715
            - (((FFrameView) arg0).getBoundBox().getWidth())) > 0.05) {
716
            return false;
717
        }
718
        if (Math.abs(this.getBoundBox().getHeight()
719
            - (((FFrameView) arg0).getBoundBox().getHeight())) > 0.05) {
720
            return false;
721
        }
722

    
723
        if (!this.toString().equals(((FFrameView) arg0).toString())) {
724
            return false;
725
        }
726

    
727
        if (this.getMapContext() != null
728
            && !this.getMapContext()
729
                .equals(((FFrameView) arg0).getMapContext())) {
730
            return false;
731
        }
732

    
733
        if (this.getRotation() != ((FFrameView) arg0).getRotation()) {
734
            return false;
735
        }
736
        return true;
737
    }
738
    
739
    public void updateScaleCtrl() {
740
            NewStatusBar statusbar = PluginServices.getMainFrame().getStatusBar();
741
            MapContext mapContext = this.getMapContext();
742
            if (mapContext==null) {
743
                    return;
744
            }
745
            statusbar.setMessage("units",
746
                            PluginServices.getText(this, mapContext.getDistanceName()));
747
            statusbar.setControlValue("layout-view-change-scale",
748
                            String.valueOf(getMapContext().getScaleView()));
749
            IProjection proj = mapContext.getViewPort().getProjection();
750
            if (proj != null) {
751
                    statusbar.setMessage("projection", proj.getAbrev());
752
            } else {
753
                    statusbar.setMessage("projection", "");
754
            }
755
    }
756

    
757
    public void fullExtent() throws ReadException {
758
        setNewEnvelope(getMapContext().getFullEnvelope());
759
    }
760

    
761
    public void setPointsToZoom(Point2D px1, Point2D px2) {
762
        p1 = px1;
763
        p2 = px2;
764
    }
765

    
766
    public void movePoints(Point2D px1, Point2D px2) {
767
        double difX = -px2.getX() + px1.getX();
768
        double difY = -px2.getY() + px1.getY();
769
        if (p1 != null) {
770
            p1.setLocation(p1.getX() + difX, p1.getY() + difY);
771
            p2.setLocation(p2.getX() + difX, p2.getY() + difY);
772
        }
773
    }
774

    
775
    /**
776
     * This method deals with places where this fframeview and the cloned
777
     * fframeview (frame) are registered as listeners. The goal should be
778
     * leaving the cloned instance (frame) as listener in the same way
779
     * that 'this' instance is doing.
780
     */
781
    protected void cloneActions(FFrameView frame) {
782
    }
783

    
784
    public Object clone() throws CloneNotSupportedException {
785
            Document d = ProjectManager.getInstance().getCurrentProject().getDocuments().get(0);
786
        FFrameView frame = (FFrameView) super.clone();
787
        frame.createListeners(); // necessary to create the listeners within the right scope
788
        frame.setView(this.getView());
789

    
790
        if (grid != null) {
791
            FFrameGrid newGrid = (FFrameGrid) this.grid.clone();
792
            newGrid.setFFrameDependence(frame);
793
            frame.setGrid(newGrid);
794
        }
795
        cloneActions(frame);
796
        return frame;
797
    }
798

    
799
    public void setGrid(IFFrame grid) {
800
        this.grid = grid;
801
        this.grid.setRotation(this.getRotation());
802
    }
803

    
804
    public IFFrame getGrid() {
805
        return this.grid;
806
    }
807

    
808
    public void setRotation(double rotation) {
809
        super.setRotation(rotation);
810
        if (grid != null) {
811
            grid.setRotation(rotation);
812
        }
813
    }
814

    
815
    public void showGrid(boolean b) {
816
        showGrid = b;
817
    }
818

    
819
    public boolean isShowGrid() {
820
        return showGrid;
821
    }
822

    
823
    public void refreshOriginalExtent() {
824
    }
825

    
826
    public static void registerPersistent() {
827
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
828
        if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) {          
829
            DynStruct definition =
830
                manager.addDefinition(FFrameView.class,
831
                    PERSISTENCE_DEFINITION_NAME,
832
                    "FFrameView persistence definition", null, null); 
833
            definition.extend(manager
834
                .getDefinition(FFrame.PERSISTENCE_DEFINITION_NAME));
835
            definition.addDynFieldInt(QUALITY_FIELD).setMandatory(true);
836
            definition.addDynFieldInt(MAPUNITS_FIELD).setMandatory(true);
837
            definition.addDynFieldDouble(SCALE_FIELD).setMandatory(false);
838
            definition.addDynFieldObject(VIEW_FIELD)
839
                .setClassOfValue(ViewDocument.class).setMandatory(false);
840
            definition.addDynFieldObject(ENVELOPE_FIELD)
841
                .setClassOfValue(Envelope.class).setMandatory(false);
842
            definition.addDynFieldBoolean(SHOWGRID_FIELD).setMandatory(true);
843
            definition.addDynFieldObject(GRID_FIELD)
844
                .setClassOfValue(IFFrame.class).setMandatory(false);
845
            definition.addDynFieldBoolean(HAS_TOC_FIELD).setMandatory(false);
846
            definition.addDynFieldBoolean(EXTENT_SYNC_FIELD).setMandatory(false);
847
            definition.addDynFieldBoolean(LAYER_SYNC_FIELD).setMandatory(false);
848
            // unused fields, kept for backward compatibility
849
            definition.addDynFieldInt(MODE_FIELD).setMandatory(false);
850
            definition.addDynFieldInt(TYPESCALE_FIELD).setMandatory(false);
851
            definition.addDynFieldBoolean(BLINKED_FIELD).setMandatory(false);
852
            definition.addDynFieldObject(MAPCONTEXT_FIELD)
853
            .setClassOfValue(MapContext.class).setMandatory(false);
854
            definition.addDynFieldInt(VIEWING_FIELD).setMandatory(false);
855
            definition.addDynFieldInt(EXTENSION_FIELD).setMandatory(false);
856
        }
857
    }
858

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

    
898
        }
899
        showGrid = state.getBoolean(SHOWGRID_FIELD);
900
        grid = (IFFrame) state.get(GRID_FIELD);
901
    }
902

    
903
    @Override
904
    public void saveToState(PersistentState state) throws PersistenceException {
905
        super.saveToState(state);
906
        state.set(EXTENT_SYNC_FIELD, syncExtents);
907
        state.set(LAYER_SYNC_FIELD, syncLayers);
908
        state.set(QUALITY_FIELD, quality);
909
        state.set(MAPUNITS_FIELD, mapUnits);
910
        state.set(VIEW_FIELD, viewDocument);
911
        state.set(HAS_TOC_FIELD, b_hasToc);
912

    
913
        if (getMapContext() != null
914
            && getMapContext().getViewPort().getEnvelope() != null) {
915
            state.set(ENVELOPE_FIELD, getMapContext().getViewPort()
916
                .getEnvelope());
917
            state.set(SCALE_FIELD, (double)getMapContext().getScaleView());
918
        }
919

    
920
        state.set(SHOWGRID_FIELD, showGrid);
921
        state.set(GRID_FIELD, grid);
922
    }
923
    
924
    @Override
925
    public void setBoundBox(Rectangle2D r) {
926
            super.setBoundBox(r);
927
            if (getMapContext()!=null) {
928
                    AffineTransform at = this.getLayoutContext().getAT();
929
                    getMapContext().getViewPort().setImageSize(
930
                                    new Dimension((int)getBoundingBox(at).getWidth(), (int)getBoundingBox(at).getHeight()));
931
                    getMapContext().getViewPort().setDPI(getDrawPaperDPI());
932
                    updateScaleCtrl();
933
                    // FIXME: what should we do here? should we invalidate the cache?
934
                    // should we also trigger a Layout redraw?
935
                    refresh();
936
            }
937
    }   
938

    
939
    /**
940
     * Gets the rotation of the frame
941
     * 
942
     * @return Rotation in degrees
943
     */
944
    public double getMapRotation() {
945
        return 0;
946
    }
947
    
948
        protected void invalidateLayout() {
949
                b_validCache = false;
950
                if (getLayoutContext()!=null) {
951
                        getLayoutContext().notifAllObservers();
952
                }
953
        observers.notifyObservers(this, 
954
                new DefaultLayoutNotification(LayoutNotification.LAYOUT_REFRESH));
955
        }
956
        
957
        protected void invalidateToc() {
958
                if (getLayoutContext()!=null) {
959
                        getLayoutContext().notifyTocUpdated(TocModelChangedNotification.Type.MODEL_CHANGED);
960
                }
961
        }
962

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

    
1025
        public void frameRemoved() {
1026
                if (mapContext!=null) {
1027
                        clearOwnListeners(mapContext);
1028
                }
1029
                if (this.getView()!=null && this.getView().getMapContext()!=null) {
1030
                        clearViewListeners(this.getView().getMapContext());
1031
                }
1032
                if (b_hasToc && getLayoutContext()!=null) {
1033
                        getLayoutContext().setTocModel(null);
1034
                }
1035
                m_image = null; // FIXME: we could instead move it to a LRU cache to keep the last N images
1036
        }
1037

    
1038
        public void frameAdded() {
1039
                setListeners();
1040
                setTocModel();
1041
                updateScaleCtrl();
1042
        }
1043
        
1044
        public void setHasToc(boolean hasToc) {
1045
                this.b_hasToc = hasToc;
1046
                setTocModel();
1047
        }
1048
        
1049
        protected void setTocModel() {
1050
                if (getLayoutContext()!=null) {
1051
                        if (b_hasToc && getMapContext()!=null) {
1052
                                getLayoutContext().setTocModel(getMapContext());
1053
                        }
1054
                        else {
1055
                                getLayoutContext().setTocModel(null);
1056
                        }
1057
                }
1058
        }
1059
        
1060
        @Override
1061
        protected void doSetSelected(int selectedStatus) {
1062
                boolean oldSelectedStatus = isSelected();
1063
                super.doSetSelected(selectedStatus);
1064
                if (!oldSelectedStatus && isSelected()) { // changed from not selected to selected
1065
                        setTocModel();
1066
                        updateScaleCtrl();
1067
                }
1068
        }
1069
        
1070
        public boolean getLayerSynced() {
1071
                return syncLayers;
1072
        }
1073

    
1074
        public void setLayerSynced(boolean synced) {
1075
        syncLayers = synced;
1076
        resetListeners();
1077
        }
1078

    
1079
        public boolean getExtentSynced() {
1080
                return syncExtents;
1081
        }
1082

    
1083
        public void setExtentSynced(boolean synced) {
1084
                syncExtents = synced;
1085
        resetListeners();
1086
        }
1087

    
1088
        private class ViewDocListener
1089
        implements ViewPortListener, LegendListener, LayerCollectionListener, AtomicEventListener {
1090

    
1091
                public void extentChanged(ExtentEvent e) {
1092
                        if (!b_updating && getExtentSynced()) {
1093
                                if (!b_frameInitialized) {
1094
                                        b_frameInitialized = true;
1095
                                        return;
1096
                                }
1097
                                if (getMapContext()!=null) {
1098
                                        b_updating = true;
1099
                                        getMapContext().getViewPort().setEnvelope(e.getNewExtent());
1100
                                        updateScaleCtrl();
1101
                                        invalidateLayout();
1102
                                        b_updating = false;
1103
                                }
1104
                        }                        
1105
                }
1106

    
1107
                public void backColorChanged(ColorEvent e) {
1108
                        if (!b_updating && syncLayers) {
1109
                                if (getMapContext()!=null) {
1110
                                        b_updating = true;
1111
                                        mapContext.getViewPort().setBackColor(e.getNewColor());
1112
                                        invalidateLayout();
1113
                                        b_updating = true;
1114
                                }
1115
                        }
1116
                }
1117

    
1118
                public void projectionChanged(ProjectionEvent e) {
1119
                        if (!b_updating && getExtentSynced()) {
1120
                                if (getMapContext()!=null) {
1121
                                        b_updating = true;
1122
                                        getMapContext().getViewPort().setProjection(e.getNewProjection());
1123
                                        invalidateLayout();
1124
                                        // FIXME: force also a view redraw someway??
1125
                                        b_updating = false;
1126
                                }
1127
                        }
1128
                }
1129

    
1130
                public void conditionalRedraw() {
1131
                        if (!b_updating && syncLayers) {
1132
                                b_updating = true;
1133
                                invalidateLayout();
1134
                                // the view should also receive the event and update automatically
1135
                                b_updating = false;
1136
                        }                        
1137
                }
1138

    
1139
                public void legendChanged(LegendChangedEvent e) {
1140
                        conditionalRedraw();
1141
                        invalidateToc();
1142
                }
1143

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

    
1149
                public void layerMoved(LayerPositionEvent e) {
1150
                        conditionalRedraw();
1151
                        invalidateToc();
1152
                }
1153

    
1154
                public void layerRemoved(LayerCollectionEvent e) {
1155
                        conditionalRedraw();
1156
                        invalidateToc();
1157
                }
1158

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

    
1164
                public void layerMoving(LayerPositionEvent e)
1165
                                throws CancelationException {
1166
                        // nothing needed
1167
                }
1168

    
1169
                public void layerRemoving(LayerCollectionEvent e)
1170
                                throws CancelationException {
1171
                        // nothing needed
1172
                }
1173

    
1174
                public void visibilityChanged(LayerCollectionEvent e)
1175
                                throws CancelationException {
1176
                        // AtomicEvent is catching visibility changes instead of this one,
1177
                        // as this event is not being received. Maybe is only triggered if the
1178
                        // visibility of the whole group changes??
1179
                        conditionalRedraw();
1180
                        invalidateToc();
1181
                }
1182

    
1183
                public void atomicEvent(AtomicEvent e) {
1184
                        boolean needRedraw = false;
1185
                        // not all the events require a fframeview redraw
1186
                        for (int i=e.getLayerEvents().length-1; i>=0; i--) {
1187
                                FMapEvent at = e.getEvent(i);
1188
                                if (at instanceof LayerEvent) {
1189
                                        if (at.getEventType()==LayerEvent.DRAW_VALUES_CHANGED) {
1190
                                                needRedraw = true;
1191
                                                break;
1192
                                        }
1193
                                }
1194
                        }
1195
                        if (needRedraw) {
1196
                                conditionalRedraw();
1197
                        }
1198
                        invalidateToc();
1199
                }
1200
        }
1201

    
1202
        private class OwnMapContextListener
1203
                implements ViewPortListener, LegendListener, LayerCollectionListener {
1204

    
1205
                public void extentChanged(ExtentEvent e) {
1206
                        if (!b_drawing && !b_updating) {
1207
                                if (getView()!=null) {
1208
                                        b_updating = true;
1209
                                        if (getExtentSynced()){
1210
                                                getView().getMapContext().getViewPort().setEnvelope(e.getNewExtent());
1211
                                        }
1212
                                        updateScaleCtrl();
1213
                                        invalidateLayout();
1214
                                        b_updating = false;
1215
                                }
1216
                        }                        
1217
                }
1218

    
1219
                public void backColorChanged(ColorEvent e) {
1220
                        if (!b_updating) {
1221
                                if (getView()!=null) {
1222
                                        b_updating = true;
1223
                                        if (getLayerSynced()) {
1224
                                                getView().getMapContext().getViewPort().setBackColor(e.getNewColor());
1225
                                        }
1226
                                        invalidateLayout();
1227
                                        b_updating = false;
1228
                                }
1229
                        }
1230
                }
1231

    
1232
                public void projectionChanged(ProjectionEvent e) {
1233
                        if (!b_updating && getExtentSynced()) {
1234
                                if (getView()!=null) {
1235
                                        b_updating = true;
1236
                                        if (getLayerSynced()) {
1237
                                                getView().getMapContext().getViewPort().setProjection(e.getNewProjection());
1238
                                        }
1239
                                        invalidateLayout();
1240
                                        // FIXME: force also a view redraw someway??
1241
                                        b_updating = false;
1242
                                }
1243
                        }
1244
                }
1245

    
1246
                public void conditionalRedraw() {
1247
                        if (!b_updating) {
1248
                                b_updating = true;
1249
                                invalidateLayout();
1250
                                // the view should also receive the event and update automatically
1251
                                b_updating = false;
1252
                        }
1253
                }
1254

    
1255
                public void legendChanged(final LegendChangedEvent e) {
1256
                        conditionalRedraw();
1257
                        invalidateToc();
1258
                }
1259

    
1260
                public void layerAdded(final LayerCollectionEvent e) {
1261
                        // necessary to set an envelope when the first layer is added
1262
                        if (!b_updating && getMapContext().getViewPort().getEnvelope()==null) {
1263
                                try {
1264
                                        b_updating = true;
1265
                                        fullExtent();
1266
                                        
1267
                                } catch (ReadException e1) {
1268
                                } finally {
1269
                                        b_updating = false;
1270
                                }
1271
                        }
1272
                        conditionalRedraw();
1273
                        invalidateToc();
1274
                }
1275

    
1276
                public void layerMoved(final LayerPositionEvent e) {
1277
                        conditionalRedraw();
1278
                        invalidateToc();
1279
                }
1280

    
1281
                public void layerRemoved(final LayerCollectionEvent e) {
1282
                        conditionalRedraw();
1283
                        invalidateToc();
1284
                }
1285

    
1286
                public void layerAdding(LayerCollectionEvent e)
1287
                                throws CancelationException {
1288
                        // nothing neededO
1289

    
1290
                }
1291

    
1292
                public void layerMoving(LayerPositionEvent e)
1293
                                throws CancelationException {
1294
                        // nothing needed
1295

    
1296
                }
1297

    
1298
                public void layerRemoving(LayerCollectionEvent e)
1299
                                throws CancelationException {
1300
                        // nothing needed
1301

    
1302
                }
1303

    
1304
                public void visibilityChanged(LayerCollectionEvent e)
1305
                                throws CancelationException {
1306
                        conditionalRedraw();
1307
                }
1308
        }
1309
}