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

History | View | Annotate | Download (31.6 KB)

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

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

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

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

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

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

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

    
99
    private static Image iNEResize = null;
100
    public static Image iEResize = null;
101
    public static Image iNResize = null;
102
    private static Image iMove = null;
103
    private static Image iSEResize = null;
104

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

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

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

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

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

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

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

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

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

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

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

    
184
    /**
185
     * Sets the type of selection performed on the frame, based on the position
186
     * of the provided Point compared with the boundaries of the FFrame.
187
     * This method is usually called when the user clicks on the FFrame
188
     * 
189
     * @param p
190
     *            Point which should be evaluated to establish if the FFrame must
191
     *            be selected or not
192
     * @param e   Mouse event that triggered this method call
193
     * @see {@link #isSelected()}, {@link #getSelected()}
194
     */
195
    @Override
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
    @Override
210
    public void updateRect(Rectangle2D r, AffineTransform at) {
211
        Rectangle2D.Double rec = FLayoutUtilities.toSheetRect(r, at);
212
        rec.setRect((int) rec.getMinX(), (int) rec.getMinY(),
213
            (int) rec.getWidth(), (int) rec.getHeight());
214
        setBoundBox(rec);
215
    }
216

    
217
    /**
218
     * Devuelve el rect�ngulo a partir del desplazamiento en el eje x y el
219
     * desplazamiento en el eje y.
220
     * 
221
     * @param difx
222
     *            desplazamiento sobre el eje x.
223
     * @param dify
224
     *            desplazamiento sobre el eje y.
225
     * 
226
     * @return rect�ngulo modificado en funci�n del desplazamiento
227
     *         realizado.
228
     */
229
    @Override
230
    public Rectangle2D getMovieRect(int difx, int dify) {
231
        return getMovieRect(difx, dify, false);
232
    }
233
    
234
    @Override
235
    public Rectangle2D getMovieRect(int difx, int dify, boolean prop) {
236
        double x;
237
        double y;
238
        double w;
239
        double h;
240

    
241
        lastMoveRect =
242
            new Rectangle2D.Double(this.getBoundingBox(null).x,
243
                this.getBoundingBox(null).y, this.getBoundingBox(null).width,
244
                this.getBoundingBox(null).height);
245
        Rectangle2D.Double rec = this.getBoundingBox(null);
246
        
247
        x = lastMoveRect.getX();
248
        y = lastMoveRect.getY();
249
        w = lastMoveRect.getWidth();
250
        h = lastMoveRect.getHeight();
251
        double ratio = w / h;
252

    
253
        switch (this.getSelected()) {
254
        case (RECT):
255
            lastMoveRect.setRect((x + difx), (y + dify), w, h);
256

    
257
            break;
258

    
259
        case (N):
260
            
261
            if ((y + dify) > rec.getMaxY()) {
262
                y = rec.getMaxY();
263
            } else {
264
                y = y + dify;
265
            }
266

    
267
            lastMoveRect.setRect(x, y, w, Math.abs(h - dify));
268

    
269
            break;
270

    
271
        case (O):
272

    
273
            if ((x + difx) > rec.getMaxX()) {
274
                x = rec.getMaxX();
275
            } else {
276
                x = x + difx;
277
            }
278

    
279
            lastMoveRect.setRect(x, y, Math.abs(w - difx), h);
280

    
281
            break;
282

    
283
        case (S):
284

    
285
            if (y > (rec.getMaxY() + dify)) {
286
                y = rec.getMaxY() + dify;
287
            }
288

    
289
            lastMoveRect.setRect(x, y, w, Math.abs(h + dify));
290

    
291
            break;
292

    
293
        case (E):
294

    
295
            if (x > (rec.getMaxX() + difx)) {
296
                x = rec.getMaxX() + difx;
297
            }
298

    
299
            lastMoveRect.setRect(x, y, Math.abs(w + difx), h);
300

    
301
            break;
302

    
303
        case (NE):
304

    
305
            if ((y + dify) > rec.getMaxY()) {
306
                y = rec.getMaxY();
307
            } else {
308
                y = y + dify;
309
            }
310
            if(prop) {
311
                difx = -(int) (dify * ratio);
312
            }
313
            if (x > (rec.getMaxX() + difx)) {
314
                x = rec.getMaxX() + difx;
315
            }
316
            
317

    
318
            lastMoveRect.setRect(x, y, Math.abs(w + difx), Math.abs(h - dify));
319

    
320
            break;
321

    
322
        case (NO):
323

    
324
            if ((y + dify) > rec.getMaxY()) {
325
                y = rec.getMaxY();
326
            } else {
327
                y = y + dify;
328
            }
329
            if(prop) {
330
                difx = (int) (dify * ratio);
331
            }
332
            if ((x + difx) > rec.getMaxX()) {
333
                x = rec.getMaxX();
334
            } else {
335
                x = x + difx;
336
            }
337

    
338

    
339
            lastMoveRect.setRect(x, y, Math.abs(w - difx), Math.abs(h - dify));
340
            
341
            break;
342

    
343
        case (SE):
344

    
345
            if (y > (rec.getMaxY() + dify)) {
346
                y = rec.getMaxY() + dify;
347
            }
348
            if(prop) {
349
                difx = (int) (dify * ratio);
350
            }
351
            if (x > (rec.getMaxX() + difx)) {
352
                x = rec.getMaxX() + difx;
353
            }
354
            
355
            lastMoveRect.setRect(x, y, Math.abs(w + difx), Math.abs(h + dify));
356
            
357
            break;
358

    
359
        case (SO):
360

    
361
            if (y > (rec.getMaxY() + dify)) {
362
                y = rec.getMaxY() + dify;
363
            }
364
            if(prop) {
365
                difx = (int) -(dify * ratio);
366
            }
367
            if ((x + difx) > rec.getMaxX()) {
368
                x = rec.getMaxX();
369
            } else {
370
                x = x + difx;
371
            }
372

    
373
            lastMoveRect.setRect(x, y, Math.abs(w - difx), Math.abs(h + dify));
374
            
375
            break;
376

    
377
        default:
378
            lastMoveRect.setRect((x), (y), w, h);
379
        }
380

    
381
        return lastMoveRect;
382
    }
383

    
384
    /**
385
     * Devuelve el rect�ngulo que representa el �ltimo generado al desplazar
386
     * o modificar el tama�o del fframe.
387
     * 
388
     * @return Rectangle2D
389
     * 
390
     */
391
    @Override
392
    public Rectangle2D getLastMoveRect() {
393
        return lastMoveRect;
394
    }
395

    
396
    /**
397
     * Returns an integer representing the type of selection applied to the
398
     * FFrame. Valid values are:
399
     * {@link IFFrame#NOSELECT},
400
     * {@link IFFrame#NO}, {@link IFFrame#N}, {@link IFFrame#NE},
401
     * {@link IFFrame#O}, {@link IFFrame#RECT}, {@link IFFrame#E},
402
     * {@link IFFrame#SO}, {@link IFFrame#S}, {@link IFFrame#SE}.
403
     * 
404
     * @see {@link #isSelected()}, {@link #setSelected(boolean)}
405
     * @return The type of selection that has been applied
406
     */
407
    @Override
408
    public int getSelected() {
409
        return m_Selected;
410
    }
411
    
412
    /**
413
     * Gets the selection status of the frame
414
     * 
415
     * @return <code>true</code> if the frame is selected,
416
     *    <code>false</code> otherwise
417
     * @see {@link #getSelected()}, {@link #setSelected(boolean)}
418
     */
419
    @Override
420
    public boolean isSelected() {
421
            return getSelected()!=IFFrame.NOSELECT;
422
    }
423

    
424
    /**
425
     * Devuelve true, si el punto que se pasa como par�metro esta contenido
426
     * dentro del boundingbox del fframe.
427
     * 
428
     * @param p
429
     *            punto a comprobar en pixels.
430
     * 
431
     * @return true si el punto esta dentro del boundingbox.
432
     */
433
    @Override
434
    public boolean contains(Point2D p) {
435
        return getBoundingBox(null).contains(p.getX(), p.getY());
436
    }
437

    
438
    /*
439
     * (non-Javadoc)
440
     * @see org.gvsig.app.project.documents.layout.fframes.IFFrame#getContains(Point2D)
441
     */
442
    @Override
443
    public int getContains(Point2D p) {
444
            Point2D point = new Point2D.Double();
445
            AffineTransform rotationAT = getRotationAT();
446
            if (rotationAT!=null) {
447
                    // if the frame is rotated, we need to inversely rotate the point in order
448
                    // to decide whether it is contained or not in the non-rotated frame
449
                    try {
450
                                rotationAT.createInverse().transform(p, point);
451
                        } catch (NoninvertibleTransformException e1) {}
452
            }
453
            else {
454
                    point = p;
455
            }
456
        if (n.contains(point.getX(), point.getY())) {
457
            return N;
458
        } else
459
            if (ne.contains(point.getX(), point.getY())) {
460
                return NE;
461
            } else
462
                if (e.contains(point.getX(), point.getY())) {
463
                    return E;
464
                } else
465
                    if (se.contains(point.getX(), point.getY())) {
466
                        return SE;
467
                    } else
468
                        if (s.contains(point.getX(), point.getY())) {
469
                            return S;
470
                        } else
471
                            if (so.contains(point.getX(), point.getY())) {
472
                                return SO;
473
                            } else
474
                                if (o.contains(point.getX(), point.getY())) {
475
                                    return O;
476
                                } else
477
                                    if (no.contains(point.getX(), point.getY())) {
478
                                        return NO;
479
                                    } else
480
                                        if (getBoundingBox(null).contains(
481
                                            point.getX(), point.getY())) {
482
                                            return RECT;
483
                                        }
484

    
485
        return NOSELECT;
486
    }
487

    
488
    /**
489
     * Devuelve el Cursor adecuado seg�n como est� contenido el punto, si es
490
     * para desplazamiento, o cambio de tama�o.
491
     * 
492
     * @param p
493
     *            punto a comprobar.
494
     * 
495
     * @return Cursor adecuado a la posici�n.
496
     */
497
    @Override
498
    public Image getMapCursor(Point2D p) {
499
        int select = getContains(p);
500

    
501
        switch (select) {
502
        case (N):
503
            return iNResize;
504

    
505
        case (NE):
506
            return iNEResize;
507

    
508
        case (E):
509
            return iEResize;
510

    
511
        case (SE):
512
            return iSEResize;
513

    
514
        case (S):
515
            return iNResize;
516

    
517
        case (SO):
518
            return iNEResize;
519

    
520
        case (O):
521
            return iEResize;
522

    
523
        case (NO):
524
            return iSEResize;
525

    
526
        case (RECT):
527
            return iMove;
528
        }
529

    
530
        return null;
531
    }
532

    
533
    /**
534
     * Draws the FFrame on the provided Graphics, according to the
535
     * provided affine transform and the visible rectangle. It has to
536
     * to be implemented by each FFrame, as each of them usually draws
537
     * diffently.
538
     * 
539
     * @param g Graphics2D
540
     * @param at Affine transform to translate sheet coordinates (in cm)
541
     *                                 to screen coordinates (in pixels)
542
     * @param visibleLayoutDocRect visible rectangle
543
     * @param imgBase Image used to speed up the drawing process
544
     */
545
    @Override
546
    public abstract void draw(Graphics2D g, AffineTransform at, Rectangle2D r,
547
        BufferedImage imgBase);
548

    
549
    /**
550
     * Returns the bounding box (in pixels) of this FFrame, based on the provided
551
     * AffineTransform. If the AffineTransform is null, it returns the last
552
     * calculated bounding box.
553
     * 
554
     * @param at Affine transform to apply to the sheet coordinates to get the
555
     *                  bounding box in pixels.
556
     * @return Rectangle representing the bounding box (in pixels) of this
557
     * FFrame
558
     */
559
    @Override
560
    public Rectangle2D.Double getBoundingBox(AffineTransform at) {
561
        if (at != null) {
562
            lastAT = (AffineTransform) at.clone();
563
        }
564
        return FLayoutUtilities.fromSheetRect(m_BoundBox, lastAT);
565
    }
566

    
567
    /**
568
     * Sets the bounding box in centimeters of this FFrame, using  paper
569
     * coordinates.
570
     * 
571
     * @param r
572
     *            Rectangle in centimeters
573
     */
574
    @Override
575
    public void setBoundBox(Rectangle2D r) {
576
        if (r == null) {
577
            LOG.info("Warning: BBOX set to NULL in FFrame!");
578
            m_BoundBox = null;
579
        } else {
580
            m_BoundBox = new Rectangle2D.Double(r.getX(), r.getY(),
581
                r.getWidth(), r.getHeight());
582
        }
583
    }
584

    
585
    /**
586
     * Returns the bounding box in centimeters of this FFrame, using paper
587
     * coordinates
588
     * 
589
     * @return The bounding box of this FFrame, measured in centimeters.
590
     */
591
    @Override
592
    public Rectangle2D.Double getBoundBox() {
593
        return m_BoundBox;
594
    }
595

    
596
    /**
597
     * Sets the selected status of the frame.
598
     * 
599
     * @param selected
600
     *            <code>true</code> to select the frame, <code>false</code> to
601
     *            unselect it
602
     * @see {@link #isSelected()}, {@link #getSelected()}
603
     */
604
    @Override
605
    public void setSelected(boolean selected) {
606
        if (selected) {
607
                doSetSelected(IFFrame.RECT);
608
        } else {
609
                doSetSelected(IFFrame.NOSELECT);
610
        }
611
    }
612
    
613
    protected void doSetSelected(int selectedStatus) {
614
            m_Selected = selectedStatus;
615
    }
616

    
617
    /**
618
     * Dibuja sobre el graphics el rect�ngulo del fframe en modo borrador.
619
     * 
620
     * @param g
621
     *            Graphics so bre el que dibujar.
622
     */
623
    @Override
624
    public void drawDraft(Graphics2D g) {
625
        Rectangle2D r = getBoundingBox(null);
626

    
627
        g.setColor(Color.lightGray);
628
        g.fillRect((int) r.getX(), (int) r.getY(), (int) r.getWidth(),
629
            (int) r.getHeight());
630
        g.setColor(Color.black);
631
        g.drawRect((int) r.getX(), (int) r.getY(), (int) r.getWidth() - 1,
632
            (int) r.getHeight() - 1);
633
        int scale = (int) (r.getWidth() / 12);
634
        Font f = new Font("SansSerif", Font.PLAIN, scale);
635
        g.setFont(f);
636
        g.drawString(getName(),
637
            (int) (r.getCenterX() - ((getName().length() * scale) / 4)),
638
            (int) (r.getCenterY()));
639
    }
640

    
641
    /**
642
     * Rellena con el n�mero de FFrame.
643
     * 
644
     * @param i
645
     *            n�mero
646
     */
647
    @Override
648
    public void setNum(int i) {
649
        num = i;
650
    }
651

    
652
    /**
653
     * Draws the FFrame rectangle on the provided Graphics2D, only showing the
654
     * FFrame name on an empty rectangle.
655
     * 
656
     * @param g The graphics to draw on
657
     */
658
    public void drawEmpty(Graphics2D g) {
659
        Rectangle2D r = getBoundingBox(null);
660
        g.setColor(Color.lightGray);
661
        g.fillRect((int) r.getX(), (int) r.getY(), (int) r.getWidth(),
662
            (int) r.getHeight());
663
        g.setColor(Color.darkGray);
664
        g.setStroke(new BasicStroke(2));
665
        g.drawRect((int) r.getX(), (int) r.getY(), (int) r.getWidth(),
666
            (int) r.getHeight());
667
        g.setColor(Color.black);
668

    
669
        int scale = (int) (r.getWidth() / 12);
670
        Font f = new Font("SansSerif", Font.PLAIN, scale);
671
        g.setFont(f);
672

    
673
        String str =
674
            this.getNameFFrame() + " " + PluginServices.getText(this, "vacia");
675

    
676
        g.drawString(str, (int) (r.getCenterX() - ((str.length() * scale) / 4)),
677
            (int) (r.getCenterY()));
678
    }
679

    
680
    /**
681
     * Devuelve true si el rect�ngulo primero es null o si es distinto de null
682
     * e intersecta.
683
     * 
684
     * @param rv
685
     *            Rect�ngulo
686
     * @param r
687
     *            Rect�ngulo
688
     * 
689
     * @return True si intersecta o es null.
690
     */
691
    @Override
692
    public boolean intersects(Rectangle2D rv, Rectangle2D r) {
693
        return (((rv != null) && rv.intersects(r)) || (rv == null));
694
    }
695

    
696
    /**
697
     * Rellena el tag del FFrame.
698
     * 
699
     * @param s
700
     *            String que representa el valor a guardar en el tag.
701
     */
702
    @Override
703
    public void setTag(String s) {
704
        tag = s;
705
    }
706

    
707
    /**
708
     * Devuelve el tag.
709
     * 
710
     * @return tag.
711
     */
712
    @Override
713
    public String getTag() {
714
        return tag;
715
    }
716

    
717
    /**
718
     * Dibuja sobre el graphics que se pasa como par�metro el icono que
719
     * representa que contiene un tag.
720
     * 
721
     * @param g
722
     *            Graphics sobre el que dibujar el icono.
723
     */
724
    @Override
725
    public void drawSymbolTag(Graphics2D g) {
726
        Rectangle2D rec = getBoundingBox(null);
727
        g.rotate(Math.toRadians(getRotation()), rec.getX()
728
            + (rec.getWidth() / 2), rec.getY() + (rec.getHeight() / 2));
729

    
730
        try {
731
            Image image =
732
                PluginServices.getIconTheme().get("symboltag-icon").getImage();
733
            g.drawImage(image, (int) rec.getX(), (int) rec.getCenterY(), 30,
734
                30, null);
735
        } catch (NullPointerException npe) {
736
        }
737

    
738
        g.rotate(Math.toRadians(-getRotation()), rec.getX()
739
            + (rec.getWidth() / 2), rec.getY() + (rec.getHeight() / 2));
740
    }
741

    
742
    /**
743
     * Sets the rotation of the frame, measured in arc degrees
744
     * 
745
     * @param rotation
746
     *            Rotation to apply to the frame
747
     */
748
    @Override
749
    public void setRotation(double rotation) {
750
        m_rotation = rotation;
751
    }
752
    
753
    /**
754
     * Gets the affine transform used to rotate the graphics when rotation is not 0
755
     * 
756
     * @return
757
     */
758
    protected AffineTransform getRotationAT() {
759
            // it has to be calculated each time as the frameRect may change, for instance
760
            // because a zoom in/out to paper has been performed
761
            double rotation = getRotation();
762
            if (getLayoutContext()!=null && getLayoutContext().getAT()!=null && Math.abs(rotation)>0.00001) {
763
                    AffineTransform rotationAT = new AffineTransform();
764
                Rectangle2D.Double frameRect = getBoundingBox(getLayoutContext().getAT());
765
                rotationAT.rotate(Math.toRadians(getRotation()), frameRect.getCenterX(), frameRect.getCenterY());
766
                return rotationAT;
767
            }
768
            return null;
769
    }
770

    
771
    /**
772
     * Gets the rotation of the frame, measured in arc degrees
773
     * 
774
     * @return Rotation of the frame
775
     */
776
    @Override
777
    public double getRotation() {
778
        return m_rotation;
779
    }
780

    
781
    /**
782
     * Devuelve el nivel en el que se encuentra el FFrame.
783
     * 
784
     * @return nivel
785
     */
786
    @Override
787
    public int getLevel() {
788
        return level;
789
    }
790

    
791
    /**
792
     * Inserta el nivel al que se encuentra el FFrame.
793
     * 
794
     * @param l
795
     *            entero que refleja el nivel del FFrame.
796
     */
797
    @Override
798
    public void setLevel(int l) {
799
        level = l;
800
    }
801

    
802
    @Override
803
    public Object clone() throws CloneNotSupportedException {
804
        FFrame frame = (FFrame) super.clone();
805
        frame.m_BoundBox = (Rectangle2D.Double)this.m_BoundBox.clone();
806
        return frame;
807
    }
808

    
809
    @Override
810
    public void setFrameFactory(FrameFactory flf) {
811
        frameFactory = flf;
812
    }
813

    
814
    @Override
815
    public FrameFactory getFrameFactory() {
816
        return frameFactory;
817
    }
818

    
819
    /**
820
     * Initilizes the static icons
821
     */
822
    public static void initializeIcons() {
823
        iNEResize =
824
            PluginServices.getIconTheme().get("neresize-icon").getImage();
825
        iEResize = PluginServices.getIconTheme().get("eresize-icon").getImage();
826
        iNResize = PluginServices.getIconTheme().get("nresize-icon").getImage();
827
        iMove = PluginServices.getIconTheme().get("graphic-move-icon").getImage();
828
        iSEResize =
829
            PluginServices.getIconTheme().get("sereresize-icon").getImage();
830
    }
831

    
832
    public static void registerPersistent() {
833
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
834
        if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) {
835
            DynStruct definition =
836
                manager.addDefinition(FFrame.class,
837
                    PERSISTENCE_DEFINITION_NAME,
838
                    "FFrame persistence definition", null, null);
839

    
840
            definition.addDynFieldObject(BOUNDINGBOX_FIELD)
841
                .setClassOfValue(Rectangle2D.class).setMandatory(true);
842
            definition.addDynFieldInt(SELECTED_FIELD).setMandatory(true);
843
            definition.addDynFieldString(TAG_FIELD).setMandatory(false);
844
            definition.addDynFieldDouble(ROTATION_FIELD).setMandatory(true);
845
            definition.addDynFieldInt(LEVEL_FIELD).setMandatory(true);
846
            definition.addDynFieldInt(NUM_FIELD).setMandatory(true);
847
            definition.addDynFieldObject(DOCUMENT_FIELD).setClassOfValue(LayoutDocument.class).setMandatory(false);
848
            definition.addDynFieldObject(LAYOUT_CONTEXT_FIELD).setClassOfValue(LayoutContext.class).setMandatory(false);
849
        }
850

    
851
        Attributes.registerPersistent();
852
        AbstractFFrameViewDependence.registerPersistent();
853
        FFrameBasic.registerPersistent();
854
        FFrameGraphics.registerPersistent();
855
        FFrameSymbol.registerPersistent();
856
        FFrameGrid.registerPersistent();
857
        FFrameGroup.registerPersistent();
858
        FFrameTable.registerPersistent();
859
        FFrameLegend.registerPersistent();
860
        FFramePicture.registerPersistent();
861
        FFrameNorth.registerPersistent();
862
        FFrameScaleBar.registerPersistent();
863
        FFrameText.registerPersistent();
864
        FFrameView.registerPersistent();
865
        FFrameOverView.registerPersistent();
866
        FFrameGridCoordinateFormat.registerPersistence();
867
    }
868

    
869
    @Override
870
    public void loadFromState(PersistentState state)
871
        throws PersistenceException {
872
        m_BoundBox = (Rectangle2D.Double) state.get(BOUNDINGBOX_FIELD);
873
        m_Selected = state.getInt(SELECTED_FIELD);
874
        tag = state.getString(TAG_FIELD);
875
        m_rotation = state.getDouble(ROTATION_FIELD);
876
        level = state.getInt(LEVEL_FIELD);
877
        num = state.getInt(NUM_FIELD);
878
        if (state.hasValue(DOCUMENT_FIELD)) {
879
                setDocument((LayoutDocument)state.get(DOCUMENT_FIELD ));
880
        }
881
        if (state.hasValue(LAYOUT_CONTEXT_FIELD)) {
882
                setLayoutContext((LayoutContext) state.get(LAYOUT_CONTEXT_FIELD));
883
        }
884
    }
885

    
886
    @Override
887
    public void saveToState(PersistentState state) throws PersistenceException {
888
        state.set(BOUNDINGBOX_FIELD, getBoundBox());
889
        state.set(SELECTED_FIELD, m_Selected);
890
        state.set(TAG_FIELD, getTag());
891
        state.set(ROTATION_FIELD, getRotation());
892
        state.set(LEVEL_FIELD, getLevel());
893
        state.set(NUM_FIELD, num);
894
        state.set(DOCUMENT_FIELD, getDocument());
895
        state.set(LAYOUT_CONTEXT_FIELD, getLayoutContext());
896
    }
897

    
898
    @Override
899
    public void addObserver(Observer o) {
900
        observers.addObserver(o);        
901
    }
902

    
903
    @Override
904
    public void deleteObserver(Observer o) {
905
      observers.deleteObserver(o);        
906
    }
907

    
908
    @Override
909
    public void deleteObservers() {
910
       observers.deleteObservers();        
911
    }
912
    
913
    /*
914
     * (non-Javadoc)
915
     * @see org.gvsig.tools.dispose.Disposable#dispose()
916
     */
917
    @Override
918
        public void dispose() {
919
                
920
        }
921
        
922
    /*
923
     * (non-Javadoc)
924
     * @see org.gvsig.app.project.documents.layout.fframes.IFFrame#frameRemoved()
925
     */
926
    @Override
927
        public void frameRemoved() {}
928
        
929
    /*
930
     * (non-Javadoc)
931
     * @see org.gvsig.app.project.documents.layout.fframes.IFFrame#frameAdded()
932
     */
933
    @Override
934
        public void frameAdded() {}
935
        
936
    @Override
937
        public LayoutContext getLayoutContext() {
938
                return layoutContext;
939
        }
940

    
941
    @Override
942
        public void setLayoutContext(LayoutContext layoutContext) {
943
                this.layoutContext = layoutContext;
944
        }
945

    
946
    @Override
947
        public Document getDocument() {
948
                return document;
949
        }
950

    
951
    @Override
952
        public void setDocument(Document document) {
953
                this.document = document;
954
        }
955
        
956
    /**
957
     * Gets the visible rectangle of the frame, taking rotation into
958
     * consideration. The result of this method is the rectangular area
959
     * of the unrotated frame that will be visible when the frame gets
960
     * rotated.
961
     * 
962
     * @param visibleLayoutDocRect
963
     *                         The visible area of the layout document
964
     * @param frame
965
     *                         The bounding box of this frame
966
     * @return
967
     *                         the rectangular area of the unrotated frame that will be
968
     * visible when the frame gets rotated, measured in screen coordinates  
969
     */
970
    protected Rectangle2D getVisibleRect(Rectangle2D visibleLayoutDocRect, Rectangle2D frame) {
971
            if (Math.abs(getRotation())>0.00001d) { // non-zero rotation
972
                    Area area = new Area(frame);
973
                    AffineTransform at = new AffineTransform();
974
                    at.rotate(Math.toRadians(getRotation()), frame.getCenterX(), frame.getCenterY());
975
                    Area rotatedArea = area.createTransformedArea(at);
976
                    Area visibleArea = new Area(visibleLayoutDocRect);
977
                    // this is the visible rectangle of the rotated fframeview in layout coordinates
978
                    visibleArea.intersect(rotatedArea);
979
                    if (visibleArea.isEmpty()) {
980
                            return null;
981
                    }
982
                    // now we need to calculate the corresponding visible area of the fframeview before rotating,
983
                    // in order to know which area of the non-rotated fframeview must be drawn
984
                    try {
985
                            Area nonRotatedVisibleArea = visibleArea.createTransformedArea(at.createInverse());
986
                            Rectangle2D nonRotatedVisibleBounds = nonRotatedVisibleArea.getBounds2D();
987
                            return nonRotatedVisibleBounds;
988
                        } catch (NoninvertibleTransformException ex) {
989
                                LoggerFactory.getLogger(FFrame.class).error(ex.getMessage(), ex);
990
                                return null;
991
                        }
992
            }
993
            else {
994
                    Rectangle2D.Double visibleArea = new Rectangle2D.Double();
995
                    Rectangle2D.intersect(visibleLayoutDocRect, frame, visibleArea);
996
                    if (visibleArea.isEmpty()) {
997
                            return null;
998
                    }
999
                    return visibleArea;
1000
            }
1001
    }
1002

    
1003
}