Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / applications / appgvSIG / src / org / gvsig / app / project / documents / layout / fframes / FFrameView.java @ 33420

History | View | Annotate | Download (39.2 KB)

1
/*
2
 * Created on 20-feb-2004
3
 *
4
 */
5
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
6
 *
7
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
8
 *
9
 * This program is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU General Public License
11
 * as published by the Free Software Foundation; either version 2
12
 * of the License, or (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
22
 *
23
 * For more information, contact:
24
 *
25
 *  Generalitat Valenciana
26
 *   Conselleria d'Infraestructures i Transport
27
 *   Av. Blasco Ib??ez, 50
28
 *   46010 VALENCIA
29
 *   SPAIN
30
 *
31
 *      +34 963862235
32
 *   gvsig@gva.es
33
 *      www.gvsig.gva.es
34
 *
35
 *    or
36
 *
37
 *   IVER T.I. S.A
38
 *   Salamanca 50
39
 *   46005 Valencia
40
 *   Spain
41
 *
42
 *   +34 963163400
43
 *   dac@iver.es
44
 */
45
package org.gvsig.app.project.documents.layout.fframes;
46

    
47
import java.awt.Color;
48
import java.awt.Dimension;
49
import java.awt.Graphics2D;
50
import java.awt.Point;
51
import java.awt.Rectangle;
52
import java.awt.geom.AffineTransform;
53
import java.awt.geom.Point2D;
54
import java.awt.geom.Rectangle2D;
55
import java.awt.image.BufferedImage;
56

    
57
import org.cresques.cts.IProjection;
58
import org.slf4j.Logger;
59
import org.slf4j.LoggerFactory;
60

    
61
import org.gvsig.andami.PluginServices;
62
import org.gvsig.andami.messages.NotificationManager;
63
import org.gvsig.app.project.Project;
64
import org.gvsig.app.project.documents.exceptions.SaveException;
65
import org.gvsig.app.project.documents.layout.FLayoutUtilities;
66
import org.gvsig.app.project.documents.layout.LayoutControl;
67
import org.gvsig.app.project.documents.layout.fframes.gui.dialogs.FFrameViewDialog;
68
import org.gvsig.app.project.documents.layout.fframes.gui.dialogs.IFFrameDialog;
69
import org.gvsig.app.project.documents.layout.gui.LayoutPanel;
70
import org.gvsig.app.project.documents.view.DefaultViewDocument;
71
import org.gvsig.app.project.documents.view.ViewDocument;
72
import org.gvsig.compat.print.PrintAttributes;
73
import org.gvsig.fmap.dal.exception.ReadException;
74
import org.gvsig.fmap.geom.Geometry;
75
import org.gvsig.fmap.geom.GeometryLocator;
76
import org.gvsig.fmap.geom.GeometryManager;
77
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
78
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
79
import org.gvsig.fmap.geom.primitive.Envelope;
80
import org.gvsig.fmap.mapcontext.MapContext;
81
import org.gvsig.fmap.mapcontext.MapContextException;
82
import org.gvsig.fmap.mapcontext.ViewPort;
83
import org.gvsig.fmap.mapcontext.events.ColorEvent;
84
import org.gvsig.fmap.mapcontext.events.ExtentEvent;
85
import org.gvsig.fmap.mapcontext.events.ProjectionEvent;
86
import org.gvsig.fmap.mapcontext.events.listeners.ViewPortListener;
87
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendChangedEvent;
88
import org.gvsig.fmap.mapcontext.rendering.legend.events.listeners.LegendListener;
89
import org.gvsig.tools.ToolsLocator;
90
import org.gvsig.tools.dynobject.DynStruct;
91
import org.gvsig.tools.persistence.PersistenceManager;
92
import org.gvsig.tools.persistence.PersistentState;
93
import org.gvsig.tools.persistence.exception.PersistenceException;
94
import org.gvsig.utils.XMLEntity;
95

    
96

    
97

    
98
/**
99
 * FFrame para introducir una vista en el Layout.
100
 *
101
 * @author Vicente Caballero Navarro
102
 */
103
public class FFrameView extends FFrame implements ViewPortListener,
104
    LegendListener, IFFrameUseProject, IFFrameUseFMap {
105
        public static final String PERSISTENCE_DEFINITION_NAME = "FFrameText";
106
        
107
        private static final String MODE_FIELD = "mode";
108
        private static final String TYPESCALE_FIELD = "typeScale";  
109
        private static final String EXTENSION_FIELD = "extension";
110
        private static final String QUALITY_FIELD  = "quality";  
111
        private static final String VIEWING_FIELD = "viewing";
112
        private static final String BLINKED_FIELD = "bLinked";  
113
        private static final String MAPUNITS_FIELD = "mapUnits";
114
        private static final String SCALE_FIELD = "scale";  
115
        private static final String VIEW_FIELD = "view";
116
        private static final String ENVELOPE_FIELD = "envelope";     
117
        private static final String SHOWGRID_FIELD = "showGrid";  
118
        private static final String GRID_FIELD = "gridview";
119
        
120
        private static final GeometryManager geomManager = GeometryLocator.getGeometryManager();
121
        private static final Logger logger = LoggerFactory.getLogger(FFrameView.class);
122
    public static final int PRESENTACION = 0;
123
    public static final int BORRADOR = 1;
124
    protected int m_Mode;
125
    protected int m_typeScale = AUTOMATICO;
126
    protected int m_extension = 0;
127
    protected int m_quality = PRESENTACION;
128
    protected int m_viewing = 0;
129
    protected boolean m_bLinked = true;
130
    protected ViewDocument view = null;
131
    protected MapContext m_fmap = null;
132
    protected double m_Scale = 0;
133
    protected int m_mapUnits = 1; //Metros.
134

    
135
    private BufferedImage m_image = null;
136
    private AffineTransform at = null;
137
    protected Project project = null;
138
    private double scaleAnt;
139
        private boolean refresh=false;
140
        private Point origin;
141
        private Point2D p1;
142
        private Point2D p2;
143
        private IFFrame grid;
144
        private boolean showGrid=false;
145
        /**
146
     * Creates a new FFrameView object.
147
     */
148
    public FFrameView() {
149
        num++;
150
    }
151

    
152
    /**
153
     * Devuelve una descripci?n del FFrameView.
154
     *
155
     * @return Descripci?n.
156
     */
157
    public String toString() {
158
        if (getView() == null) {
159
            return "FFrameView " + num + ": " + "Vacio";
160
        }
161

    
162
        return "FFrameView " + num + ": " + getView().getName();
163
    }
164

    
165
    /**
166
     * Rellena la escala de la vista que contiene el fframe.
167
     *
168
     * @param d escala de la vista.
169
     */
170
    public void setScale(double d) {
171
        m_Scale = d;
172
    }
173

    
174
    /**
175
     * Inserta el nuevo extent a la FFrameView.
176
     *
177
     * @param r Rect?ngulo a ocupar por el FFrameView.
178
     */
179
    public void setNewEnvelope(Envelope r) {
180
        getMapContext().getViewPort().setEnvelope(r);
181
        refresh = true;
182
        m_Scale = FLayoutUtilities.getScaleView(getMapContext().getViewPort(),
183
                getBoundBox().width,
184
                getBoundingBox(null).width / getBoundBox().width);
185
    }
186

    
187
    /**
188
     * Devuelve el FMap de la vista o una clonaci?n de este si se utiliza una
189
     * escala fija.
190
     *
191
     * @return FMap.
192
     */
193
    public MapContext getMapContext() {
194
            return m_fmap;
195
    }
196

    
197
    /**
198
     * Rellena la calidad que se quiere aplicar.
199
     *
200
     * @param q entero que representa la calidad a aplicar.
201
     */
202
    public void setQuality(int q) {
203
        m_quality = q;
204
    }
205

    
206
    /**
207
     * Devuelve un entero que representa la calidad que est? seleccionada.
208
     *
209
     * @return tipo de calidad selccionada.
210
     */
211
    public int getQuality() {
212
        return m_quality;
213
    }
214

    
215
    /**
216
     * Devuelve un entero que representa la forma en que se actualiza la vista.
217
     *
218
     * @return forma que se actualiza la vista.
219
     */
220
    public int getViewing() {
221
        return m_viewing;
222
    }
223

    
224
    /**
225
     * Rellena la forma de actualizar la vista(cuando activo o siempre). De
226
     * momento esta opci?n esta deshabilitada.
227
     *
228
     * @param v entero que representa la forma de actualizar la vista.
229
     */
230
    public void setViewing(int v) {
231
        m_viewing = v;
232
    }
233

    
234
    /**
235
     * Inserta el ProjectView de donde obtener las propiedades de la vista a
236
     * mostrar.
237
     *
238
     * @param v Modelo de la vista.
239
     */
240
    public void setView(DefaultViewDocument v) {
241
            view=v;
242
            ViewPort vp =null;
243
            if (getMapContext()!=null){
244
                vp=getMapContext().getViewPort();
245
        }else{
246
                vp = v.getMapContext().getViewPort().cloneViewPort();
247
        }
248
        vp.setImageSize(new Dimension((int) getBoundingBox(null).width,
249
                (int) getBoundingBox(null).height));
250

    
251
        if (m_bLinked) {
252
            if (getTypeScale() == AUTOMATICO) {
253
                m_fmap = v.getMapContext().createNewFMap(v.getMapContext()
254
                                                          .getViewPort()
255
                                                          .cloneViewPort());
256
                m_fmap.getViewPort().setImageSize(new Dimension(
257
                        (int) getBoundingBox(null).width,
258
                        (int) getBoundingBox(null).height));
259
                v.getMapContext().getViewPort().addViewPortListener(this);
260
                v.getMapContext().addLayerListener(this);
261
            } else if (getTypeScale() == CONSTANTE) {
262
                    m_fmap = v.getMapContext().createNewFMap(vp);
263
                    vp.setEnvelope(getNewEnvelope(getScale()));
264
                    v.getMapContext().getViewPort().addViewPortListener(this);
265
                v.getMapContext().addLayerListener(this);
266
            } else if (getTypeScale() == MANUAL) {
267
                m_fmap = v.getMapContext().createNewFMap(vp);
268
                vp.setEnvelope(getNewEnvelope(getScale()));
269
                v.getMapContext().getViewPort().addViewPortListener(this);
270
                v.getMapContext().addLayerListener(this);
271
            }
272
        } else if (!m_bLinked) {
273
//            try {
274
                if (getTypeScale() == AUTOMATICO) {
275
                    m_fmap = v.getMapContext().cloneFMap(); //(v.getMapContext().getViewPort().cloneViewPort());
276
                    m_fmap.setViewPort(v.getMapContext().getViewPort()
277
                                        .cloneViewPort());
278
                    m_fmap.getViewPort().setImageSize(new Dimension(
279
                            (int) getBoundingBox(null).width,
280
                            (int) getBoundingBox(null).height));
281
                    v.getMapContext().getViewPort().addViewPortListener(this);
282
                } else if (getTypeScale() == CONSTANTE) {
283
                        m_fmap = v.getMapContext().cloneFMap();
284
                        vp.setEnvelope(getNewEnvelope(getScale()));
285
                    m_fmap.setViewPort(vp);
286
                    v.getMapContext().getViewPort().addViewPortListener(this);
287
                } else if (getTypeScale() == MANUAL) {
288
                    m_fmap = v.getMapContext().cloneFMap();
289
                    vp.setEnvelope(getNewEnvelope(getScale()));
290
                    m_fmap.setViewPort(vp);
291
                    v.getMapContext().getViewPort().addViewPortListener(this);
292
                }
293
//            } catch (XMLException e1) {
294
//                NotificationManager.addError("Cuando se a?ade una vista al Layout",
295
//                    e1);
296
//            }
297
        }
298
    }
299

    
300
    /**
301
     * Devuelve el modelo de la vista.
302
     *
303
     * @return Modelo de la vista.
304
     */
305
    public ViewDocument getView() {
306
        return view;
307
    }
308

    
309
    /**
310
     * Devuelve un Rect?ngulo que representa  el extent de la vista que se
311
     * requiere a partir  de una escala.
312
     *
313
     * @param scale Escala a mostrar.
314
     *
315
     * @return Rect?ngulo.
316
     */
317
    protected Envelope getNewEnvelope(long scale) {
318
        double hview = getBoundBox().getHeight();
319
        double wview = getBoundBox().getWidth();
320
        double hextent = (scale * hview) / 100.0;
321
        double wextent = (scale * wview) / 100.0;
322

    
323
        if (m_fmap.getViewPort().getEnvelope()==null) {
324
                        try {
325
                                return geomManager.createEnvelope(0,0,0,0, SUBTYPES.GEOM2D);
326
                        } catch (CreateEnvelopeException e) {
327
                                logger.error("Error creating the envelope", e);
328
                                return null;
329
                        }
330
                }
331
        double newx = m_fmap.getViewPort().getEnvelope().getCenter(Geometry.DIMENSIONS.X) - (wextent / 2.0);
332
        double newy = m_fmap.getViewPort().getEnvelope().getCenter(Geometry.DIMENSIONS.Y) -  (hextent / 2.0);
333
        IProjection proj=m_fmap.getViewPort().getProjection();
334
                 Envelope r = null;
335
                try {
336
                        r = geomManager.createEnvelope(newx, newy, newx+ wextent,newy+ hextent, SUBTYPES.GEOM2D);
337
                } catch (CreateEnvelopeException e) {
338
                        logger.error("Error creating the envelope", e);
339
                }
340
        if (!proj.isProjected()){
341
                Rectangle2D auxR=new Rectangle2D.Double(newx,newy,wextent,hextent);
342
                         Rectangle2D aux = m_fmap.getViewPort().getProjection().getExtent(auxR,scale,wview,hview,1,100,2.54);
343
                         try {
344
                                r = geomManager.createEnvelope(aux.getX(),aux.getY(), aux.getMaxX(),aux.getMaxY(), SUBTYPES.GEOM2D);
345
                        } catch (CreateEnvelopeException e) {
346
                                logger.error("Error creating the envelope", e);
347
                        }
348
        }
349
        return r;
350
    }
351

    
352
    /**
353
         * M?todo que dibuja sobre el graphics que se le pasa como par?metro, seg?n
354
         * la transformada afin que se debe de aplicar y el rect?ngulo que se debe
355
         * de dibujar.
356
         *
357
         * @param g
358
         *            Graphics2D
359
         * @param at
360
         *            Transformada af?n.
361
         * @param rv
362
         *            rect?ngulo sobre el que hacer un clip.
363
         * @param imgBase
364
         *            Imagen para acelerar el dibujado.
365
         */
366
        public void draw(Graphics2D g, AffineTransform at, Rectangle2D rv,
367
                        BufferedImage imgBase) {
368
                Rectangle2D.Double r = getBoundingBox(at);
369
                if (getRotation() != 0) {
370
                        g.rotate(Math.toRadians(getRotation()), r.x + (r.width / 2), r.y
371
                                        + (r.height / 2));
372
                }
373
                if (intersects(rv, r)) {
374
                        if (getMapContext() == null) {
375
                                drawEmpty(g);
376
                        } else {
377
                                if (rv != null) {
378
                                        // Dibujamos en pantalla
379
                                        Rectangle rclip = null;
380
                                        if (g.getClipBounds()!=null) {
381
                                                rclip = (Rectangle)g.getClipBounds().clone();
382
                                        }
383
                                        g.clipRect((int) r.getMinX(), (int) r.getMinY(), (int) r
384
                                                        .getWidth(), (int) r.getHeight());
385

    
386
                                        if (getQuality() == PRESENTACION) {
387
                                                if (rv.intersects(r)) {
388
                                                        ViewPort viewPort = this.getMapContext()
389
                                                        .getViewPort();
390
                                                        Color theBackColor = viewPort.getBackColor();
391

    
392
                                                        if (origin != null
393
                                                                        && origin.equals(getLayout().getLayoutControl().getRectOrigin())
394
                                                                        && getLayout() != null
395
                                                                        && getLayout().getLayoutControl().getAT().getScaleX() == scaleAnt
396
                                                                        && m_image != null && !refresh && !(r.getWidth() > getLayout().getWidth()
397
                                                                                        || r.getHeight() > getLayout().getHeight())) {
398
                                                                if (theBackColor != null) {
399
                                                                        g.setColor(theBackColor);
400
                                                                        g.fillRect((int) r.x, (int) r.y, viewPort
401
                                                                                        .getImageWidth(), viewPort
402
                                                                                        .getImageHeight());
403
                                                                }
404
                                                                g.translate(r.getX(), r.getY());
405
                                                                g.drawImage(m_image, 0, 0, getLayout().getLayoutControl().getComponent());
406
                                                                g.translate(-r.getX(), -r.getY());
407
                                                                scaleAnt = getLayout().getLayoutControl().getAT().getScaleX();
408
                                                                origin = getLayout().getLayoutControl().getRectOrigin();//.clone();
409
                                                        } else {
410

    
411
//                                                                System.err.println("r : " + r);
412
                                                                if (r.getWidth() > getLayout().getWidth()
413
                                                                                || r.getHeight() > getLayout().getHeight()) {
414
                                                                        viewPort.setOffset(
415
                                                                                        new Point2D.Double(r.getX(), r
416
                                                                                                        .getY()));
417
                                                                        viewPort.setImageSize(
418
                                                                                        new Dimension((int) r.getWidth(),
419
                                                                                                        (int) r.getHeight()));
420
                                                                        MapContext fmap = getMapContext().cloneToDraw();
421
                                                                        ViewPort viewp = viewPort.cloneViewPort();
422
                                                                        viewp.setImageSize(new Dimension(
423
                                                                                        getLayout().getWidth(),
424
                                                                                        getLayout().getHeight()));
425
                                                                        Envelope r1 = calculateEnvelope();
426
                                                                        double width = getLayout().getLayoutContext().getAttributes()
427
                                                                                        .getSizeInUnits().getAncho();
428
                                                                        double scale = FLayoutUtilities
429
                                                                                        .getScaleView(viewp, width, r1
430
                                                                                                        .getLength(0)
431
                                                                                                        / width);
432
                                                                        viewp.setEnvelope(r1);
433

    
434
                                                                        fmap.setViewPort(viewp);
435
                                                                        g.translate(-r.getX(), -r.getY());
436
                                                                        if (theBackColor != null) {
437
                                                                                g.setColor(theBackColor);
438
                                                                                g.fillRect((int) r.x, (int) r.y, viewp
439
                                                                                                .getImageWidth(), viewp
440
                                                                                                .getImageHeight());
441
                                                                        }
442
                                                                        try {
443
                                                                                fmap.draw(imgBase, g, scale);
444
                                                                        } catch (ReadException e) {
445
                                                                                e.printStackTrace();
446
                                                                        } catch (MapContextException mpex) {
447
                                        mpex.printStackTrace();
448
                                                                        }
449

    
450
                                                                        g.translate(r.getX(), r.getY());
451

    
452
                                                                } else {
453
                                                                        viewPort.setOffset(
454
                                                                                        new Point2D.Double(r.x, r.y));
455
                                                                        viewPort.setImageSize(
456
                                                                                        new Dimension((int) r.width,
457
                                                                                                        (int) r.height));
458
                                                                        viewPort.refreshExtent();
459
                                                                        m_image = new BufferedImage((int) r
460
                                                                                        .getWidth(), (int) r.getHeight(),
461
                                                                                        BufferedImage.TYPE_INT_ARGB);
462
                                                                        Graphics2D gimg = (Graphics2D) m_image
463
                                                                                        .getGraphics();
464
                                                                        gimg.translate(-((int) r.getX()), -((int) r
465
                                                                                        .getY()));
466
                                                                        try {
467
                                                                                getMapContext().draw(m_image, gimg, getScale());
468
                                                                        } catch (ReadException e) {
469
                                                                                e.printStackTrace();
470
                                                                        } catch (MapContextException mpex) {
471
                                        mpex.printStackTrace();
472
                                    }
473
                                                                        gimg.translate(((int) r.getX()), ((int) r
474
                                                                                        .getY()));
475
                                                                        if (theBackColor != null) {
476
                                                                                g.setColor(theBackColor);
477
                                                                                g.fillRect((int) r.x, (int) r.y, viewPort
478
                                                                                                .getImageWidth(), viewPort
479
                                                                                                .getImageHeight());
480
                                                                        }
481
                                                                        g.drawImage(m_image, (int) r.getX(),
482
                                                                                        (int) r.getY(), getLayout());
483
                                                                }
484
                                                                scaleAnt = getLayout().getLayoutControl().getAT().getScaleX();
485
                                                                origin = getLayout().getLayoutControl().getRectOrigin();//.clone();
486
                                                                refresh = false;
487
                                                        }
488
                                                }
489
                                        } else {
490
                                                drawDraft(g);
491
                                        }
492
                                        if (rclip != null) {
493
                                                g.setClip(rclip.x, rclip.y, rclip.width,
494
                                                                rclip.height);
495
                                        }
496
                                } else {
497
                                        printX(g, at);
498
                                }
499
                        }
500
                }
501
                if (getRotation() != 0) {
502
                        g.rotate(Math.toRadians(-getRotation()), r.x + (r.width / 2), r.y
503
                                        + (r.height / 2));
504
                }
505

    
506
                if (getMapContext() != null) {
507
                        setATMap(getMapContext().getViewPort()
508
                                        .getAffineTransform());
509

    
510
                }
511
                if (showGrid && grid!=null){
512
                        ((FFrameGrid)grid).setFFrameDependence(this);
513
                        grid.draw(g,at,rv,imgBase);
514
                }
515
        }
516

    
517
    private Envelope calculateEnvelope() {
518
            if (p1==null||p2==null) {
519
                        try {
520
                                return geomManager.createEnvelope(0,0,0,0, SUBTYPES.GEOM2D);
521
                        } catch (CreateEnvelopeException e) {
522
                                logger.error("Error creating the envelope", e);
523
                        }
524
                }
525
            Envelope r = null;
526
                try {
527
                        r = geomManager.createEnvelope(p1.getX(),p1.getY(),p2.getX(),p2.getY(), SUBTYPES.GEOM2D);
528
                } catch (CreateEnvelopeException e) {
529
                        logger.error("Error creating the envelope", e);
530
                }
531
                return r;
532
    }
533

    
534
    public void print(Graphics2D g, AffineTransform at, Geometry geom,
535
                        PrintAttributes prroperties) {
536
        draw(g, at, null, null);
537
    }
538

    
539
    private void printX(Graphics2D g, AffineTransform at) {
540
        Rectangle2D.Double r = getBoundingBox(at);
541

    
542
        // Dibujamos en impresora
543
        Rectangle rclip = g.getClipBounds();
544
        g.clipRect((int) r.getMinX(), (int) r.getMinY(), (int) r.getWidth(),
545
            (int) r.getHeight());
546
        this.getMapContext().getViewPort().setOffset(new Point2D.Double(r.x, r.y));
547
        this.getMapContext().getViewPort().setImageSize(new Dimension((int) r.width,
548
                (int) r.height));
549

    
550
        try {
551
                this.getMapContext().print(g, getScale(),getLayout().getLayoutContext().getAttributes().toPrintAttributes());
552
        } catch (ReadException e) {
553
            NotificationManager.addError(e.getMessage(), e);
554
        } catch (MapContextException e) {
555
            NotificationManager.addError(e.getMessage(), e);
556
        }
557

    
558
        g.setClip(rclip.x, rclip.y, rclip.width, rclip.height);
559
    }
560

    
561
    /**
562
     * Rellena la unidad de medida en la que est? la vista.
563
     *
564
     * @param i entero que representa la unidad de medida de la vista.
565
     */
566
    public void setMapUnits(int i) {
567
        m_mapUnits = i;
568
    }
569

    
570
    /**
571
     * Obtiene la unidad de medida en la que est? la vista.
572
     *
573
     * @return Unidad de medida.
574
     */
575
    public int getMapUnits() {
576
        return m_mapUnits;
577
    }
578

    
579
    /**
580
     * Devuelve la escala seg?n el tipo de escala que se haya seleccionado al
581
     * a?adida la vista.
582
     *
583
     * @return escala.
584
     */
585
    public long getScale() {
586
        /*if (m_bLinked){
587
           return getScaleView1(METROS);
588
               }
589
         */
590
            if (getMapContext()==null) {
591
                        return 0;
592
                }
593
        if (getTypeScale() == AUTOMATICO) {
594
            return FLayoutUtilities.getScaleView(getMapContext().getViewPort(),
595
                getBoundBox().width, getBoundingBox(null).width);
596
        } else if (getTypeScale() == CONSTANTE) {
597
            return (long) m_Scale;
598
        } else if (getTypeScale() == MANUAL) {
599
            return (long) m_Scale;
600
        }
601

    
602
        return (long) m_Scale;
603
    }
604

    
605
    /**
606
     * Seleccionar si la vista esta relacionada o no con la original.
607
     *
608
     * @param b true si est? ligada y false si no lo est?.
609
     */
610
    public void setLinked(boolean b) {
611
        m_bLinked = b;
612
    }
613

    
614
    /**
615
     * Devuelve si est? ligada o no el FFrameView con la vista.
616
     *
617
     * @return True si la vista est? ligada.
618
     */
619
    public boolean getLinked() {
620
        return m_bLinked;
621
    }
622

    
623
    /**
624
     * Devuelve la opci?n seleccionada:Rellenar marco de la vista o recorte a
625
     * la vista.
626
     *
627
     * @return entero que representa la opci?n elegida.
628
     */
629
    public int getExtension() {
630
        return m_extension;
631
    }
632

    
633
    /**
634
     * Devuelve el tipo de escala que est? seleccionada AUTOMATICO,CONSTANTE o
635
     * MANUAL.
636
     *
637
     * @return entero que representa el tipo seleccionado.
638
     */
639
    public int getTypeScale() {
640
        return m_typeScale;
641
    }
642

    
643
    /**
644
     * Rellenar si se quiere:Rellenar marco de la vista o recorte a la vista.
645
     *
646
     * @param i entero que representa la opci?n elegida.
647
     */
648
    public void setExtension(int i) {
649
        m_extension = i;
650
    }
651

    
652
    /**
653
     * Rellenar el tipo de escala que se desea.
654
     *
655
     * @param i entero que representa el tipo de escala.
656
     */
657
    public void setTypeScale(int i) {
658
        m_typeScale = i;
659
    }
660

    
661
    /**
662
     * DOCUMENT ME!
663
     *
664
     * @return DOCUMENT ME!
665
     *
666
     * @throws SaveException
667
     *
668
     * @see org.gvsig.app.project.documents.layout.fframes.IFFrame#getXMLEntity()
669
     */
670
    public XMLEntity getXMLEntity() throws SaveException {
671
        XMLEntity xml = super.getXMLEntity();
672

    
673
//        try {
674
////            xml.putProperty("type", Layout.RECTANGLEVIEW);
675
//            xml.putProperty("m_Mode", m_Mode);
676
//            xml.putProperty("m_typeScale", m_typeScale);
677
//            xml.putProperty("m_extension", m_extension);
678
//            xml.putProperty("m_quality", m_quality);
679
//            xml.putProperty("m_viewing", m_viewing);
680
//            xml.putProperty("m_bLinked", m_bLinked);
681
//            xml.putProperty("m_mapUnits", m_mapUnits);
682
//            xml.putProperty("m_Scale", m_Scale);
683
//
684
//            ProjectExtension pe = (ProjectExtension) PluginServices.getExtension(ProjectExtension.class);
685
//            ArrayList views = pe.getProject().getDocumentsByType(ProjectViewFactory.registerName);
686
//
687
//            boolean hasIndex = false;
688
//
689
//
690
//            if (view != null) {
691
//                    xml.putProperty("viewName",view.getName());
692
//                    for (int i = 0; i < views.size(); i++) {
693
//                        if (view.getName().equals(((ProjectView) views.get(i)).getName())) {
694
//                            xml.putProperty("indice", i);
695
//                            hasIndex = true;
696
//                            break;
697
//                        }
698
//                    }
699
//            }
700
//
701
//            if (!hasIndex) {
702
//                xml.putProperty("indice", -1);
703
//            }
704
//
705
//            if (getMapContext() != null && getMapContext().getViewPort().getExtent()!=null) {
706
//                xml.putProperty("extentX",
707
//                    getMapContext().getViewPort().getExtent().getX());
708
//                xml.putProperty("extentY",
709
//                    getMapContext().getViewPort().getExtent().getY());
710
//                xml.putProperty("extentW",
711
//                    getMapContext().getViewPort().getExtent().getWidth());
712
//                xml.putProperty("extentH",
713
//                    getMapContext().getViewPort().getExtent().getHeight());
714
//
715
//                xml.addChild(getMapContext().getXMLEntity());
716
//            }
717
//            xml.putProperty("showGrid", showGrid);
718
//            if (grid!=null) {
719
//                                xml.addChild(grid.getXMLEntity());
720
//                        }
721
//        } catch (Exception e) {
722
//            throw new SaveException(e, this.getClass().getName());
723
//        }
724

    
725
        return xml;
726
    }
727

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

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

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

    
755
    /**
756
     * Inserta la matriz de transformaci?n.
757
     *
758
     * @param transform Matriz de transformaci?n.
759
     */
760
    public void setATMap(AffineTransform transform) {
761
        at = transform;
762
    }
763
    /**
764
     * Inserta el proyecto.
765
     *
766
     * @param p Proyecto.
767
     */
768
    public void setProject(Project p) {
769
        project = p;
770
    }
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
    /**
781
     * @see com.iver.cit.gvsig.fmap.ExtentListener#extentChanged(org.gvsig.fmap.mapcontext.events.ExtentEvent)
782
     */
783
    public void extentChanged(ExtentEvent e) {
784
        if (getTypeScale() == AUTOMATICO) {
785
            m_fmap.getViewPort().setEnvelope(e.getNewExtent());
786
            if (getLayout() != null) {
787
                    getLayout().getLayoutControl().setStatus(LayoutControl.DESACTUALIZADO);
788
            }
789
        }else if (getTypeScale() == MANUAL) {
790
                Envelope oldExtent = m_fmap.getViewPort().getEnvelope();
791
                Envelope newExtent=e.getNewExtent();
792
                double xDif=newExtent.getCenter(0)-oldExtent.getCenter(0);
793
                double yDif=newExtent.getCenter(1)-oldExtent.getCenter(1);
794
                try {
795
                                m_fmap.getViewPort().setEnvelope(geomManager.createEnvelope(oldExtent.getMinimum(0)+xDif,oldExtent.getMinimum(1)+yDif,oldExtent.getMaximum(0)+xDif,oldExtent.getMaximum(1)+yDif, SUBTYPES.GEOM2D));
796
                        } catch (CreateEnvelopeException e1) {
797
                                e1.printStackTrace();
798
                        }
799
            if (getLayout() != null) {
800
                    getLayout().getLayoutControl().setStatus(LayoutControl.DESACTUALIZADO);
801
            }
802
        }
803
        refresh=true;
804
    }
805

    
806
    /**
807
     * @see org.gvsig.fmap.mapcontext.events.listeners.ViewPortListener#backColorChanged(org.gvsig.fmap.mapcontext.events.ColorEvent)
808
     */
809
    public void backColorChanged(ColorEvent e) {
810
        if (getLinked()) {
811
            m_fmap.getViewPort().setBackColor(e.getNewColor());
812
            getLayout().getLayoutControl().setStatus(LayoutControl.DESACTUALIZADO);
813

    
814
            //setBufferedImage(null);
815
        }
816
    }
817

    
818
    /**
819
     * @see org.gvsig.fmap.mapcontext.events.listeners.ViewPortListener#projectionChanged(org.gvsig.fmap.mapcontext.events.ProjectionEvent)
820
     */
821
        public void projectionChanged(ProjectionEvent e) {
822
        if (getTypeScale() == AUTOMATICO) {
823
            m_fmap.getViewPort().setProjection(e.getNewProjection());
824

    
825
            if (getLayout() != null) {
826
                    getLayout().getLayoutControl().setStatus(LayoutControl.DESACTUALIZADO);
827
            }
828
        }
829
        }
830

    
831
    /**
832
     * DOCUMENT ME!
833
     *
834
     * @param e DOCUMENT ME!
835
     */
836
    public void legendChanged(LegendChangedEvent e) {
837
        if (getLinked()) {
838
                getLayout().getLayoutControl().setStatus(LayoutControl.DESACTUALIZADO);
839
            refresh=true;
840
            //setBufferedImage(null);
841
        }
842
    }
843

    
844
    /**
845
     * DOCUMENT ME!
846
     *
847
     * @param xml DOCUMENT ME!
848
     */
849
    public void setXMLEntity(XMLEntity xml) {
850
//        if (xml.getIntProperty("m_Selected") != 0) {
851
//            this.setSelected(true);
852
//        } else {
853
//            this.setSelected(false);
854
//        }
855
//
856
//        this.setName(xml.getStringProperty("m_name"));
857
//        this.setBoundBox(new Rectangle2D.Double(xml.getDoubleProperty("x"),
858
//                xml.getDoubleProperty("y"), xml.getDoubleProperty("w"),
859
//                xml.getDoubleProperty("h")));
860
//
861
//        this.m_Mode = xml.getIntProperty("m_Mode");
862
//        this.m_typeScale = xml.getIntProperty("m_typeScale");
863
//        this.m_extension = xml.getIntProperty("m_extension");
864
//        this.m_quality = xml.getIntProperty("m_quality");
865
//        this.m_viewing = xml.getIntProperty("m_viewing");
866
//        this.m_bLinked = xml.getBooleanProperty("m_bLinked");
867
//        this.m_mapUnits = xml.getIntProperty("m_mapUnits");
868
//        setRotation(xml.getDoubleProperty("m_rotation"));
869
//
870
//        this.m_Scale = xml.getDoubleProperty("m_Scale");
871
//
872
//        int indice = xml.getIntProperty("indice");
873
//
874
//        ProjectView view = null;
875
//
876
//        if (xml.contains("viewName")){
877
//                view = (ProjectView)project.getProjectDocumentByName(xml.getStringProperty("viewName"),ProjectViewFactory.registerName);
878
//        }else {
879
//                if (indice != -1) {
880
//                        try {
881
//                                ArrayList views = project.getDocumentsByType(ProjectViewFactory.registerName);
882
//
883
//                                view = (ProjectView) views.get(indice);
884
//                        } catch (IndexOutOfBoundsException e) {
885
//                                NotificationManager.addError("No se ha encontrado la vista de indice "+ indice,
886
//                                            e);
887
//                        }
888
//                }
889
//        }
890
//
891
//
892
//        if (view != null) {
893
//                this.setView(view);
894
//
895
//                try {
896
//                        if (xml.contains("extentX")) {
897
//                                if (m_bLinked) {
898
//                                        double x=xml.getDoubleProperty("extentX");
899
//                                        double y=xml.getDoubleProperty("extentY");
900
//                                        double w=xml.getDoubleProperty("extentW");
901
//                                        double h=xml.getDoubleProperty("extentH");
902
//                                        try {
903
//                                                        this.getMapContext().getViewPort().setEnvelope(geomManager.createEnvelope(x,y,x+w,y+h, SUBTYPES.GEOM2D));
904
//                                                } catch (CreateEnvelopeException e) {
905
//                                                        logger.error("Error creating the envelope", e);
906
//                                                }
907
//                                } else if (!m_bLinked) {
908
//                                        this.m_fmap = MapContext.createFromXML(xml.getChild(0));
909
//                                }
910
//                        }
911
//                } catch (XMLException e) {
912
//                        NotificationManager.addError("Pasando las propiedades del XMLEntity al objeto",
913
//                                        e);
914
//                }
915
//        } else if (!m_bLinked) {
916
//            try {
917
//                this.m_fmap = MapContext.createFromXML(xml.getChild(0));
918
//            } catch (XMLException e) {
919
//                e.printStackTrace();
920
//            }
921
//        }
922
    }
923

    
924
    /**
925
     * DOCUMENT ME!
926
     *
927
     * @param arg0 DOCUMENT ME!
928
     *
929
     * @return DOCUMENT ME!
930
     */
931
    public boolean compare(Object arg0) {
932
        if (!(arg0 instanceof FFrameView)) {
933
            return false;
934
        }
935

    
936
        if (!this.getName().equals(((FFrameView) arg0).getName())) {
937
            return false;
938
        }
939

    
940
        if (Math.abs(this.getBoundBox().getWidth()-(((FFrameView) arg0).getBoundBox().getWidth()))>0.05) {
941
            return false;
942
        }
943
        if (Math.abs(this.getBoundBox().getHeight()-(((FFrameView) arg0).getBoundBox().getHeight()))>0.05) {
944
            return false;
945
        }
946

    
947
        if (!this.toString().equals(((FFrameView) arg0).toString())) {
948
            return false;
949
        }
950

    
951
        if (this.getMapContext()!=null && !this.getMapContext().equals(((FFrameView) arg0).getMapContext())) {
952
            return false;
953
        }
954

    
955
        if (this.getRotation()!=((FFrameView)arg0).getRotation()){
956
                return false;
957
        }
958
        return true;
959
    }
960

    
961
    /**
962
     * DOCUMENT ME!
963
     *
964
     * @param arg0 DOCUMENT ME!
965
     *
966
     * @return DOCUMENT ME!
967
     */
968
    public boolean equals(Object arg0) {
969
        return this.compare(arg0);
970
    }
971

    
972
        public void refresh() {
973
                if (view!=null && (getTypeScale() == MANUAL || getTypeScale() == CONSTANTE )) {
974
                        getMapContext().getViewPort().setEnvelope(getNewEnvelope(getScale()));
975
                }
976
                refresh=true;
977
        }
978

    
979
        public void fullExtent() throws ReadException {
980
                setNewEnvelope(getMapContext().getFullEnvelope());
981
        }
982

    
983
        public void setPointsToZoom(Point2D px1, Point2D px2) {
984
                p1=px1;
985
                p2=px2;
986
        }
987

    
988
        public void movePoints(Point2D px1, Point2D px2) {
989
                double difX=-px2.getX()+px1.getX();
990
                double difY=-px2.getY()+px1.getY();
991
                if (p1!=null) {
992
                        p1.setLocation(p1.getX()+difX,p1.getY()+difY);
993
                        p2.setLocation(p2.getX()+difX,p2.getY()+difY);
994
                }
995
        }
996

    
997
        public void cloneActions(IFFrame frame) {
998
                if (view ==null || view.getMapContext()==null) {
999
                        return;
1000
                }
1001
                if (m_bLinked) {
1002
            if (getTypeScale() == AUTOMATICO) {
1003
                    view.getMapContext().getViewPort().addViewPortListener(this);
1004
                view.getMapContext().addLayerListener(this);
1005
            } else if (getTypeScale() == CONSTANTE) {
1006
                view.getMapContext().getViewPort().removeViewPortListener(this);
1007
                view.getMapContext().addLayerListener(this);
1008
            } else if (getTypeScale() == MANUAL) {
1009
                view.getMapContext().getViewPort().removeViewPortListener(this);
1010
                view.getMapContext().addLayerListener(this);
1011
            }
1012
        } else if (!m_bLinked) {
1013
                if (getTypeScale() == AUTOMATICO) {
1014
                view.getMapContext().getViewPort().addViewPortListener(this);
1015
            } else if (getTypeScale() == CONSTANTE) {
1016
                view.getMapContext().getViewPort().removeViewPortListener(this);
1017
            } else if (getTypeScale() == MANUAL) {
1018
                view.getMapContext().getViewPort().removeViewPortListener(this);
1019
            }
1020
        }
1021
                ((FFrameView)frame).view.getMapContext().removeLayerListener((FFrameView)frame);
1022
            ((FFrameView)frame).view.getMapContext().getViewPort().removeViewPortListener((FFrameView)frame);
1023

    
1024

    
1025
        }
1026
        public IFFrame cloneFFrame(LayoutPanel layout) {
1027
                FFrameView frame =(FFrameView)FrameFactory.createFrameFromName(FFrameViewFactory.registerName);
1028
        frame.setLevel(this.getLevel());
1029
        frame.setNum(this.num);
1030
        frame.setName(this.getName());
1031
        frame.setBoundBox(this.getBoundBox());
1032
        frame.setTag(this.getTag());
1033
        frame.m_Mode = this.m_Mode;
1034
        frame.m_typeScale = this.m_typeScale;
1035
        frame.m_extension = this.m_extension;
1036
        frame.m_quality = this.m_quality;
1037
        frame.m_viewing = this.m_viewing;
1038
        frame.m_bLinked = this.m_bLinked;
1039
        frame.m_mapUnits = this.m_mapUnits;
1040
        frame.setRotation(this.getRotation());
1041

    
1042
        frame.m_Scale = this.m_Scale;
1043
        frame.view=this.getView();
1044
        frame.m_fmap = this.getMapContext();
1045
        frame.setSelected(this.getSelected()!=IFFrame.NOSELECT);
1046
        frame.setLayout(layout);
1047
        frame.origin=this.origin;
1048
        frame.scaleAnt=this.scaleAnt;
1049
        frame.m_image=this.m_image;
1050
        frame.refresh=this.refresh;
1051

    
1052
        if (frame instanceof IFFrameViewDependence) {
1053
            ((IFFrameViewDependence) frame).initDependence(layout.getLayoutContext().getAllFFrames());
1054
        }
1055
        if (grid!=null){
1056
                FFrameGrid newGrid=(FFrameGrid)this.grid.cloneFFrame(layout);
1057
                newGrid.setFFrameDependence(frame);
1058
                frame.setGrid(newGrid);
1059
        }
1060
        frame.showGrid=showGrid;
1061
        cloneActions(frame);
1062
        return frame;
1063
    }
1064
        public void setGrid(IFFrame grid) {
1065
                this.grid=grid;
1066
                this.grid.setRotation(this.getRotation());
1067
        }
1068
        public IFFrame getGrid(){
1069
                return this.grid;
1070
        }
1071

    
1072
        public void setRotation(double rotation) {
1073
                super.setRotation(rotation);
1074
                if (grid!=null) {
1075
                        grid.setRotation(rotation);
1076
                }
1077
        }
1078
        public IFFrameDialog getPropertyDialog() {
1079
                return new FFrameViewDialog(getLayout(),this);
1080
        }
1081
        public void showGrid(boolean b){
1082
                showGrid=b;
1083
        }
1084

    
1085
        public boolean isShowGrid() {
1086
                return showGrid;
1087
        }
1088
        public void refreshOriginalExtent(){
1089
                if (getTypeScale() == AUTOMATICO) {
1090
                        view.getMapContext().getViewPort().setEnvelope(getMapContext().getViewPort().getEnvelope());
1091
                        view.getMapContext().getViewPort().refreshExtent();
1092
                }else if (getTypeScale() == MANUAL){
1093
                        Envelope oldExtent = view.getMapContext().getViewPort().getEnvelope();
1094
                Envelope newExtent=getMapContext().getViewPort().getEnvelope();
1095
                double xDif=newExtent.getCenter(0)-oldExtent.getCenter(0);
1096
                double yDif=newExtent.getCenter(1)-oldExtent.getCenter(1);
1097
                try {
1098
                                view.getMapContext().getViewPort().setEnvelope(geomManager.createEnvelope(oldExtent.getMinimum(0)+xDif,oldExtent.getMinimum(1)+yDif,oldExtent.getMaximum(0)+xDif,oldExtent.getMaximum(1)+yDif, SUBTYPES.GEOM2D));
1099
                        } catch (CreateEnvelopeException e) {
1100
                                e.printStackTrace();
1101
                        }
1102
                view.getMapContext().getViewPort().refreshExtent();
1103
                }
1104
        }
1105
        
1106
        public static void registerPersistent() {
1107
                PersistenceManager manager = ToolsLocator.getPersistenceManager();
1108
                if( manager.getDefinition(PERSISTENCE_DEFINITION_NAME)==null ) {
1109
                        DynStruct definition = manager.addDefinition(
1110
                                        FFrameView.class,
1111
                                        PERSISTENCE_DEFINITION_NAME,
1112
                                        "FFrameView persistence definition",
1113
                                        null, 
1114
                                        null
1115
                        ); 
1116

    
1117
                        definition.extend(manager.getDefinition(FFrame.PERSISTENCE_DEFINITION_NAME));        
1118
                
1119
                        
1120
                        definition.addDynFieldInt(MODE_FIELD).setMandatory(true);        
1121
                        definition.addDynFieldInt(TYPESCALE_FIELD).setMandatory(true);        
1122
                        definition.addDynFieldInt(EXTENSION_FIELD).setMandatory(true);
1123
                        definition.addDynFieldInt(QUALITY_FIELD).setMandatory(true);
1124
                        definition.addDynFieldInt(VIEWING_FIELD).setMandatory(true);
1125
                        definition.addDynFieldBoolean(BLINKED_FIELD).setMandatory(true);
1126
                        definition.addDynFieldInt(MAPUNITS_FIELD).setMandatory(true);
1127
                        definition.addDynFieldDouble(SCALE_FIELD).setMandatory(true);
1128
                        definition.addDynField(VIEW_FIELD).setClassOfValue(ViewDocument.class).setMandatory(true);
1129
                        definition.addDynFieldBoolean(ENVELOPE_FIELD).setClassOfValue(Envelope.class).setMandatory(false);
1130
                        definition.addDynFieldBoolean(SHOWGRID_FIELD).setMandatory(true);
1131
                        definition.addDynFieldString(GRID_FIELD).setClassOfValue(IFFrame.class).setMandatory(true);
1132
                }
1133
        }
1134

    
1135
        @Override
1136
        public void loadFromState(PersistentState state)
1137
        throws PersistenceException {
1138
                super.loadFromState(state);
1139
                m_Mode = state.getInt(MODE_FIELD);
1140
                m_typeScale = state.getInt(TYPESCALE_FIELD);  
1141
                m_extension = state.getInt(EXTENSION_FIELD);
1142
                m_quality = state.getInt(QUALITY_FIELD);  
1143
                m_viewing = state.getInt(VIEWING_FIELD);
1144
                m_bLinked = state.getBoolean(BLINKED_FIELD);  
1145
                m_mapUnits = state.getInt(MAPUNITS_FIELD);
1146
                m_Scale = state.getDouble(SCALE_FIELD);  
1147
                view = (ViewDocument)state.get(VIEW_FIELD);
1148

    
1149
                if (state.hasValue(ENVELOPE_FIELD)){
1150
                        this.getMapContext().getViewPort().setEnvelope((Envelope)state.get(ENVELOPE_FIELD));
1151
                }
1152
         
1153
        showGrid = state.getBoolean(SHOWGRID_FIELD);  
1154
        grid = (IFFrame)state.get(GRID_FIELD);
1155
        }
1156

    
1157
        @Override
1158
        public void saveToState(PersistentState state) throws PersistenceException {
1159
                super.saveToState(state);
1160
                state.set(MODE_FIELD, m_Mode);
1161
                state.set(TYPESCALE_FIELD, m_typeScale);  
1162
                state.set(EXTENSION_FIELD, m_extension);
1163
                state.set(QUALITY_FIELD, m_quality);  
1164
                state.set(VIEWING_FIELD, m_viewing);
1165
                state.set(BLINKED_FIELD, m_bLinked);  
1166
                state.set(MAPUNITS_FIELD, m_mapUnits);
1167
                state.set(SCALE_FIELD, m_Scale);  
1168
                state.set(VIEW_FIELD, view);
1169

    
1170
        if (getMapContext() != null && getMapContext().getViewPort().getEnvelope() != null) {
1171
                state.set(ENVELOPE_FIELD, getMapContext().getViewPort().getEnvelope());  
1172
        }
1173
        
1174
        state.set(SHOWGRID_FIELD, showGrid);  
1175
                state.set(GRID_FIELD, grid);
1176
        }
1177
}