Statistics
| Revision:

svn-document-layout / trunk / org.gvsig.app.document.layout2.app / org.gvsig.app.document.layout2.app.mainplugin / src / main / java / org / gvsig / app / project / documents / layout / fframes / FFrameView.java @ 213

History | View | Annotate | Download (42.6 KB)

1
/* 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 MODE_FIELD = "mode";
110
    private static final String TYPESCALE_FIELD = "typeScale";
111
    private static final String QUALITY_FIELD = "quality";
112
    private static final String BLINKED_FIELD = "bLinked";
113
    private static final String MAPUNITS_FIELD = "mapUnits";
114
    private static final String SCALE_FIELD = "scale";
115
    private static final String VIEW_FIELD = "view";
116
    private static final String ENVELOPE_FIELD = "envelope";
117
    private static final String SHOWGRID_FIELD = "showGrid";
118
    private static final String GRID_FIELD = "gridview";
119
    private static final String HAS_TOC = "hasToc";
120
    // following fields are unused - should be deleted? 
121
    private static final String EXTENSION_FIELD = "extension";
122

    
123
    private static final Logger logger = LoggerFactory
124
        .getLogger(FFrameView.class);
125
    public static final int PRESENTATION = 0;
126
    public static final int DRAFT = 1;
127
    protected int mode;
128
    protected int typeScale = AUTOMATICO;
129
    protected int quality = PRESENTATION;
130
    protected boolean linked = true;
131
    protected ViewDocument viewDocument = null;
132
    protected MapContext mapContext = null;
133
    protected int mapUnits = 1; // Meters.
134

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

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

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

    
160

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

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

    
184
        return "FFrameView " + num + ": " + getView().getName();
185
    }
186

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

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

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

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

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

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

    
301
    }
302

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

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

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

    
390
        int scale = (int) (r.getWidth() / 24);
391
        Font f = new Font("SansSerif", Font.PLAIN, scale);
392
        g.setFont(f);
393

    
394
        g.drawString(msg, (int) (r.getCenterX() - ((msg.length() * scale) / 4)),
395
            (int) (r.getCenterY()));        
396
    }
397

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

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

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

    
458
        // paint the MapContext on m_image, if not already cached
459
        createImage(affineTransform, drawWidth, drawHeight, mapOrigin);
460

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

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

    
486
                    viewPort.setDPI(getDrawPaperDPI());
487
                viewPort.setImageSize(new Dimension(width, height)); 
488
            
489
            m_image =
490
                    new BufferedImage(
491
                                    width,
492
                                    height,
493
                                    BufferedImage.TYPE_INT_ARGB);
494

    
495
            Graphics2D gimg = (Graphics2D) m_image.createGraphics();
496
            getMapContext().draw(m_image, gimg, getScale());
497
            gimg.dispose();
498
            b_validCache = true;
499
        } 
500

    
501
    }
502
    
503
    protected void drawImage(Graphics2D g, BufferedImage image,
504
                    Rectangle2D.Double visibleRectangle) {
505

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

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

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

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

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

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

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

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

    
624
    /**
625
     * Seleccionar si la vista esta relacionada o no con la original.
626
     * 
627
     * @param b
628
     *            true si est? ligada y false si no lo est?.
629
     */
630
    public void setLinked(boolean b) {
631
        linked = b;
632
        resetListeners();
633
    }
634

    
635
    /**
636
     * Devuelve si est? ligada o no el FFrameView con la vista.
637
     * 
638
     * @return True si la vista est? ligada.
639
     */
640
    public boolean getLinked() {
641
        return linked;
642
    }
643

    
644
    /**
645
     * Devuelve el tipo de escala que est? seleccionada AUTOMATICO o
646
     * MANUAL.
647
     * 
648
     * @return entero que representa el tipo seleccionado.
649
     */
650
    public int getTypeScale() {
651
        return typeScale;
652
    }
653

    
654
    /**
655
     * Rellenar el tipo de escala que se desea.
656
     * 
657
     * @param i
658
     *            entero que representa el tipo de escala.
659
     */
660
    public void setTypeScale(int i) {
661
        typeScale = i;
662
        resetListeners();
663
    }
664

    
665
    /**
666
     * Inserta la imagen para repintar el FFrameView.
667
     * 
668
     * @param bi
669
     *            Imagen para repintar.
670
     */
671
    public void setBufferedImage(BufferedImage bi) {
672
        m_image = bi;
673
    }
674

    
675
    /**
676
     * Devuelve la imagen para repintar.
677
     * 
678
     * @return Imagen para repintar.
679
     */
680
    public BufferedImage getBufferedImage() {
681
        return m_image;
682
    }
683

    
684
    /**
685
     * Devuelve la MAtriz de transformaci?n utilizada por la FFrameView.
686
     * 
687
     * @return MAtriz de transformaci?n.
688
     */
689
    public AffineTransform getATMap() {
690
        return at;
691
    }
692

    
693
    /**
694
     * Inserta la matriz de transformaci?n.
695
     * 
696
     * @param transform
697
     *            Matriz de transformaci?n.
698
     */
699
    public void setATMap(AffineTransform transform) {
700
        at = transform;
701
    }
702

    
703
    /**
704
     * Inserta el proyecto.
705
     * 
706
     * @param p
707
     *            Proyecto.
708
     */
709
    public void setProject(Project p) {
710
        project = p;
711
    }
712

    
713
    /**
714
     * @see org.gvsig.app.project.documents.layout.fframes.IFFrame#getNameFFrame()
715
     */
716
    public String getNameFFrame() {
717
        return PluginServices.getText(this, "Vista") + num;
718
    }
719

    
720
    public String getName() {
721
        return PERSISTENCE_DEFINITION_NAME;
722
    }
723

    
724
    /**
725
     * DOCUMENT ME!
726
     * 
727
     * @param arg0
728
     *            DOCUMENT ME!
729
     * 
730
     * @return DOCUMENT ME!
731
     */
732
    public boolean compare(Object arg0) {
733
        if (!(arg0 instanceof FFrameView)) {
734
            return false;
735
        }
736

    
737
        if (!this.getName().equals(((FFrameView) arg0).getName())) {
738
            return false;
739
        }
740

    
741
        if (Math.abs(this.getBoundBox().getWidth()
742
            - (((FFrameView) arg0).getBoundBox().getWidth())) > 0.05) {
743
            return false;
744
        }
745
        if (Math.abs(this.getBoundBox().getHeight()
746
            - (((FFrameView) arg0).getBoundBox().getHeight())) > 0.05) {
747
            return false;
748
        }
749

    
750
        if (!this.toString().equals(((FFrameView) arg0).toString())) {
751
            return false;
752
        }
753

    
754
        if (this.getMapContext() != null
755
            && !this.getMapContext()
756
                .equals(((FFrameView) arg0).getMapContext())) {
757
            return false;
758
        }
759

    
760
        if (this.getRotation() != ((FFrameView) arg0).getRotation()) {
761
            return false;
762
        }
763
        return true;
764
    }
765
    
766
    public void updateScaleCtrl() {
767
            NewStatusBar statusbar = PluginServices.getMainFrame().getStatusBar();
768
            MapContext mapContext = this.getMapContext();
769
            if (mapContext==null) {
770
                    return;
771
            }
772
            statusbar.setMessage("units",
773
                            PluginServices.getText(this, mapContext.getDistanceName()));
774
            statusbar.setControlValue("layout-view-change-scale",
775
                            String.valueOf(getMapContext().getScaleView()));
776
            IProjection proj = mapContext.getViewPort().getProjection();
777
            if (proj != null) {
778
                    statusbar.setMessage("projection", proj.getAbrev());
779
            } else {
780
                    statusbar.setMessage("projection", "");
781
            }
782
    }
783

    
784
    public void fullExtent() throws ReadException {
785
        setNewEnvelope(getMapContext().getFullEnvelope());
786
    }
787

    
788
    public void setPointsToZoom(Point2D px1, Point2D px2) {
789
        p1 = px1;
790
        p2 = px2;
791
    }
792

    
793
    public void movePoints(Point2D px1, Point2D px2) {
794
        double difX = -px2.getX() + px1.getX();
795
        double difY = -px2.getY() + px1.getY();
796
        if (p1 != null) {
797
            p1.setLocation(p1.getX() + difX, p1.getY() + difY);
798
            p2.setLocation(p2.getX() + difX, p2.getY() + difY);
799
        }
800
    }
801

    
802
    /**
803
     * This method deals with places where this fframeview and the cloned
804
     * fframeview (frame) are registered as listeners. The goal should be
805
     * leaving the cloned instance (frame) as listener in the same way
806
     * that 'this' instance is doing.
807
     */
808
    protected void cloneActions(FFrameView frame) {
809
    }
810

    
811
    public Object clone() throws CloneNotSupportedException {
812
            Document d = ProjectManager.getInstance().getCurrentProject().getDocuments().get(0);
813
        FFrameView frame = (FFrameView) super.clone();
814
        frame.createListeners(); // necessary to create the listeners within the right scope
815
        frame.setView(this.getView());        
816

    
817
        if (grid != null) {
818
            FFrameGrid newGrid = (FFrameGrid) this.grid.clone();
819
            newGrid.setFFrameDependence(frame);
820
            frame.setGrid(newGrid);
821
        }
822
        cloneActions(frame);
823
        return frame;
824
    }
825

    
826
    public void setGrid(IFFrame grid) {
827
        this.grid = grid;
828
        this.grid.setRotation(this.getRotation());
829
    }
830

    
831
    public IFFrame getGrid() {
832
        return this.grid;
833
    }
834

    
835
    public void setRotation(double rotation) {
836
        super.setRotation(rotation);
837
        if (grid != null) {
838
            grid.setRotation(rotation);
839
        }
840
    }
841

    
842
    public void showGrid(boolean b) {
843
        showGrid = b;
844
    }
845

    
846
    public boolean isShowGrid() {
847
        return showGrid;
848
    }
849

    
850
    public void refreshOriginalExtent() {
851
    }
852

    
853
    public static void registerPersistent() {
854
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
855
        if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) {          
856
            DynStruct definition =
857
                manager.addDefinition(FFrameView.class,
858
                    PERSISTENCE_DEFINITION_NAME,
859
                    "FFrameView persistence definition", null, null); 
860
            definition.extend(manager
861
                .getDefinition(FFrame.PERSISTENCE_DEFINITION_NAME));
862

    
863
            definition.addDynFieldInt(MODE_FIELD).setMandatory(true);
864
            definition.addDynFieldInt(TYPESCALE_FIELD).setMandatory(true);
865
            definition.addDynFieldInt(EXTENSION_FIELD).setMandatory(false);
866
            definition.addDynFieldInt(QUALITY_FIELD).setMandatory(true);
867
            definition.addDynFieldBoolean(BLINKED_FIELD).setMandatory(true);
868
            definition.addDynFieldInt(MAPUNITS_FIELD).setMandatory(true);
869
            definition.addDynFieldDouble(SCALE_FIELD).setMandatory(false);
870
            definition.addDynFieldObject(VIEW_FIELD)
871
                .setClassOfValue(ViewDocument.class).setMandatory(false);
872
            definition.addDynFieldObject(ENVELOPE_FIELD)
873
                .setClassOfValue(Envelope.class).setMandatory(false);
874
            definition.addDynFieldBoolean(SHOWGRID_FIELD).setMandatory(true);
875
            definition.addDynFieldObject(GRID_FIELD)
876
                .setClassOfValue(IFFrame.class).setMandatory(false);
877
            definition.addDynFieldBoolean(HAS_TOC).setMandatory(false);
878
        }
879
    }
880

    
881
    @Override
882
    public void loadFromState(PersistentState state)
883
        throws PersistenceException {
884
        super.loadFromState(state);
885
        b_frameInitialized = false;
886
        mode = state.getInt(MODE_FIELD);
887
        typeScale = state.getInt(TYPESCALE_FIELD);
888
        quality = state.getInt(QUALITY_FIELD);
889
        linked = state.getBoolean(BLINKED_FIELD);
890
        mapUnits = state.getInt(MAPUNITS_FIELD);;
891
        viewDocument = (ViewDocument) state.get(VIEW_FIELD);
892
        if (state.hasValue(HAS_TOC)) {
893
                this.b_hasToc = state.getBoolean(HAS_TOC);
894
        }        
895
        if (viewDocument!=null) {
896
                this.setView(viewDocument);
897
                // it is crucial to don't persist the MapContext and get a cloned one from the View instead,
898
                // as the cloned instance is different from the one created using persistence. In particular,
899
                // the cloned one will share the EventBuffer with the original one, while persistence would
900
                // create 2 separate EventBuffers, which will then have a very stange behaviour
901
        }
902
        if (getMapContext()!=null) {
903
                double mapScale = state.getDouble(SCALE_FIELD);
904
                getMapContext().setScaleView((long)mapScale);
905
                getMapContext().getViewPort().setEnvelope(
906
                (Envelope) state.get(ENVELOPE_FIELD));
907
                if (this.getLayoutContext()!=null) {
908
                        this.getLayoutContext().setTocModel(getMapContext());
909
                }
910

    
911
        }
912
        showGrid = state.getBoolean(SHOWGRID_FIELD);
913
        grid = (IFFrame) state.get(GRID_FIELD);
914
    }
915

    
916
    @Override
917
    public void saveToState(PersistentState state) throws PersistenceException {
918
        super.saveToState(state);
919
        state.set(MODE_FIELD, mode);
920
        state.set(TYPESCALE_FIELD, typeScale);
921
        state.set(QUALITY_FIELD, quality);
922
        state.set(BLINKED_FIELD, linked);
923
        state.set(MAPUNITS_FIELD, mapUnits);
924
        state.set(VIEW_FIELD, viewDocument);
925
        state.set(HAS_TOC, b_hasToc);
926

    
927
        if (getMapContext() != null
928
            && getMapContext().getViewPort().getEnvelope() != null) {
929
            state.set(ENVELOPE_FIELD, getMapContext().getViewPort()
930
                .getEnvelope());
931
            state.set(SCALE_FIELD, (double)getMapContext().getScaleView());
932
        }
933

    
934
        state.set(SHOWGRID_FIELD, showGrid);
935
        state.set(GRID_FIELD, grid);
936
    }
937
    
938
    @Override
939
    public void setBoundBox(Rectangle2D r) {
940
            super.setBoundBox(r);
941
            if (getMapContext()!=null) {
942
                    AffineTransform at = this.getLayoutContext().getAT();
943
                    getMapContext().getViewPort().setImageSize(
944
                                    new Dimension((int)getBoundingBox(at).getWidth(), (int)getBoundingBox(at).getHeight()));
945
                    getMapContext().getViewPort().setDPI(getDrawPaperDPI());
946
                    updateScaleCtrl();
947
                    // FIXME: what should we do here? should we invalidate the cache?
948
                    // should we also trigger a Layout redraw?
949
                    refresh();
950
            }
951
    }   
952

    
953
    /**
954
     * Gets the rotation of the frame
955
     * 
956
     * @return Rotation in degrees
957
     */
958
    public double getMapRotation() {
959
        return 0;
960
    }
961
    
962
        protected void invalidateLayout() {
963
                b_validCache = false;
964
                if (getLayoutContext()!=null) {
965
                        getLayoutContext().notifAllObservers();
966
                }
967
        observers.notifyObservers(this, 
968
                new DefaultLayoutNotification(LayoutNotification.LAYOUT_REFRESH));
969
        }
970
        
971
        protected void invalidateToc() {
972
                if (getLayoutContext()!=null) {
973
                        getLayoutContext().notifyTocUpdated(TocModelChangedNotification.Type.MODEL_CHANGED);
974
                }
975
        }
976

    
977
        public void refresh() {
978
        // FIXME: what should we do here? do we really need to invalidate cache??
979
            b_validCache = false;                
980
        }
981
    
982
    protected void resetListeners() {
983
                if (this.getMapContext()!=null) {
984
                        clearOwnListeners(this.getMapContext());
985
                }
986
                if (this.getView()!=null && this.getView().getMapContext()!=null) {
987
                        clearViewListeners(this.getView().getMapContext());
988
                }
989
            setListeners();
990
    }
991
    
992
    protected void setListeners() {
993
            if (getView()!=null) {
994
                    if (linked) {
995
                            getView().getMapContext().addLayerListener(viewDocListener);
996
                            getView().getMapContext().getLayers().addLayerCollectionListener(viewDocListener);
997
                            getView().getMapContext().addAtomicEventListener(viewDocListener);
998
                    }
999
                    if (getTypeScale()==IFFrameUseFMap.AUTOMATICO) {
1000
                            getView().getMapContext().getViewPort().addViewPortListener(viewDocListener);
1001
                    }
1002
            }
1003
            if (getMapContext()!=null) {
1004
                    getMapContext().addLayerListener(ownMapContextListener);
1005
                    getMapContext().getLayers().addLayerCollectionListener(ownMapContextListener);
1006
                    getMapContext().getViewPort().addViewPortListener(ownMapContextListener);
1007
            }
1008
    }
1009
    protected void clearOwnListeners(MapContext mapContext) {
1010
            mapContext.removeLayerListener(ownMapContextListener);
1011
            mapContext.getViewPort().removeViewPortListener(ownMapContextListener);
1012
            mapContext.getLayers().removeLayerCollectionListener(ownMapContextListener);
1013
    }
1014
    protected void clearViewListeners(MapContext mapContext) {
1015
            mapContext.removeLayerListener(viewDocListener);
1016
            mapContext.getViewPort().removeViewPortListener(viewDocListener);
1017
            mapContext.getLayers().removeLayerCollectionListener(viewDocListener);
1018
            mapContext.removeAtomicEventListener(viewDocListener);
1019
    }
1020
    
1021
    /*
1022
     * (non-Javadoc)
1023
     * @see org.gvsig.tools.dispose.Disposable#dispose()
1024
     */
1025
        public void dispose() {
1026
                try {
1027
                        if (this.getMapContext()!=null) {
1028
                                clearOwnListeners(this.getMapContext());
1029
                        }
1030
                        if (this.getView()!=null && this.getView().getMapContext()!=null) {
1031
                                clearViewListeners(this.getView().getMapContext());
1032
                        }
1033
                }
1034
                catch (Exception ex) {}
1035
                this.viewDocument = null;
1036
                this.mapContext = null;
1037
        }
1038

    
1039
        public void frameRemoved() {
1040
                if (mapContext!=null) {
1041
                        clearOwnListeners(mapContext);
1042
                }
1043
                if (this.getView()!=null && this.getView().getMapContext()!=null) {
1044
                        clearViewListeners(this.getView().getMapContext());
1045
                }
1046
                if (b_hasToc && getLayoutContext()!=null) {
1047
                        getLayoutContext().setTocModel(null);
1048
                }
1049
                m_image = null; // FIXME: we could instead move it to a LRU cache to keep the last N images
1050
        }
1051

    
1052
        public void frameAdded() {
1053
                setListeners();
1054
                setTocModel();
1055
                updateScaleCtrl();
1056
        }
1057
        
1058
        public void setHasToc(boolean hasToc) {
1059
                this.b_hasToc = hasToc;
1060
                setTocModel();
1061
        }
1062
        
1063
        protected void setTocModel() {
1064
                if (getLayoutContext()!=null) {
1065
                        if (b_hasToc && getMapContext()!=null) {
1066
                                getLayoutContext().setTocModel(getMapContext());
1067
                        }
1068
                        else {
1069
                                getLayoutContext().setTocModel(null);
1070
                        }
1071
                }
1072
        }
1073
        
1074
        @Override
1075
        protected void doSetSelected(int selectedStatus) {
1076
                boolean oldSelectedStatus = isSelected();
1077
                super.doSetSelected(selectedStatus);
1078
                if (!oldSelectedStatus && isSelected()) { // changed from not selected to selected
1079
                        setTocModel();
1080
                        updateScaleCtrl();
1081
                }
1082
        }
1083

    
1084
        private class ViewDocListener
1085
        implements ViewPortListener, LegendListener, LayerCollectionListener, AtomicEventListener {
1086

    
1087
                public void extentChanged(ExtentEvent e) {
1088
                        if (!b_updating && getTypeScale()==AUTOMATICO) {
1089
                                if (!b_frameInitialized) {
1090
                                        b_frameInitialized = true;
1091
                                        return;
1092
                                }
1093
                                if (getMapContext()!=null) {
1094
                                        b_updating = true;
1095
                                        getMapContext().getViewPort().setEnvelope(e.getNewExtent());
1096
                                        updateScaleCtrl();
1097
                                        invalidateLayout();
1098
                                        b_updating = false;
1099
                                }
1100
                        }                        
1101
                }
1102

    
1103
                public void backColorChanged(ColorEvent e) {
1104
                        if (!b_updating && linked) {
1105
                                if (getMapContext()!=null) {
1106
                                        b_updating = true;
1107
                                        mapContext.getViewPort().setBackColor(e.getNewColor());
1108
                                        invalidateLayout();
1109
                                        b_updating = true;
1110
                                }
1111
                        }
1112
                }
1113

    
1114
                public void projectionChanged(ProjectionEvent e) {
1115
                        if (!b_updating && getTypeScale()==AUTOMATICO) {
1116
                                if (getMapContext()!=null) {
1117
                                        b_updating = true;
1118
                                        getMapContext().getViewPort().setProjection(e.getNewProjection());
1119
                                        invalidateLayout();
1120
                                        // FIXME: force also a view redraw someway??
1121
                                        b_updating = false;
1122
                                }
1123
                        }
1124
                }
1125

    
1126
                public void conditionalRedraw() {
1127
                        if (!b_updating && linked) {
1128
                                b_updating = true;
1129
                                invalidateLayout();
1130
                                // the view should also receive the event and update automatically
1131
                                b_updating = false;
1132
                        }                        
1133
                }
1134

    
1135
                public void legendChanged(LegendChangedEvent e) {
1136
                        conditionalRedraw();
1137
                        invalidateToc();
1138
                }
1139

    
1140
                public void layerAdded(LayerCollectionEvent e) {
1141
                        conditionalRedraw();
1142
                        invalidateToc();
1143
                }
1144

    
1145
                public void layerMoved(LayerPositionEvent e) {
1146
                        conditionalRedraw();
1147
                        invalidateToc();
1148
                }
1149

    
1150
                public void layerRemoved(LayerCollectionEvent e) {
1151
                        conditionalRedraw();
1152
                        invalidateToc();
1153
                }
1154

    
1155
                public void layerAdding(LayerCollectionEvent e)
1156
                                throws CancelationException {
1157
                        // nothing needed
1158
                }
1159

    
1160
                public void layerMoving(LayerPositionEvent e)
1161
                                throws CancelationException {
1162
                        // nothing needed
1163
                }
1164

    
1165
                public void layerRemoving(LayerCollectionEvent e)
1166
                                throws CancelationException {
1167
                        // nothing needed
1168
                }
1169

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

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

    
1198
        private class OwnMapContextListener
1199
                implements ViewPortListener, LegendListener, LayerCollectionListener {
1200

    
1201
                public void extentChanged(ExtentEvent e) {
1202
                        if (!b_drawing && !b_updating && (getTypeScale() == AUTOMATICO)) {
1203
                                if (getView()!=null) {
1204
                                        b_updating = true;
1205
                                        getView().getMapContext().getViewPort().setEnvelope(e.getNewExtent());
1206
                                        updateScaleCtrl();
1207
                                        invalidateLayout();
1208
                                        b_updating = false;
1209
                                }
1210
                        }                        
1211
                }
1212

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

    
1224
                public void projectionChanged(ProjectionEvent e) {
1225
                        if (!b_updating && (getTypeScale() == AUTOMATICO)) {
1226
                                if (getView()!=null) {
1227
                                        b_updating = true;
1228
                                        getView().getMapContext().getViewPort().setProjection(e.getNewProjection());
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
        }
1300
}