Statistics
| Revision:

svn-document-layout / trunk / 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 @ 110

History | View | Annotate | Download (41.6 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.Graphics;
29
import java.awt.Graphics2D;
30
import java.awt.Image;
31
import java.awt.Point;
32
import java.awt.Rectangle;
33
import java.awt.geom.AffineTransform;
34
import java.awt.geom.Point2D;
35
import java.awt.geom.Rectangle2D;
36
import java.awt.image.BufferedImage;
37

    
38
import javax.swing.SwingUtilities;
39

    
40
import org.cresques.cts.IProjection;
41
import org.slf4j.Logger;
42
import org.slf4j.LoggerFactory;
43

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

    
77
/**
78
 * FFrame para introducir una vista en el Layout.
79
 * 
80
 * @author Vicente Caballero Navarro
81
 */
82
public class FFrameView extends FFrame implements ViewPortListener,
83
    LegendListener, 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 EXTENSION_FIELD = "extension";
90
    private static final String QUALITY_FIELD = "quality";
91
    private static final String VIEWING_FIELD = "viewing";
92
    private static final String BLINKED_FIELD = "bLinked";
93
    private static final String MAPUNITS_FIELD = "mapUnits";
94
    private static final String SCALE_FIELD = "scale";
95
    private static final String VIEW_FIELD = "view";
96
    private static final String ENVELOPE_FIELD = "envelope";
97
    private static final String SHOWGRID_FIELD = "showGrid";
98
    private static final String GRID_FIELD = "gridview";
99
    private static final String MAPCONTEXT_FIELD = "mapContext";
100

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

    
118
    protected BufferedImage m_image = null;
119
    protected AffineTransform at = null;
120
    protected Project project = null;
121
    protected double scaleAnt;
122
    protected boolean refresh = false;
123
    protected Point origin;
124
    protected Point2D p1;
125
    protected Point2D p2;
126
    protected IFFrame grid;
127
    protected boolean showGrid = false;
128

    
129
    /**
130
     * Creates a new FFrameView object.
131
     */
132
    public FFrameView() {
133
        num++;
134
    }
135

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

    
146
        return "FFrameView " + num + ": " + getView().getName();
147
    }
148

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

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

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

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

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

    
203
    /**
204
     * Devuelve un entero que representa la forma en que se actualiza la vista.
205
     * 
206
     * @return forma que se actualiza la vista.
207
     */
208
    public int getViewing() {
209
        return viewing;
210
    }
211

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

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

    
245
        }
246
        vp.setImageSize(new Dimension((int) getBoundingBox(null).width,
247
            (int) getBoundingBox(null).height));
248

    
249
        if (linked){
250
            if (getTypeScale() == AUTOMATICO) {
251
                try {
252
                    mapContext =
253
                        mctxt.createNewFMap(
254
                            (ViewPort) mctxt.getViewPort().clone());
255
                } catch (CloneNotSupportedException e1) {
256
                    NotificationManager.addError("Excepci?n :", e1);
257
                }
258

    
259
                mapContext.getViewPort().setImageSize(
260
                    new Dimension((int) getBoundingBox(null).width,
261
                        (int) getBoundingBox(null).height));
262
                mctxt.getViewPort().addViewPortListener(this);
263
                mctxt.addLayerListener(this);
264
            }else{
265
                if (getTypeScale() == CONSTANTE) {
266
                    mapContext = mctxt.createNewFMap(vp);
267
                    vp.setEnvelope(getNewEnvelope(getScale()));
268
                    mctxt.getViewPort().addViewPortListener(this);
269
                    mctxt.addLayerListener(this);
270
                }else{
271
                    if (getTypeScale() == MANUAL) {
272
                        mapContext = mctxt.createNewFMap(vp);
273
                        vp.setEnvelope(getNewEnvelope(getScale()));
274
                        mctxt.getViewPort()
275
                            .addViewPortListener(this);
276
                        mctxt.addLayerListener(this);
277
                    }
278
                }
279
            }
280
        }else{
281
            if (!linked) {
282

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

    
316
    /**
317
     * Devuelve el modelo de la vista.
318
     * 
319
     * @return Modelo de la vista.
320
     */
321
    public ViewDocument getView() {
322
        return viewDocument;
323
    }
324

    
325
    /**
326
     * Devuelve un Rect?ngulo que representa el extent de la vista que se
327
     * requiere a partir de una escala.
328
     * 
329
     * @param scale
330
     *            Escala a mostrar.
331
     * 
332
     * @return Rect?ngulo.
333
     */
334
    protected Envelope getNewEnvelope(long scale) {
335
        double hview = getBoundBox().getHeight();
336
        double wview = getBoundBox().getWidth();
337
        double hextent = (scale * hview) / 100.0;
338
        double wextent = (scale * wview) / 100.0;
339

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

    
380
    /**
381
     * M?todo que dibuja sobre el graphics que se le pasa como par?metro, seg?n
382
     * la transformada afin que se debe de aplicar y el rect?ngulo que se debe
383
     * de dibujar.
384
     * 
385
     * @param g
386
     *            Graphics2D
387
     * @param at
388
     *            Transformada af?n.
389
     * @param rectangleView
390
     *            rect?ngulo sobre el que hacer un clip.
391
     * @param imgBase
392
     *            Imagen para acelerar el dibujado.
393
     */
394
    public void draw(Graphics2D g, AffineTransform at, Rectangle2D rectangleView, BufferedImage imgBase) {
395
        Rectangle2D.Double rectangleLayout = getBoundingBox(at);  
396
        Rectangle originalClip = preDraw(g, rectangleLayout);    
397
        if (intersects(rectangleView, rectangleLayout)) {
398
            if (getMapContext() == null) {
399
                drawEmpty(g);
400
            } else {
401
                if (FLayoutUtilities.hasEditingLayers(getView())) {
402
                    
403
                    /*
404
                     * We are not drawing if any layer is in editing mode
405
                     */
406
                    drawMessage(g, Messages.getText(
407
                        "_Cannot_draw_view_if_layers_in_editing_mode"));
408
                    
409
                } else {
410
                    if (getQuality() == PRESENTATION) {
411
                        try {
412
                            drawPresentation(g, at, rectangleLayout, rectangleView, imgBase);
413
                        } catch (Exception exc) {
414
                            drawMessage(g, FLayoutFunctions.getLastMessage(exc));
415
                        }
416
                        
417
                    } else {
418
                        drawDraft(g);
419
                    }               
420
                }
421
            }
422
        }
423
        postDraw(g, rectangleLayout, rectangleView, imgBase, originalClip, at); 
424
        if (showGrid && grid != null) {           
425
            grid.draw(g, at, rectangleView, imgBase);
426
        }    
427
    }
428
    
429
    private void drawMessage(Graphics2D g, String msg) {
430
        
431
        Rectangle2D r = getBoundingBox(null);
432
        g.setColor(Color.lightGray);
433
        g.fillRect((int) r.getX(), (int) r.getY(), (int) r.getWidth(),
434
            (int) r.getHeight());
435
        g.setColor(Color.darkGray);
436
        g.setStroke(new BasicStroke(2));
437
        g.drawRect((int) r.getX(), (int) r.getY(), (int) r.getWidth(),
438
            (int) r.getHeight());
439
        g.setColor(Color.black);
440

    
441
        int scale = (int) (r.getWidth() / 24);
442
        Font f = new Font("SansSerif", Font.PLAIN, scale);
443
        g.setFont(f);
444

    
445
        g.drawString(msg, (int) (r.getCenterX() - ((msg.length() * scale) / 4)),
446
            (int) (r.getCenterY()));        
447
    }
448

    
449
    protected void drawPresentation(
450
        Graphics2D g,
451
        AffineTransform affineTransform,
452
        Rectangle2D.Double rectangleLayout,
453
        Rectangle2D rectangleView,
454
        BufferedImage imgBase) throws Exception {
455
        
456
        Point mapOrigin = new Point((int)rectangleView.getMinX(), (int)rectangleView.getMaxY());
457

    
458
        ViewPort viewPort = this.getMapContext().getViewPort();
459
        Color theBackColor = viewPort.getBackColor();
460

    
461
        //If the image has to be created...
462
        if (!(origin != null
463
            && origin.equals(mapOrigin)
464
            && affineTransform.getScaleX() == scaleAnt
465
            && m_image != null
466
            && !refresh
467
            && !(rectangleLayout.getWidth() > rectangleView.getWidth() || rectangleLayout.getHeight() > rectangleView.getHeight()))) {
468

    
469
            double scale1_1 = MapContext.getScreenDPI() / 2.54;
470
            /*
471
             * This is the ratio between the size assumed by the
472
             * mapcontext drawer and the true size on screen
473
             */
474
            double visible_factor = affineTransform.getScaleX() / scale1_1;
475
            int draw_w = (int) (1d * rectangleLayout.width / visible_factor);
476
            int draw_h = (int) (1d * rectangleLayout.height / visible_factor);
477

    
478
            viewPort.setImageSize(new Dimension(draw_w, draw_h));
479
            viewPort.refreshExtent();
480

    
481
            /*
482
            viewPort.setOffset(new Point2D.Double(rectangleLayout.x, rectangleLayout.y));
483
            */
484

    
485
            m_image =
486
                new BufferedImage(
487
                    draw_w, //(int) rectangleLayout.getWidth(),
488
                    draw_h, //(int) rectangleLayout.getHeight(),
489
                    BufferedImage.TYPE_INT_ARGB);
490

    
491
            Graphics2D gimg = (Graphics2D) m_image.createGraphics();
492
            
493
            /*
494
            gimg.translate(-((int) rectangleLayout.getX()),
495
                -((int) rectangleLayout.getY()));
496
            */
497

    
498
            getMapContext().draw(m_image, gimg, getScale());
499
            gimg.dispose();
500
            /*
501
            gimg.translate(((int) rectangleLayout.getX()),
502
                ((int) rectangleLayout.getY()));
503
                */
504
            refresh = false;    
505
        } 
506

    
507
        //Draw the created image
508
        if (theBackColor != null) {
509
            g.setColor(theBackColor);
510
            g.fillRect((int) rectangleLayout.x, (int) rectangleLayout.y,
511
                viewPort.getImageWidth(),
512
                viewPort.getImageHeight());
513
        }
514
        
515
        m_image = copyForcingImageSize(
516
            m_image,
517
            (int) rectangleLayout.getWidth(),
518
            (int) rectangleLayout.getHeight());
519

    
520
        g.drawImage(m_image,
521
            (int) rectangleLayout.getX(),
522
            (int) rectangleLayout.getY(), null);
523
        
524
        scaleAnt = affineTransform.getScaleX();
525
        origin = mapOrigin;             
526
    }
527
    
528
    /**
529
     * @param m_image2
530
     * @param width
531
     * @param height
532
     * @return
533
     */
534
    protected BufferedImage copyForcingImageSize(
535
        BufferedImage disp_img, int w, int h) {
536
        
537
        Graphics rg = null;
538
        
539
        try {
540
            if (disp_img == null || w < 1 || h < 1) {
541
                return new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
542
            }
543
            int from_w = disp_img.getWidth(null);
544
            int from_h = disp_img.getHeight(null);
545
            if (from_w < 1 || from_h < 1) {
546
                return new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
547
            }
548
            
549
            BufferedImage resp =
550
                new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
551
            rg = resp.createGraphics();
552
            
553
            double rat_w = (1d*w) / (1d*from_w);
554
            double rat_h = (1d*h) / (1d*from_h);
555
            int offset_w = 0;
556
            int offset_h = 0;
557
            Image aux = null;
558

    
559
            if (rat_w <= rat_h) {
560
                // apply resize of width
561
                int target_h = Math.max(1, (int) (from_h * rat_w));
562
                // w, target_h
563
                offset_w = 0;
564
                offset_h = (h - target_h) / 2;
565
                aux = disp_img.getScaledInstance(w, target_h, Image.SCALE_FAST);
566
                rg.drawImage(aux, offset_w, offset_h, null);
567

    
568
            } else {
569
                // apply resize from height
570
                int target_w = Math.max(1, (int) (from_w * rat_h));
571
                // target_w, h
572
                offset_w = (w - target_w) / 2;
573
                offset_h = 0;
574
                aux = disp_img.getScaledInstance(target_w, h, Image.SCALE_FAST);
575
                rg.drawImage(aux, offset_w, offset_h, null);
576
            }
577
            
578
            aux = null;
579
            resp.flush();
580
            rg.dispose();
581
            return resp;
582
        } catch (Throwable th) {
583
            logger.info("While resizing image.", th);
584
            if (rg != null) {
585
                rg.dispose();
586
            }
587
            return null;
588
        }
589
        
590
    }
591

    
592
    protected Rectangle preDraw(Graphics2D g, Rectangle2D.Double rectangleLayout){
593
        Rectangle originalClip = null;
594
        if (g.getClipBounds() != null) {
595
            originalClip = (Rectangle) g.getClipBounds().clone();
596
        }
597
        if (getRotation() != 0) {
598
            g.rotate(Math.toRadians(getRotation()), rectangleLayout.getCenterX(), rectangleLayout.getCenterY()
599
                + (rectangleLayout.height / 2));
600
        }       
601
        g.clipRect((int) rectangleLayout.getMinX(), (int) rectangleLayout.getMinY(),
602
            (int) rectangleLayout.getWidth(), (int) rectangleLayout.getHeight());
603
        return originalClip;
604
    }
605
    
606
    protected void postDraw(Graphics2D g, Rectangle2D.Double rectangleLayout, Rectangle2D rectangleView, BufferedImage imgBase, 
607
        Rectangle originalClip, AffineTransform at){
608
        if (getRotation() != 0) {
609
            g.rotate(Math.toRadians(-getRotation()), rectangleLayout.getCenterX(), rectangleLayout.getCenterY());
610
        }
611
        if (getMapContext() != null) {
612
            setATMap(getMapContext().getViewPort().getAffineTransform());
613
        }
614
        if (originalClip != null) {
615
            g.setClip(originalClip.x, originalClip.y, originalClip.width, originalClip.height);
616
        }            
617
    }
618

    
619
    private Envelope calculateEnvelope() {
620
        if (p1 == null || p2 == null) {
621
            try {
622
                return geomManager.createEnvelope(0, 0, 0, 0, SUBTYPES.GEOM2D);
623
            } catch (CreateEnvelopeException e) {
624
                logger.error("Error creating the envelope", e);
625
            }
626
        }
627
        Envelope r = null;
628
        try {
629
            r =
630
                geomManager.createEnvelope(p1.getX(), p1.getY(), p2.getX(),
631
                    p2.getY(), SUBTYPES.GEOM2D);
632
        } catch (CreateEnvelopeException e) {
633
            logger.error("Error creating the envelope", e);
634
        }
635
        return r;
636
    }
637

    
638
    public void print(Graphics2D g, AffineTransform at, Geometry geom,
639
        PrintAttributes printAttributes) {
640
        Rectangle2D.Double rectangleLayout = getBoundingBox(at);  
641
        
642
        Rectangle originalClip = preDraw(g, rectangleLayout);
643
        print(g, at, printAttributes);
644
        postDraw(g, rectangleLayout, null, null, originalClip, at);
645
        if (showGrid && grid != null) {
646
            grid.print(g, at, geom, printAttributes);
647
        }    
648
    }
649

    
650
    protected void print(Graphics2D g, AffineTransform at, PrintAttributes printAttributes) {
651
        Rectangle2D.Double layoutRectangle = getBoundingBox(at);
652
              
653
        ViewPort viewPort = this.getMapContext().getViewPort();
654
        
655
        Point2D old_offset = viewPort.getOffset();
656
        Dimension old_imgsize = viewPort.getImageSize();
657
        
658
        viewPort.setOffset(new Point2D.Double(layoutRectangle.x, layoutRectangle.y));
659
        viewPort.setImageSize(new Dimension((int) layoutRectangle.width, (int) layoutRectangle.height));
660

    
661
        //Draw the backgroung color of the map
662
        Color theBackColor = viewPort.getBackColor();
663
        if (theBackColor != null) {
664
            g.setColor(theBackColor);
665
            g.fillRect((int) layoutRectangle.x, (int) layoutRectangle.y, viewPort
666
                    .getImageWidth(), viewPort
667
                    .getImageHeight());
668
        }        
669
        
670
        //Print the map
671
        try {
672
            this.getMapContext().print(g, getScale(), printAttributes);
673
        } catch (ReadException e) {
674
            NotificationManager.addError(e.getMessage(), e);
675
        } catch (MapContextException e) {
676
            NotificationManager.addError(e.getMessage(), e);
677
        }      
678
        
679
        // Restore offset, imgsize
680
        viewPort.setOffset(old_offset);
681
        viewPort.setImageSize(old_imgsize);
682
    }
683

    
684
    /**
685
     * Rellena la unidad de medida en la que est? la vista.
686
     * 
687
     * @param i
688
     *            entero que representa la unidad de medida de la vista.
689
     */
690
    public void setMapUnits(int i) {
691
        mapUnits = i;
692
    }
693

    
694
    /**
695
     * Obtiene la unidad de medida en la que est? la vista.
696
     * 
697
     * @return Unidad de medida.
698
     */
699
    public int getMapUnits() {
700
        return mapUnits;
701
    }
702

    
703
    /**
704
     * Devuelve la escala seg?n el tipo de escala que se haya seleccionado al
705
     * a?adida la vista.
706
     * 
707
     * @return escala.
708
     */
709
    public long getScale() {
710
        /*
711
         * if (m_bLinked){
712
         * return getScaleView1(METROS);
713
         * }
714
         */
715
        if (getMapContext() == null) {
716
            return 0;
717
        }
718
        if (getTypeScale() == AUTOMATICO) {
719
            return FLayoutUtilities.getScaleView(getMapContext().getViewPort(),
720
                getBoundBox().width, getBoundingBox(null).width);
721
        } else
722
            if (getTypeScale() == CONSTANTE) {
723
                return (long) mapScale;
724
            } else
725
                if (getTypeScale() == MANUAL) {
726
                    return (long) mapScale;
727
                }
728

    
729
        return (long) mapScale;
730
    }
731

    
732
    /**
733
     * Seleccionar si la vista esta relacionada o no con la original.
734
     * 
735
     * @param b
736
     *            true si est? ligada y false si no lo est?.
737
     */
738
    public void setLinked(boolean b) {
739
        linked = b;
740
    }
741

    
742
    /**
743
     * Devuelve si est? ligada o no el FFrameView con la vista.
744
     * 
745
     * @return True si la vista est? ligada.
746
     */
747
    public boolean getLinked() {
748
        return linked;
749
    }
750

    
751
    /**
752
     * Devuelve la opci?n seleccionada:Rellenar marco de la vista o recorte a
753
     * la vista.
754
     * 
755
     * @return entero que representa la opci?n elegida.
756
     */
757
    public int getExtension() {
758
        return extension;
759
    }
760

    
761
    /**
762
     * Devuelve el tipo de escala que est? seleccionada AUTOMATICO,CONSTANTE o
763
     * MANUAL.
764
     * 
765
     * @return entero que representa el tipo seleccionado.
766
     */
767
    public int getTypeScale() {
768
        return typeScale;
769
    }
770

    
771
    /**
772
     * Rellenar si se quiere:Rellenar marco de la vista o recorte a la vista.
773
     * 
774
     * @param i
775
     *            entero que representa la opci?n elegida.
776
     */
777
    public void setExtension(int i) {
778
        extension = i;
779
    }
780

    
781
    /**
782
     * Rellenar el tipo de escala que se desea.
783
     * 
784
     * @param i
785
     *            entero que representa el tipo de escala.
786
     */
787
    public void setTypeScale(int i) {
788
        typeScale = i;
789
    }
790

    
791
    /**
792
     * Inserta la imagen para repintar el FFrameView.
793
     * 
794
     * @param bi
795
     *            Imagen para repintar.
796
     */
797
    public void setBufferedImage(BufferedImage bi) {
798
        m_image = bi;
799
    }
800

    
801
    /**
802
     * Devuelve la imagen para repintar.
803
     * 
804
     * @return Imagen para repintar.
805
     */
806
    public BufferedImage getBufferedImage() {
807
        return m_image;
808
    }
809

    
810
    /**
811
     * Devuelve la MAtriz de transformaci?n utilizada por la FFrameView.
812
     * 
813
     * @return MAtriz de transformaci?n.
814
     */
815
    public AffineTransform getATMap() {
816
        return at;
817
    }
818

    
819
    /**
820
     * Inserta la matriz de transformaci?n.
821
     * 
822
     * @param transform
823
     *            Matriz de transformaci?n.
824
     */
825
    public void setATMap(AffineTransform transform) {
826
        at = transform;
827
    }
828

    
829
    /**
830
     * Inserta el proyecto.
831
     * 
832
     * @param p
833
     *            Proyecto.
834
     */
835
    public void setProject(Project p) {
836
        project = p;
837
    }
838

    
839
    /**
840
     * @see org.gvsig.app.project.documents.layout.fframes.IFFrame#getNameFFrame()
841
     */
842
    public String getNameFFrame() {
843
        return PluginServices.getText(this, "Vista") + num;
844
    }
845

    
846
    public String getName() {
847
        return PERSISTENCE_DEFINITION_NAME;
848
    }
849

    
850
    /**
851
     * @see com.iver.cit.gvsig.fmap.ExtentListener#extentChanged(org.gvsig.fmap.mapcontext.events.ExtentEvent)
852
     */
853
    public void extentChanged(ExtentEvent e) {
854
        if (linked){
855
            if (getTypeScale() == AUTOMATICO) {
856
                mapContext.getViewPort().setEnvelope(e.getNewExtent());
857
                observers.notifyObservers(this, 
858
                    new DefaultLayoutNotification(LayoutNotification.LAYOUT_INVALIDATED));      
859
            } else
860
                if (getTypeScale() == MANUAL) {
861
                    Envelope oldExtent = mapContext.getViewPort().getEnvelope();
862
                    Envelope newExtent = e.getNewExtent();
863
                    double xDif = newExtent.getCenter(0) - oldExtent.getCenter(0);
864
                    double yDif = newExtent.getCenter(1) - oldExtent.getCenter(1);
865
                    try {
866
                        mapContext.getViewPort().setEnvelope(
867
                            geomManager.createEnvelope(oldExtent.getMinimum(0)
868
                                + xDif, oldExtent.getMinimum(1) + yDif,
869
                                oldExtent.getMaximum(0) + xDif,
870
                                oldExtent.getMaximum(1) + yDif, SUBTYPES.GEOM2D));
871
                    } catch (CreateEnvelopeException e1) {
872
                        e1.printStackTrace();
873
                    }
874
                   
875
                    observers.notifyObservers(this, 
876
                        new DefaultLayoutNotification(LayoutNotification.LAYOUT_INVALIDATED));           
877
                  
878
                }
879
            refresh = true;
880
        }
881
    }
882

    
883
    /**
884
     * @see org.gvsig.fmap.mapcontext.events.listeners.ViewPortListener#backColorChanged(org.gvsig.fmap.mapcontext.events.ColorEvent)
885
     */
886
    public void backColorChanged(ColorEvent e) {
887
        if (getLinked()) {
888
            mapContext.getViewPort().setBackColor(e.getNewColor());
889
            observers.notifyObservers(this, 
890
                new DefaultLayoutNotification(LayoutNotification.LAYOUT_INVALIDATED));          
891
        }
892
    }
893

    
894
    /**
895
     * @see org.gvsig.fmap.mapcontext.events.listeners.ViewPortListener#projectionChanged(org.gvsig.fmap.mapcontext.events.ProjectionEvent)
896
     */
897
    public void projectionChanged(ProjectionEvent e) {
898
        if (getTypeScale() == AUTOMATICO) {
899
            mapContext.getViewPort().setProjection(e.getNewProjection());
900
            observers.notifyObservers(this, 
901
                new DefaultLayoutNotification(LayoutNotification.LAYOUT_INVALIDATED));      
902
        }
903
    }
904

    
905
    /**
906
     * DOCUMENT ME!
907
     * 
908
     * @param e
909
     *            DOCUMENT ME!
910
     */
911
    public void legendChanged(final LegendChangedEvent e) {
912
        if (!SwingUtilities.isEventDispatchThread()) {
913
            SwingUtilities.invokeLater(new Runnable() {
914

    
915
                public void run() {
916
                    legendChanged(e);
917
                }
918
            });
919
            return;
920
        }
921
        if (getLinked()) {
922
            observers.notifyObservers(this, 
923
                new DefaultLayoutNotification(LayoutNotification.LAYOUT_INVALIDATED));      
924
            refresh = true;
925
        }
926
    }
927

    
928
    /**
929
     * DOCUMENT ME!
930
     * 
931
     * @param arg0
932
     *            DOCUMENT ME!
933
     * 
934
     * @return DOCUMENT ME!
935
     */
936
    public boolean compare(Object arg0) {
937
        if (!(arg0 instanceof FFrameView)) {
938
            return false;
939
        }
940

    
941
        if (!this.getName().equals(((FFrameView) arg0).getName())) {
942
            return false;
943
        }
944

    
945
        if (Math.abs(this.getBoundBox().getWidth()
946
            - (((FFrameView) arg0).getBoundBox().getWidth())) > 0.05) {
947
            return false;
948
        }
949
        if (Math.abs(this.getBoundBox().getHeight()
950
            - (((FFrameView) arg0).getBoundBox().getHeight())) > 0.05) {
951
            return false;
952
        }
953

    
954
        if (!this.toString().equals(((FFrameView) arg0).toString())) {
955
            return false;
956
        }
957

    
958
        if (this.getMapContext() != null
959
            && !this.getMapContext()
960
                .equals(((FFrameView) arg0).getMapContext())) {
961
            return false;
962
        }
963

    
964
        if (this.getRotation() != ((FFrameView) arg0).getRotation()) {
965
            return false;
966
        }
967
        return true;
968
    }
969

    
970
    /*
971
     * This was causing issues with the notifications
972
     * because different instances were considered the same
973
     * after cloning a frame (the frame is cloned for example
974
     * when the user changes size of frame)
975
     * 
976
    public boolean equals(Object arg0) {
977
        return this.compare(arg0);
978
    }
979
    */
980

    
981
    public void refresh() {
982
        if (viewDocument != null
983
            && (getTypeScale() == MANUAL || getTypeScale() == CONSTANTE)) {
984
            getMapContext().getViewPort().setEnvelope(
985
                getNewEnvelope(getScale()));
986
        }
987
        refresh = true;
988
    }
989

    
990
    public void fullExtent() throws ReadException {
991
        setNewEnvelope(getMapContext().getFullEnvelope());
992
    }
993

    
994
    public void setPointsToZoom(Point2D px1, Point2D px2) {
995
        p1 = px1;
996
        p2 = px2;
997
    }
998

    
999
    public void movePoints(Point2D px1, Point2D px2) {
1000
        double difX = -px2.getX() + px1.getX();
1001
        double difY = -px2.getY() + px1.getY();
1002
        if (p1 != null) {
1003
            p1.setLocation(p1.getX() + difX, p1.getY() + difY);
1004
            p2.setLocation(p2.getX() + difX, p2.getY() + difY);
1005
        }
1006
    }
1007

    
1008
    /**
1009
     * This method deals with places where this fframeview and the cloned
1010
     * fframeview (frame) are registered as listeners. The goal should be
1011
     * leaving the cloned instance (frame) as listener in the same way
1012
     * that 'this' instance is doing.
1013
     */
1014
    protected void cloneActions(FFrameView frame) {
1015
        if (viewDocument == null || viewDocument.getMapContext() == null) {
1016
            return;
1017
        }
1018
        
1019
        frame.setTypeScale(this.getTypeScale());
1020
        frame.setLinked(linked);
1021
        
1022
        if (linked) {
1023
            if (getTypeScale() == AUTOMATICO) {
1024
                frame.viewDocument.getMapContext().getViewPort().addViewPortListener(frame);
1025
                frame.viewDocument.getMapContext().addLayerListener(frame);
1026
            } else
1027
                if (getTypeScale() == CONSTANTE) {
1028
                    frame.viewDocument.getMapContext().getViewPort().removeViewPortListener(frame);
1029
                    frame.viewDocument.getMapContext().addLayerListener(frame);
1030
                } else
1031
                    if (getTypeScale() == MANUAL) {
1032
                        frame.viewDocument.getMapContext().getViewPort().removeViewPortListener(frame);
1033
                        frame.viewDocument.getMapContext().addLayerListener(frame);
1034
                    }
1035
        } else
1036
            if (!linked) {
1037
                if (getTypeScale() == AUTOMATICO) {
1038
                    frame.viewDocument.getMapContext().getViewPort().addViewPortListener(frame);
1039
                } else
1040
                    if (getTypeScale() == CONSTANTE) {
1041
                        frame.viewDocument.getMapContext().getViewPort().removeViewPortListener(frame);
1042
                    } else
1043
                        if (getTypeScale() == MANUAL) {
1044
                            frame.viewDocument.getMapContext().getViewPort().removeViewPortListener(frame);
1045
                        }
1046
            }
1047
        /*
1048
        ((FFrameView) frame).viewDocument.getMapContext().removeLayerListener(
1049
            (FFrameView) frame);
1050
        ((FFrameView) frame).viewDocument.getMapContext().getViewPort()
1051
            .removeViewPortListener((FFrameView) frame);
1052
        */
1053
    }
1054

    
1055
    public Object clone() throws CloneNotSupportedException {
1056
        FFrameView frame = (FFrameView) super.clone();
1057

    
1058
        frame.setSelected(this.getSelected() != IFFrame.NOSELECT);
1059

    
1060
        if (grid != null) {
1061
            FFrameGrid newGrid = (FFrameGrid) this.grid.clone();
1062
            newGrid.setFFrameDependence(frame);
1063
            frame.setGrid(newGrid);
1064
        }
1065
        cloneActions(frame);
1066
        return frame;
1067
    }
1068

    
1069
    public void setGrid(IFFrame grid) {
1070
        this.grid = grid;
1071
        this.grid.setRotation(this.getRotation());
1072
    }
1073

    
1074
    public IFFrame getGrid() {
1075
        return this.grid;
1076
    }
1077

    
1078
    public void setRotation(double rotation) {
1079
        super.setRotation(rotation);
1080
        if (grid != null) {
1081
            grid.setRotation(rotation);
1082
        }
1083
    }
1084

    
1085
    public void showGrid(boolean b) {
1086
        showGrid = b;
1087
    }
1088

    
1089
    public boolean isShowGrid() {
1090
        return showGrid;
1091
    }
1092

    
1093
    public void refreshOriginalExtent() {
1094
        if (getTypeScale() == AUTOMATICO) {
1095
            viewDocument.getMapContext().getViewPort()
1096
                .setEnvelope(getMapContext().getViewPort().getEnvelope());
1097
            viewDocument.getMapContext().getViewPort().refreshExtent();
1098
        } else
1099
            if (getTypeScale() == MANUAL) {
1100
                Envelope oldExtent =
1101
                    viewDocument.getMapContext().getViewPort().getEnvelope();
1102
                Envelope newExtent =
1103
                    getMapContext().getViewPort().getEnvelope();
1104
                double xDif = newExtent.getCenter(0) - oldExtent.getCenter(0);
1105
                double yDif = newExtent.getCenter(1) - oldExtent.getCenter(1);
1106
                try {
1107
                    viewDocument.getMapContext()
1108
                        .getViewPort()
1109
                        .setEnvelope(
1110
                            geomManager.createEnvelope(oldExtent.getMinimum(0)
1111
                                + xDif, oldExtent.getMinimum(1) + yDif,
1112
                                oldExtent.getMaximum(0) + xDif,
1113
                                oldExtent.getMaximum(1) + yDif, SUBTYPES.GEOM2D));
1114
                } catch (CreateEnvelopeException e) {
1115
                    e.printStackTrace();
1116
                }
1117
                viewDocument.getMapContext().getViewPort().refreshExtent();
1118
            }
1119
    }
1120

    
1121
    public static void registerPersistent() {
1122
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
1123
        if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) {
1124
            DynStruct definition =
1125
                manager.addDefinition(FFrameView.class,
1126
                    PERSISTENCE_DEFINITION_NAME,
1127
                    "FFrameView persistence definition", null, null);
1128

    
1129
            definition.extend(manager
1130
                .getDefinition(FFrame.PERSISTENCE_DEFINITION_NAME));
1131

    
1132
            definition.addDynFieldInt(MODE_FIELD).setMandatory(true);
1133
            definition.addDynFieldInt(TYPESCALE_FIELD).setMandatory(true);
1134
            definition.addDynFieldInt(EXTENSION_FIELD).setMandatory(true);
1135
            definition.addDynFieldInt(QUALITY_FIELD).setMandatory(true);
1136
            definition.addDynFieldInt(VIEWING_FIELD).setMandatory(true);
1137
            definition.addDynFieldBoolean(BLINKED_FIELD).setMandatory(true);
1138
            definition.addDynFieldInt(MAPUNITS_FIELD).setMandatory(true);
1139
            definition.addDynFieldDouble(SCALE_FIELD).setMandatory(true);
1140
            definition.addDynFieldObject(VIEW_FIELD)
1141
                .setClassOfValue(ViewDocument.class).setMandatory(false);
1142
            definition.addDynFieldObject(ENVELOPE_FIELD)
1143
                .setClassOfValue(Envelope.class).setMandatory(false);
1144
            definition.addDynFieldBoolean(SHOWGRID_FIELD).setMandatory(true);
1145
            definition.addDynFieldObject(GRID_FIELD)
1146
                .setClassOfValue(IFFrame.class).setMandatory(false);
1147
            definition.addDynFieldObject(MAPCONTEXT_FIELD)
1148
                .setClassOfValue(MapContext.class).setMandatory(false);
1149
        }
1150
    }
1151

    
1152
    @Override
1153
    public void loadFromState(PersistentState state)
1154
        throws PersistenceException {
1155
        super.loadFromState(state);
1156
        mode = state.getInt(MODE_FIELD);
1157
        typeScale = state.getInt(TYPESCALE_FIELD);
1158
        extension = state.getInt(EXTENSION_FIELD);
1159
        quality = state.getInt(QUALITY_FIELD);
1160
        viewing = state.getInt(VIEWING_FIELD);
1161
        linked = state.getBoolean(BLINKED_FIELD);
1162
        mapUnits = state.getInt(MAPUNITS_FIELD);
1163
        mapScale = state.getDouble(SCALE_FIELD);
1164
        viewDocument = (ViewDocument) state.get(VIEW_FIELD);
1165

    
1166
        if (state.hasValue(MAPCONTEXT_FIELD)) {
1167
            mapContext = (MapContext) state.get(MAPCONTEXT_FIELD);
1168
            mapContext.getViewPort().setEnvelope(
1169
                (Envelope) state.get(ENVELOPE_FIELD));
1170
        }
1171

    
1172
        showGrid = state.getBoolean(SHOWGRID_FIELD);
1173
        grid = (IFFrame) state.get(GRID_FIELD);
1174
    }
1175

    
1176
    @Override
1177
    public void saveToState(PersistentState state) throws PersistenceException {
1178
        super.saveToState(state);
1179
        state.set(MODE_FIELD, mode);
1180
        state.set(TYPESCALE_FIELD, typeScale);
1181
        state.set(EXTENSION_FIELD, extension);
1182
        state.set(QUALITY_FIELD, quality);
1183
        state.set(VIEWING_FIELD, viewing);
1184
        state.set(BLINKED_FIELD, linked);
1185
        state.set(MAPUNITS_FIELD, mapUnits);
1186
        state.set(SCALE_FIELD, mapScale);
1187
        state.set(VIEW_FIELD, viewDocument);
1188

    
1189
        if (getMapContext() != null
1190
            && getMapContext().getViewPort().getEnvelope() != null) {
1191
            state.set(ENVELOPE_FIELD, getMapContext().getViewPort()
1192
                .getEnvelope());
1193
            state.set(MAPCONTEXT_FIELD, mapContext);
1194
        }
1195

    
1196
        state.set(SHOWGRID_FIELD, showGrid);
1197
        state.set(GRID_FIELD, grid);
1198
    }
1199
    
1200
    @Override
1201
    public void setBoundBox(Rectangle2D r) {      
1202
        super.setBoundBox(r);
1203
        refresh();
1204
    }   
1205

    
1206
    /**
1207
     * getRotation returns rotation of the frame
1208
     * getMapRotation returns rotation of the map
1209
     * 
1210
     * @return in degrees
1211
     */
1212
    public double getMapRotation() {
1213
        return 0;
1214
    }
1215
}