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

History | View | Annotate | Download (28.8 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 */
22
package org.gvsig.app.project.documents.layout.fframes;
23

    
24
import java.awt.BasicStroke;
25
import java.awt.Color;
26
import java.awt.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.app.project.ProjectManager;
40
import org.gvsig.app.project.documents.Document;
41
import org.gvsig.app.project.documents.layout.Attributes;
42
import org.gvsig.app.project.documents.layout.DefaultLayoutManager;
43
import org.gvsig.app.project.documents.layout.FLayoutUtilities;
44
import org.gvsig.app.project.documents.layout.LayoutContext;
45
import org.gvsig.app.project.documents.layout.LayoutDocument;
46
import org.gvsig.app.project.documents.layout.LayoutManager;
47
import org.gvsig.tools.ToolsLocator;
48
import org.gvsig.tools.dynobject.DynStruct;
49
import org.gvsig.tools.observer.ObservableHelper;
50
import org.gvsig.tools.observer.Observer;
51
import org.gvsig.tools.persistence.PersistenceManager;
52
import org.gvsig.tools.persistence.PersistentState;
53
import org.gvsig.tools.persistence.exception.PersistenceException;
54
import org.slf4j.Logger;
55
import org.slf4j.LoggerFactory;
56

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

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

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

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

    
80
    protected Rectangle2D.Double m_BoundBox = new Rectangle2D.Double();
81
    // initially identity
82
    protected AffineTransform lastAT = AffineTransform.getShearInstance(0,0);
83
    // private Rectangle2D.Double m_BoundingBox = new Rectangle2D.Double();
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
     * Devuelve un entero que representa donde esta contenido el punto que se
406
     * pasa como par�metro.
407
     * 
408
     * @param p
409
     *            punto a comparar.
410
     * 
411
     * @return entero que representa como esta contenido el punto.
412
     */
413
    public int getContains(Point2D p) {
414
        if (n.contains(p.getX(), p.getY())) {
415
            return N;
416
        } else
417
            if (ne.contains(p.getX(), p.getY())) {
418
                return NE;
419
            } else
420
                if (e.contains(p.getX(), p.getY())) {
421
                    return E;
422
                } else
423
                    if (se.contains(p.getX(), p.getY())) {
424
                        return SE;
425
                    } else
426
                        if (s.contains(p.getX(), p.getY())) {
427
                            return S;
428
                        } else
429
                            if (so.contains(p.getX(), p.getY())) {
430
                                return SO;
431
                            } else
432
                                if (o.contains(p.getX(), p.getY())) {
433
                                    return O;
434
                                } else
435
                                    if (no.contains(p.getX(), p.getY())) {
436
                                        return NO;
437
                                    } else
438
                                        if (getBoundingBox(null).contains(
439
                                            p.getX(), p.getY())) {
440
                                            return RECT;
441
                                        }
442

    
443
        return NOSELECT;
444
    }
445

    
446
    /**
447
     * Devuelve el Cursor adecuado seg�n como est� contenido el punto, si es
448
     * para desplazamiento, o cambio de tama�o.
449
     * 
450
     * @param p
451
     *            punto a comprobar.
452
     * 
453
     * @return Cursor adecuado a la posici�n.
454
     */
455
    public Image getMapCursor(Point2D p) {
456
        int select = getContains(p);
457

    
458
        switch (select) {
459
        case (N):
460
            return iNResize;
461

    
462
        case (NE):
463
            return iNEResize;
464

    
465
        case (E):
466
            return iEResize;
467

    
468
        case (SE):
469
            return iSEResize;
470

    
471
        case (S):
472
            return iNResize;
473

    
474
        case (SO):
475
            return iNEResize;
476

    
477
        case (O):
478
            return iEResize;
479

    
480
        case (NO):
481
            return iSEResize;
482

    
483
        case (RECT):
484
            return iMove;
485
        }
486

    
487
        return null;
488
    }
489

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

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

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

    
539
    /**
540
     * Returns the bounding box in centimeters of this FFrame, using paper
541
     * coordinates
542
     * 
543
     * @return The bounding box of this FFrame, measured in centimeters.
544
     */
545
    public Rectangle2D.Double getBoundBox() {
546
        return m_BoundBox;
547
    }
548

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

    
569
    /**
570
     * Dibuja sobre el graphics el rect�ngulo del fframe en modo borrador.
571
     * 
572
     * @param g
573
     *            Graphics so bre el que dibujar.
574
     */
575
    public void drawDraft(Graphics2D g) {
576
        Rectangle2D r = getBoundingBox(null);
577

    
578
        g.setColor(Color.lightGray);
579
        g.fillRect((int) r.getX(), (int) r.getY(), (int) r.getWidth(),
580
            (int) r.getHeight());
581
        g.setColor(Color.black);
582
        g.drawRect((int) r.getX(), (int) r.getY(), (int) r.getWidth() - 1,
583
            (int) r.getHeight() - 1);
584
        int scale = (int) (r.getWidth() / 12);
585
        Font f = new Font("SansSerif", Font.PLAIN, scale);
586
        g.setFont(f);
587
        g.drawString(getName(),
588
            (int) (r.getCenterX() - ((getName().length() * scale) / 4)),
589
            (int) (r.getCenterY()));
590
    }
591

    
592
    /**
593
     * Rellena con el n�mero de FFrame.
594
     * 
595
     * @param i
596
     *            n�mero
597
     */
598
    public void setNum(int i) {
599
        num = i;
600
    }
601

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

    
619
        int scale = (int) (r.getWidth() / 12);
620
        Font f = new Font("SansSerif", Font.PLAIN, scale);
621
        g.setFont(f);
622

    
623
        String s =
624
            this.getNameFFrame() + " " + PluginServices.getText(this, "vacia");
625

    
626
        g.drawString(s, (int) (r.getCenterX() - ((s.length() * scale) / 4)),
627
            (int) (r.getCenterY()));
628
    }
629

    
630
    /**
631
     * Devuelve true si el rect�ngulo primero es null o si es distinto de null
632
     * e intersecta.
633
     * 
634
     * @param rv
635
     *            Rect�ngulo
636
     * @param r
637
     *            Rect�ngulo
638
     * 
639
     * @return True si intersecta o es null.
640
     */
641
    public boolean intersects(Rectangle2D rv, Rectangle2D r) {
642
        return (((rv != null) && rv.intersects(r)) || (rv == null));
643
    }
644

    
645
    /**
646
     * Rellena el tag del FFrame.
647
     * 
648
     * @param s
649
     *            String que representa el valor a guardar en el tag.
650
     */
651
    public void setTag(String s) {
652
        tag = s;
653
    }
654

    
655
    /**
656
     * Devuelve el tag.
657
     * 
658
     * @return tag.
659
     */
660
    public String getTag() {
661
        return tag;
662
    }
663

    
664
    /**
665
     * Dibuja sobre el graphics que se pasa como par�metro el icono que
666
     * representa que contiene un tag.
667
     * 
668
     * @param g
669
     *            Graphics sobre el que dibujar el icono.
670
     */
671
    public void drawSymbolTag(Graphics2D g) {
672
        Rectangle2D rec = getBoundingBox(null);
673
        g.rotate(Math.toRadians(getRotation()), rec.getX()
674
            + (rec.getWidth() / 2), rec.getY() + (rec.getHeight() / 2));
675

    
676
        try {
677
            Image image =
678
                PluginServices.getIconTheme().get("symboltag-icon").getImage();
679
            g.drawImage(image, (int) rec.getX(), (int) rec.getCenterY(), 30,
680
                30, null);
681
        } catch (NullPointerException npe) {
682
        }
683

    
684
        g.rotate(Math.toRadians(-getRotation()), rec.getX()
685
            + (rec.getWidth() / 2), rec.getY() + (rec.getHeight() / 2));
686
    }
687

    
688
    /**
689
     * Rellenar la rotaci�n para aplicar al FFrame.
690
     * 
691
     * @param rotation
692
     *            rotaci�n que se quiere aplicar.
693
     */
694
    public void setRotation(double rotation) {
695
        m_rotation = rotation;
696
    }
697

    
698
    /**
699
     * Devuelve la rotaci�n del FFrame.
700
     * 
701
     * @return Rotaci�n del FFrame.
702
     */
703
    public double getRotation() {
704
        return m_rotation;
705
    }
706

    
707
    /**
708
     * Devuelve el nivel en el que se encuentra el FFrame.
709
     * 
710
     * @return nivel
711
     */
712
    public int getLevel() {
713
        return level;
714
    }
715

    
716
    /**
717
     * Inserta el nivel al que se encuentra el FFrame.
718
     * 
719
     * @param l
720
     *            entero que refleja el nivel del FFrame.
721
     */
722
    public void setLevel(int l) {
723
        level = l;
724
    }
725

    
726
    @Override
727
    public Object clone() throws CloneNotSupportedException {
728
        IFFrame frame = (IFFrame) super.clone();
729
        frame.setBoundBox(this.getBoundBox());
730
        return frame;
731
    }
732

    
733
    public void setFrameFactory(FrameFactory flf) {
734
        frameFactory = flf;
735
    }
736

    
737
    public FrameFactory getFrameFactory() {
738
        return frameFactory;
739
    }
740

    
741
    /**
742
     * Initilizes the static icons
743
     */
744
    public static void initializeIcons() {
745
        iNEResize =
746
            PluginServices.getIconTheme().get("neresize-icon").getImage();
747
        iEResize = PluginServices.getIconTheme().get("eresize-icon").getImage();
748
        iNResize = PluginServices.getIconTheme().get("nresize-icon").getImage();
749
        iMove = PluginServices.getIconTheme().get("graphic-move-icon").getImage();
750
        iSEResize =
751
            PluginServices.getIconTheme().get("sereresize-icon").getImage();
752
    }
753

    
754
    public static void registerPersistent() {
755
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
756
        if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) {
757
            DynStruct definition =
758
                manager.addDefinition(FFrame.class,
759
                    PERSISTENCE_DEFINITION_NAME,
760
                    "FFrame persistence definition", null, null);
761

    
762
            definition.addDynFieldObject(BOUNDINGBOX_FIELD)
763
                .setClassOfValue(Rectangle2D.class).setMandatory(true);
764
            definition.addDynFieldInt(SELECTED_FIELD).setMandatory(true);
765
            definition.addDynFieldString(TAG_FIELD).setMandatory(false);
766
            definition.addDynFieldDouble(ROTATION_FIELD).setMandatory(true);
767
            definition.addDynFieldInt(LEVEL_FIELD).setMandatory(true);
768
            definition.addDynFieldInt(NUM_FIELD).setMandatory(true);
769
            definition.addDynFieldObject(DOCUMENT_FIELD).setClassOfValue(LayoutDocument.class).setMandatory(false);
770
            definition.addDynFieldObject(LAYOUT_CONTEXT_FIELD).setClassOfValue(LayoutContext.class).setMandatory(false);
771
        }
772

    
773
        Attributes.registerPersistent();
774
        AbstractFFrameViewDependence.registerPersistent();
775
        FFrameBasic.registerPersistent();
776
        FFrameGraphics.registerPersistent();
777
        FFrameSymbol.registerPersistent();
778
        FFrameGrid.registerPersistent();
779
        FFrameGroup.registerPersistent();
780
        FFrameTable.registerPersistent();
781
        FFrameLegend.registerPersistent();
782
        FFramePicture.registerPersistent();
783
        FFrameNorth.registerPersistent();
784
        FFrameScaleBar.registerPersistent();
785
        FFrameText.registerPersistent();
786
        FFrameView.registerPersistent();
787
        FFrameOverView.registerPersistent();
788
    }
789

    
790
    public void loadFromState(PersistentState state)
791
        throws PersistenceException {
792
        m_BoundBox = (Rectangle2D.Double) state.get(BOUNDINGBOX_FIELD);
793
        m_Selected = state.getInt(SELECTED_FIELD);
794
        tag = state.getString(TAG_FIELD);
795
        m_rotation = state.getDouble(ROTATION_FIELD);
796
        level = state.getInt(LEVEL_FIELD);
797
        num = state.getInt(NUM_FIELD);
798
        if (state.hasValue(DOCUMENT_FIELD)) {
799
                setDocument((LayoutDocument)state.get(DOCUMENT_FIELD ));
800
        }
801
        if (state.hasValue(LAYOUT_CONTEXT_FIELD)) {
802
                setLayoutContext((LayoutContext) state.get(LAYOUT_CONTEXT_FIELD));
803
        }
804
    }
805

    
806
    public void saveToState(PersistentState state) throws PersistenceException {
807
        state.set(BOUNDINGBOX_FIELD, getBoundBox());
808
        state.set(SELECTED_FIELD, m_Selected);
809
        state.set(TAG_FIELD, getTag());
810
        state.set(ROTATION_FIELD, getRotation());
811
        state.set(LEVEL_FIELD, getLevel());
812
        state.set(NUM_FIELD, num);
813
        state.set(DOCUMENT_FIELD, getDocument());
814
        state.set(LAYOUT_CONTEXT_FIELD, getLayoutContext());
815
    }
816

    
817
    public void addObserver(Observer o) {
818
        observers.addObserver(o);        
819
    }
820

    
821
    public void deleteObserver(Observer o) {
822
      observers.deleteObserver(o);        
823
    }
824

    
825
    public void deleteObservers() {
826
       observers.deleteObservers();        
827
    }
828
    
829
    /*
830
     * (non-Javadoc)
831
     * @see org.gvsig.tools.dispose.Disposable#dispose()
832
     */
833
        public void dispose() {
834
                
835
        }
836
        
837
        public void frameRemoved() {}
838
        
839
        public void frameAdded() {}
840
        
841
        public LayoutContext getLayoutContext() {
842
                return layoutContext;
843
        }
844

    
845
        public void setLayoutContext(LayoutContext layoutContext) {
846
                this.layoutContext = layoutContext;
847
        }
848

    
849
        public Document getDocument() {
850
                return document;
851
        }
852

    
853
        public void setDocument(Document document) {
854
                this.document = document;
855
        }
856
        
857
    /**
858
     * Gets the visible rectangle of the frame, taking rotation into
859
     * consideration. The result of this method is the rectangular area
860
     * of the unrotated frame that will be visible when the frame gets
861
     * rotated.
862
     * 
863
     * @param visibleLayoutDocRect
864
     *                         The visible area of the layout document
865
     * @param frame
866
     *                         The bounding box of this frame
867
     * @return
868
     *                         the rectangular area of the unrotated frame that will be
869
     * visible when the frame gets rotated, measured in screen coordinates  
870
     */
871
    protected Rectangle2D getVisibleRect(Rectangle2D visibleLayoutDocRect, Rectangle2D frame) {
872
            if (getRotation()>0) {
873
                    Area area = new Area(frame);
874
                    AffineTransform at = new AffineTransform();
875
                    at.rotate(Math.toRadians(getRotation()), frame.getCenterX(), frame.getCenterY());
876
                    Area rotatedArea = area.createTransformedArea(at);
877
                    Area visibleArea = new Area(visibleLayoutDocRect);
878
                    // this is the visible rectangle of the rotated fframeview in layout coordinates
879
                    visibleArea.intersect(rotatedArea);
880
                    if (visibleArea.isEmpty()) {
881
                            return null;
882
                    }
883
                    // now we need to calculate the corresponding visible area of the fframeview before rotating,
884
                    // in order to know which area of the non-rotated fframeview must be drawn
885
                    try {
886
                            Area nonRotatedVisibleArea = visibleArea.createTransformedArea(at.createInverse());
887
                            Rectangle2D nonRotatedVisibleBounds = nonRotatedVisibleArea.getBounds2D();
888
                            return nonRotatedVisibleBounds;
889
                        } catch (NoninvertibleTransformException e) {
890
                                LoggerFactory.getLogger(FFrame.class).error(e.getMessage(), e);
891
                                return null;
892
                        }
893
            }
894
            else {
895
                    Rectangle2D.Double visibleArea = new Rectangle2D.Double();
896
                    Rectangle2D.intersect(visibleLayoutDocRect, frame, visibleArea);
897
                    if (visibleArea.isEmpty()) {
898
                            return null;
899
                    }
900
                    return visibleArea;
901
            }
902
    }
903

    
904
}