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

History | View | Annotate | Download (36.7 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.view.ViewDocument;
48
import org.gvsig.app.project.documents.view.toc.gui.TOC;
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.primitive.Envelope;
53
import org.gvsig.fmap.mapcontext.MapContext;
54
import org.gvsig.fmap.mapcontext.MapContextException;
55
import org.gvsig.fmap.mapcontext.ViewPort;
56
import org.gvsig.fmap.mapcontext.events.AtomicEvent;
57
import org.gvsig.fmap.mapcontext.events.ColorEvent;
58
import org.gvsig.fmap.mapcontext.events.ExtentEvent;
59
import org.gvsig.fmap.mapcontext.events.ProjectionEvent;
60
import org.gvsig.fmap.mapcontext.events.listeners.AtomicEventListener;
61
import org.gvsig.fmap.mapcontext.events.listeners.ViewPortListener;
62
import org.gvsig.fmap.mapcontext.layers.CancelationException;
63
import org.gvsig.fmap.mapcontext.layers.LayerCollectionEvent;
64
import org.gvsig.fmap.mapcontext.layers.LayerCollectionListener;
65
import org.gvsig.fmap.mapcontext.layers.LayerPositionEvent;
66
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
67
import org.gvsig.fmap.mapcontext.rendering.legend.IVectorLegend;
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
    private static final String MAPCONTEXT_FIELD = "mapContext";
99
    // following fields are unused - should be deleted? 
100
    private static final String EXTENSION_FIELD = "extension";
101
    private static final String HAS_TOC = "hasToc";
102

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

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

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

    
132

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
735
    public void refreshOriginalExtent() {
736
    }
737

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

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

    
780
    @Override
781
    public void loadFromState(PersistentState state)
782
        throws PersistenceException {
783
        super.loadFromState(state);
784
        mode = state.getInt(MODE_FIELD);
785
        typeScale = state.getInt(TYPESCALE_FIELD);
786
        quality = state.getInt(QUALITY_FIELD);
787
        linked = state.getBoolean(BLINKED_FIELD);
788
        mapUnits = state.getInt(MAPUNITS_FIELD);;
789
        viewDocument = (ViewDocument) state.get(VIEW_FIELD);
790

    
791
        if (state.hasValue(MAPCONTEXT_FIELD)) {
792
            MapContext mctxt = (MapContext) state.get(MAPCONTEXT_FIELD);
793
            this.setViewMapContext(mctxt);
794
            double mapScale = state.getDouble(SCALE_FIELD);
795
            mapContext.getViewPort().setDPI(getDrawPaperDPI());
796
            mapContext.setScaleView((long)mapScale); // FIXME: really needed?? probably already persisted on Mapcontext
797
            mapContext.getViewPort().setEnvelope(
798
                (Envelope) state.get(ENVELOPE_FIELD));
799
            if (state.hasValue(HAS_TOC)) {
800
                    this.b_hasToc = state.getBoolean(HAS_TOC);
801
                    if (this.getLayoutContext()!=null) {
802
                            this.getLayoutContext().setTocModel(mapContext);
803
                    }
804
            }
805
        }
806

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

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

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

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

    
848
    /**
849
     * getRotation returns rotation of the frame
850
     * getMapRotation returns rotation of the map
851
     * 
852
     * @return in degrees
853
     */
854
    public double getMapRotation() {
855
        return 0;
856
    }
857
    
858
        protected void invalidateLayout() {
859
                b_validCache = false;
860
                if (getLayoutContext()!=null) {
861
                        getLayoutContext().notifAllObservers();
862
                }
863
        observers.notifyObservers(this, 
864
                new DefaultLayoutNotification(LayoutNotification.LAYOUT_REFRESH));
865
        }
866
        
867
        protected void invalidateToc() {
868
                if (getLayoutContext()!=null) {
869
                        getLayoutContext().updateFFrames();
870
                }
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
                        conditionalRedraw();
1064
                        invalidateToc();
1065
                }
1066

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

    
1073
        private class OwnMapContextListener
1074
        implements ViewPortListener, LegendListener, LayerCollectionListener {
1075

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

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

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

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

    
1120
                public void legendChanged(final LegendChangedEvent e) {
1121
                        conditionalRedraw();
1122
                }
1123

    
1124
                public void layerAdded(final LayerCollectionEvent e) {
1125
                        conditionalRedraw();
1126
                }
1127

    
1128
                public void layerMoved(final LayerPositionEvent e) {
1129
                        conditionalRedraw();
1130
                }
1131

    
1132
                public void layerRemoved(final LayerCollectionEvent e) {
1133
                        conditionalRedraw();
1134
                }
1135

    
1136
                public void layerAdding(LayerCollectionEvent e)
1137
                                throws CancelationException {
1138
                        // nothing neededO
1139

    
1140
                }
1141

    
1142
                public void layerMoving(LayerPositionEvent e)
1143
                                throws CancelationException {
1144
                        // nothing needed
1145

    
1146
                }
1147

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

    
1152
                }
1153

    
1154
                public void visibilityChanged(LayerCollectionEvent e)
1155
                                throws CancelationException {
1156
                        conditionalRedraw();
1157
                }
1158

    
1159
        }
1160
}