Statistics
| Revision:

svn-document-layout / trunk / org.gvsig.app.document.layout2.app / org.gvsig.app.document.layout2.app.mainplugin / src / main / java / org / gvsig / app / project / documents / layout / fframes / FFrame.java @ 357

History | View | Annotate | Download (30.2 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.Font;
27
import java.awt.Graphics2D;
28
import java.awt.Image;
29
import java.awt.Rectangle;
30
import java.awt.event.MouseEvent;
31
import java.awt.geom.AffineTransform;
32
import java.awt.geom.Area;
33
import java.awt.geom.NoninvertibleTransformException;
34
import java.awt.geom.Point2D;
35
import java.awt.geom.Rectangle2D;
36
import java.awt.image.BufferedImage;
37

    
38
import org.gvsig.andami.PluginServices;
39
import org.gvsig.andami.ui.mdiManager.IWindowListener;
40
import org.gvsig.app.project.ProjectManager;
41
import org.gvsig.app.project.documents.Document;
42
import org.gvsig.app.project.documents.layout.Attributes;
43
import org.gvsig.app.project.documents.layout.DefaultLayoutManager;
44
import org.gvsig.app.project.documents.layout.FLayoutUtilities;
45
import org.gvsig.app.project.documents.layout.LayoutContext;
46
import org.gvsig.app.project.documents.layout.LayoutDocument;
47
import org.gvsig.app.project.documents.layout.LayoutManager;
48
import org.gvsig.tools.ToolsLocator;
49
import org.gvsig.tools.dynobject.DynStruct;
50
import org.gvsig.tools.observer.ObservableHelper;
51
import org.gvsig.tools.observer.Observer;
52
import org.gvsig.tools.persistence.PersistenceManager;
53
import org.gvsig.tools.persistence.PersistentState;
54
import org.gvsig.tools.persistence.exception.PersistenceException;
55
import org.slf4j.Logger;
56
import org.slf4j.LoggerFactory;
57

    
58
/**
59
 * Class implementing the IFFrame interface, that will be extended by all the
60
 * FFrames. It provides default methods useful for all fframes and abstract
61
 * methods to be implemented by them.
62
 * 
63
 * @author Vicente Caballero Navarro
64
 * @author Cesar Martinez Izquierdo
65
 */
66
public abstract class FFrame implements IFFrame {
67

    
68
    public static final String PERSISTENCE_DEFINITION_NAME = "FFrame";
69

    
70
    private static final String BOUNDINGBOX_FIELD = "boundingBox";
71
    private static final String SELECTED_FIELD = "selected";
72
    private static final String TAG_FIELD = "tag";
73
    private static final String ROTATION_FIELD = "rotation";
74
    private static final String LEVEL_FIELD = "level";
75
    private static final String NUM_FIELD = "num";
76
        private static final String DOCUMENT_FIELD = "layoutDocument";
77
        private static final String LAYOUT_CONTEXT_FIELD = "layoutContext";
78

    
79
    protected static final Logger LOG = LoggerFactory.getLogger(FFrame.class);
80

    
81
    protected Rectangle2D.Double m_BoundBox = new Rectangle2D.Double();
82
    // initially identity
83
    protected AffineTransform lastAT = new AffineTransform();
84
    
85
    protected int m_Selected = 0;
86
    protected Rectangle n = new Rectangle();
87
    protected Rectangle ne = new Rectangle();
88
    protected Rectangle e = new Rectangle();
89
    protected Rectangle se = new Rectangle();
90
    protected Rectangle s = new Rectangle();
91
    protected Rectangle so = new Rectangle();
92
    protected Rectangle o = new Rectangle();
93
    protected Rectangle no = new Rectangle();
94
    private String tag = null;
95
    protected int num = 0;
96
    private double m_rotation = 0;
97
    private int level = -1;
98
    private Rectangle2D lastMoveRect;
99
    protected FrameFactory frameFactory;
100

    
101
    private static Image iNEResize = null;
102
    private static Image iEResize = null;
103
    private static Image iNResize = null;
104
    private static Image iMove = null;
105
    private static Image iSEResize = null;
106

    
107
    protected LayoutManager layoutManager = null;
108
    // user getters to access these variables:
109
    private LayoutContext layoutContext = null;
110
    private Document document = null;
111
        
112
    protected ObservableHelper observers;
113
    
114
    public FFrame() {
115
        super();
116
        layoutManager =
117
            (LayoutManager) ProjectManager.getInstance().getDocumentManager(
118
                DefaultLayoutManager.TYPENAME);
119
        observers = new ObservableHelper();
120
    }
121

    
122
    /**
123
     * Dibuja los handlers sobre el boundingBox en el graphics que se pasa como
124
     * par�metro.
125
     * 
126
     * @param g
127
     *            Graphics sobre el que dibujar.
128
     */
129
    public void drawHandlers(Graphics2D g) {
130
        int size = 10;
131
        Rectangle2D r = getBoundingBox(null);
132
        Point2D p = new Point2D.Double();
133
        g.rotate(Math.toRadians(getRotation()), r.getX() + (r.getWidth() / 2),
134
            r.getY() + (r.getHeight() / 2));
135

    
136
        AffineTransform atRotate = new AffineTransform();
137
        atRotate.rotate(Math.toRadians(getRotation()), r.getX()
138
            + (r.getWidth() / 2), r.getY() + (r.getHeight() / 2));
139

    
140
        g.fillRect((int) r.getX() - size, (int) r.getY() - size, size, size);
141
        atRotate.transform(
142
            new Point2D.Double(r.getX() - size, r.getY() - size), p);
143
        no.setRect((int) p.getX(), (int) p.getY(), size, size);
144

    
145
        g.fillRect((int) r.getMaxX(), (int) r.getY() - size, size, size);
146
        atRotate.transform(new Point2D.Double(r.getMaxX(), r.getY() - size), p);
147
        ne.setRect((int) p.getX(), (int) p.getY(), size, size);
148

    
149
        g.fillRect((int) r.getX() - size, (int) r.getMaxY(), size, size);
150
        atRotate.transform(new Point2D.Double(r.getX() - size, r.getMaxY()), p);
151
        so.setRect((int) p.getX(), (int) p.getY(), size, size);
152

    
153
        g.fillRect((int) r.getMaxX(), (int) r.getMaxY(), size, size);
154
        atRotate.transform(new Point2D.Double(r.getMaxX(), r.getMaxY()), p);
155
        se.setRect((int) p.getX(), (int) p.getY(), size, size);
156

    
157
        g.fillRect((int) r.getCenterX() - (size / 2), (int) r.getY() - size,
158
            size, size);
159
        atRotate
160
            .transform(new Point2D.Double(r.getCenterX() - (size / 2), r.getY()
161
                - size), p);
162
        n.setRect((int) p.getX(), (int) p.getY(), size, size);
163

    
164
        g.fillRect((int) r.getCenterX() - (size / 2), (int) r.getMaxY(), size,
165
            size);
166
        atRotate.transform(
167
            new Point2D.Double(r.getCenterX() - (size / 2), r.getMaxY()), p);
168
        s.setRect((int) p.getX(), (int) p.getY(), size, size);
169

    
170
        g.fillRect((int) r.getX() - size, (int) r.getCenterY() - (size / 2),
171
            size, size);
172
        atRotate.transform(new Point2D.Double(r.getX() - size, r.getCenterY()
173
            - (size / 2)), p);
174
        o.setRect((int) p.getX(), (int) p.getY(), size, size);
175

    
176
        g.fillRect((int) r.getMaxX(), (int) r.getCenterY() - (size / 2), size,
177
            size);
178
        atRotate.transform(new Point2D.Double(r.getMaxX(), r.getCenterY()
179
            - (size / 2)), p);
180
        e.setRect((int) p.getX(), (int) p.getY(), size, size);
181
        g.rotate(Math.toRadians(-getRotation()), r.getX() + (r.getWidth() / 2),
182
            r.getY() + (r.getHeight() / 2));
183
    }
184

    
185
    /**
186
     * Sets the type of selection performed on the frame, based on the position
187
     * of the provided Point compared with the boundaries of the FFrame.
188
     * This method is usually called when the user clicks on the FFrame
189
     * 
190
     * @param p
191
     *            Point which should be evaluated to establish if the FFrame must
192
     *            be selected or not
193
     * @param e   Mouse event that triggered this method call
194
     * @see {@link #isSelected()}, {@link #getSelected()}
195
     */
196
    public void setSelected(Point2D p, MouseEvent e) {
197
        doSetSelected(getContains(p));
198
    }
199

    
200
    /**
201
     * Actualiza el BoundBox del FFrame a partir de su rect�ngulo en pixels y
202
     * la matriz de transformaci�n.
203
     * 
204
     * @param r
205
     *            Rect�ngulo.
206
     * @param at
207
     *            Matriz de transformaci�n.
208
     */
209
    public void updateRect(Rectangle2D r, AffineTransform at) {
210
        Rectangle2D.Double rec = FLayoutUtilities.toSheetRect(r, at);
211
        rec.setRect((int) rec.getMinX(), (int) rec.getMinY(),
212
            (int) rec.getWidth(), (int) rec.getHeight());
213
        setBoundBox(rec);
214
    }
215

    
216
    /**
217
     * Devuelve el rect�ngulo a partir del desplazamiento en el eje x y el
218
     * desplazamiento en el eje y.
219
     * 
220
     * @param difx
221
     *            desplazamiento sobre el eje x.
222
     * @param dify
223
     *            desplazamiento sobre el eje y.
224
     * 
225
     * @return rect�ngulo modificado en funci�n del desplazamiento
226
     *         realizado.
227
     */
228
    public Rectangle2D getMovieRect(int difx, int dify) {
229
        double x = 0;
230
        double y = 0;
231
        double w = 0;
232
        double h = 0;
233

    
234
        lastMoveRect =
235
            new Rectangle2D.Double(this.getBoundingBox(null).x,
236
                this.getBoundingBox(null).y, this.getBoundingBox(null).width,
237
                this.getBoundingBox(null).height);
238
        Rectangle2D.Double rec = this.getBoundingBox(null);
239
        int difn = 0;
240
        difn = difx;
241
        x = lastMoveRect.getX();
242
        y = lastMoveRect.getY();
243
        w = lastMoveRect.getWidth();
244
        h = lastMoveRect.getHeight();
245

    
246
        switch (this.getSelected()) {
247
        case (RECT):
248
            lastMoveRect.setRect((x + difx), (y + dify), w, h);
249

    
250
            break;
251

    
252
        case (N):
253

    
254
            if ((y + dify) > rec.getMaxY()) {
255
                y = rec.getMaxY();
256
            } else {
257
                y = y + dify;
258
            }
259

    
260
            lastMoveRect.setRect(x, y, w, Math.abs(h - dify));
261

    
262
            break;
263

    
264
        case (O):
265

    
266
            if ((x + difx) > rec.getMaxX()) {
267
                x = rec.getMaxX();
268
            } else {
269
                x = x + difx;
270
            }
271

    
272
            lastMoveRect.setRect(x, y, Math.abs(w - difx), h);
273

    
274
            break;
275

    
276
        case (S):
277

    
278
            if (y > (rec.getMaxY() + dify)) {
279
                y = rec.getMaxY() + dify;
280
            }
281

    
282
            lastMoveRect.setRect(x, y, w, Math.abs(h + dify));
283

    
284
            break;
285

    
286
        case (E):
287

    
288
            if (x > (rec.getMaxX() + difx)) {
289
                x = rec.getMaxX() + difx;
290
            }
291

    
292
            lastMoveRect.setRect(x, y, Math.abs(w + difx), h);
293

    
294
            break;
295

    
296
        case (NE):
297

    
298
            if ((y - difn) > rec.getMaxY()) {
299
                y = rec.getMaxY();
300
                x = rec.getMaxX() + difn;
301
            } else {
302
                y = y - difn;
303
            }
304

    
305
            lastMoveRect.setRect(x, y, Math.abs(w + difn), Math.abs(h + difn));
306

    
307
            break;
308

    
309
        case (NO):
310

    
311
            if ((y + difn) > rec.getMaxY()) {
312
                y = rec.getMaxY();
313
                x = rec.getMaxX();
314
            } else {
315
                x = x + difn;
316
                y = y + difn;
317
            }
318

    
319
            lastMoveRect.setRect(x, y, Math.abs(w - difn), Math.abs(h - difn));
320

    
321
            break;
322

    
323
        case (SE):
324

    
325
            if (y > (rec.getMaxY() + difn)) {
326
                y = rec.getMaxY() + difn;
327
                x = rec.getMaxX() + difn;
328
            }
329

    
330
            lastMoveRect.setRect(x, y, Math.abs(w + difn), Math.abs(h + difn));
331

    
332
            break;
333

    
334
        case (SO):
335

    
336
            if ((x + difn) > rec.getMaxX()) {
337
                x = rec.getMaxX();
338
                y = rec.getMaxY() - difn;
339
            } else {
340
                x = x + difn;
341
            }
342

    
343
            lastMoveRect.setRect(x, y, Math.abs(w - difn), Math.abs(h - difn));
344

    
345
            break;
346

    
347
        default:
348
            lastMoveRect.setRect((x), (y), w, h);
349
        }
350

    
351
        return lastMoveRect;
352
    }
353

    
354
    /**
355
     * Devuelve el rect�ngulo que representa el �ltimo generado al desplazar
356
     * o modificar el tama�o del fframe.
357
     * 
358
     * @return Rectangle2D
359
     * 
360
     */
361
    public Rectangle2D getLastMoveRect() {
362
        return lastMoveRect;
363
    }
364

    
365
    /**
366
     * Returns an integer representing the type of selection applied to the
367
     * FFrame. Valid values are:
368
     * {@link IFFrame#NOSELECT},
369
     * {@link IFFrame#NO}, {@link IFFrame#N}, {@link IFFrame#NE},
370
     * {@link IFFrame#O}, {@link IFFrame#RECT}, {@link IFFrame#E},
371
     * {@link IFFrame#SO}, {@link IFFrame#S}, {@link IFFrame#SE}.
372
     * 
373
     * @see {@link #isSelected()}, {@link #setSelected(boolean)}
374
     * @return The type of selection that has been applied
375
     */
376
    public int getSelected() {
377
        return m_Selected;
378
    }
379
    
380
    /**
381
     * Gets the selection status of the frame
382
     * 
383
     * @return <code>true</code> if the frame is selected,
384
     *    <code>false</code> otherwise
385
     * @see {@link #getSelected()}, {@link #setSelected(boolean)}
386
     */
387
    public boolean isSelected() {
388
            return getSelected()!=IFFrame.NOSELECT;
389
    }
390

    
391
    /**
392
     * Devuelve true, si el punto que se pasa como par�metro esta contenido
393
     * dentro del boundingbox del fframe.
394
     * 
395
     * @param p
396
     *            punto a comprobar.
397
     * 
398
     * @return true si el punto esta dentro del boundingbox.
399
     */
400
    public boolean contains(Point2D p) {
401
        return getBoundingBox(null).contains(p.getX(), p.getY());
402
    }
403

    
404
    /*
405
     * (non-Javadoc)
406
     * @see org.gvsig.app.project.documents.layout.fframes.IFFrame#getContains(Point2D)
407
     */
408
    public int getContains(Point2D p) {
409
            Point2D point = new Point2D.Double();
410
            AffineTransform rotationAT = getRotationAT();
411
            if (rotationAT!=null) {
412
                    // if the frame is rotated, we need to inversely rotate the point in order
413
                    // to decide whether it is contained or not in the non-rotated frame
414
                    try {
415
                                rotationAT.createInverse().transform(p, point);
416
                        } catch (NoninvertibleTransformException e1) {}
417
            }
418
            else {
419
                    point = p;
420
            }
421
        if (n.contains(point.getX(), point.getY())) {
422
            return N;
423
        } else
424
            if (ne.contains(point.getX(), point.getY())) {
425
                return NE;
426
            } else
427
                if (e.contains(point.getX(), point.getY())) {
428
                    return E;
429
                } else
430
                    if (se.contains(point.getX(), point.getY())) {
431
                        return SE;
432
                    } else
433
                        if (s.contains(point.getX(), point.getY())) {
434
                            return S;
435
                        } else
436
                            if (so.contains(point.getX(), point.getY())) {
437
                                return SO;
438
                            } else
439
                                if (o.contains(point.getX(), point.getY())) {
440
                                    return O;
441
                                } else
442
                                    if (no.contains(point.getX(), point.getY())) {
443
                                        return NO;
444
                                    } else
445
                                        if (getBoundingBox(null).contains(
446
                                            point.getX(), point.getY())) {
447
                                            return RECT;
448
                                        }
449

    
450
        return NOSELECT;
451
    }
452

    
453
    /**
454
     * Devuelve el Cursor adecuado seg�n como est� contenido el punto, si es
455
     * para desplazamiento, o cambio de tama�o.
456
     * 
457
     * @param p
458
     *            punto a comprobar.
459
     * 
460
     * @return Cursor adecuado a la posici�n.
461
     */
462
    public Image getMapCursor(Point2D p) {
463
        int select = getContains(p);
464

    
465
        switch (select) {
466
        case (N):
467
            return iNResize;
468

    
469
        case (NE):
470
            return iNEResize;
471

    
472
        case (E):
473
            return iEResize;
474

    
475
        case (SE):
476
            return iSEResize;
477

    
478
        case (S):
479
            return iNResize;
480

    
481
        case (SO):
482
            return iNEResize;
483

    
484
        case (O):
485
            return iEResize;
486

    
487
        case (NO):
488
            return iSEResize;
489

    
490
        case (RECT):
491
            return iMove;
492
        }
493

    
494
        return null;
495
    }
496

    
497
    /**
498
     * Draws the FFrame on the provided Graphics, according to the
499
     * provided affine transform and the visible rectangle. It has to
500
     * to be implemented by each FFrame, as each of them usually draws
501
     * diffently.
502
     * 
503
     * @param g Graphics2D
504
     * @param at Affine transform to translate sheet coordinates (in cm)
505
     *                                 to screen coordinates (in pixels)
506
     * @param visibleLayoutDocRect visible rectangle
507
     * @param imgBase Image used to speed up the drawing process
508
     */
509
    public abstract void draw(Graphics2D g, AffineTransform at, Rectangle2D r,
510
        BufferedImage imgBase);
511

    
512
    /**
513
     * Returns the bounding box (in pixels) of this FFrame, based on the provided
514
     * AffineTransform. If the AffineTransform is null, it returns the last
515
     * calculated bounding box.
516
     * 
517
     * @param at Affine transform to apply to the sheet coordinates to get the
518
     *                  bounding box in pixels.
519
     * @return Rectangle representing the bounding box (in pixels) of this
520
     * FFrame
521
     */
522
    public Rectangle2D.Double getBoundingBox(AffineTransform at) {
523
        if (at != null) {
524
            lastAT = (AffineTransform) at.clone();
525
        }
526
        return FLayoutUtilities.fromSheetRect(m_BoundBox, lastAT);
527
    }
528

    
529
    /**
530
     * Sets the bounding box in centimeters of this FFrame, using  paper
531
     * coordinates.
532
     * 
533
     * @param r
534
     *            Rectangle in centimeters
535
     */
536
    public void setBoundBox(Rectangle2D r) {
537
        if (r == null) {
538
            LOG.info("Warning: BBOX set to NULL in FFrame!");
539
            m_BoundBox = null;
540
        } else {
541
            m_BoundBox = new Rectangle2D.Double(r.getX(), r.getY(),
542
                r.getWidth(), r.getHeight());
543
        }
544
    }
545

    
546
    /**
547
     * Returns the bounding box in centimeters of this FFrame, using paper
548
     * coordinates
549
     * 
550
     * @return The bounding box of this FFrame, measured in centimeters.
551
     */
552
    public Rectangle2D.Double getBoundBox() {
553
        return m_BoundBox;
554
    }
555

    
556
    /**
557
     * Sets the selected status of the frame.
558
     * 
559
     * @param selected
560
     *            <code>true</code> to select the frame, <code>false</code> to
561
     *            unselect it
562
     * @see {@link #isSelected()}, {@link #getSelected()}
563
     */
564
    public void setSelected(boolean selected) {
565
        if (selected) {
566
                doSetSelected(IFFrame.RECT);
567
        } else {
568
                doSetSelected(IFFrame.NOSELECT);
569
        }
570
    }
571
    
572
    protected void doSetSelected(int selectedStatus) {
573
            m_Selected = selectedStatus;
574
    }
575

    
576
    /**
577
     * Dibuja sobre el graphics el rect�ngulo del fframe en modo borrador.
578
     * 
579
     * @param g
580
     *            Graphics so bre el que dibujar.
581
     */
582
    public void drawDraft(Graphics2D g) {
583
        Rectangle2D r = getBoundingBox(null);
584

    
585
        g.setColor(Color.lightGray);
586
        g.fillRect((int) r.getX(), (int) r.getY(), (int) r.getWidth(),
587
            (int) r.getHeight());
588
        g.setColor(Color.black);
589
        g.drawRect((int) r.getX(), (int) r.getY(), (int) r.getWidth() - 1,
590
            (int) r.getHeight() - 1);
591
        int scale = (int) (r.getWidth() / 12);
592
        Font f = new Font("SansSerif", Font.PLAIN, scale);
593
        g.setFont(f);
594
        g.drawString(getName(),
595
            (int) (r.getCenterX() - ((getName().length() * scale) / 4)),
596
            (int) (r.getCenterY()));
597
    }
598

    
599
    /**
600
     * Rellena con el n�mero de FFrame.
601
     * 
602
     * @param i
603
     *            n�mero
604
     */
605
    public void setNum(int i) {
606
        num = i;
607
    }
608

    
609
    /**
610
     * Draws the FFrame rectangle on the provided Graphics2D, only showing the
611
     * FFrame name on an empty rectangle.
612
     * 
613
     * @param g The graphics to draw on
614
     */
615
    public void drawEmpty(Graphics2D g) {
616
        Rectangle2D r = getBoundingBox(null);
617
        g.setColor(Color.lightGray);
618
        g.fillRect((int) r.getX(), (int) r.getY(), (int) r.getWidth(),
619
            (int) r.getHeight());
620
        g.setColor(Color.darkGray);
621
        g.setStroke(new BasicStroke(2));
622
        g.drawRect((int) r.getX(), (int) r.getY(), (int) r.getWidth(),
623
            (int) r.getHeight());
624
        g.setColor(Color.black);
625

    
626
        int scale = (int) (r.getWidth() / 12);
627
        Font f = new Font("SansSerif", Font.PLAIN, scale);
628
        g.setFont(f);
629

    
630
        String s =
631
            this.getNameFFrame() + " " + PluginServices.getText(this, "vacia");
632

    
633
        g.drawString(s, (int) (r.getCenterX() - ((s.length() * scale) / 4)),
634
            (int) (r.getCenterY()));
635
    }
636

    
637
    /**
638
     * Devuelve true si el rect�ngulo primero es null o si es distinto de null
639
     * e intersecta.
640
     * 
641
     * @param rv
642
     *            Rect�ngulo
643
     * @param r
644
     *            Rect�ngulo
645
     * 
646
     * @return True si intersecta o es null.
647
     */
648
    public boolean intersects(Rectangle2D rv, Rectangle2D r) {
649
        return (((rv != null) && rv.intersects(r)) || (rv == null));
650
    }
651

    
652
    /**
653
     * Rellena el tag del FFrame.
654
     * 
655
     * @param s
656
     *            String que representa el valor a guardar en el tag.
657
     */
658
    public void setTag(String s) {
659
        tag = s;
660
    }
661

    
662
    /**
663
     * Devuelve el tag.
664
     * 
665
     * @return tag.
666
     */
667
    public String getTag() {
668
        return tag;
669
    }
670

    
671
    /**
672
     * Dibuja sobre el graphics que se pasa como par�metro el icono que
673
     * representa que contiene un tag.
674
     * 
675
     * @param g
676
     *            Graphics sobre el que dibujar el icono.
677
     */
678
    public void drawSymbolTag(Graphics2D g) {
679
        Rectangle2D rec = getBoundingBox(null);
680
        g.rotate(Math.toRadians(getRotation()), rec.getX()
681
            + (rec.getWidth() / 2), rec.getY() + (rec.getHeight() / 2));
682

    
683
        try {
684
            Image image =
685
                PluginServices.getIconTheme().get("symboltag-icon").getImage();
686
            g.drawImage(image, (int) rec.getX(), (int) rec.getCenterY(), 30,
687
                30, null);
688
        } catch (NullPointerException npe) {
689
        }
690

    
691
        g.rotate(Math.toRadians(-getRotation()), rec.getX()
692
            + (rec.getWidth() / 2), rec.getY() + (rec.getHeight() / 2));
693
    }
694

    
695
    /**
696
     * Sets the rotation of the frame, measured in arc degrees
697
     * 
698
     * @param rotation
699
     *            Rotation to apply to the frame
700
     */
701
    public void setRotation(double rotation) {
702
        m_rotation = rotation;
703
    }
704
    
705
    /**
706
     * Gets the affine transform used to rotate the graphics when rotation is not 0
707
     * 
708
     * @return
709
     */
710
    protected AffineTransform getRotationAT() {
711
            // it has to be calculated each time as the frameRect may change, for instance
712
            // because a zoom in/out to paper has been performed
713
            double rotation = getRotation();
714
            if (getLayoutContext()!=null && getLayoutContext().getAT()!=null && Math.abs(rotation)>0.00001) {
715
                    AffineTransform rotationAT = new AffineTransform();
716
                Rectangle2D.Double frameRect = getBoundingBox(getLayoutContext().getAT());
717
                rotationAT.rotate(Math.toRadians(getRotation()), frameRect.getCenterX(), frameRect.getCenterY());
718
                return rotationAT;
719
            }
720
            return null;
721
    }
722

    
723
    /**
724
     * Gets the rotation of the frame, measured in arc degrees
725
     * 
726
     * @return Rotation of the frame
727
     */
728
    public double getRotation() {
729
        return m_rotation;
730
    }
731

    
732
    /**
733
     * Devuelve el nivel en el que se encuentra el FFrame.
734
     * 
735
     * @return nivel
736
     */
737
    public int getLevel() {
738
        return level;
739
    }
740

    
741
    /**
742
     * Inserta el nivel al que se encuentra el FFrame.
743
     * 
744
     * @param l
745
     *            entero que refleja el nivel del FFrame.
746
     */
747
    public void setLevel(int l) {
748
        level = l;
749
    }
750

    
751
    @Override
752
    public Object clone() throws CloneNotSupportedException {
753
        IFFrame frame = (IFFrame) super.clone();
754
        frame.setBoundBox(this.getBoundBox());
755
        return frame;
756
    }
757

    
758
    public void setFrameFactory(FrameFactory flf) {
759
        frameFactory = flf;
760
    }
761

    
762
    public FrameFactory getFrameFactory() {
763
        return frameFactory;
764
    }
765

    
766
    /**
767
     * Initilizes the static icons
768
     */
769
    public static void initializeIcons() {
770
        iNEResize =
771
            PluginServices.getIconTheme().get("neresize-icon").getImage();
772
        iEResize = PluginServices.getIconTheme().get("eresize-icon").getImage();
773
        iNResize = PluginServices.getIconTheme().get("nresize-icon").getImage();
774
        iMove = PluginServices.getIconTheme().get("graphic-move-icon").getImage();
775
        iSEResize =
776
            PluginServices.getIconTheme().get("sereresize-icon").getImage();
777
    }
778

    
779
    public static void registerPersistent() {
780
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
781
        if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) {
782
            DynStruct definition =
783
                manager.addDefinition(FFrame.class,
784
                    PERSISTENCE_DEFINITION_NAME,
785
                    "FFrame persistence definition", null, null);
786

    
787
            definition.addDynFieldObject(BOUNDINGBOX_FIELD)
788
                .setClassOfValue(Rectangle2D.class).setMandatory(true);
789
            definition.addDynFieldInt(SELECTED_FIELD).setMandatory(true);
790
            definition.addDynFieldString(TAG_FIELD).setMandatory(false);
791
            definition.addDynFieldDouble(ROTATION_FIELD).setMandatory(true);
792
            definition.addDynFieldInt(LEVEL_FIELD).setMandatory(true);
793
            definition.addDynFieldInt(NUM_FIELD).setMandatory(true);
794
            definition.addDynFieldObject(DOCUMENT_FIELD).setClassOfValue(LayoutDocument.class).setMandatory(false);
795
            definition.addDynFieldObject(LAYOUT_CONTEXT_FIELD).setClassOfValue(LayoutContext.class).setMandatory(false);
796
        }
797

    
798
        Attributes.registerPersistent();
799
        AbstractFFrameViewDependence.registerPersistent();
800
        FFrameBasic.registerPersistent();
801
        FFrameGraphics.registerPersistent();
802
        FFrameSymbol.registerPersistent();
803
        FFrameGrid.registerPersistent();
804
        FFrameGroup.registerPersistent();
805
        FFrameTable.registerPersistent();
806
        FFrameLegend.registerPersistent();
807
        FFramePicture.registerPersistent();
808
        FFrameNorth.registerPersistent();
809
        FFrameScaleBar.registerPersistent();
810
        FFrameText.registerPersistent();
811
        FFrameView.registerPersistent();
812
        FFrameOverView.registerPersistent();
813
    }
814

    
815
    public void loadFromState(PersistentState state)
816
        throws PersistenceException {
817
        m_BoundBox = (Rectangle2D.Double) state.get(BOUNDINGBOX_FIELD);
818
        m_Selected = state.getInt(SELECTED_FIELD);
819
        tag = state.getString(TAG_FIELD);
820
        m_rotation = state.getDouble(ROTATION_FIELD);
821
        level = state.getInt(LEVEL_FIELD);
822
        num = state.getInt(NUM_FIELD);
823
        if (state.hasValue(DOCUMENT_FIELD)) {
824
                setDocument((LayoutDocument)state.get(DOCUMENT_FIELD ));
825
        }
826
        if (state.hasValue(LAYOUT_CONTEXT_FIELD)) {
827
                setLayoutContext((LayoutContext) state.get(LAYOUT_CONTEXT_FIELD));
828
        }
829
    }
830

    
831
    public void saveToState(PersistentState state) throws PersistenceException {
832
        state.set(BOUNDINGBOX_FIELD, getBoundBox());
833
        state.set(SELECTED_FIELD, m_Selected);
834
        state.set(TAG_FIELD, getTag());
835
        state.set(ROTATION_FIELD, getRotation());
836
        state.set(LEVEL_FIELD, getLevel());
837
        state.set(NUM_FIELD, num);
838
        state.set(DOCUMENT_FIELD, getDocument());
839
        state.set(LAYOUT_CONTEXT_FIELD, getLayoutContext());
840
    }
841

    
842
    public void addObserver(Observer o) {
843
        observers.addObserver(o);        
844
    }
845

    
846
    public void deleteObserver(Observer o) {
847
      observers.deleteObserver(o);        
848
    }
849

    
850
    public void deleteObservers() {
851
       observers.deleteObservers();        
852
    }
853
    
854
    /*
855
     * (non-Javadoc)
856
     * @see org.gvsig.tools.dispose.Disposable#dispose()
857
     */
858
        public void dispose() {
859
                
860
        }
861
        
862
    /*
863
     * (non-Javadoc)
864
     * @see org.gvsig.app.project.documents.layout.fframes.IFFrame#frameRemoved()
865
     */
866
        public void frameRemoved() {}
867
        
868
    /*
869
     * (non-Javadoc)
870
     * @see org.gvsig.app.project.documents.layout.fframes.IFFrame#frameAdded()
871
     */
872
        public void frameAdded() {}
873
        
874
        public LayoutContext getLayoutContext() {
875
                return layoutContext;
876
        }
877

    
878
        public void setLayoutContext(LayoutContext layoutContext) {
879
                this.layoutContext = layoutContext;
880
        }
881

    
882
        public Document getDocument() {
883
                return document;
884
        }
885

    
886
        public void setDocument(Document document) {
887
                this.document = document;
888
        }
889
        
890
    /**
891
     * Gets the visible rectangle of the frame, taking rotation into
892
     * consideration. The result of this method is the rectangular area
893
     * of the unrotated frame that will be visible when the frame gets
894
     * rotated.
895
     * 
896
     * @param visibleLayoutDocRect
897
     *                         The visible area of the layout document
898
     * @param frame
899
     *                         The bounding box of this frame
900
     * @return
901
     *                         the rectangular area of the unrotated frame that will be
902
     * visible when the frame gets rotated, measured in screen coordinates  
903
     */
904
    protected Rectangle2D getVisibleRect(Rectangle2D visibleLayoutDocRect, Rectangle2D frame) {
905
            if (Math.abs(getRotation())>0.00001d) { // non-zero rotation
906
                    Area area = new Area(frame);
907
                    AffineTransform at = new AffineTransform();
908
                    at.rotate(Math.toRadians(getRotation()), frame.getCenterX(), frame.getCenterY());
909
                    Area rotatedArea = area.createTransformedArea(at);
910
                    Area visibleArea = new Area(visibleLayoutDocRect);
911
                    // this is the visible rectangle of the rotated fframeview in layout coordinates
912
                    visibleArea.intersect(rotatedArea);
913
                    if (visibleArea.isEmpty()) {
914
                            return null;
915
                    }
916
                    // now we need to calculate the corresponding visible area of the fframeview before rotating,
917
                    // in order to know which area of the non-rotated fframeview must be drawn
918
                    try {
919
                            Area nonRotatedVisibleArea = visibleArea.createTransformedArea(at.createInverse());
920
                            Rectangle2D nonRotatedVisibleBounds = nonRotatedVisibleArea.getBounds2D();
921
                            return nonRotatedVisibleBounds;
922
                        } catch (NoninvertibleTransformException e) {
923
                                LoggerFactory.getLogger(FFrame.class).error(e.getMessage(), e);
924
                                return null;
925
                        }
926
            }
927
            else {
928
                    Rectangle2D.Double visibleArea = new Rectangle2D.Double();
929
                    Rectangle2D.intersect(visibleLayoutDocRect, frame, visibleArea);
930
                    if (visibleArea.isEmpty()) {
931
                            return null;
932
                    }
933
                    return visibleArea;
934
            }
935
    }
936

    
937
}