Statistics
| Revision:

svn-document-layout / branches / usability_v2 / org.gvsig.app.document.layout.app / org.gvsig.app.document.layout.app.mainplugin / src / main / java / org / gvsig / app / project / documents / layout / fframes / FFrameView.java @ 147

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.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
                viewPort.refreshExtent(); // really needed (calculateAffineTransform is already called by setImageSize, but extentChanged listeners are not notified 
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.extend(manager
762
                .getDefinition(FFrame.PERSISTENCE_DEFINITION_NAME));
763

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

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

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

    
811
        showGrid = state.getBoolean(SHOWGRID_FIELD);
812
        grid = (IFFrame) state.get(GRID_FIELD);
813
    }
814

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

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

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

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

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

    
939
        /**
940
         * This method is called just before the FFrame is going to
941
         * be removed from the Layout
942
         */
943
        protected void beforeRemoved() {
944
                if (mapContext!=null) {
945
                        clearOwnListeners(mapContext);
946
                }
947
                if (this.getView()!=null && this.getView().getMapContext()!=null) {
948
                        clearViewListeners(this.getView().getMapContext());
949
                }
950
                if (b_hasToc && getLayoutContext()!=null) {
951
                        getLayoutContext().setTocModel(null);
952
                }
953
        }
954

    
955
        /**
956
         * This method is called just after the FFrame has been
957
         * added to the Layout
958
         */
959
        protected void afterAdded() {
960
                setListeners();
961
                updateScaleCtrl();
962
        }
963
        
964
        public void setHasToc(boolean hasToc) {
965
                this.b_hasToc = hasToc;
966
                setTocModel();
967
        }
968
        
969
        protected void setTocModel() {
970
                if (getLayoutContext()!=null) {
971
                        if (b_hasToc && getMapContext()!=null) {
972
                                getLayoutContext().setTocModel(getMapContext());
973
                        }
974
                        else {
975
                                getLayoutContext().setTocModel(null);
976
                        }
977
                }
978
        }
979
        
980
        @Override
981
        protected void doSetSelected(int selectedStatus) {
982
                boolean oldSelectedStatus = isSelected();
983
                super.doSetSelected(selectedStatus);
984
                if (!oldSelectedStatus && isSelected()) { // changed from not selected to selected
985
                        setTocModel();
986
                        updateScaleCtrl();
987
                }
988
        }
989

    
990
        private class ViewDocListener
991
        implements ViewPortListener, LegendListener, LayerCollectionListener, AtomicEventListener {
992

    
993
                public void extentChanged(ExtentEvent e) {
994
                        if (!b_fframeOriginatedUpdate && getTypeScale()==AUTOMATICO) {
995
                                if (getMapContext()!=null) {
996
                                        b_viewOriginatedUpdate = true;
997
                                        getMapContext().getViewPort().setEnvelope(e.getNewExtent());
998
                                        updateScaleCtrl();
999
                                        invalidateLayout();
1000
                                        b_viewOriginatedUpdate = false;
1001
                                }
1002
                        }                        
1003
                }
1004

    
1005
                public void backColorChanged(ColorEvent e) {
1006
                        if (!b_fframeOriginatedUpdate && linked) {
1007
                                if (getMapContext()!=null) {
1008
                                        b_viewOriginatedUpdate = true;
1009
                                        mapContext.getViewPort().setBackColor(e.getNewColor());
1010
                                        invalidateLayout();
1011
                                        b_viewOriginatedUpdate = true;
1012
                                }
1013
                        }
1014
                }
1015

    
1016
                public void projectionChanged(ProjectionEvent e) {
1017
                        if (!b_fframeOriginatedUpdate && getTypeScale()==AUTOMATICO) {
1018
                                if (getMapContext()!=null) {
1019
                                        b_viewOriginatedUpdate = true;
1020
                                        getMapContext().getViewPort().setProjection(e.getNewProjection());
1021
                                        invalidateLayout();
1022
                                        // FIXME: force also a view redraw someway??
1023
                                        b_viewOriginatedUpdate = false;
1024
                                }
1025
                        }
1026
                }
1027

    
1028
                public void conditionalRedraw() {
1029
                        if (!b_fframeOriginatedUpdate && linked) {
1030
                                b_viewOriginatedUpdate = true;
1031
                                invalidateLayout();
1032
                                // the view should also receive the event and update automatically
1033
                                b_viewOriginatedUpdate = false;
1034
                        }                        
1035
                }
1036

    
1037
                public void legendChanged(LegendChangedEvent e) {
1038
                        conditionalRedraw();
1039
                        invalidateToc();
1040
                }
1041

    
1042
                public void layerAdded(LayerCollectionEvent e) {
1043
                        conditionalRedraw();
1044
                        invalidateToc();
1045
                }
1046

    
1047
                public void layerMoved(LayerPositionEvent e) {
1048
                        conditionalRedraw();
1049
                        invalidateToc();
1050
                }
1051

    
1052
                public void layerRemoved(LayerCollectionEvent e) {
1053
                        conditionalRedraw();
1054
                        invalidateToc();
1055
                }
1056

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

    
1062
                public void layerMoving(LayerPositionEvent e)
1063
                                throws CancelationException {
1064
                        // nothing needed
1065
                }
1066

    
1067
                public void layerRemoving(LayerCollectionEvent e)
1068
                                throws CancelationException {
1069
                        // nothing needed
1070
                }
1071

    
1072
                public void visibilityChanged(LayerCollectionEvent e)
1073
                                throws CancelationException {
1074
                        conditionalRedraw();
1075
                        invalidateToc();
1076
                }
1077

    
1078
                public void atomicEvent(AtomicEvent e) {
1079
                        conditionalRedraw();
1080
                        invalidateToc();
1081
                }
1082
        }
1083

    
1084
        private class OwnMapContextListener
1085
        implements ViewPortListener, LegendListener, LayerCollectionListener {
1086

    
1087
                public void extentChanged(ExtentEvent e) {
1088
                        if (!b_viewOriginatedUpdate && (getTypeScale() == AUTOMATICO)) {
1089
                                if (getView()!=null) {
1090
                                        b_fframeOriginatedUpdate = true;
1091
                                        getView().getMapContext().getViewPort().setEnvelope(e.getNewExtent());
1092
                                        updateScaleCtrl();
1093
                                        invalidateLayout();
1094
                                        b_fframeOriginatedUpdate = false;
1095
                                }
1096
                        }                        
1097
                }
1098

    
1099
                public void backColorChanged(ColorEvent e) {
1100
                        if (!b_viewOriginatedUpdate && linked) {
1101
                                if (getView()!=null) {
1102
                                        b_fframeOriginatedUpdate = true;
1103
                                        getView().getMapContext().getViewPort().setBackColor(e.getNewColor());
1104
                                        invalidateLayout();
1105
                                        b_fframeOriginatedUpdate = false;
1106
                                }
1107
                        }
1108
                }
1109

    
1110
                public void projectionChanged(ProjectionEvent e) {
1111
                        if (!b_viewOriginatedUpdate && (getTypeScale() == AUTOMATICO)) {
1112
                                if (getView()!=null) {
1113
                                        b_fframeOriginatedUpdate = true;
1114
                                        getView().getMapContext().getViewPort().setProjection(e.getNewProjection());
1115
                                        invalidateLayout();
1116
                                        // FIXME: force also a view redraw someway??
1117
                                        b_fframeOriginatedUpdate = false;
1118
                                }
1119
                        }
1120
                }
1121

    
1122
                public void conditionalRedraw() {
1123
                        if (!b_viewOriginatedUpdate && linked) {
1124
                                b_fframeOriginatedUpdate = true;
1125
                                invalidateLayout();
1126
                                // the view should also receive the event and update automatically
1127
                                b_fframeOriginatedUpdate = false;
1128
                        }
1129
                }
1130

    
1131
                public void legendChanged(final LegendChangedEvent e) {
1132
                        conditionalRedraw();
1133
                }
1134

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

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

    
1143
                public void layerRemoved(final LayerCollectionEvent e) {
1144
                        conditionalRedraw();
1145
                }
1146

    
1147
                public void layerAdding(LayerCollectionEvent e)
1148
                                throws CancelationException {
1149
                        // nothing neededO
1150

    
1151
                }
1152

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

    
1157
                }
1158

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

    
1163
                }
1164

    
1165
                public void visibilityChanged(LayerCollectionEvent e)
1166
                                throws CancelationException {
1167
                        conditionalRedraw();
1168
                }
1169

    
1170
        }
1171
}