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

History | View | Annotate | Download (37.1 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.TocModelChangedImpl;
48
import org.gvsig.app.project.documents.layout.TocModelChangedNotification;
49
import org.gvsig.app.project.documents.view.ViewDocument;
50
import org.gvsig.compat.print.PrintAttributes;
51
import org.gvsig.fmap.dal.exception.ReadException;
52
import org.gvsig.fmap.geom.Geometry;
53
import org.gvsig.fmap.geom.primitive.Envelope;
54
import org.gvsig.fmap.mapcontext.MapContext;
55
import org.gvsig.fmap.mapcontext.MapContextException;
56
import org.gvsig.fmap.mapcontext.ViewPort;
57
import org.gvsig.fmap.mapcontext.events.AtomicEvent;
58
import org.gvsig.fmap.mapcontext.events.ColorEvent;
59
import org.gvsig.fmap.mapcontext.events.ExtentEvent;
60
import org.gvsig.fmap.mapcontext.events.ProjectionEvent;
61
import org.gvsig.fmap.mapcontext.events.listeners.AtomicEventListener;
62
import org.gvsig.fmap.mapcontext.events.listeners.ViewPortListener;
63
import org.gvsig.fmap.mapcontext.layers.CancelationException;
64
import org.gvsig.fmap.mapcontext.layers.LayerCollectionEvent;
65
import org.gvsig.fmap.mapcontext.layers.LayerCollectionListener;
66
import org.gvsig.fmap.mapcontext.layers.LayerEvent;
67
import org.gvsig.fmap.mapcontext.layers.LayerPositionEvent;
68
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendChangedEvent;
69
import org.gvsig.fmap.mapcontext.rendering.legend.events.listeners.LegendListener;
70
import org.gvsig.gui.beans.Messages;
71
import org.gvsig.tools.ToolsLocator;
72
import org.gvsig.tools.dynobject.DynStruct;
73
import org.gvsig.tools.persistence.PersistenceManager;
74
import org.gvsig.tools.persistence.PersistentState;
75
import org.gvsig.tools.persistence.exception.PersistenceException;
76
import org.slf4j.Logger;
77
import org.slf4j.LoggerFactory;
78

    
79
/**
80
 * FFrame para introducir una vista en el Layout.
81
 * 
82
 * @author Vicente Caballero Navarro
83
 */
84
public class FFrameView extends FFrame implements IFFrameUseProject, IFFrameUseFMap {
85

    
86
    public static final String PERSISTENCE_DEFINITION_NAME = "FFrameView";
87

    
88
    private static final String MODE_FIELD = "mode";
89
    private static final String TYPESCALE_FIELD = "typeScale";
90
    private static final String QUALITY_FIELD = "quality";
91
    private static final String BLINKED_FIELD = "bLinked";
92
    private static final String MAPUNITS_FIELD = "mapUnits";
93
    private static final String SCALE_FIELD = "scale";
94
    private static final String VIEW_FIELD = "view";
95
    private static final String ENVELOPE_FIELD = "envelope";
96
    private static final String SHOWGRID_FIELD = "showGrid";
97
    private static final String GRID_FIELD = "gridview";
98
    // following fields are unused - should be deleted? 
99
    private static final String EXTENSION_FIELD = "extension";
100
    private static final String HAS_TOC = "hasToc";
101

    
102
    private static final Logger logger = LoggerFactory
103
        .getLogger(FFrameView.class);
104
    public static final int PRESENTATION = 0;
105
    public static final int DRAFT = 1;
106
    protected int mode;
107
    protected int typeScale = AUTOMATICO;
108
    protected int quality = PRESENTATION;
109
    protected boolean linked = true;
110
    protected ViewDocument viewDocument = null;
111
    protected MapContext mapContext = null;
112
    protected int mapUnits = 1; // Meters.
113

    
114
    protected BufferedImage m_image = null;
115
    protected AffineTransform at = null;
116
    protected Project project = null;
117
    protected double scaleAnt;
118
    protected Point origin;
119
    protected Point2D p1;
120
    protected Point2D p2;
121
    protected IFFrame grid;
122
    protected boolean showGrid = false;
123

    
124
        private boolean b_viewOriginatedUpdate = false;
125
        private boolean b_fframeOriginatedUpdate = false;
126
        protected boolean b_validCache = false;
127
        protected ViewDocListener viewDocListener;
128
        protected OwnMapContextListener ownMapContextListener;
129
        private boolean b_hasToc = false;
130

    
131
        private boolean b_updatingToc=false;
132

    
133

    
134
    /**
135
     * Creates a new FFrameView object.
136
     */
137
    public FFrameView() {
138
        num++;
139
        createListeners();
140
    }
141
    
142
    protected void createListeners() {
143
            viewDocListener = new ViewDocListener();
144
            ownMapContextListener = new OwnMapContextListener();
145
    }
146

    
147
    /**
148
     * Devuelve una descripci?n del FFrameView.
149
     * 
150
     * @return Descripci?n.
151
     */
152
    public String toString() {
153
        if (getView() == null) {
154
            return "FFrameView " + num + ": " + "Vacio";
155
        }
156

    
157
        return "FFrameView " + num + ": " + getView().getName();
158
    }
159

    
160
    /**
161
     * Rellena la escala de la vista que contiene el fframe.
162
     * 
163
     * @param d
164
     *            escala de la vista.
165
     */
166
    public void setScale(double d) {
167
            if (getMapContext()!=null) {
168
                    getMapContext().setScaleView((long) d);
169
            }
170
    }
171

    
172
    /**
173
     * Inserta el nuevo extent a la FFrameView.
174
     * 
175
     * @param r
176
     *            Rect?ngulo a ocupar por el FFrameView.
177
     */
178
    public void setNewEnvelope(Envelope r) {
179
            getMapContext().getViewPort().setEnvelope(r);
180
            updateScaleCtrl();
181
    }
182
    
183
    /**
184
     * Calculates the resolution (measured on dots per inch, DPI) to be
185
     * considered to draw the FFrameView on screen. It is calculated by
186
     * dividing the width (in pixels) of the FFrame divided by the width
187
     * in inches of the paper.
188
     */
189
    protected double getDrawPaperDPI() {
190
            return (2.54*getBoundingBox(null).width)/getBoundBox().width;        
191
    }
192

    
193
    /**
194
     * Devuelve el FMap de la vista o una clonaci?n de este si se utiliza una
195
     * escala fija.
196
     * 
197
     * @return FMap.
198
     */
199
    public MapContext getMapContext() {
200
        return mapContext;
201
    }
202

    
203
    /**
204
     * Rellena la calidad que se quiere aplicar.
205
     * 
206
     * @param q
207
     *            entero que representa la calidad a aplicar.
208
     */
209
    public void setQuality(int q) {
210
        quality = q;
211
    }
212

    
213
    /**
214
     * Devuelve un entero que representa la calidad que est? seleccionada.
215
     * 
216
     * @return tipo de calidad selccionada.
217
     */
218
    public int getQuality() {
219
        return quality;
220
    }
221

    
222
    public void setViewMapContext(MapContext viewMapContext) {
223
            if (mapContext!=null) {
224
                    clearOwnListeners(mapContext);
225
            }
226
            try {
227
                    if (linked){
228
                            mapContext =
229
                                            viewMapContext.createNewFMap(
230
                                                            (ViewPort) viewMapContext.getViewPort().clone());
231
                    }
232
                    else {
233
                            mapContext = viewMapContext.cloneFMap();
234
                            mapContext.setViewPort((ViewPort) viewMapContext
235
                                            .getViewPort().clone());
236
                    }
237
                    ViewPort newViewPort = getMapContext().getViewPort();
238
                    newViewPort.setImageSize(new Dimension((int) getBoundingBox(null).width,
239
                                    (int) getBoundingBox(null).height));
240
                    newViewPort.setDPI(getDrawPaperDPI());
241
                    setListeners();
242
                    updateScaleCtrl();
243
                    setTocModel();
244
            } catch (CloneNotSupportedException e1) {
245
                    NotificationManager.addError("Excepci?n :", e1);
246
            }
247

    
248
    }
249
    /**
250
     * Inserta el ProjectView de donde obtener las propiedades de la vista a
251
     * mostrar.
252
     * 
253
     * @param v
254
     *            Modelo de la vista.
255
     */
256
    public void setView(ViewDocument dvd) {
257
            ViewDocument oldDoc = dvd;
258
            if (oldDoc!=null && oldDoc.getMapContext()!=null) {
259
                    clearViewListeners(oldDoc.getMapContext());
260
            }
261
        viewDocument = dvd;
262
        if (dvd!=null) {
263
            setViewMapContext(dvd.getMapContext());
264
        }
265
    }
266

    
267
    /**
268
     * Devuelve el modelo de la vista.
269
     * 
270
     * @return Modelo de la vista.
271
     */
272
    public ViewDocument getView() {
273
        return viewDocument;
274
    }
275

    
276
    /**
277
     * Draws the FFrameView on the provided Graphics, according to the
278
     * provided affine transform and the visible rectangle.
279
     * 
280
     * @param g Graphics2D
281
     * @param at Affine transform to translate sheet coordinates (in cm)
282
     *                                 to screen coordinates (in pixels)
283
     * @param visibleLayoutDocRect visible rectangle
284
     * @param imgBase Image used to speed up the drawing process
285
     */
286
    public void draw(Graphics2D g, AffineTransform at, Rectangle2D visibleLayoutDocRect, BufferedImage imgBase) {
287
        Rectangle2D.Double fframeViewRect = getBoundingBox(at);  
288
        Rectangle originalClip = preDraw(g, fframeViewRect);    
289
        if (intersects(visibleLayoutDocRect, fframeViewRect)) {
290
            if (getMapContext() == null) {
291
                drawEmpty(g);
292
            } else {
293
                if (FLayoutUtilities.hasEditingLayers(getView())) {
294
                    
295
                    /*
296
                     * We are not drawing if any layer is in editing mode
297
                     */
298
                    drawMessage(g, Messages.getText(
299
                        "_Cannot_draw_view_if_layers_in_editing_mode"));
300
                    
301
                } else {
302
                    if (getQuality() == PRESENTATION) {
303
                        try {
304
                            drawPresentation(g, at, fframeViewRect, visibleLayoutDocRect, imgBase);
305
                        } catch (Exception exc) {
306
                            drawMessage(g, FLayoutFunctions.getLastMessage(exc));
307
                        }
308
                        
309
                    } else {
310
                        drawDraft(g);
311
                    }               
312
                }
313
            }
314
        }
315
        postDraw(g, fframeViewRect, visibleLayoutDocRect, imgBase, originalClip, at); 
316
        if (showGrid && grid != null) {           
317
            grid.draw(g, at, visibleLayoutDocRect, imgBase);
318
        }    
319
    }
320
    
321
    private void drawMessage(Graphics2D g, String msg) {
322
        
323
        Rectangle2D r = getBoundingBox(null);
324
        g.setColor(Color.lightGray);
325
        g.fillRect((int) r.getX(), (int) r.getY(), (int) r.getWidth(),
326
            (int) r.getHeight());
327
        g.setColor(Color.darkGray);
328
        g.setStroke(new BasicStroke(2));
329
        g.drawRect((int) r.getX(), (int) r.getY(), (int) r.getWidth(),
330
            (int) r.getHeight());
331
        g.setColor(Color.black);
332

    
333
        int scale = (int) (r.getWidth() / 24);
334
        Font f = new Font("SansSerif", Font.PLAIN, scale);
335
        g.setFont(f);
336

    
337
        g.drawString(msg, (int) (r.getCenterX() - ((msg.length() * scale) / 4)),
338
            (int) (r.getCenterY()));        
339
    }
340

    
341
    protected void drawPresentation(
342
        Graphics2D g,
343
        AffineTransform affineTransform,
344
        Rectangle2D.Double fframeViewRect,
345
        Rectangle2D visibleLayoutDocRect,
346
        BufferedImage imgBase) throws Exception {
347
        
348
        Point mapOrigin = new Point((int)visibleLayoutDocRect.getMinX(), (int)visibleLayoutDocRect.getMaxY());
349
            int drawWidth = (int)fframeViewRect.width;
350
            int drawHeight = (int)fframeViewRect.height;
351
        // paint the MapContext on m_image, if not already cached
352
        createImage(g, affineTransform, drawWidth, drawHeight, mapOrigin);
353

    
354
        //Draw the created image
355
        drawImage(g, m_image, fframeViewRect);
356
        
357
        scaleAnt = affineTransform.getScaleX();
358
        origin = mapOrigin;             
359
    }
360
    
361
    protected void createImage(Graphics2D g, AffineTransform affineTransform,
362
                    int width, int height, Point mapOrigin) throws ReadException, MapContextException {
363
            ViewPort viewPort = this.getMapContext().getViewPort();
364

    
365
        //If the image has to be created...
366
            if (origin == null ||
367
                            !origin.equals(mapOrigin) ||
368
                            affineTransform.getScaleX() != scaleAnt ||
369
                            m_image == null ||
370
                            !b_validCache) { 
371

    
372
                    viewPort.setDPI(getDrawPaperDPI());
373
                viewPort.setImageSize(new Dimension(width, height)); 
374
            
375
            m_image =
376
                    new BufferedImage(
377
                                    width,
378
                                    height,
379
                                    BufferedImage.TYPE_INT_ARGB);
380

    
381
            Graphics2D gimg = (Graphics2D) m_image.createGraphics();
382
            getMapContext().draw(m_image, gimg, getScale());
383
            gimg.dispose();
384
            b_validCache = true;
385
        } 
386

    
387
    }
388
    
389
    protected void drawImage(Graphics2D g, BufferedImage image,
390
                    Rectangle2D.Double visibleRectangle) {
391

    
392
            Color theBackColor = getMapContext().getViewPort().getBackColor();
393
        if (theBackColor != null) {
394
            g.setColor(theBackColor);
395
            g.fillRect((int) visibleRectangle.x, (int) visibleRectangle.y,
396
                            (int)visibleRectangle.width,
397
                            (int)visibleRectangle.height);
398
        }
399
        g.drawImage(m_image, 
400
                        (int) visibleRectangle.x,
401
                        (int) visibleRectangle.y,
402
                        null);            
403
    }
404

    
405
    protected Rectangle preDraw(Graphics2D g, Rectangle2D.Double fframeViewRect){
406
        Rectangle originalClip = null;
407
        if (g.getClipBounds() != null) {
408
            originalClip = (Rectangle) g.getClipBounds().clone();
409
        }
410
        if (getRotation() != 0) {
411
            g.rotate(Math.toRadians(getRotation()), fframeViewRect.getCenterX(), fframeViewRect.getCenterY()
412
                + (fframeViewRect.height / 2));
413
        }       
414
        g.clipRect((int) fframeViewRect.getMinX(), (int) fframeViewRect.getMinY(),
415
            (int) fframeViewRect.getWidth(), (int) fframeViewRect.getHeight());
416
        return originalClip;
417
    }
418
    
419
    protected void postDraw(Graphics2D g, Rectangle2D.Double fframeViewRect, Rectangle2D visibleLayoutDocRect, BufferedImage imgBase, 
420
        Rectangle originalClip, AffineTransform at){
421
        if (getRotation() != 0) {
422
            g.rotate(Math.toRadians(-getRotation()), fframeViewRect.getCenterX(), fframeViewRect.getCenterY());
423
        }
424
        if (getMapContext() != null) {
425
            setATMap(getMapContext().getViewPort().getAffineTransform());
426
        }
427
        if (originalClip != null) {
428
            g.setClip(originalClip.x, originalClip.y, originalClip.width, originalClip.height);
429
        }            
430
    }
431

    
432
    public void print(Graphics2D g, AffineTransform at, Geometry geom,
433
        PrintAttributes printAttributes) {
434
        Rectangle2D.Double rectangleLayout = getBoundingBox(at);  
435
        
436
        Rectangle originalClip = preDraw(g, rectangleLayout);
437
        print(g, at, printAttributes);
438
        postDraw(g, rectangleLayout, null, null, originalClip, at);
439
        if (showGrid && grid != null) {
440
            grid.print(g, at, geom, printAttributes);
441
        }    
442
    }
443

    
444
    protected void print(Graphics2D g, AffineTransform at, PrintAttributes printAttributes) {
445
        Rectangle2D.Double layoutRectangle = getBoundingBox(at);
446
        
447
        // FIXME: should we clone the mapcontext and viewport before printing ??
448
        // otherwise we will probably have unexpected results if the user modifies
449
        // the layout while printing
450
        ViewPort viewPort = this.getMapContext().getViewPort();
451
        
452
        Point2D old_offset = viewPort.getOffset();
453
        Dimension old_imgsize = viewPort.getImageSize();
454
        
455
        viewPort.setOffset(new Point2D.Double(layoutRectangle.x, layoutRectangle.y));
456
        viewPort.setImageSize(new Dimension((int) layoutRectangle.width, (int) layoutRectangle.height));
457

    
458
        //Draw the backgroung color of the map
459
        Color theBackColor = viewPort.getBackColor();
460
        if (theBackColor != null) {
461
            g.setColor(theBackColor);
462
            g.fillRect((int) layoutRectangle.x, (int) layoutRectangle.y, viewPort
463
                    .getImageWidth(), viewPort
464
                    .getImageHeight());
465
        }        
466
        
467
        //Print the map
468
        try {
469
            this.getMapContext().print(g, getScale(), printAttributes);
470
        } catch (ReadException e) {
471
            NotificationManager.addError(e.getMessage(), e);
472
        } catch (MapContextException e) {
473
            NotificationManager.addError(e.getMessage(), e);
474
        }      
475
        
476
        // Restore offset, imgsize
477
        viewPort.setOffset(old_offset);
478
        viewPort.setImageSize(old_imgsize);
479
    }
480

    
481
    /**
482
     * Rellena la unidad de medida en la que est? la vista.
483
     * 
484
     * @param i
485
     *            entero que representa la unidad de medida de la vista.
486
     */
487
    public void setMapUnits(int i) {
488
        mapUnits = i;
489
    }
490

    
491
    /**
492
     * Obtiene la unidad de medida en la que est? la vista.
493
     * 
494
     * @return Unidad de medida.
495
     */
496
    public int getMapUnits() {
497
        return mapUnits;
498
    }
499

    
500
    /**
501
     * Devuelve la escala seg?n el tipo de escala que se haya seleccionado al
502
     * a?adida la vista.
503
     * 
504
     * @return escala.
505
     */
506
    public long getScale() {
507
            return (long) getMapContext().getScaleView();
508
    }
509

    
510
    /**
511
     * Seleccionar si la vista esta relacionada o no con la original.
512
     * 
513
     * @param b
514
     *            true si est? ligada y false si no lo est?.
515
     */
516
    public void setLinked(boolean b) {
517
        linked = b;
518
        resetListeners();
519
    }
520

    
521
    /**
522
     * Devuelve si est? ligada o no el FFrameView con la vista.
523
     * 
524
     * @return True si la vista est? ligada.
525
     */
526
    public boolean getLinked() {
527
        return linked;
528
    }
529

    
530
    /**
531
     * Devuelve el tipo de escala que est? seleccionada AUTOMATICO o
532
     * MANUAL.
533
     * 
534
     * @return entero que representa el tipo seleccionado.
535
     */
536
    public int getTypeScale() {
537
        return typeScale;
538
    }
539

    
540
    /**
541
     * Rellenar el tipo de escala que se desea.
542
     * 
543
     * @param i
544
     *            entero que representa el tipo de escala.
545
     */
546
    public void setTypeScale(int i) {
547
        typeScale = i;
548
        resetListeners();
549
    }
550

    
551
    /**
552
     * Inserta la imagen para repintar el FFrameView.
553
     * 
554
     * @param bi
555
     *            Imagen para repintar.
556
     */
557
    public void setBufferedImage(BufferedImage bi) {
558
        m_image = bi;
559
    }
560

    
561
    /**
562
     * Devuelve la imagen para repintar.
563
     * 
564
     * @return Imagen para repintar.
565
     */
566
    public BufferedImage getBufferedImage() {
567
        return m_image;
568
    }
569

    
570
    /**
571
     * Devuelve la MAtriz de transformaci?n utilizada por la FFrameView.
572
     * 
573
     * @return MAtriz de transformaci?n.
574
     */
575
    public AffineTransform getATMap() {
576
        return at;
577
    }
578

    
579
    /**
580
     * Inserta la matriz de transformaci?n.
581
     * 
582
     * @param transform
583
     *            Matriz de transformaci?n.
584
     */
585
    public void setATMap(AffineTransform transform) {
586
        at = transform;
587
    }
588

    
589
    /**
590
     * Inserta el proyecto.
591
     * 
592
     * @param p
593
     *            Proyecto.
594
     */
595
    public void setProject(Project p) {
596
        project = p;
597
    }
598

    
599
    /**
600
     * @see org.gvsig.app.project.documents.layout.fframes.IFFrame#getNameFFrame()
601
     */
602
    public String getNameFFrame() {
603
        return PluginServices.getText(this, "Vista") + num;
604
    }
605

    
606
    public String getName() {
607
        return PERSISTENCE_DEFINITION_NAME;
608
    }
609

    
610
    /**
611
     * DOCUMENT ME!
612
     * 
613
     * @param arg0
614
     *            DOCUMENT ME!
615
     * 
616
     * @return DOCUMENT ME!
617
     */
618
    public boolean compare(Object arg0) {
619
        if (!(arg0 instanceof FFrameView)) {
620
            return false;
621
        }
622

    
623
        if (!this.getName().equals(((FFrameView) arg0).getName())) {
624
            return false;
625
        }
626

    
627
        if (Math.abs(this.getBoundBox().getWidth()
628
            - (((FFrameView) arg0).getBoundBox().getWidth())) > 0.05) {
629
            return false;
630
        }
631
        if (Math.abs(this.getBoundBox().getHeight()
632
            - (((FFrameView) arg0).getBoundBox().getHeight())) > 0.05) {
633
            return false;
634
        }
635

    
636
        if (!this.toString().equals(((FFrameView) arg0).toString())) {
637
            return false;
638
        }
639

    
640
        if (this.getMapContext() != null
641
            && !this.getMapContext()
642
                .equals(((FFrameView) arg0).getMapContext())) {
643
            return false;
644
        }
645

    
646
        if (this.getRotation() != ((FFrameView) arg0).getRotation()) {
647
            return false;
648
        }
649
        return true;
650
    }
651
    
652
    public void updateScaleCtrl() {
653
            NewStatusBar statusbar = PluginServices.getMainFrame().getStatusBar();
654
            MapContext mapContext = this.getMapContext();
655
            if (mapContext==null) {
656
                    return;
657
            }
658
            statusbar.setMessage("units",
659
                            PluginServices.getText(this, mapContext.getDistanceName()));
660
            statusbar.setControlValue("layout-view-change-scale",
661
                            String.valueOf(getMapContext().getScaleView()));
662
            IProjection proj = mapContext.getViewPort().getProjection();
663
            if (proj != null) {
664
                    statusbar.setMessage("projection", proj.getAbrev());
665
            } else {
666
                    statusbar.setMessage("projection", "");
667
            }
668
    }
669

    
670
    public void fullExtent() throws ReadException {
671
        setNewEnvelope(getMapContext().getFullEnvelope());
672
    }
673

    
674
    public void setPointsToZoom(Point2D px1, Point2D px2) {
675
        p1 = px1;
676
        p2 = px2;
677
    }
678

    
679
    public void movePoints(Point2D px1, Point2D px2) {
680
        double difX = -px2.getX() + px1.getX();
681
        double difY = -px2.getY() + px1.getY();
682
        if (p1 != null) {
683
            p1.setLocation(p1.getX() + difX, p1.getY() + difY);
684
            p2.setLocation(p2.getX() + difX, p2.getY() + difY);
685
        }
686
    }
687

    
688
    /**
689
     * This method deals with places where this fframeview and the cloned
690
     * fframeview (frame) are registered as listeners. The goal should be
691
     * leaving the cloned instance (frame) as listener in the same way
692
     * that 'this' instance is doing.
693
     */
694
    protected void cloneActions(FFrameView frame) {
695
    }
696

    
697
    public Object clone() throws CloneNotSupportedException {
698
            Document d = ProjectManager.getInstance().getCurrentProject().getDocuments().get(0);
699
        FFrameView frame = (FFrameView) super.clone();
700
        frame.setView(this.getView());
701
        frame.createListeners(); // necessary to create the listeners within the right scope
702

    
703
        if (grid != null) {
704
            FFrameGrid newGrid = (FFrameGrid) this.grid.clone();
705
            newGrid.setFFrameDependence(frame);
706
            frame.setGrid(newGrid);
707
        }
708
        cloneActions(frame);
709
        return frame;
710
    }
711

    
712
    public void setGrid(IFFrame grid) {
713
        this.grid = grid;
714
        this.grid.setRotation(this.getRotation());
715
    }
716

    
717
    public IFFrame getGrid() {
718
        return this.grid;
719
    }
720

    
721
    public void setRotation(double rotation) {
722
        super.setRotation(rotation);
723
        if (grid != null) {
724
            grid.setRotation(rotation);
725
        }
726
    }
727

    
728
    public void showGrid(boolean b) {
729
        showGrid = b;
730
    }
731

    
732
    public boolean isShowGrid() {
733
        return showGrid;
734
    }
735

    
736
    public void refreshOriginalExtent() {
737
    }
738

    
739
    public static void registerPersistent() {
740
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
741
        if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) {
742
//            DynStruct definition =
743
//                    manager.addDefinition(FLyrVect.class,
744
//                        "FLyrVect",
745
//                        "FLyrVect Persistence definition",
746
//                        null,
747
//                        null);
748
//                definition.extend(PersistenceManager.PERSISTENCE_NAMESPACE,
749
//                    "FLyrDefault");
750
//
751
//                definition.addDynFieldObject("legend")
752
//                    .setClassOfValue(IVectorLegend.class)
753
                
754
            DynStruct definition =
755
                manager.addDefinition(FFrameView.class,
756
                    PERSISTENCE_DEFINITION_NAME,
757
                    "FFrameView persistence definition", null, null); 
758
            definition.extend(manager
759
                .getDefinition(FFrame.PERSISTENCE_DEFINITION_NAME));
760

    
761
            definition.addDynFieldInt(MODE_FIELD).setMandatory(true);
762
            definition.addDynFieldInt(TYPESCALE_FIELD).setMandatory(true);
763
            definition.addDynFieldInt(EXTENSION_FIELD).setMandatory(false);
764
            definition.addDynFieldInt(QUALITY_FIELD).setMandatory(true);
765
            definition.addDynFieldBoolean(BLINKED_FIELD).setMandatory(true);
766
            definition.addDynFieldInt(MAPUNITS_FIELD).setMandatory(true);
767
            definition.addDynFieldDouble(SCALE_FIELD).setMandatory(false);
768
            definition.addDynFieldObject(VIEW_FIELD)
769
                .setClassOfValue(ViewDocument.class).setMandatory(false);
770
            definition.addDynFieldObject(ENVELOPE_FIELD)
771
                .setClassOfValue(Envelope.class).setMandatory(false);
772
            definition.addDynFieldBoolean(SHOWGRID_FIELD).setMandatory(true);
773
            definition.addDynFieldObject(GRID_FIELD)
774
                .setClassOfValue(IFFrame.class).setMandatory(false);
775
            definition.addDynFieldBoolean(HAS_TOC).setMandatory(false);
776
        }
777
    }
778

    
779
    @Override
780
    public void loadFromState(PersistentState state)
781
        throws PersistenceException {
782
        super.loadFromState(state);
783
        mode = state.getInt(MODE_FIELD);
784
        typeScale = state.getInt(TYPESCALE_FIELD);
785
        quality = state.getInt(QUALITY_FIELD);
786
        linked = state.getBoolean(BLINKED_FIELD);
787
        mapUnits = state.getInt(MAPUNITS_FIELD);;
788
        viewDocument = (ViewDocument) state.get(VIEW_FIELD);
789
        if (state.hasValue(HAS_TOC)) {
790
                this.b_hasToc = state.getBoolean(HAS_TOC);
791
        }        
792
        if (viewDocument!=null) {
793
                this.setView(viewDocument);
794
                // it is crucial to don't persist the MapContext and get a cloned one from the View instead,
795
                // as the cloned instance is different from the one created using persistence. In particular,
796
                // the cloned one will share the EventBuffer with the original one, while persistence would
797
                // create 2 separate EventBuffers, which will then have a very stange behaviour
798
        }
799
        if (getMapContext()!=null) {
800
                double mapScale = state.getDouble(SCALE_FIELD);
801
                getMapContext().setScaleView((long)mapScale); // FIXME: really needed?? probably already persisted on Mapcontext
802
                getMapContext().getViewPort().setEnvelope(
803
                (Envelope) state.get(ENVELOPE_FIELD));
804
                if (this.getLayoutContext()!=null) {
805
                        this.getLayoutContext().setTocModel(getMapContext());
806
                }
807

    
808
        }
809
        showGrid = state.getBoolean(SHOWGRID_FIELD);
810
        grid = (IFFrame) state.get(GRID_FIELD);
811
    }
812

    
813
    @Override
814
    public void saveToState(PersistentState state) throws PersistenceException {
815
        super.saveToState(state);
816
        state.set(MODE_FIELD, mode);
817
        state.set(TYPESCALE_FIELD, typeScale);
818
        state.set(QUALITY_FIELD, quality);
819
        state.set(BLINKED_FIELD, linked);
820
        state.set(MAPUNITS_FIELD, mapUnits);
821
        state.set(VIEW_FIELD, viewDocument);
822
        state.set(HAS_TOC, b_hasToc);
823

    
824
        if (getMapContext() != null
825
            && getMapContext().getViewPort().getEnvelope() != null) {
826
            state.set(ENVELOPE_FIELD, getMapContext().getViewPort()
827
                .getEnvelope());
828
            state.set(SCALE_FIELD, (double)getMapContext().getScaleView());
829
        }
830

    
831
        state.set(SHOWGRID_FIELD, showGrid);
832
        state.set(GRID_FIELD, grid);
833
    }
834
    
835
    @Override
836
    public void setBoundBox(Rectangle2D r) {
837
            super.setBoundBox(r);
838
            if (getMapContext()!=null) {
839
                    getMapContext().getViewPort().setImageSize(
840
                                    new Dimension((int)r.getWidth(), (int)r.getHeight()));
841
                    getMapContext().getViewPort().setDPI(getDrawPaperDPI());
842
                    updateScaleCtrl();
843
                    // FIXME: what should we do here? should we invalidate the cache?
844
                    // should we also trigger a Layout redraw?
845
                    refresh();
846
            }
847
    }   
848

    
849
    /**
850
     * getRotation returns rotation of the frame
851
     * getMapRotation returns rotation of the map
852
     * 
853
     * @return in degrees
854
     */
855
    public double getMapRotation() {
856
        return 0;
857
    }
858
    
859
        protected void invalidateLayout() {
860
                b_validCache = false;
861
                if (getLayoutContext()!=null) {
862
                        getLayoutContext().notifAllObservers();
863
                }
864
        observers.notifyObservers(this, 
865
                new DefaultLayoutNotification(LayoutNotification.LAYOUT_REFRESH));
866
        }
867
        
868
        protected void invalidateToc() {
869
                if (getLayoutContext()!=null) {
870
                        getLayoutContext().notifyTocUpdated(TocModelChangedNotification.Type.MODEL_CHANGED);
871
                }
872
        }
873

    
874
        public void refresh() {
875
        // FIXME: what should we do here? do we really need to invalidate cache??
876
            b_validCache = false;                
877
        }
878
    
879
    protected void resetListeners() {
880
                if (this.getMapContext()!=null) {
881
                        clearOwnListeners(this.getMapContext());
882
                }
883
                if (this.getView()!=null && this.getView().getMapContext()!=null) {
884
                        clearViewListeners(this.getView().getMapContext());
885
                }
886
            setListeners();
887
    }
888
    
889
    protected void setListeners() {
890
            if (getView()!=null) {
891
                    if (linked) {
892
                            getView().getMapContext().addLayerListener(viewDocListener);
893
                            getView().getMapContext().getLayers().addLayerCollectionListener(viewDocListener);
894
                            getView().getMapContext().addAtomicEventListener(viewDocListener);
895
                    }
896
                    if (getTypeScale()==IFFrameUseFMap.AUTOMATICO) {
897
                            getView().getMapContext().getViewPort().addViewPortListener(viewDocListener);
898
                    }
899
            }
900
            if (getMapContext()!=null) {
901
                    getMapContext().addLayerListener(ownMapContextListener);
902
                    getMapContext().getLayers().addLayerCollectionListener(ownMapContextListener);
903
                    getMapContext().getViewPort().addViewPortListener(ownMapContextListener);
904
            }
905
    }
906
    protected void clearOwnListeners(MapContext mapContext) {
907
            mapContext.removeLayerListener(ownMapContextListener);
908
            mapContext.getViewPort().removeViewPortListener(ownMapContextListener);
909
            mapContext.getLayers().removeLayerCollectionListener(ownMapContextListener);
910
    }
911
    protected void clearViewListeners(MapContext mapContext) {
912
            mapContext.removeLayerListener(viewDocListener);
913
            mapContext.getViewPort().removeViewPortListener(viewDocListener);
914
            mapContext.getLayers().removeLayerCollectionListener(viewDocListener);
915
    }
916
    
917
    /*
918
     * (non-Javadoc)
919
     * @see org.gvsig.tools.dispose.Disposable#dispose()
920
     */
921
        public void dispose() {
922
                try {
923
                        if (this.getMapContext()!=null) {
924
                                clearOwnListeners(this.getMapContext());
925
                        }
926
                        if (this.getView()!=null && this.getView().getMapContext()!=null) {
927
                                clearViewListeners(this.getView().getMapContext());
928
                        }
929
                }
930
                catch (Exception ex) {}
931
                this.viewDocument = null;
932
                this.mapContext = null;
933
        }
934

    
935
        public void frameRemoved() {
936
                if (mapContext!=null) {
937
                        clearOwnListeners(mapContext);
938
                }
939
                if (this.getView()!=null && this.getView().getMapContext()!=null) {
940
                        clearViewListeners(this.getView().getMapContext());
941
                }
942
                if (b_hasToc && getLayoutContext()!=null) {
943
                        getLayoutContext().setTocModel(null);
944
                }
945
                m_image = null; // FIXME: we could instead move it to a LRU cache to keep the last N images
946
        }
947

    
948
        public void frameAdded() {
949
                setListeners();
950
                updateScaleCtrl();
951
        }
952
        
953
        public void setHasToc(boolean hasToc) {
954
                this.b_hasToc = hasToc;
955
                setTocModel();
956
        }
957
        
958
        protected void setTocModel() {
959
                if (getLayoutContext()!=null) {
960
                        if (b_hasToc && getMapContext()!=null) {
961
                                getLayoutContext().setTocModel(getMapContext());
962
                        }
963
                        else {
964
                                getLayoutContext().setTocModel(null);
965
                        }
966
                }
967
        }
968
        
969
        @Override
970
        protected void doSetSelected(int selectedStatus) {
971
                boolean oldSelectedStatus = isSelected();
972
                super.doSetSelected(selectedStatus);
973
                if (!oldSelectedStatus && isSelected()) { // changed from not selected to selected
974
                        setTocModel();
975
                        updateScaleCtrl();
976
                }
977
        }
978

    
979
        private class ViewDocListener
980
        implements ViewPortListener, LegendListener, LayerCollectionListener, AtomicEventListener {
981

    
982
                public void extentChanged(ExtentEvent e) {
983
                        if (!b_fframeOriginatedUpdate && getTypeScale()==AUTOMATICO) {
984
                                if (getMapContext()!=null) {
985
                                        b_viewOriginatedUpdate = true;
986
                                        getMapContext().getViewPort().setEnvelope(e.getNewExtent());
987
                                        updateScaleCtrl();
988
                                        invalidateLayout();
989
                                        b_viewOriginatedUpdate = false;
990
                                }
991
                        }                        
992
                }
993

    
994
                public void backColorChanged(ColorEvent e) {
995
                        if (!b_fframeOriginatedUpdate && linked) {
996
                                if (getMapContext()!=null) {
997
                                        b_viewOriginatedUpdate = true;
998
                                        mapContext.getViewPort().setBackColor(e.getNewColor());
999
                                        invalidateLayout();
1000
                                        b_viewOriginatedUpdate = true;
1001
                                }
1002
                        }
1003
                }
1004

    
1005
                public void projectionChanged(ProjectionEvent e) {
1006
                        if (!b_fframeOriginatedUpdate && getTypeScale()==AUTOMATICO) {
1007
                                if (getMapContext()!=null) {
1008
                                        b_viewOriginatedUpdate = true;
1009
                                        getMapContext().getViewPort().setProjection(e.getNewProjection());
1010
                                        invalidateLayout();
1011
                                        // FIXME: force also a view redraw someway??
1012
                                        b_viewOriginatedUpdate = false;
1013
                                }
1014
                        }
1015
                }
1016

    
1017
                public void conditionalRedraw() {
1018
                        if (!b_fframeOriginatedUpdate && linked) {
1019
                                b_viewOriginatedUpdate = true;
1020
                                invalidateLayout();
1021
                                // the view should also receive the event and update automatically
1022
                                b_viewOriginatedUpdate = false;
1023
                        }                        
1024
                }
1025

    
1026
                public void legendChanged(LegendChangedEvent e) {
1027
                        conditionalRedraw();
1028
                        invalidateToc();
1029
                }
1030

    
1031
                public void layerAdded(LayerCollectionEvent e) {
1032
                        conditionalRedraw();
1033
                        invalidateToc();
1034
                }
1035

    
1036
                public void layerMoved(LayerPositionEvent e) {
1037
                        conditionalRedraw();
1038
                        invalidateToc();
1039
                }
1040

    
1041
                public void layerRemoved(LayerCollectionEvent e) {
1042
                        conditionalRedraw();
1043
                        invalidateToc();
1044
                }
1045

    
1046
                public void layerAdding(LayerCollectionEvent e)
1047
                                throws CancelationException {
1048
                        // nothing needed
1049
                }
1050

    
1051
                public void layerMoving(LayerPositionEvent e)
1052
                                throws CancelationException {
1053
                        // nothing needed
1054
                }
1055

    
1056
                public void layerRemoving(LayerCollectionEvent e)
1057
                                throws CancelationException {
1058
                        // nothing needed
1059
                }
1060

    
1061
                public void visibilityChanged(LayerCollectionEvent e)
1062
                                throws CancelationException {
1063
                        // this event is not being received, maybe is only triggered if the
1064
                        // visibility of the whole group changes??
1065
                        conditionalRedraw();
1066
                        invalidateToc();
1067
                }
1068

    
1069
                public void atomicEvent(AtomicEvent e) {
1070
                        conditionalRedraw();
1071
                        invalidateToc();
1072
                }
1073
        }
1074

    
1075
        private class OwnMapContextListener
1076
                implements ViewPortListener, LegendListener, LayerCollectionListener {
1077

    
1078
                public void extentChanged(ExtentEvent e) {
1079
                        if (!b_viewOriginatedUpdate && (getTypeScale() == AUTOMATICO)) {
1080
                                if (getView()!=null) {
1081
                                        b_fframeOriginatedUpdate = true;
1082
                                        getView().getMapContext().getViewPort().setEnvelope(e.getNewExtent());
1083
                                        updateScaleCtrl();
1084
                                        invalidateLayout();
1085
                                        b_fframeOriginatedUpdate = false;
1086
                                }
1087
                        }                        
1088
                }
1089

    
1090
                public void backColorChanged(ColorEvent e) {
1091
                        if (!b_viewOriginatedUpdate && linked) {
1092
                                if (getView()!=null) {
1093
                                        b_fframeOriginatedUpdate = true;
1094
                                        getView().getMapContext().getViewPort().setBackColor(e.getNewColor());
1095
                                        invalidateLayout();
1096
                                        b_fframeOriginatedUpdate = false;
1097
                                }
1098
                        }
1099
                }
1100

    
1101
                public void projectionChanged(ProjectionEvent e) {
1102
                        if (!b_viewOriginatedUpdate && (getTypeScale() == AUTOMATICO)) {
1103
                                if (getView()!=null) {
1104
                                        b_fframeOriginatedUpdate = true;
1105
                                        getView().getMapContext().getViewPort().setProjection(e.getNewProjection());
1106
                                        invalidateLayout();
1107
                                        // FIXME: force also a view redraw someway??
1108
                                        b_fframeOriginatedUpdate = false;
1109
                                }
1110
                        }
1111
                }
1112

    
1113
                public void conditionalRedraw() {
1114
                        if (!b_viewOriginatedUpdate && linked) {
1115
                                b_fframeOriginatedUpdate = true;
1116
                                invalidateLayout();
1117
                                // the view should also receive the event and update automatically
1118
                                b_fframeOriginatedUpdate = false;
1119
                        }
1120
                }
1121

    
1122
                public void legendChanged(final LegendChangedEvent e) {
1123
                        conditionalRedraw();
1124
                        invalidateToc();
1125
                }
1126

    
1127
                public void layerAdded(final LayerCollectionEvent e) {
1128
                        conditionalRedraw();
1129
                        invalidateToc();
1130
                }
1131

    
1132
                public void layerMoved(final LayerPositionEvent e) {
1133
                        conditionalRedraw();
1134
                        invalidateToc();
1135
                }
1136

    
1137
                public void layerRemoved(final LayerCollectionEvent e) {
1138
                        conditionalRedraw();
1139
                        invalidateToc();
1140
                }
1141

    
1142
                public void layerAdding(LayerCollectionEvent e)
1143
                                throws CancelationException {
1144
                        // nothing neededO
1145

    
1146
                }
1147

    
1148
                public void layerMoving(LayerPositionEvent e)
1149
                                throws CancelationException {
1150
                        // nothing needed
1151

    
1152
                }
1153

    
1154
                public void layerRemoving(LayerCollectionEvent e)
1155
                                throws CancelationException {
1156
                        // nothing needed
1157

    
1158
                }
1159

    
1160
                public void visibilityChanged(LayerCollectionEvent e)
1161
                                throws CancelationException {
1162
                        conditionalRedraw();
1163
                }
1164

    
1165
        }
1166
}