Statistics
| Revision:

svn-document-layout / tags / 2059 / org.gvsig.app.document.layout.app.mainplugin / src / main / java / org / gvsig / app / project / documents / layout / fframes / FFrameView.java @ 46

History | View | Annotate | Download (39.5 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.Color;
25
import java.awt.Dimension;
26
import java.awt.Graphics;
27
import java.awt.Graphics2D;
28
import java.awt.Image;
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 javax.swing.SwingUtilities;
37

    
38
import org.cresques.cts.IProjection;
39
import org.slf4j.Logger;
40
import org.slf4j.LoggerFactory;
41

    
42
import org.gvsig.andami.PluginServices;
43
import org.gvsig.andami.messages.NotificationManager;
44
import org.gvsig.app.project.Project;
45
import org.gvsig.app.project.documents.layout.DefaultLayoutNotification;
46
import org.gvsig.app.project.documents.layout.FLayoutUtilities;
47
import org.gvsig.app.project.documents.layout.LayoutNotification;
48
import org.gvsig.app.project.documents.view.DefaultViewDocument;
49
import org.gvsig.app.project.documents.view.ViewDocument;
50
import org.gvsig.compat.print.PrintAttributes;
51
import org.gvsig.fmap.dal.exception.ReadException;
52
import org.gvsig.fmap.geom.Geometry;
53
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
54
import org.gvsig.fmap.geom.GeometryLocator;
55
import org.gvsig.fmap.geom.GeometryManager;
56
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
57
import org.gvsig.fmap.geom.primitive.Envelope;
58
import org.gvsig.fmap.mapcontext.MapContext;
59
import org.gvsig.fmap.mapcontext.MapContextException;
60
import org.gvsig.fmap.mapcontext.ViewPort;
61
import org.gvsig.fmap.mapcontext.events.ColorEvent;
62
import org.gvsig.fmap.mapcontext.events.ExtentEvent;
63
import org.gvsig.fmap.mapcontext.events.ProjectionEvent;
64
import org.gvsig.fmap.mapcontext.events.listeners.ViewPortListener;
65
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendChangedEvent;
66
import org.gvsig.fmap.mapcontext.rendering.legend.events.listeners.LegendListener;
67
import org.gvsig.tools.ToolsLocator;
68
import org.gvsig.tools.dynobject.DynStruct;
69
import org.gvsig.tools.persistence.PersistenceManager;
70
import org.gvsig.tools.persistence.PersistentState;
71
import org.gvsig.tools.persistence.exception.PersistenceException;
72

    
73
/**
74
 * FFrame para introducir una vista en el Layout.
75
 * 
76
 * @author Vicente Caballero Navarro
77
 */
78
public class FFrameView extends FFrame implements ViewPortListener,
79
    LegendListener, IFFrameUseProject, IFFrameUseFMap {
80

    
81
    public static final String PERSISTENCE_DEFINITION_NAME = "FFrameView";
82

    
83
    private static final String MODE_FIELD = "mode";
84
    private static final String TYPESCALE_FIELD = "typeScale";
85
    private static final String EXTENSION_FIELD = "extension";
86
    private static final String QUALITY_FIELD = "quality";
87
    private static final String VIEWING_FIELD = "viewing";
88
    private static final String BLINKED_FIELD = "bLinked";
89
    private static final String MAPUNITS_FIELD = "mapUnits";
90
    private static final String SCALE_FIELD = "scale";
91
    private static final String VIEW_FIELD = "view";
92
    private static final String ENVELOPE_FIELD = "envelope";
93
    private static final String SHOWGRID_FIELD = "showGrid";
94
    private static final String GRID_FIELD = "gridview";
95
    private static final String MAPCONTEXT_FIELD = "mapContext";
96

    
97
    private static final GeometryManager geomManager = GeometryLocator
98
        .getGeometryManager();
99
    private static final Logger logger = LoggerFactory
100
        .getLogger(FFrameView.class);
101
    public static final int PRESENTATION = 0;
102
    public static final int DRAFT = 1;
103
    protected int mode;
104
    protected int typeScale = AUTOMATICO;
105
    protected int extension = 0;
106
    protected int quality = PRESENTATION;
107
    protected int viewing = 0;
108
    protected boolean linked = true;
109
    protected ViewDocument viewDocument = null;
110
    protected MapContext mapContext = null;
111
    protected double mapScale = 0;
112
    protected int mapUnits = 1; // Meters.
113

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

    
125
    /**
126
     * Creates a new FFrameView object.
127
     */
128
    public FFrameView() {
129
        num++;
130
    }
131

    
132
    /**
133
     * Devuelve una descripci?n del FFrameView.
134
     * 
135
     * @return Descripci?n.
136
     */
137
    public String toString() {
138
        if (getView() == null) {
139
            return "FFrameView " + num + ": " + "Vacio";
140
        }
141

    
142
        return "FFrameView " + num + ": " + getView().getName();
143
    }
144

    
145
    /**
146
     * Rellena la escala de la vista que contiene el fframe.
147
     * 
148
     * @param d
149
     *            escala de la vista.
150
     */
151
    public void setScale(double d) {
152
        mapScale = d;
153
    }
154

    
155
    /**
156
     * Inserta el nuevo extent a la FFrameView.
157
     * 
158
     * @param r
159
     *            Rect?ngulo a ocupar por el FFrameView.
160
     */
161
    public void setNewEnvelope(Envelope r) {
162
        getMapContext().getViewPort().setEnvelope(r);
163
        refresh = true;
164
        mapScale =
165
            FLayoutUtilities.getScaleView(getMapContext().getViewPort(),
166
                getBoundBox().width, getBoundingBox(null).width
167
                    / getBoundBox().width);
168
    }
169

    
170
    /**
171
     * Devuelve el FMap de la vista o una clonaci?n de este si se utiliza una
172
     * escala fija.
173
     * 
174
     * @return FMap.
175
     */
176
    public MapContext getMapContext() {
177
        return mapContext;
178
    }
179

    
180
    /**
181
     * Rellena la calidad que se quiere aplicar.
182
     * 
183
     * @param q
184
     *            entero que representa la calidad a aplicar.
185
     */
186
    public void setQuality(int q) {
187
        quality = q;
188
    }
189

    
190
    /**
191
     * Devuelve un entero que representa la calidad que est? seleccionada.
192
     * 
193
     * @return tipo de calidad selccionada.
194
     */
195
    public int getQuality() {
196
        return quality;
197
    }
198

    
199
    /**
200
     * Devuelve un entero que representa la forma en que se actualiza la vista.
201
     * 
202
     * @return forma que se actualiza la vista.
203
     */
204
    public int getViewing() {
205
        return viewing;
206
    }
207

    
208
    /**
209
     * Rellena la forma de actualizar la vista(cuando activo o siempre). De
210
     * momento esta opci?n esta deshabilitada.
211
     * 
212
     * @param v
213
     *            entero que representa la forma de actualizar la vista.
214
     */
215
    public void setViewing(int v) {
216
        viewing = v;
217
    }
218

    
219
    /**
220
     * Inserta el ProjectView de donde obtener las propiedades de la vista a
221
     * mostrar.
222
     * 
223
     * @param v
224
     *            Modelo de la vista.
225
     */
226
    public void setView(DefaultViewDocument v) {
227
        viewDocument = v;
228
        ViewPort vp = null;
229
        if (getMapContext() != null) {
230
            vp = getMapContext().getViewPort();
231
        }else{
232
            try {
233
                vp = (ViewPort) v.getMapContext().getViewPort().clone();
234
            } catch (CloneNotSupportedException e1) {
235
                NotificationManager.addError("Excepci?n :", e1);
236
            }
237

    
238
        }
239
        vp.setImageSize(new Dimension((int) getBoundingBox(null).width,
240
            (int) getBoundingBox(null).height));
241

    
242
        if (linked){
243
            if (getTypeScale() == AUTOMATICO) {
244
                try {
245
                    mapContext =
246
                        v.getMapContext().createNewFMap(
247
                            (ViewPort) v.getMapContext().getViewPort().clone());
248
                } catch (CloneNotSupportedException e1) {
249
                    NotificationManager.addError("Excepci?n :", e1);
250
                }
251

    
252
                mapContext.getViewPort().setImageSize(
253
                    new Dimension((int) getBoundingBox(null).width,
254
                        (int) getBoundingBox(null).height));
255
                v.getMapContext().getViewPort().addViewPortListener(this);
256
                v.getMapContext().addLayerListener(this);
257
            }else{
258
                if (getTypeScale() == CONSTANTE) {
259
                    mapContext = v.getMapContext().createNewFMap(vp);
260
                    vp.setEnvelope(getNewEnvelope(getScale()));
261
                    v.getMapContext().getViewPort().addViewPortListener(this);
262
                    v.getMapContext().addLayerListener(this);
263
                }else{
264
                    if (getTypeScale() == MANUAL) {
265
                        mapContext = v.getMapContext().createNewFMap(vp);
266
                        vp.setEnvelope(getNewEnvelope(getScale()));
267
                        v.getMapContext().getViewPort()
268
                            .addViewPortListener(this);
269
                        v.getMapContext().addLayerListener(this);
270
                    }
271
                }
272
            }
273
        }else{
274
            if (!linked) {
275

    
276
                if (getTypeScale() == AUTOMATICO) {
277
                    mapContext = v.getMapContext().cloneFMap(); // (v.getMapContext().getViewPort().cloneViewPort());
278
                    try {
279
                        mapContext.setViewPort((ViewPort) v.getMapContext()
280
                            .getViewPort().clone());
281
                    } catch (CloneNotSupportedException e1) {
282
                        NotificationManager.addError("Excepci?n :", e1);
283
                    }
284
                    mapContext.getViewPort().setImageSize(
285
                        new Dimension((int) getBoundingBox(null).width,
286
                            (int) getBoundingBox(null).height));
287
                    v.getMapContext().getViewPort().addViewPortListener(this);
288
                }else{
289
                    if (getTypeScale() == CONSTANTE) {
290
                        mapContext = v.getMapContext().cloneFMap();
291
                        vp.setEnvelope(getNewEnvelope(getScale()));
292
                        mapContext.setViewPort(vp);
293
                        v.getMapContext().getViewPort()
294
                            .addViewPortListener(this);
295
                    }else{
296
                        if (getTypeScale() == MANUAL) {
297
                            mapContext = v.getMapContext().cloneFMap();
298
                            vp.setEnvelope(getNewEnvelope(getScale()));
299
                            mapContext.setViewPort(vp);
300
                            v.getMapContext().getViewPort()
301
                                .addViewPortListener(this);
302
                        }
303
                    }
304
                }               
305
            }
306
        }
307
    }
308

    
309
    /**
310
     * Devuelve el modelo de la vista.
311
     * 
312
     * @return Modelo de la vista.
313
     */
314
    public ViewDocument getView() {
315
        return viewDocument;
316
    }
317

    
318
    /**
319
     * Devuelve un Rect?ngulo que representa el extent de la vista que se
320
     * requiere a partir de una escala.
321
     * 
322
     * @param scale
323
     *            Escala a mostrar.
324
     * 
325
     * @return Rect?ngulo.
326
     */
327
    protected Envelope getNewEnvelope(long scale) {
328
        double hview = getBoundBox().getHeight();
329
        double wview = getBoundBox().getWidth();
330
        double hextent = (scale * hview) / 100.0;
331
        double wextent = (scale * wview) / 100.0;
332

    
333
        if (mapContext.getViewPort().getEnvelope() == null) {
334
            try {
335
                return geomManager.createEnvelope(0, 0, 0, 0, SUBTYPES.GEOM2D);
336
            } catch (CreateEnvelopeException e) {
337
                logger.error("Error creating the envelope", e);
338
                return null;
339
            }
340
        }
341
        double newx =
342
            mapContext.getViewPort().getEnvelope().getCenter(Geometry.DIMENSIONS.X)
343
                - (wextent / 2.0);
344
        double newy =
345
            mapContext.getViewPort().getEnvelope().getCenter(Geometry.DIMENSIONS.Y)
346
                - (hextent / 2.0);
347
        IProjection proj = mapContext.getViewPort().getProjection();
348
        Envelope r = null;
349
        try {
350
            r =
351
                geomManager.createEnvelope(newx, newy, newx + wextent, newy
352
                    + hextent, SUBTYPES.GEOM2D);
353
        } catch (CreateEnvelopeException e) {
354
            logger.error("Error creating the envelope", e);
355
        }
356
        if (!proj.isProjected()) {
357
            Rectangle2D auxR =
358
                new Rectangle2D.Double(newx, newy, wextent, hextent);
359
            Rectangle2D aux =
360
                mapContext.getViewPort().getProjection()
361
                    .getExtent(auxR, scale, wview, hview, 1, 100, 2.54);
362
            try {
363
                r =
364
                    geomManager.createEnvelope(aux.getX(), aux.getY(),
365
                        aux.getMaxX(), aux.getMaxY(), SUBTYPES.GEOM2D);
366
            } catch (CreateEnvelopeException e) {
367
                logger.error("Error creating the envelope", e);
368
            }
369
        }
370
        return r;
371
    }
372

    
373
    /**
374
     * M?todo que dibuja sobre el graphics que se le pasa como par?metro, seg?n
375
     * la transformada afin que se debe de aplicar y el rect?ngulo que se debe
376
     * de dibujar.
377
     * 
378
     * @param g
379
     *            Graphics2D
380
     * @param at
381
     *            Transformada af?n.
382
     * @param rectangleView
383
     *            rect?ngulo sobre el que hacer un clip.
384
     * @param imgBase
385
     *            Imagen para acelerar el dibujado.
386
     */
387
    public void draw(Graphics2D g, AffineTransform at, Rectangle2D rectangleView, BufferedImage imgBase) {
388
        Rectangle2D.Double rectangleLayout = getBoundingBox(at);  
389
        Rectangle originalClip = preDraw(g, rectangleLayout);    
390
        if (intersects(rectangleView, rectangleLayout)) {
391
            if (getMapContext() == null) {
392
                drawEmpty(g);
393
            } else {      
394
                if (getQuality() == PRESENTATION) {
395
                    drawPresentation(g, at, rectangleLayout, rectangleView, imgBase);
396
                } else {
397
                    drawDraft(g);
398
                }               
399
            }
400
        }
401
        postDraw(g, rectangleLayout, rectangleView, imgBase, originalClip, at); 
402
        if (showGrid && grid != null) {           
403
            grid.draw(g, at, rectangleView, imgBase);
404
        }    
405
    }
406
    
407
    private void drawPresentation(Graphics2D g, AffineTransform affineTransform, Rectangle2D.Double rectangleLayout, Rectangle2D rectangleView, BufferedImage imgBase){
408
        Point mapOrigin = new Point((int)rectangleView.getMinX(), (int)rectangleView.getMaxY());
409

    
410
        ViewPort viewPort = this.getMapContext().getViewPort();
411
        Color theBackColor = viewPort.getBackColor();
412

    
413
        //If the image has to be created...
414
        if (!(origin != null
415
            && origin.equals(mapOrigin)
416
            && affineTransform.getScaleX() == scaleAnt
417
            && m_image != null
418
            && !refresh
419
            && !(rectangleLayout.getWidth() > rectangleView.getWidth() || rectangleLayout.getHeight() > rectangleView.getHeight()))) {
420

    
421
            double scale1_1 = MapContext.getScreenDPI() / 2.54;
422
            /*
423
             * This is the ratio between the size assumed by the
424
             * mapcontext drawer and the true size on screen
425
             */
426
            double visible_factor = affineTransform.getScaleX() / scale1_1;
427
            int draw_w = (int) (1d * rectangleLayout.width / visible_factor);
428
            int draw_h = (int) (1d * rectangleLayout.height / visible_factor);
429

    
430
            viewPort.setImageSize(new Dimension(draw_w, draw_h));
431
            viewPort.refreshExtent();
432

    
433
            /*
434
            viewPort.setOffset(new Point2D.Double(rectangleLayout.x, rectangleLayout.y));
435
            */
436

    
437
            m_image =
438
                new BufferedImage(
439
                    draw_w, //(int) rectangleLayout.getWidth(),
440
                    draw_h, //(int) rectangleLayout.getHeight(),
441
                    BufferedImage.TYPE_INT_ARGB);
442

    
443
            Graphics2D gimg = (Graphics2D) m_image.getGraphics();
444
            
445
            /*
446
            gimg.translate(-((int) rectangleLayout.getX()),
447
                -((int) rectangleLayout.getY()));
448
            */
449
            
450
            try {
451
                getMapContext().draw(m_image, gimg, getScale());
452
            } catch (ReadException e) {
453
                LOG.error("Error reading the provider" , e);
454
            } catch (MapContextException mpex) {
455
                LOG.error("Error reading the provider" , e);
456
            }
457
            /*
458
            gimg.translate(((int) rectangleLayout.getX()),
459
                ((int) rectangleLayout.getY()));
460
                */
461
            refresh = false;    
462
        } 
463

    
464
        //Draw the created image
465
        if (theBackColor != null) {
466
            g.setColor(theBackColor);
467
            g.fillRect((int) rectangleLayout.x, (int) rectangleLayout.y,
468
                viewPort.getImageWidth(),
469
                viewPort.getImageHeight());
470
        }
471
        
472
        m_image = copyForcingImageSize(
473
            m_image,
474
            (int) rectangleLayout.getWidth(),
475
            (int) rectangleLayout.getHeight());
476

    
477
        g.drawImage(m_image,
478
            (int) rectangleLayout.getX(),
479
            (int) rectangleLayout.getY(), null);
480
        
481
        scaleAnt = affineTransform.getScaleX();
482
        origin = mapOrigin;             
483
    }
484
    
485
    /**
486
     * @param m_image2
487
     * @param width
488
     * @param height
489
     * @return
490
     */
491
    private BufferedImage copyForcingImageSize(Image img, int w, int h) {
492
        
493
        if (img == null || w < 1 || h < 1) {
494
            return new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
495
        }
496
        int from_w = img.getWidth(null);
497
        int from_h = img.getHeight(null);
498
        if (from_w < 1 || from_h < 1) {
499
            return new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
500
        }
501
        
502
        BufferedImage resp =
503
            new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
504
        Graphics rg = resp.getGraphics();
505
        
506
        double rat_w = (1d*w) / (1d*from_w);
507
        double rat_h = (1d*h) / (1d*from_h);
508
        int offset_w = 0;
509
        int offset_h = 0;
510
        Image aux = null;
511

    
512
        if (rat_w <= rat_h) {
513
            // apply resize of width
514
            int target_h = Math.max(1, (int) (from_h * rat_w));
515
            // w, target_h
516
            offset_w = 0;
517
            offset_h = (h - target_h) / 2;
518
            aux = img.getScaledInstance(w, target_h, Image.SCALE_FAST);
519
            rg.drawImage(aux, offset_w, offset_h, null);
520

    
521
        } else {
522
            // apply resize from height
523
            int target_w = Math.max(1, (int) (from_w * rat_h));
524
            // target_w, h
525
            offset_w = (w - target_w) / 2;
526
            offset_h = 0;
527
            aux = img.getScaledInstance(target_w, h, Image.SCALE_FAST);
528
            rg.drawImage(aux, offset_w, offset_h, null);
529
        }
530
        return resp;
531
    }
532

    
533
    private Rectangle preDraw(Graphics2D g, Rectangle2D.Double rectangleLayout){
534
        Rectangle originalClip = null;
535
        if (g.getClipBounds() != null) {
536
            originalClip = (Rectangle) g.getClipBounds().clone();
537
        }
538
        if (getRotation() != 0) {
539
            g.rotate(Math.toRadians(getRotation()), rectangleLayout.getCenterX(), rectangleLayout.getCenterY()
540
                + (rectangleLayout.height / 2));
541
        }       
542
        g.clipRect((int) rectangleLayout.getMinX(), (int) rectangleLayout.getMinY(),
543
            (int) rectangleLayout.getWidth(), (int) rectangleLayout.getHeight());
544
        return originalClip;
545
    }
546
    
547
    private void postDraw(Graphics2D g, Rectangle2D.Double rectangleLayout, Rectangle2D rectangleView, BufferedImage imgBase, 
548
        Rectangle originalClip, AffineTransform at){
549
        if (getRotation() != 0) {
550
            g.rotate(Math.toRadians(-getRotation()), rectangleLayout.getCenterX(), rectangleLayout.getCenterY());
551
        }
552
        if (getMapContext() != null) {
553
            setATMap(getMapContext().getViewPort().getAffineTransform());
554
        }
555
        if (originalClip != null) {
556
            g.setClip(originalClip.x, originalClip.y, originalClip.width, originalClip.height);
557
        }            
558
    }
559

    
560
    private Envelope calculateEnvelope() {
561
        if (p1 == null || p2 == null) {
562
            try {
563
                return geomManager.createEnvelope(0, 0, 0, 0, SUBTYPES.GEOM2D);
564
            } catch (CreateEnvelopeException e) {
565
                logger.error("Error creating the envelope", e);
566
            }
567
        }
568
        Envelope r = null;
569
        try {
570
            r =
571
                geomManager.createEnvelope(p1.getX(), p1.getY(), p2.getX(),
572
                    p2.getY(), SUBTYPES.GEOM2D);
573
        } catch (CreateEnvelopeException e) {
574
            logger.error("Error creating the envelope", e);
575
        }
576
        return r;
577
    }
578

    
579
    public void print(Graphics2D g, AffineTransform at, Geometry geom,
580
        PrintAttributes printAttributes) {
581
        Rectangle2D.Double rectangleLayout = getBoundingBox(at);  
582
        
583
        Rectangle originalClip = preDraw(g, rectangleLayout);
584
        print(g, at, printAttributes);
585
        postDraw(g, rectangleLayout, null, null, originalClip, at);
586
        if (showGrid && grid != null) {
587
            grid.print(g, at, geom, printAttributes);
588
        }    
589
    }
590

    
591
    private void print(Graphics2D g, AffineTransform at, PrintAttributes printAttributes) {
592
        Rectangle2D.Double layoutRectangle = getBoundingBox(at);
593
              
594
        ViewPort viewPort = this.getMapContext().getViewPort();
595
        
596
        viewPort.setOffset(new Point2D.Double(layoutRectangle.x, layoutRectangle.y));
597
        viewPort.setImageSize(new Dimension((int) layoutRectangle.width, (int) layoutRectangle.height));
598

    
599
        //Draw the backgroung color of the map
600
        Color theBackColor = viewPort.getBackColor();
601
        if (theBackColor != null) {
602
            g.setColor(theBackColor);
603
            g.fillRect((int) layoutRectangle.x, (int) layoutRectangle.y, viewPort
604
                    .getImageWidth(), viewPort
605
                    .getImageHeight());
606
        }        
607
        
608
        //Print the map
609
        try {
610
            this.getMapContext().print(g, getScale(), printAttributes);
611
        } catch (ReadException e) {
612
            NotificationManager.addError(e.getMessage(), e);
613
        } catch (MapContextException e) {
614
            NotificationManager.addError(e.getMessage(), e);
615
        }         
616
    }
617

    
618
    /**
619
     * Rellena la unidad de medida en la que est? la vista.
620
     * 
621
     * @param i
622
     *            entero que representa la unidad de medida de la vista.
623
     */
624
    public void setMapUnits(int i) {
625
        mapUnits = i;
626
    }
627

    
628
    /**
629
     * Obtiene la unidad de medida en la que est? la vista.
630
     * 
631
     * @return Unidad de medida.
632
     */
633
    public int getMapUnits() {
634
        return mapUnits;
635
    }
636

    
637
    /**
638
     * Devuelve la escala seg?n el tipo de escala que se haya seleccionado al
639
     * a?adida la vista.
640
     * 
641
     * @return escala.
642
     */
643
    public long getScale() {
644
        /*
645
         * if (m_bLinked){
646
         * return getScaleView1(METROS);
647
         * }
648
         */
649
        if (getMapContext() == null) {
650
            return 0;
651
        }
652
        if (getTypeScale() == AUTOMATICO) {
653
            return FLayoutUtilities.getScaleView(getMapContext().getViewPort(),
654
                getBoundBox().width, getBoundingBox(null).width);
655
        } else
656
            if (getTypeScale() == CONSTANTE) {
657
                return (long) mapScale;
658
            } else
659
                if (getTypeScale() == MANUAL) {
660
                    return (long) mapScale;
661
                }
662

    
663
        return (long) mapScale;
664
    }
665

    
666
    /**
667
     * Seleccionar si la vista esta relacionada o no con la original.
668
     * 
669
     * @param b
670
     *            true si est? ligada y false si no lo est?.
671
     */
672
    public void setLinked(boolean b) {
673
        linked = b;
674
    }
675

    
676
    /**
677
     * Devuelve si est? ligada o no el FFrameView con la vista.
678
     * 
679
     * @return True si la vista est? ligada.
680
     */
681
    public boolean getLinked() {
682
        return linked;
683
    }
684

    
685
    /**
686
     * Devuelve la opci?n seleccionada:Rellenar marco de la vista o recorte a
687
     * la vista.
688
     * 
689
     * @return entero que representa la opci?n elegida.
690
     */
691
    public int getExtension() {
692
        return extension;
693
    }
694

    
695
    /**
696
     * Devuelve el tipo de escala que est? seleccionada AUTOMATICO,CONSTANTE o
697
     * MANUAL.
698
     * 
699
     * @return entero que representa el tipo seleccionado.
700
     */
701
    public int getTypeScale() {
702
        return typeScale;
703
    }
704

    
705
    /**
706
     * Rellenar si se quiere:Rellenar marco de la vista o recorte a la vista.
707
     * 
708
     * @param i
709
     *            entero que representa la opci?n elegida.
710
     */
711
    public void setExtension(int i) {
712
        extension = i;
713
    }
714

    
715
    /**
716
     * Rellenar el tipo de escala que se desea.
717
     * 
718
     * @param i
719
     *            entero que representa el tipo de escala.
720
     */
721
    public void setTypeScale(int i) {
722
        typeScale = i;
723
    }
724

    
725
    /**
726
     * Inserta la imagen para repintar el FFrameView.
727
     * 
728
     * @param bi
729
     *            Imagen para repintar.
730
     */
731
    public void setBufferedImage(BufferedImage bi) {
732
        m_image = bi;
733
    }
734

    
735
    /**
736
     * Devuelve la imagen para repintar.
737
     * 
738
     * @return Imagen para repintar.
739
     */
740
    public BufferedImage getBufferedImage() {
741
        return m_image;
742
    }
743

    
744
    /**
745
     * Devuelve la MAtriz de transformaci?n utilizada por la FFrameView.
746
     * 
747
     * @return MAtriz de transformaci?n.
748
     */
749
    public AffineTransform getATMap() {
750
        return at;
751
    }
752

    
753
    /**
754
     * Inserta la matriz de transformaci?n.
755
     * 
756
     * @param transform
757
     *            Matriz de transformaci?n.
758
     */
759
    public void setATMap(AffineTransform transform) {
760
        at = transform;
761
    }
762

    
763
    /**
764
     * Inserta el proyecto.
765
     * 
766
     * @param p
767
     *            Proyecto.
768
     */
769
    public void setProject(Project p) {
770
        project = p;
771
    }
772

    
773
    /**
774
     * @see org.gvsig.app.project.documents.layout.fframes.IFFrame#getNameFFrame()
775
     */
776
    public String getNameFFrame() {
777
        return PluginServices.getText(this, "Vista") + num;
778
    }
779

    
780
    public String getName() {
781
        return PERSISTENCE_DEFINITION_NAME;
782
    }
783

    
784
    /**
785
     * @see com.iver.cit.gvsig.fmap.ExtentListener#extentChanged(org.gvsig.fmap.mapcontext.events.ExtentEvent)
786
     */
787
    public void extentChanged(ExtentEvent e) {
788
        if (linked){
789
            if (getTypeScale() == AUTOMATICO) {
790
                mapContext.getViewPort().setEnvelope(e.getNewExtent());
791
                observers.notifyObservers(this, 
792
                    new DefaultLayoutNotification(LayoutNotification.LAYOUT_INVALIDATED));      
793
            } else
794
                if (getTypeScale() == MANUAL) {
795
                    Envelope oldExtent = mapContext.getViewPort().getEnvelope();
796
                    Envelope newExtent = e.getNewExtent();
797
                    double xDif = newExtent.getCenter(0) - oldExtent.getCenter(0);
798
                    double yDif = newExtent.getCenter(1) - oldExtent.getCenter(1);
799
                    try {
800
                        mapContext.getViewPort().setEnvelope(
801
                            geomManager.createEnvelope(oldExtent.getMinimum(0)
802
                                + xDif, oldExtent.getMinimum(1) + yDif,
803
                                oldExtent.getMaximum(0) + xDif,
804
                                oldExtent.getMaximum(1) + yDif, SUBTYPES.GEOM2D));
805
                    } catch (CreateEnvelopeException e1) {
806
                        e1.printStackTrace();
807
                    }
808
                   
809
                    observers.notifyObservers(this, 
810
                        new DefaultLayoutNotification(LayoutNotification.LAYOUT_INVALIDATED));           
811
                  
812
                }
813
            refresh = true;
814
        }
815
    }
816

    
817
    /**
818
     * @see org.gvsig.fmap.mapcontext.events.listeners.ViewPortListener#backColorChanged(org.gvsig.fmap.mapcontext.events.ColorEvent)
819
     */
820
    public void backColorChanged(ColorEvent e) {
821
        if (getLinked()) {
822
            mapContext.getViewPort().setBackColor(e.getNewColor());
823
            observers.notifyObservers(this, 
824
                new DefaultLayoutNotification(LayoutNotification.LAYOUT_INVALIDATED));          
825
        }
826
    }
827

    
828
    /**
829
     * @see org.gvsig.fmap.mapcontext.events.listeners.ViewPortListener#projectionChanged(org.gvsig.fmap.mapcontext.events.ProjectionEvent)
830
     */
831
    public void projectionChanged(ProjectionEvent e) {
832
        if (getTypeScale() == AUTOMATICO) {
833
            mapContext.getViewPort().setProjection(e.getNewProjection());
834
            observers.notifyObservers(this, 
835
                new DefaultLayoutNotification(LayoutNotification.LAYOUT_INVALIDATED));      
836
        }
837
    }
838

    
839
    /**
840
     * DOCUMENT ME!
841
     * 
842
     * @param e
843
     *            DOCUMENT ME!
844
     */
845
    public void legendChanged(final LegendChangedEvent e) {
846
        if (!SwingUtilities.isEventDispatchThread()) {
847
            SwingUtilities.invokeLater(new Runnable() {
848

    
849
                public void run() {
850
                    legendChanged(e);
851
                }
852
            });
853
            return;
854
        }
855
        if (getLinked()) {
856
            observers.notifyObservers(this, 
857
                new DefaultLayoutNotification(LayoutNotification.LAYOUT_INVALIDATED));      
858
            refresh = true;
859
        }
860
    }
861

    
862
    /**
863
     * DOCUMENT ME!
864
     * 
865
     * @param arg0
866
     *            DOCUMENT ME!
867
     * 
868
     * @return DOCUMENT ME!
869
     */
870
    public boolean compare(Object arg0) {
871
        if (!(arg0 instanceof FFrameView)) {
872
            return false;
873
        }
874

    
875
        if (!this.getName().equals(((FFrameView) arg0).getName())) {
876
            return false;
877
        }
878

    
879
        if (Math.abs(this.getBoundBox().getWidth()
880
            - (((FFrameView) arg0).getBoundBox().getWidth())) > 0.05) {
881
            return false;
882
        }
883
        if (Math.abs(this.getBoundBox().getHeight()
884
            - (((FFrameView) arg0).getBoundBox().getHeight())) > 0.05) {
885
            return false;
886
        }
887

    
888
        if (!this.toString().equals(((FFrameView) arg0).toString())) {
889
            return false;
890
        }
891

    
892
        if (this.getMapContext() != null
893
            && !this.getMapContext()
894
                .equals(((FFrameView) arg0).getMapContext())) {
895
            return false;
896
        }
897

    
898
        if (this.getRotation() != ((FFrameView) arg0).getRotation()) {
899
            return false;
900
        }
901
        return true;
902
    }
903

    
904
    /*
905
     * This was causing issues with the notifications
906
     * because different instances were considered the same
907
     * after cloning a frame (the frame is cloned for example
908
     * when the user changes size of frame)
909
     * 
910
    public boolean equals(Object arg0) {
911
        return this.compare(arg0);
912
    }
913
    */
914

    
915
    public void refresh() {
916
        if (viewDocument != null
917
            && (getTypeScale() == MANUAL || getTypeScale() == CONSTANTE)) {
918
            getMapContext().getViewPort().setEnvelope(
919
                getNewEnvelope(getScale()));
920
        }
921
        refresh = true;
922
    }
923

    
924
    public void fullExtent() throws ReadException {
925
        setNewEnvelope(getMapContext().getFullEnvelope());
926
    }
927

    
928
    public void setPointsToZoom(Point2D px1, Point2D px2) {
929
        p1 = px1;
930
        p2 = px2;
931
    }
932

    
933
    public void movePoints(Point2D px1, Point2D px2) {
934
        double difX = -px2.getX() + px1.getX();
935
        double difY = -px2.getY() + px1.getY();
936
        if (p1 != null) {
937
            p1.setLocation(p1.getX() + difX, p1.getY() + difY);
938
            p2.setLocation(p2.getX() + difX, p2.getY() + difY);
939
        }
940
    }
941

    
942
    /**
943
     * This method deals with places where this fframeview and the cloned
944
     * fframeview (frame) are registered as listeners. The goal should be
945
     * leaving the cloned instance (frame) as listener in the same way
946
     * that 'this' instance is doing.
947
     */
948
    protected void cloneActions(FFrameView frame) {
949
        if (viewDocument == null || viewDocument.getMapContext() == null) {
950
            return;
951
        }
952
        
953
        frame.setTypeScale(this.getTypeScale());
954
        frame.setLinked(linked);
955
        
956
        if (linked) {
957
            if (getTypeScale() == AUTOMATICO) {
958
                frame.viewDocument.getMapContext().getViewPort().addViewPortListener(frame);
959
                frame.viewDocument.getMapContext().addLayerListener(frame);
960
            } else
961
                if (getTypeScale() == CONSTANTE) {
962
                    frame.viewDocument.getMapContext().getViewPort().removeViewPortListener(frame);
963
                    frame.viewDocument.getMapContext().addLayerListener(frame);
964
                } else
965
                    if (getTypeScale() == MANUAL) {
966
                        frame.viewDocument.getMapContext().getViewPort().removeViewPortListener(frame);
967
                        frame.viewDocument.getMapContext().addLayerListener(frame);
968
                    }
969
        } else
970
            if (!linked) {
971
                if (getTypeScale() == AUTOMATICO) {
972
                    frame.viewDocument.getMapContext().getViewPort().addViewPortListener(frame);
973
                } else
974
                    if (getTypeScale() == CONSTANTE) {
975
                        frame.viewDocument.getMapContext().getViewPort().removeViewPortListener(frame);
976
                    } else
977
                        if (getTypeScale() == MANUAL) {
978
                            frame.viewDocument.getMapContext().getViewPort().removeViewPortListener(frame);
979
                        }
980
            }
981
        /*
982
        ((FFrameView) frame).viewDocument.getMapContext().removeLayerListener(
983
            (FFrameView) frame);
984
        ((FFrameView) frame).viewDocument.getMapContext().getViewPort()
985
            .removeViewPortListener((FFrameView) frame);
986
        */
987
    }
988

    
989
    public Object clone() throws CloneNotSupportedException {
990
        FFrameView frame = (FFrameView) super.clone();
991

    
992
        frame.setSelected(this.getSelected() != IFFrame.NOSELECT);
993

    
994
        if (grid != null) {
995
            FFrameGrid newGrid = (FFrameGrid) this.grid.clone();
996
            newGrid.setFFrameDependence(frame);
997
            frame.setGrid(newGrid);
998
        }
999
        cloneActions(frame);
1000
        return frame;
1001
    }
1002

    
1003
    public void setGrid(IFFrame grid) {
1004
        this.grid = grid;
1005
        this.grid.setRotation(this.getRotation());
1006
    }
1007

    
1008
    public IFFrame getGrid() {
1009
        return this.grid;
1010
    }
1011

    
1012
    public void setRotation(double rotation) {
1013
        super.setRotation(rotation);
1014
        if (grid != null) {
1015
            grid.setRotation(rotation);
1016
        }
1017
    }
1018

    
1019
    public void showGrid(boolean b) {
1020
        showGrid = b;
1021
    }
1022

    
1023
    public boolean isShowGrid() {
1024
        return showGrid;
1025
    }
1026

    
1027
    public void refreshOriginalExtent() {
1028
        if (getTypeScale() == AUTOMATICO) {
1029
            viewDocument.getMapContext().getViewPort()
1030
                .setEnvelope(getMapContext().getViewPort().getEnvelope());
1031
            viewDocument.getMapContext().getViewPort().refreshExtent();
1032
        } else
1033
            if (getTypeScale() == MANUAL) {
1034
                Envelope oldExtent =
1035
                    viewDocument.getMapContext().getViewPort().getEnvelope();
1036
                Envelope newExtent =
1037
                    getMapContext().getViewPort().getEnvelope();
1038
                double xDif = newExtent.getCenter(0) - oldExtent.getCenter(0);
1039
                double yDif = newExtent.getCenter(1) - oldExtent.getCenter(1);
1040
                try {
1041
                    viewDocument.getMapContext()
1042
                        .getViewPort()
1043
                        .setEnvelope(
1044
                            geomManager.createEnvelope(oldExtent.getMinimum(0)
1045
                                + xDif, oldExtent.getMinimum(1) + yDif,
1046
                                oldExtent.getMaximum(0) + xDif,
1047
                                oldExtent.getMaximum(1) + yDif, SUBTYPES.GEOM2D));
1048
                } catch (CreateEnvelopeException e) {
1049
                    e.printStackTrace();
1050
                }
1051
                viewDocument.getMapContext().getViewPort().refreshExtent();
1052
            }
1053
    }
1054

    
1055
    public static void registerPersistent() {
1056
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
1057
        if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) {
1058
            DynStruct definition =
1059
                manager.addDefinition(FFrameView.class,
1060
                    PERSISTENCE_DEFINITION_NAME,
1061
                    "FFrameView persistence definition", null, null);
1062

    
1063
            definition.extend(manager
1064
                .getDefinition(FFrame.PERSISTENCE_DEFINITION_NAME));
1065

    
1066
            definition.addDynFieldInt(MODE_FIELD).setMandatory(true);
1067
            definition.addDynFieldInt(TYPESCALE_FIELD).setMandatory(true);
1068
            definition.addDynFieldInt(EXTENSION_FIELD).setMandatory(true);
1069
            definition.addDynFieldInt(QUALITY_FIELD).setMandatory(true);
1070
            definition.addDynFieldInt(VIEWING_FIELD).setMandatory(true);
1071
            definition.addDynFieldBoolean(BLINKED_FIELD).setMandatory(true);
1072
            definition.addDynFieldInt(MAPUNITS_FIELD).setMandatory(true);
1073
            definition.addDynFieldDouble(SCALE_FIELD).setMandatory(true);
1074
            definition.addDynFieldObject(VIEW_FIELD)
1075
                .setClassOfValue(ViewDocument.class).setMandatory(false);
1076
            definition.addDynFieldObject(ENVELOPE_FIELD)
1077
                .setClassOfValue(Envelope.class).setMandatory(false);
1078
            definition.addDynFieldBoolean(SHOWGRID_FIELD).setMandatory(true);
1079
            definition.addDynFieldObject(GRID_FIELD)
1080
                .setClassOfValue(IFFrame.class).setMandatory(false);
1081
            definition.addDynFieldObject(MAPCONTEXT_FIELD)
1082
                .setClassOfValue(MapContext.class).setMandatory(false);
1083
        }
1084
    }
1085

    
1086
    @Override
1087
    public void loadFromState(PersistentState state)
1088
        throws PersistenceException {
1089
        super.loadFromState(state);
1090
        mode = state.getInt(MODE_FIELD);
1091
        typeScale = state.getInt(TYPESCALE_FIELD);
1092
        extension = state.getInt(EXTENSION_FIELD);
1093
        quality = state.getInt(QUALITY_FIELD);
1094
        viewing = state.getInt(VIEWING_FIELD);
1095
        linked = state.getBoolean(BLINKED_FIELD);
1096
        mapUnits = state.getInt(MAPUNITS_FIELD);
1097
        mapScale = state.getDouble(SCALE_FIELD);
1098
        viewDocument = (ViewDocument) state.get(VIEW_FIELD);
1099

    
1100
        if (state.hasValue(MAPCONTEXT_FIELD)) {
1101
            mapContext = (MapContext) state.get(MAPCONTEXT_FIELD);
1102
            mapContext.getViewPort().setEnvelope(
1103
                (Envelope) state.get(ENVELOPE_FIELD));
1104
        }
1105

    
1106
        showGrid = state.getBoolean(SHOWGRID_FIELD);
1107
        grid = (IFFrame) state.get(GRID_FIELD);
1108
    }
1109

    
1110
    @Override
1111
    public void saveToState(PersistentState state) throws PersistenceException {
1112
        super.saveToState(state);
1113
        state.set(MODE_FIELD, mode);
1114
        state.set(TYPESCALE_FIELD, typeScale);
1115
        state.set(EXTENSION_FIELD, extension);
1116
        state.set(QUALITY_FIELD, quality);
1117
        state.set(VIEWING_FIELD, viewing);
1118
        state.set(BLINKED_FIELD, linked);
1119
        state.set(MAPUNITS_FIELD, mapUnits);
1120
        state.set(SCALE_FIELD, mapScale);
1121
        state.set(VIEW_FIELD, viewDocument);
1122

    
1123
        if (getMapContext() != null
1124
            && getMapContext().getViewPort().getEnvelope() != null) {
1125
            state.set(ENVELOPE_FIELD, getMapContext().getViewPort()
1126
                .getEnvelope());
1127
            state.set(MAPCONTEXT_FIELD, mapContext);
1128
        }
1129

    
1130
        state.set(SHOWGRID_FIELD, showGrid);
1131
        state.set(GRID_FIELD, grid);
1132
    }
1133
    
1134
    @Override
1135
    public void setBoundBox(Rectangle2D r) {      
1136
        super.setBoundBox(r);
1137
        refresh();
1138
    }   
1139
}