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

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

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

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

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

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

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

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

    
130
        private TOC toc;
131
        private boolean b_hasToc = false;
132

    
133

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

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

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

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

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

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

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

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

    
222
    public void setViewMapContext(MapContext viewMapContext) {
223
            if (mapContext!=null) {
224
                    clearOwnListeners(mapContext);
225
            }
226
            try {
227
                    if (linked){
228
                            mapContext =
229
                                            viewMapContext.createNewFMap(
230
                                                            (ViewPort) viewMapContext.getViewPort().clone());
231
                    }
232
                    else {
233
                            mapContext = viewMapContext.cloneFMap();
234
                            mapContext.setViewPort((ViewPort) viewMapContext
235
                                            .getViewPort().clone());
236
                    }
237
                    ViewPort newViewPort = getMapContext().getViewPort();
238
                    newViewPort.setImageSize(new Dimension((int) getBoundingBox(null).width,
239
                                    (int) getBoundingBox(null).height));
240
                    newViewPort.setDPI(getDrawPaperDPI());
241
                    setListeners();
242
                    updateScaleCtrl();
243
            } 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

    
349
        ViewPort viewPort = this.getMapContext().getViewPort();
350
        Color theBackColor = viewPort.getBackColor();
351
            int drawWidth = (int)fframeViewRect.width;
352
            int drawHeight = (int)fframeViewRect.height;
353

    
354
        //If the image has to be created...
355
            if (origin == null ||
356
                            !origin.equals(mapOrigin) ||
357
                            affineTransform.getScaleX() != scaleAnt ||
358
                            m_image == null ||
359
                            !b_validCache) { 
360

    
361
                viewPort.setImageSize(new Dimension(drawWidth, drawHeight));
362
            viewPort.setDPI(getDrawPaperDPI());
363
            m_image =
364
                    new BufferedImage(
365
                                    drawWidth,
366
                                    drawHeight,
367
                                    BufferedImage.TYPE_INT_ARGB);
368

    
369
            Graphics2D gimg = (Graphics2D) m_image.createGraphics();
370
            getMapContext().draw(m_image, gimg, getScale());
371
            gimg.dispose();
372
            b_validCache = true;
373
        } 
374

    
375
        //Draw the created image
376
        if (theBackColor != null) {
377
            g.setColor(theBackColor);
378
            g.fillRect((int) fframeViewRect.x, (int) fframeViewRect.y,
379
                            (int)fframeViewRect.width,
380
                            (int)fframeViewRect.height);
381
        }
382
        g.drawImage(m_image, 
383
                        (int) fframeViewRect.x,
384
                        (int) fframeViewRect.y,
385
                        null);
386
        
387
        scaleAnt = affineTransform.getScaleX();
388
        origin = mapOrigin;             
389
    }
390

    
391
    protected Rectangle preDraw(Graphics2D g, Rectangle2D.Double fframeViewRect){
392
        Rectangle originalClip = null;
393
        if (g.getClipBounds() != null) {
394
            originalClip = (Rectangle) g.getClipBounds().clone();
395
        }
396
        if (getRotation() != 0) {
397
            g.rotate(Math.toRadians(getRotation()), fframeViewRect.getCenterX(), fframeViewRect.getCenterY()
398
                + (fframeViewRect.height / 2));
399
        }       
400
        g.clipRect((int) fframeViewRect.getMinX(), (int) fframeViewRect.getMinY(),
401
            (int) fframeViewRect.getWidth(), (int) fframeViewRect.getHeight());
402
        return originalClip;
403
    }
404
    
405
    protected void postDraw(Graphics2D g, Rectangle2D.Double fframeViewRect, Rectangle2D visibleLayoutDocRect, BufferedImage imgBase, 
406
        Rectangle originalClip, AffineTransform at){
407
        if (getRotation() != 0) {
408
            g.rotate(Math.toRadians(-getRotation()), fframeViewRect.getCenterX(), fframeViewRect.getCenterY());
409
        }
410
        if (getMapContext() != null) {
411
            setATMap(getMapContext().getViewPort().getAffineTransform());
412
        }
413
        if (originalClip != null) {
414
            g.setClip(originalClip.x, originalClip.y, originalClip.width, originalClip.height);
415
        }            
416
    }
417

    
418
    public void print(Graphics2D g, AffineTransform at, Geometry geom,
419
        PrintAttributes printAttributes) {
420
        Rectangle2D.Double rectangleLayout = getBoundingBox(at);  
421
        
422
        Rectangle originalClip = preDraw(g, rectangleLayout);
423
        print(g, at, printAttributes);
424
        postDraw(g, rectangleLayout, null, null, originalClip, at);
425
        if (showGrid && grid != null) {
426
            grid.print(g, at, geom, printAttributes);
427
        }    
428
    }
429

    
430
    protected void print(Graphics2D g, AffineTransform at, PrintAttributes printAttributes) {
431
        Rectangle2D.Double layoutRectangle = getBoundingBox(at);
432
        
433
        // FIXME: should we clone the mapcontext and viewport before printing ??
434
        // otherwise we will probably have unexpected results if the user modifies
435
        // the layout while printing
436
        ViewPort viewPort = this.getMapContext().getViewPort();
437
        
438
        Point2D old_offset = viewPort.getOffset();
439
        Dimension old_imgsize = viewPort.getImageSize();
440
        
441
        viewPort.setOffset(new Point2D.Double(layoutRectangle.x, layoutRectangle.y));
442
        viewPort.setImageSize(new Dimension((int) layoutRectangle.width, (int) layoutRectangle.height));
443

    
444
        //Draw the backgroung color of the map
445
        Color theBackColor = viewPort.getBackColor();
446
        if (theBackColor != null) {
447
            g.setColor(theBackColor);
448
            g.fillRect((int) layoutRectangle.x, (int) layoutRectangle.y, viewPort
449
                    .getImageWidth(), viewPort
450
                    .getImageHeight());
451
        }        
452
        
453
        //Print the map
454
        try {
455
            this.getMapContext().print(g, getScale(), printAttributes);
456
        } catch (ReadException e) {
457
            NotificationManager.addError(e.getMessage(), e);
458
        } catch (MapContextException e) {
459
            NotificationManager.addError(e.getMessage(), e);
460
        }      
461
        
462
        // Restore offset, imgsize
463
        viewPort.setOffset(old_offset);
464
        viewPort.setImageSize(old_imgsize);
465
    }
466

    
467
    /**
468
     * Rellena la unidad de medida en la que est? la vista.
469
     * 
470
     * @param i
471
     *            entero que representa la unidad de medida de la vista.
472
     */
473
    public void setMapUnits(int i) {
474
        mapUnits = i;
475
    }
476

    
477
    /**
478
     * Obtiene la unidad de medida en la que est? la vista.
479
     * 
480
     * @return Unidad de medida.
481
     */
482
    public int getMapUnits() {
483
        return mapUnits;
484
    }
485

    
486
    /**
487
     * Devuelve la escala seg?n el tipo de escala que se haya seleccionado al
488
     * a?adida la vista.
489
     * 
490
     * @return escala.
491
     */
492
    public long getScale() {
493
            return (long) getMapContext().getScaleView();
494
    }
495

    
496
    /**
497
     * Seleccionar si la vista esta relacionada o no con la original.
498
     * 
499
     * @param b
500
     *            true si est? ligada y false si no lo est?.
501
     */
502
    public void setLinked(boolean b) {
503
        linked = b;
504
        resetListeners();
505
    }
506

    
507
    /**
508
     * Devuelve si est? ligada o no el FFrameView con la vista.
509
     * 
510
     * @return True si la vista est? ligada.
511
     */
512
    public boolean getLinked() {
513
        return linked;
514
    }
515

    
516
    /**
517
     * Devuelve el tipo de escala que est? seleccionada AUTOMATICO o
518
     * MANUAL.
519
     * 
520
     * @return entero que representa el tipo seleccionado.
521
     */
522
    public int getTypeScale() {
523
        return typeScale;
524
    }
525

    
526
    /**
527
     * Rellenar el tipo de escala que se desea.
528
     * 
529
     * @param i
530
     *            entero que representa el tipo de escala.
531
     */
532
    public void setTypeScale(int i) {
533
        typeScale = i;
534
        resetListeners();
535
    }
536

    
537
    /**
538
     * Inserta la imagen para repintar el FFrameView.
539
     * 
540
     * @param bi
541
     *            Imagen para repintar.
542
     */
543
    public void setBufferedImage(BufferedImage bi) {
544
        m_image = bi;
545
    }
546

    
547
    /**
548
     * Devuelve la imagen para repintar.
549
     * 
550
     * @return Imagen para repintar.
551
     */
552
    public BufferedImage getBufferedImage() {
553
        return m_image;
554
    }
555

    
556
    /**
557
     * Devuelve la MAtriz de transformaci?n utilizada por la FFrameView.
558
     * 
559
     * @return MAtriz de transformaci?n.
560
     */
561
    public AffineTransform getATMap() {
562
        return at;
563
    }
564

    
565
    /**
566
     * Inserta la matriz de transformaci?n.
567
     * 
568
     * @param transform
569
     *            Matriz de transformaci?n.
570
     */
571
    public void setATMap(AffineTransform transform) {
572
        at = transform;
573
    }
574

    
575
    /**
576
     * Inserta el proyecto.
577
     * 
578
     * @param p
579
     *            Proyecto.
580
     */
581
    public void setProject(Project p) {
582
        project = p;
583
    }
584

    
585
    /**
586
     * @see org.gvsig.app.project.documents.layout.fframes.IFFrame#getNameFFrame()
587
     */
588
    public String getNameFFrame() {
589
        return PluginServices.getText(this, "Vista") + num;
590
    }
591

    
592
    public String getName() {
593
        return PERSISTENCE_DEFINITION_NAME;
594
    }
595

    
596
    /**
597
     * DOCUMENT ME!
598
     * 
599
     * @param arg0
600
     *            DOCUMENT ME!
601
     * 
602
     * @return DOCUMENT ME!
603
     */
604
    public boolean compare(Object arg0) {
605
        if (!(arg0 instanceof FFrameView)) {
606
            return false;
607
        }
608

    
609
        if (!this.getName().equals(((FFrameView) arg0).getName())) {
610
            return false;
611
        }
612

    
613
        if (Math.abs(this.getBoundBox().getWidth()
614
            - (((FFrameView) arg0).getBoundBox().getWidth())) > 0.05) {
615
            return false;
616
        }
617
        if (Math.abs(this.getBoundBox().getHeight()
618
            - (((FFrameView) arg0).getBoundBox().getHeight())) > 0.05) {
619
            return false;
620
        }
621

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

    
626
        if (this.getMapContext() != null
627
            && !this.getMapContext()
628
                .equals(((FFrameView) arg0).getMapContext())) {
629
            return false;
630
        }
631

    
632
        if (this.getRotation() != ((FFrameView) arg0).getRotation()) {
633
            return false;
634
        }
635
        return true;
636
    }
637
    
638
    public void updateScaleCtrl() {
639
            NewStatusBar statusbar = PluginServices.getMainFrame().getStatusBar();
640
            MapContext mapContext = this.getMapContext();
641
            if (mapContext==null) {
642
                    return;
643
            }
644
            statusbar.setMessage("units",
645
                            PluginServices.getText(this, mapContext.getDistanceName()));
646
            statusbar.setControlValue("layout-view-change-scale",
647
                            String.valueOf(getMapContext().getScaleView()));
648
            IProjection proj = mapContext.getViewPort().getProjection();
649
            if (proj != null) {
650
                    statusbar.setMessage("projection", proj.getAbrev());
651
            } else {
652
                    statusbar.setMessage("projection", "");
653
            }
654
    }
655

    
656
    public void fullExtent() throws ReadException {
657
        setNewEnvelope(getMapContext().getFullEnvelope());
658
    }
659

    
660
    public void setPointsToZoom(Point2D px1, Point2D px2) {
661
        p1 = px1;
662
        p2 = px2;
663
    }
664

    
665
    public void movePoints(Point2D px1, Point2D px2) {
666
        double difX = -px2.getX() + px1.getX();
667
        double difY = -px2.getY() + px1.getY();
668
        if (p1 != null) {
669
            p1.setLocation(p1.getX() + difX, p1.getY() + difY);
670
            p2.setLocation(p2.getX() + difX, p2.getY() + difY);
671
        }
672
    }
673

    
674
    /**
675
     * This method deals with places where this fframeview and the cloned
676
     * fframeview (frame) are registered as listeners. The goal should be
677
     * leaving the cloned instance (frame) as listener in the same way
678
     * that 'this' instance is doing.
679
     */
680
    protected void cloneActions(FFrameView frame) {
681
    }
682

    
683
    public Object clone() throws CloneNotSupportedException {
684
        FFrameView frame = (FFrameView) super.clone();
685
        frame.createListeners();
686
        frame.setSelected(this.isSelected());
687
        frame.setTypeScale(this.getTypeScale());
688
        frame.setLinked(linked);
689
        frame.setView(this.getView());
690

    
691
        if (grid != null) {
692
            FFrameGrid newGrid = (FFrameGrid) this.grid.clone();
693
            newGrid.setFFrameDependence(frame);
694
            frame.setGrid(newGrid);
695
        }
696
        cloneActions(frame);
697
        return frame;
698
    }
699

    
700
    public void setGrid(IFFrame grid) {
701
        this.grid = grid;
702
        this.grid.setRotation(this.getRotation());
703
    }
704

    
705
    public IFFrame getGrid() {
706
        return this.grid;
707
    }
708

    
709
    public void setRotation(double rotation) {
710
        super.setRotation(rotation);
711
        if (grid != null) {
712
            grid.setRotation(rotation);
713
        }
714
    }
715

    
716
    public void showGrid(boolean b) {
717
        showGrid = b;
718
    }
719

    
720
    public boolean isShowGrid() {
721
        return showGrid;
722
    }
723

    
724
    public void refreshOriginalExtent() {
725
    }
726

    
727
    public static void registerPersistent() {
728
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
729
        if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) {
730
            DynStruct definition =
731
                manager.addDefinition(FFrameView.class,
732
                    PERSISTENCE_DEFINITION_NAME,
733
                    "FFrameView persistence definition", null, null);
734

    
735
            definition.extend(manager
736
                .getDefinition(FFrame.PERSISTENCE_DEFINITION_NAME));
737

    
738
            definition.addDynFieldInt(MODE_FIELD).setMandatory(true);
739
            definition.addDynFieldInt(TYPESCALE_FIELD).setMandatory(true);
740
            definition.addDynFieldInt(EXTENSION_FIELD).setMandatory(false);
741
            definition.addDynFieldInt(QUALITY_FIELD).setMandatory(true);
742
            definition.addDynFieldBoolean(BLINKED_FIELD).setMandatory(true);
743
            definition.addDynFieldInt(MAPUNITS_FIELD).setMandatory(true);
744
            definition.addDynFieldDouble(SCALE_FIELD).setMandatory(false);
745
            definition.addDynFieldObject(VIEW_FIELD)
746
                .setClassOfValue(ViewDocument.class).setMandatory(false);
747
            definition.addDynFieldObject(ENVELOPE_FIELD)
748
                .setClassOfValue(Envelope.class).setMandatory(false);
749
            definition.addDynFieldBoolean(SHOWGRID_FIELD).setMandatory(true);
750
            definition.addDynFieldObject(GRID_FIELD)
751
                .setClassOfValue(IFFrame.class).setMandatory(false);
752
            definition.addDynFieldObject(MAPCONTEXT_FIELD)
753
                .setClassOfValue(MapContext.class).setMandatory(false);
754
            definition.addDynFieldBoolean(HAS_TOC).setMandatory(false);
755
        }
756
    }
757

    
758
    @Override
759
    public void loadFromState(PersistentState state)
760
        throws PersistenceException {
761
        super.loadFromState(state);
762
        mode = state.getInt(MODE_FIELD);
763
        typeScale = state.getInt(TYPESCALE_FIELD);
764
        quality = state.getInt(QUALITY_FIELD);
765
        linked = state.getBoolean(BLINKED_FIELD);
766
        mapUnits = state.getInt(MAPUNITS_FIELD);;
767
        viewDocument = (ViewDocument) state.get(VIEW_FIELD);
768

    
769
        if (state.hasValue(MAPCONTEXT_FIELD)) {
770
            MapContext mctxt = (MapContext) state.get(MAPCONTEXT_FIELD);
771
            this.setViewMapContext(mctxt);
772
            double mapScale = state.getDouble(SCALE_FIELD);
773
            mapContext.getViewPort().setDPI(getDrawPaperDPI());
774
            mapContext.setScaleView((long)mapScale); // FIXME: really needed?? probably already persisted on Mapcontext
775
            mapContext.getViewPort().setEnvelope(
776
                (Envelope) state.get(ENVELOPE_FIELD));
777
            if (state.hasValue(HAS_TOC)) {
778
                    this.b_hasToc = state.getBoolean(HAS_TOC);
779
                    addToc();
780
            }
781
        }
782

    
783
        showGrid = state.getBoolean(SHOWGRID_FIELD);
784
        grid = (IFFrame) state.get(GRID_FIELD);
785
    }
786
    
787
    protected void addToc() {
788
                if (b_hasToc) {
789
                        if (this.toc==null && getMapContext()!=null) {
790
                            this.toc = new TOC();
791
                            this.toc.setMapContext(getMapContext());
792
                        }
793
                        if (this.getLayoutPanel()!=null) {
794
                                this.getLayoutPanel().addLateralComponent(this.toc);
795
                        }
796
                }
797
    }
798
    
799
    protected void removeToc() {
800
            if (this.getLayoutPanel()!=null && this.toc!=null) {
801
                    this.getLayoutPanel().removeLateralComponent(this.toc);
802
                    this.toc = null;
803
            }
804
    }
805

    
806
    @Override
807
    public void saveToState(PersistentState state) throws PersistenceException {
808
        super.saveToState(state);
809
        state.set(MODE_FIELD, mode);
810
        state.set(TYPESCALE_FIELD, typeScale);
811
        state.set(QUALITY_FIELD, quality);
812
        state.set(BLINKED_FIELD, linked);
813
        state.set(MAPUNITS_FIELD, mapUnits);
814
        state.set(VIEW_FIELD, viewDocument);
815
        state.set(HAS_TOC, toc!=null);
816

    
817
        if (getMapContext() != null
818
            && getMapContext().getViewPort().getEnvelope() != null) {
819
            state.set(ENVELOPE_FIELD, getMapContext().getViewPort()
820
                .getEnvelope());
821
            state.set(SCALE_FIELD, (double)getMapContext().getScaleView());
822
            state.set(MAPCONTEXT_FIELD, mapContext);
823
        }
824

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

    
843
    /**
844
     * getRotation returns rotation of the frame
845
     * getMapRotation returns rotation of the map
846
     * 
847
     * @return in degrees
848
     */
849
    public double getMapRotation() {
850
        return 0;
851
    }
852
    
853
        protected void invalidateLayout() {
854
                b_validCache = false;
855
        observers.notifyObservers(this, 
856
                new DefaultLayoutNotification(LayoutNotification.LAYOUT_REFRESH));
857
        }
858

    
859
        public void refresh() {
860
        // FIXME: what should we do here? do we really need to invalidate cache??
861
            b_validCache = false;                
862
        }
863
    
864
    protected void resetListeners() {
865
                if (this.getMapContext()!=null) {
866
                        clearOwnListeners(this.getMapContext());
867
                }
868
                if (this.getView()!=null && this.getView().getMapContext()!=null) {
869
                        clearViewListeners(this.getView().getMapContext());
870
                }
871
            setListeners();
872
    }
873
    
874
    protected void setListeners() {
875
            if (getView()!=null) {
876
                    if (linked) {
877
                            getView().getMapContext().addLayerListener(viewDocListener);
878
                            getView().getMapContext().getLayers().addLayerCollectionListener(viewDocListener);
879
                            getView().getMapContext().addAtomicEventListener(viewDocListener);
880
                    }
881
                    if (getTypeScale()==IFFrameUseFMap.AUTOMATICO) {
882
                            getView().getMapContext().getViewPort().addViewPortListener(viewDocListener);
883
                    }
884
            }
885
            if (getMapContext()!=null) {
886
                    getMapContext().addLayerListener(ownMapContextListener);
887
                    getMapContext().getLayers().addLayerCollectionListener(ownMapContextListener);
888
                    getMapContext().getViewPort().addViewPortListener(ownMapContextListener);
889
            }
890
    }
891
    protected void clearOwnListeners(MapContext mapContext) {
892
            mapContext.removeLayerListener(ownMapContextListener);
893
            mapContext.getViewPort().removeViewPortListener(ownMapContextListener);
894
            mapContext.getLayers().removeLayerCollectionListener(ownMapContextListener);
895
    }
896
    protected void clearViewListeners(MapContext mapContext) {
897
            mapContext.removeLayerListener(viewDocListener);
898
            mapContext.getViewPort().removeViewPortListener(viewDocListener);
899
            mapContext.getLayers().removeLayerCollectionListener(viewDocListener);
900
    }
901
    
902
    /*
903
     * (non-Javadoc)
904
     * @see org.gvsig.tools.dispose.Disposable#dispose()
905
     */
906
        public void dispose() {
907
                try {
908
                        if (this.getMapContext()!=null) {
909
                                clearOwnListeners(this.getMapContext());
910
                        }
911
                        if (this.getView()!=null && this.getView().getMapContext()!=null) {
912
                                clearViewListeners(this.getView().getMapContext());
913
                        }
914
                }
915
                catch (Exception ex) {}
916
                this.viewDocument = null;
917
                this.mapContext = null;
918
        }
919

    
920
        /**
921
         * This method is called just before the FFrame is going to
922
         * be removed from the Layout
923
         */
924
        protected void beforeRemoved() {
925
                if (mapContext!=null) {
926
                        clearOwnListeners(mapContext);
927
                }
928
                if (this.getView()!=null && this.getView().getMapContext()!=null) {
929
                        clearViewListeners(this.getView().getMapContext());
930
                }
931
                if (b_hasToc) {
932
                        removeToc();
933
                }
934
        }
935

    
936
        /**
937
         * This method is called just after the FFrame has been
938
         * added to the Layout
939
         */
940
        protected void afterAdded() {
941
                addToc();
942
                setListeners();
943
                updateScaleCtrl();
944
        }
945
        
946
        public void setToc(boolean useToc) {
947
                this.b_hasToc = useToc;
948
                if (useToc) {
949
                        addToc();
950
                }
951
                else {
952
                        removeToc();
953
                }
954
        }
955
        
956
        @Override
957
        protected void doSetSelected(int selectedStatus) {
958
                super.doSetSelected(selectedStatus);
959
                addToc();
960
                updateScaleCtrl();
961
        }
962

    
963
        private class ViewDocListener
964
        implements ViewPortListener, LegendListener, LayerCollectionListener, AtomicEventListener {
965

    
966
                public void extentChanged(ExtentEvent e) {
967
                        if (!b_fframeOriginatedUpdate && getTypeScale()==AUTOMATICO) {
968
                                if (getMapContext()!=null) {
969
                                        b_viewOriginatedUpdate = true;
970
                                        getMapContext().getViewPort().setEnvelope(e.getNewExtent());
971
                                        updateScaleCtrl();
972
                                        invalidateLayout();
973
                                        b_viewOriginatedUpdate = false;
974
                                }
975
                        }                        
976
                }
977

    
978
                public void backColorChanged(ColorEvent e) {
979
                        if (!b_fframeOriginatedUpdate && linked) {
980
                                if (getMapContext()!=null) {
981
                                        b_viewOriginatedUpdate = true;
982
                                        mapContext.getViewPort().setBackColor(e.getNewColor());
983
                                        invalidateLayout();
984
                                        b_viewOriginatedUpdate = true;
985
                                }
986
                        }
987
                }
988

    
989
                public void projectionChanged(ProjectionEvent e) {
990
                        if (!b_fframeOriginatedUpdate && getTypeScale()==AUTOMATICO) {
991
                                if (getMapContext()!=null) {
992
                                        b_viewOriginatedUpdate = true;
993
                                        getMapContext().getViewPort().setProjection(e.getNewProjection());
994
                                        invalidateLayout();
995
                                        // FIXME: force also a view redraw someway??
996
                                        b_viewOriginatedUpdate = false;
997
                                }
998
                        }
999
                }
1000

    
1001
                public void conditionalRedraw() {
1002
                        if (!b_fframeOriginatedUpdate && linked) {
1003
                                b_viewOriginatedUpdate = true;
1004
                                invalidateLayout();
1005
                                // the view should also receive the event and update automatically
1006
                                b_viewOriginatedUpdate = false;
1007
                        }                        
1008
                }
1009

    
1010
                public void legendChanged(LegendChangedEvent e) {
1011
                        conditionalRedraw();
1012
                        if (linked && toc!=null) {
1013
                                toc.refresh();
1014
                        }
1015
                }
1016

    
1017
                public void layerAdded(LayerCollectionEvent e) {
1018
                        conditionalRedraw();
1019
                }
1020

    
1021
                public void layerMoved(LayerPositionEvent e) {
1022
                        conditionalRedraw();
1023
                }
1024

    
1025
                public void layerRemoved(LayerCollectionEvent e) {
1026
                        conditionalRedraw();
1027
                }
1028

    
1029
                public void layerAdding(LayerCollectionEvent e)
1030
                                throws CancelationException {
1031
                        // nothing needed
1032
                }
1033

    
1034
                public void layerMoving(LayerPositionEvent e)
1035
                                throws CancelationException {
1036
                        // nothing needed
1037
                }
1038

    
1039
                public void layerRemoving(LayerCollectionEvent e)
1040
                                throws CancelationException {
1041
                        // nothing needed
1042
                }
1043

    
1044
                public void visibilityChanged(LayerCollectionEvent e)
1045
                                throws CancelationException {
1046
                        conditionalRedraw();
1047
                }
1048

    
1049
                public void atomicEvent(AtomicEvent e) {
1050
                        conditionalRedraw();
1051
                        // TODO Auto-generated method stub
1052
                        
1053
                }
1054
        }
1055

    
1056
        private class OwnMapContextListener
1057
        implements ViewPortListener, LegendListener, LayerCollectionListener {
1058

    
1059
                public void extentChanged(ExtentEvent e) {
1060
                        if (!b_viewOriginatedUpdate && (getTypeScale() == AUTOMATICO)) {
1061
                                if (getView()!=null) {
1062
                                        b_fframeOriginatedUpdate = true;
1063
                                        getView().getMapContext().getViewPort().setEnvelope(e.getNewExtent());
1064
                                        updateScaleCtrl();
1065
                                        invalidateLayout();
1066
                                        b_fframeOriginatedUpdate = false;
1067
                                }
1068
                        }                        
1069
                }
1070

    
1071
                public void backColorChanged(ColorEvent e) {
1072
                        if (!b_viewOriginatedUpdate && linked) {
1073
                                if (getView()!=null) {
1074
                                        b_fframeOriginatedUpdate = true;
1075
                                        getView().getMapContext().getViewPort().setBackColor(e.getNewColor());
1076
                                        invalidateLayout();
1077
                                        b_fframeOriginatedUpdate = false;
1078
                                }
1079
                        }
1080
                }
1081

    
1082
                public void projectionChanged(ProjectionEvent e) {
1083
                        if (!b_viewOriginatedUpdate && (getTypeScale() == AUTOMATICO)) {
1084
                                if (getView()!=null) {
1085
                                        b_fframeOriginatedUpdate = true;
1086
                                        getView().getMapContext().getViewPort().setProjection(e.getNewProjection());
1087
                                        invalidateLayout();
1088
                                        // FIXME: force also a view redraw someway??
1089
                                        b_fframeOriginatedUpdate = false;
1090
                                }
1091
                        }
1092
                }
1093

    
1094
                public void conditionalRedraw() {
1095
                        if (!b_viewOriginatedUpdate && linked) {
1096
                                b_fframeOriginatedUpdate = true;
1097
                                invalidateLayout();
1098
                                // the view should also receive the event and update automatically
1099
                                b_fframeOriginatedUpdate = false;
1100
                        }
1101
                }
1102

    
1103
                public void legendChanged(final LegendChangedEvent e) {
1104
                        conditionalRedraw();
1105
                        if (toc!=null) {
1106
                                toc.refresh();
1107
                        }
1108
                }
1109

    
1110
                public void layerAdded(final LayerCollectionEvent e) {
1111
                        conditionalRedraw();
1112
                        if (toc!=null) {
1113
                                toc.refresh();
1114
                        }
1115
                }
1116

    
1117
                public void layerMoved(final LayerPositionEvent e) {
1118
                        conditionalRedraw();
1119
                        if (toc!=null) {
1120
                                toc.refresh();
1121
                        }
1122
                }
1123

    
1124
                public void layerRemoved(final LayerCollectionEvent e) {
1125
                        conditionalRedraw();
1126
                        if (toc!=null) {
1127
                                toc.refresh();
1128
                        }
1129
                }
1130

    
1131
                public void layerAdding(LayerCollectionEvent e)
1132
                                throws CancelationException {
1133
                        // nothing neededO
1134

    
1135
                }
1136

    
1137
                public void layerMoving(LayerPositionEvent e)
1138
                                throws CancelationException {
1139
                        // nothing needed
1140

    
1141
                }
1142

    
1143
                public void layerRemoving(LayerCollectionEvent e)
1144
                                throws CancelationException {
1145
                        // nothing needed
1146

    
1147
                }
1148

    
1149
                public void visibilityChanged(LayerCollectionEvent e)
1150
                                throws CancelationException {
1151
                        conditionalRedraw();
1152
                        toc.refresh();
1153
                }
1154

    
1155
        }
1156
}