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 / FFrameGrid.java @ 344

History | View | Annotate | Download (32.7 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.Color;
25
import java.awt.Dimension;
26
import java.awt.Font;
27
import java.awt.Graphics2D;
28
import java.awt.font.TextLayout;
29
import java.awt.geom.AffineTransform;
30
import java.awt.geom.Point2D;
31
import java.awt.geom.Rectangle2D;
32
import java.awt.image.BufferedImage;
33
import java.text.DecimalFormat;
34
import java.text.DecimalFormatSymbols;
35

    
36
import org.gvsig.andami.PluginServices;
37
import org.gvsig.compat.print.PrintAttributes;
38
import org.gvsig.fmap.geom.Geometry;
39
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
40
import org.gvsig.fmap.geom.Geometry.TYPES;
41
import org.gvsig.fmap.geom.GeometryLocator;
42
import org.gvsig.fmap.geom.GeometryManager;
43
import org.gvsig.fmap.geom.exception.CreateGeometryException;
44
import org.gvsig.fmap.geom.primitive.Curve;
45
import org.gvsig.fmap.geom.primitive.Envelope;
46
import org.gvsig.fmap.mapcontext.MapContextLocator;
47
import org.gvsig.fmap.mapcontext.ViewPort;
48
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
49
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolManager;
50
import org.gvsig.gui.awt.text.RotatedTextUtils;
51
import org.gvsig.math.intervals.IntervalUtils;
52
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.ILineSymbol;
53
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.IMarkerSymbol;
54
import org.gvsig.tools.ToolsLocator;
55
import org.gvsig.tools.dynobject.DynStruct;
56
import org.gvsig.tools.locator.LocatorException;
57
import org.gvsig.tools.persistence.PersistenceManager;
58
import org.gvsig.tools.persistence.PersistentState;
59
import org.gvsig.tools.persistence.exception.PersistenceException;
60

    
61
/**
62
 * FFrame para introducir una cuadr?cula sobre una vista en el Layout.
63
 * 
64
 * @author Vicente Caballero Navarro
65
 */
66
public class FFrameGrid extends AbstractFFrameViewDependence implements
67
    IFFrameViewDependence {
68
    private static final GeometryManager GEOMETRY_MANAGER = GeometryLocator.getGeometryManager();
69
    
70
    private static final int OFFSET_IN_PIXELS = 5;
71
    
72
    public static final String PERSISTENCE_DEFINITION_NAME = "FFrameGrid";
73
    
74
    private static final String SYMBOLLINE_FIELD = "symbolLine";
75
    private static final String SYMBOLPOINT_FIELD = "symbolPoint";
76
    private static final String FONT_FIELD = "font";
77
    private static final String INTERVALX_FIELD = "intervalX";
78
    private static final String INTERVALY_FIELD = "intervalY";
79
    private static final String ISLINE_FIELD = "isLine";
80
    private static final String FONTSYZE_FIELD = "fontsize";
81
    private static final String TEXTCOLOR_FIELD = "textColor";
82
    private static final String USE_NUM_DIVISIONS_FIELD = "useNumDivisions";
83
    private static final String NUM_DIV_HORIZ_FIELD = "numDivHoriz";
84
    private static final String NUM_DIV_VERT_FIELD = "numDivVret";
85
    private static final String LABEL_FORMAT_FIELD = "labelFormat";
86
    private static final String HORIZ_LABEL_ROTATION_FIELD = "horizLabelRotation";
87
    private static final String VERT_LABEL_ROTATION_FIELD = "vertLabelRotation";
88
    private static final String LABEL_ANCHOR = "LabelAnchor";
89
    
90
    
91
    /**
92
     * Use a fixed distance (intervalX and intervalY) 
93
     * to calculate the position of grid lines
94
     */
95
    public static final int FIXED_DISTANCE_MODE = 0;
96
    /**
97
     * Use a specific number of horizontal divisions in order
98
     * to calculate the position of grid lines
99
     */
100
    public static final int NUM_DIVISIONS_HORIZ_MODE = 1;
101
    /**
102
     * Use a specific number of vertical divisions in order to calculate
103
     * the position of grid lines
104
     */
105
    public static final int NUM_DIVISIONS_VERT_MODE = 2;
106

    
107
    private double defaultInterval = 100000;
108
    private Double intervalX = null;
109
    private Double intervalY = null;
110

    
111
    private Color textColor = Color.black;
112
    private boolean isLine;
113
    private int sizeFont = 8;
114
        private int useNumDivisions = FIXED_DISTANCE_MODE;
115
        private int numDivHoriz = 4;
116
        private int numDivVert = 4;
117
        private DecimalFormat labelFormat = new DecimalFormat("#0.00", DecimalFormatSymbols.getInstance());
118
        private double horizLabelRotation = 0.0;
119
        private double vertLabelRotation = 0.0;
120
        /**
121
         * {@link RotatedTextUtils.ANCHOR_CENTER} or {@link RotatedTextUtils.ANCHOR_CORNER}
122
         */
123
        private int labelAnchor = RotatedTextUtils.ANCHOR_CORNER;
124

    
125
    // private boolean print=false;
126
    private SymbolManager symbolManager = MapContextLocator.getSymbolManager();
127
    private ILineSymbol symbolLine = (ILineSymbol) symbolManager
128
        .createSymbol(ILineSymbol.SYMBOL_NAME);
129
    private IMarkerSymbol symbolPoint = (IMarkerSymbol) symbolManager
130
        .createSymbol(IMarkerSymbol.SYMBOL_NAME);
131
    private Font font = new Font("Arial", Font.PLAIN, sizeFont);
132
    
133
    public void draw(Graphics2D g, AffineTransform at, Rectangle2D rv,
134
        BufferedImage imgBase) {
135
            try {
136
                    Rectangle2D.Double r = getBoundingBox(at);
137
                    Rectangle2D rView = fframeViewDependence.getBoundingBox(at);
138
                    if (r==null || rView==null) {
139
                            //extent may be null, for instance if no layer has been loaded on the view
140
                            return;
141
                    }
142
                    ViewPort vp = (ViewPort) fframeViewDependence.getMapContext().getViewPort().clone();
143

    
144
                    vp.setOffset(new Point2D.Double(rView.getMinX(), rView.getMinY()));
145
                    vp.setImageSize(new Dimension((int)Math.round(rView.getWidth()), (int)Math.round(rView.getHeight())));
146
                    vp.refreshExtent();
147
                    
148
                    Envelope envelope = vp.getAdjustedEnvelope();
149
                    AffineTransform mapTransform = vp.getAffineTransform();
150
                    updateIntervals(envelope);
151
                    double intervalX = getIntervalX();
152
                    double intervalY = getIntervalY();
153

    
154
                    g.rotate(Math.toRadians(getRotation()), r.x + (r.width / 2), r.y + (r.height / 2));
155

    
156
                    double minX = envelope.getMinimum(0);
157
                    double minY = envelope.getMinimum(1);
158
                    double maxX = envelope.getMaximum(0);
159
                    double maxY = envelope.getMaximum(1);
160

    
161
                    // init point, in map coordinates
162
                    double initPointGridWCX = Math.ceil(minX / intervalX)*intervalX;
163
                    double initPointGridWCY = Math.ceil(minY / intervalY)*intervalY;
164

    
165
                    ISymbol symbolForMargins = null;
166
                    if (isLine){
167
                            symbolForMargins = symbolLine;
168
                    }else{
169
                            try {
170
                                    symbolForMargins = (ISymbol)symbolLine.clone();
171
                                    symbolForMargins.setColor(symbolPoint.getColor());
172
                            } catch (CloneNotSupportedException e) {
173
                                    LOG.error("Symbol desn't support the clone method", e);
174
                            }
175
                    }
176

    
177
                    //Draw the box
178
                    drawBox(rView, g, symbolForMargins);
179

    
180
                    //Draw the margins
181
                    double myScale = at.getScaleX() * 0.0234; // FIXME: 0.0234?? Should this depend on output resolution?
182
                    int scaledFontSize = (int) (myScale * sizeFont);
183
                    Font font = new Font(
184
                                    this.font.getFamily(), 
185
                                    this.font.getStyle(),
186
                                    scaledFontSize);
187

    
188
                    drawLabels(rView,
189
                                    initPointGridWCX,
190
                                    initPointGridWCY,
191
                                    maxX,
192
                                    maxY,
193
                                    intervalX,
194
                                    intervalY,
195
                                    mapTransform,
196
                                    g, 
197
                                    font, 
198
                                    symbolForMargins);
199

    
200
                    //Draw the lines or the points
201
                    if (isLine) { 
202
                            drawLines(rView,
203
                                        initPointGridWCX,
204
                                        initPointGridWCY,
205
                                        maxX,
206
                                        maxY,
207
                                        intervalX,
208
                                        intervalY,
209
                                        mapTransform,
210
                                        g);
211
                    } else {
212
                            drawPoints(initPointGridWCX,
213
                                initPointGridWCY,
214
                                maxX,
215
                                maxY,
216
                                intervalX,
217
                                intervalY,
218
                                mapTransform,
219
                                g);
220
                    }
221

    
222
                    g.rotate(Math.toRadians(-getRotation()), r.x + (r.width / 2), r.y
223
                                    + (r.height / 2));
224
            } catch (CloneNotSupportedException e1) {}
225
    } 
226

    
227
    /**
228
     * Draw the grid as point symbols
229
     * 
230
     * @param minGridX The starting grid point on the x axis, in map coordinates
231
     * @param minGridY The starting grid point on the y axis, in map coordinates
232
     * @param maxGridX The maximum map point on the x axis, in map coordinates.
233
     * It may be bigger than the maximum grid point
234
     * @param maxGridY The maximum map point on the y axis, in map coordinates.
235
     * It may be bigger than the maximum grid point
236
     * @param intervalGridX The grid interval on the x axis, in map coordinates
237
     * @param intervalGridY The grid interval on the y axis, in map coordinates
238
     * @param mapTransform Transforms map coordinates to screen coordinates
239
     * @param g The graphics object to draw on
240
     */
241
    private void drawPoints(
242
                    double minGridX,
243
                    double minGridY,
244
                    double maxGridX,
245
                    double maxGridY,
246
                    double intervalGridX,
247
                    double intervalGridY,
248
                        AffineTransform mapTransform, 
249
                    Graphics2D g) {
250
            
251
        Point2D currentPoint = new Point2D.Double(minGridX, minGridY);
252
        Point2D screenPoint = new Point2D.Double();
253
        while (currentPoint.getX() < maxGridX) {
254
                while (currentPoint.getY() < maxGridY) {
255
                        mapTransform.transform(currentPoint, screenPoint);
256
                drawPoint(g, screenPoint);
257
                    currentPoint.setLocation(currentPoint.getX(), currentPoint.getY()+intervalGridY);
258
                }
259
                currentPoint.setLocation(currentPoint.getX()+intervalGridX, minGridY);
260
        }
261
    }
262

    
263
    /**
264
     * Draw the grid as line symbols
265
     * 
266
     * @param rView The rectangle of the view, on screen coordinates
267
     * @param minGridX The starting grid point on the x axis, in map coordinates
268
     * @param minGridY The starting grid point on the y axis, in map coordinates
269
     * @param maxGridX The maximum map point on the x axis, in map coordinates.
270
     * It may be bigger than the maximum grid point
271
     * @param maxGridY The maximum map point on the y axis, in map coordinates.
272
     * It may be bigger than the maximum grid point
273
     * @param intervalGridX The grid interval on the x axis, in map coordinates
274
     * @param intervalGridY The grid interval on the y axis, in map coordinates
275
     * @param mapTransform Transforms map coordinates to screen coordinates
276
     * @param g The graphics object to draw on
277
     */
278
    private void drawLines(Rectangle2D rView,
279
                    double minMapX,
280
                    double minMapY,
281
                    double maxMapX,
282
                    double maxMapY,
283
                    double intervalMapX,
284
                    double intervalMapY,
285
                        AffineTransform mapTransform, 
286
                    Graphics2D g) {
287
        double minX = rView.getMinX();
288
        double maxX = rView.getMaxX();
289
        double minY = rView.getMinY();
290
        double maxY = rView.getMaxY();
291
        double xMap = minMapX;
292
        double yMap = minMapY;
293

    
294
        // transform to screen coordinates
295
        Point2D currentPoint = new Point2D.Double(minMapX, minMapY);
296
            // transform from map coordinates to screen (pixels) coordinates
297
        mapTransform.transform(currentPoint, currentPoint);
298
               
299
        //Draw the vertical lines
300
        while (xMap < maxMapX) {
301
                drawLine(currentPoint.getX(), minY, currentPoint.getX(), maxY, g, symbolLine);
302
                xMap = xMap + intervalMapX;
303
                currentPoint.setLocation(xMap, minMapY);
304
                // from map coordinates to screen (pixels)
305
                mapTransform.transform(currentPoint, currentPoint);
306
        }
307
        //Draw the horizontal lines
308
        while (yMap < maxMapY) {
309
                drawLine(minX, currentPoint.getY(), maxX , currentPoint.getY(), g, symbolLine);
310
                yMap = yMap + intervalMapY;
311
                currentPoint.setLocation(minMapX, yMap);
312
                // from map coordinates to screen (pixels)
313
                mapTransform.transform(currentPoint, currentPoint);
314
        }
315
    }
316

    
317
    /**
318
     * Draws the labels and the tick marks of labels
319
     * 
320
     * @param rView The rectangle of the view, on screen coordinates
321
     * @param minGridX The starting grid point on the x axis, in map coordinates
322
     * @param minGridY The starting grid point on the y axis, in map coordinates
323
     * @param maxGridX The maximum map point on the x axis, in map coordinates.
324
     * It may be bigger than the maximum grid point
325
     * @param maxGridY The maximum map point on the y axis, in map coordinates.
326
     * It may be bigger than the maximum grid point
327
     * @param intervalGridX The grid interval on the x axis, in map coordinates
328
     * @param intervalGridY The grid interval on the y axis, in map coordinates
329
     * @param mapTransform Transforms map coordinates to screen coordinates
330
     * @param g The graphics object to draw on
331
     * @param font
332
     * @param symbolForMargins
333
     */
334
    private void drawLabels(Rectangle2D rView,
335
                    double minGridX,
336
                    double minGridY,
337
                    double maxGridX,
338
                    double maxGridY,
339
                    double intervalGridX,
340
                    double intervalGridY,
341
                    AffineTransform mapTransform,
342
                    Graphics2D g,  
343
                    Font font,
344
                    ISymbol 
345
                    symbolForMargins) {
346
            AffineTransform defaultAt = g.getTransform();
347
            
348
            double minX = rView.getMinX();
349
            double maxX = rView.getMaxX();
350
            double minY = rView.getMinY();
351
            double maxY = rView.getMaxY();
352
            double xMap = minGridX;
353
            double yMap = minGridY;
354

    
355
            // transform to screen coordinates
356
            Point2D initGridPx = new Point2D.Double(minGridX, minGridY);
357
            mapTransform.transform(initGridPx, initGridPx);
358

    
359
            double xPx = initGridPx.getX();
360

    
361
            double angle = RotatedTextUtils.normalizeAngle(Math.toRadians(getVertLabelRotation()));
362
            int anchor = getLabelAnchor();
363
            // Draw vertical ticks and labels
364
            while (xMap < maxGridX) {   
365
                    // bottom tick
366
                    drawLine(xPx, maxY + OFFSET_IN_PIXELS, xPx , maxY, g, symbolForMargins);
367
                    // top tick
368
                    drawLine(xPx, minY, xPx, minY - OFFSET_IN_PIXELS, g, symbolForMargins);
369

    
370
                    g.rotate(angle);
371
                    g.setColor(textColor);
372

    
373
                    // bottom label
374
                    Point2D p1 = new Point2D.Double(xPx, maxY+OFFSET_IN_PIXELS); // bottom
375
                    TextLayout textaux = new TextLayout(this.labelFormat.format(xMap), font, g.getFontRenderContext());
376
                    Point2D rotatedP1 = RotatedTextUtils.getPosition(p1, textaux, angle, RotatedTextUtils.PLACEMENT_BOTTOM, anchor);
377
                    textaux.draw(g, (int) (rotatedP1.getX()), (int) rotatedP1.getY());
378

    
379
                    // top label
380
                    Point2D p2 = new Point2D.Double(xPx, minY-OFFSET_IN_PIXELS);
381
                    Point2D rotatedP2 = RotatedTextUtils.getPosition(p2, textaux, angle, RotatedTextUtils.PLACEMENT_TOP, anchor);
382
                    textaux.draw(g, (int) (rotatedP2.getX()),(int) rotatedP2.getY());
383
                    g.setTransform(defaultAt);
384

    
385

    
386
                    xMap = xMap + intervalGridX;
387

    
388
                    initGridPx.setLocation(xMap, minGridY);
389
                    mapTransform.transform(initGridPx, initGridPx);
390
                    xPx = initGridPx.getX();
391
            }
392
            double yPx = initGridPx.getY();
393
            angle = RotatedTextUtils.normalizeAngle(Math.toRadians(getHorizLabelRotation()));
394
            // horizontal ticks and labels
395
            while (yMap < maxGridY) {
396

    
397
                    // left tick
398
                    drawLine(minX - OFFSET_IN_PIXELS, yPx, minX , yPx, g, symbolForMargins);
399
                    // right tick
400
                    drawLine(maxX, yPx, maxX + OFFSET_IN_PIXELS, yPx, g, symbolForMargins);
401

    
402
                    g.rotate(angle);
403
                    g.setColor(textColor);
404
                    TextLayout textaux = new TextLayout(this.labelFormat.format(yMap), font, g.getFontRenderContext());
405

    
406
                    // left label
407
                    Point2D p1 = new Point2D.Double(minX-OFFSET_IN_PIXELS, yPx);
408
                    Point2D rotatedP1 = RotatedTextUtils.getPosition(p1, textaux, angle, RotatedTextUtils.PLACEMENT_LEFT, anchor);
409
                    textaux.draw(g, (int) (rotatedP1.getX()), (int) rotatedP1.getY());
410
                    // right label
411
                    Point2D p2 = new Point2D.Double(maxX+OFFSET_IN_PIXELS, yPx);
412
                    Point2D rotatedP2 = RotatedTextUtils.getPosition(p2, textaux, angle, RotatedTextUtils.PLACEMENT_RIGHT, anchor);
413
                    textaux.draw(g, (int) (rotatedP2.getX()),(int) rotatedP2.getY());
414
                    g.setTransform(defaultAt);
415
                    yMap = yMap + intervalGridY;
416

    
417
                    initGridPx.setLocation(minGridX, yMap);
418
                    mapTransform.transform(initGridPx, initGridPx);
419
                    yPx = initGridPx.getY();
420
            }
421
    }
422
    
423
    private void drawBox(Rectangle2D mapRectangle, Graphics2D g, ISymbol symbol){        
424
        try {
425
                // FIXME: We are adding 1 extra pixel for correct adjustment when exporting to PDF.
426
                // However, this creates 1 blank pixel on the right side when drawing on screen.
427
                // Probably this is caused by some rounding.
428
                // Separating the implementation of print and draw methods should help, too.
429
            Curve curve = (Curve) GEOMETRY_MANAGER.create(TYPES.CURVE, SUBTYPES.GEOM2D);
430
            curve.addMoveToVertex(GEOMETRY_MANAGER.createPoint(mapRectangle.getMinX()-1, mapRectangle.getMinY()-1, SUBTYPES.GEOM2D));
431
            curve.addVertex(GEOMETRY_MANAGER.createPoint(mapRectangle.getMinX()-1, mapRectangle.getMaxY()+1, SUBTYPES.GEOM2D));
432
            curve.addVertex(GEOMETRY_MANAGER.createPoint(mapRectangle.getMaxX()+1, mapRectangle.getMaxY()+1, SUBTYPES.GEOM2D));
433
            curve.addVertex(GEOMETRY_MANAGER.createPoint(mapRectangle.getMaxX()+1, mapRectangle.getMinY()-1, SUBTYPES.GEOM2D));
434
            curve.addVertex(GEOMETRY_MANAGER.createPoint(mapRectangle.getMinX()-1, mapRectangle.getMinY()-1, SUBTYPES.GEOM2D));
435
            symbol.draw(g, null, curve, null, null);
436
        } catch (CreateGeometryException e) {
437
            LOG.error("Error drawing the box", e);
438
        } 
439
    }
440
    
441
    /**
442
     * Draws a point using the configured symbol
443
     * 
444
     * @param g The graphics object to draw on
445
     * @param point Point to draw, in map coordinates
446
     * @param mapTransform Transforms from map coordinates to screen coordinates
447
     */
448
    private void drawPoint(Graphics2D g, Point2D point){
449
        try {
450
            Geometry geom =
451
                createPoint((int) point.getX(), (int) point.getY());
452
            symbolPoint.draw(g, null, geom, null, null);           
453
        }  catch (LocatorException e) {
454
            LOG.error("Error drawing the grid", e);
455
        } catch (CreateGeometryException e) {
456
            LOG.error("Error drawing the grid", e);
457
        }
458
    }
459
    
460
    private void drawLine(double startX, double startY, double endX, double endY, Graphics2D g, ISymbol symbolLine){
461
        try {
462
            Geometry geom =
463
                createLine((int) startX, (int)startY, (int) endX, (int) endY);
464
            symbolLine.draw(g, null, geom, null, null);          
465
        } catch (LocatorException e) {
466
            LOG.error("Error drawing the grid", e);
467
        } catch (CreateGeometryException e) {
468
            LOG.error("Error drawing the grid", e);
469
        }
470
    }
471

    
472
    private Geometry createLine(int i, int j, int k, int l)
473
        throws LocatorException, CreateGeometryException {
474
        Curve curve = (Curve)GEOMETRY_MANAGER.create(Geometry.TYPES.CURVE, SUBTYPES.GEOM2D);
475
        curve.addMoveToVertex(GEOMETRY_MANAGER.createPoint(i, j, SUBTYPES.GEOM2D));
476
        curve.addVertex(GEOMETRY_MANAGER.createPoint(k, l, SUBTYPES.GEOM2D));
477
        return curve; 
478
    }
479

    
480
    private Geometry createPoint(int i, int j) throws LocatorException,
481
        CreateGeometryException {
482
        return GeometryLocator.getGeometryManager().createPoint(i, j,
483
            SUBTYPES.GEOM2D);
484
    }
485

    
486
    public String getNameFFrame() {
487
        return PluginServices.getText(this, "cuadricula") + num;
488
    }
489

    
490
    public String getName() {
491
        return PERSISTENCE_DEFINITION_NAME;
492
    }
493

    
494
    public void setFFrameDependence(IFFrame f) {
495
        super.setFFrameDependence(f);
496
        fframeViewDependence.refresh();       
497
    }
498

    
499
    public void setIntervalX(double d) {
500
        intervalX = d;
501
    }
502

    
503
    public void setIntervalY(double d) {
504
        intervalY = d;
505
    }
506

    
507
    public double getIntervalX() {
508
            if (intervalX!=null) {
509
                    return intervalX;
510
            }
511
            intervalX = intervalY = getReasonableInterval();
512
            return intervalX;
513
    }
514
    
515
    private double getReasonableInterval() {
516
            if (fframeViewDependence!=null
517
                            && fframeViewDependence.getMapContext()!=null
518
                            && fframeViewDependence.getMapContext().getViewPort().getAdjustedEnvelope()!=null) {
519
                    Envelope env = fframeViewDependence.getMapContext().getViewPort().getAdjustedEnvelope();
520
                    return IntervalUtils.roundIntervalDivision(env.getLength(0), 5);
521
            }
522
            return defaultInterval;
523
    }
524
    
525

    
526
    public double getIntervalY() {
527
            if (intervalX!=null) {
528
                    return intervalX;
529
            }
530
            intervalX = intervalY = new Double(getReasonableInterval());
531
            return intervalY;
532
    }
533

    
534
    public void setTextColor(Color textcolor) {
535
        textColor = textcolor;
536
    }
537

    
538
    public void setIsLine(boolean b) {
539
        isLine = b;
540
    }
541

    
542
    public boolean isLine() {
543
        return isLine;
544
    }
545

    
546
    public Color getFontColor() {
547
        return textColor;
548
    }
549

    
550
    public int getSizeFont() {
551
        return sizeFont;
552
    }
553

    
554
    public void setSizeFont(int sizeFont) {
555
        this.sizeFont = sizeFont;
556
    }
557
    
558
    public Rectangle2D.Double getBoundingBox(AffineTransform at) {
559
        if ((fframeViewDependence == null) ||  (fframeViewDependence.getMapContext() == null)){
560
            return super.getBoundingBox(at);
561
        }
562
        Rectangle2D.Double r = fframeViewDependence.getBoundingBox(at);
563
        Envelope extent =
564
            fframeViewDependence.getMapContext().getViewPort()
565
                .getAdjustedEnvelope();
566
        if (extent==null) {
567
                //extent may be null, for instance if no layer has been loaded on the view
568
                return null;
569
        }
570
        double extentX = extent.getMaximum(0);
571
        double extentY = extent.getMaximum(1);
572
        int lengthX = String.valueOf((long) extentX).length();
573
        double myScale = at.getScaleX() * 0.0234; 
574
        int scaledFontSize = (int) (myScale * sizeFont);
575
        int pixelsX = (int) (lengthX * scaledFontSize * 0.7);
576
        int lengthY = String.valueOf((long) extentY).length();
577
        int pixelsY = (lengthY * scaledFontSize);       
578
        return new Rectangle2D.Double(r.getMinX() - pixelsX, r.getMinY() - pixelsY,
579
                r.getWidth() + pixelsX * 2, r.getHeight() + pixelsY * 2);        
580
    }
581

    
582
    public Rectangle2D getMovieRect(int difx, int dify) {
583
        return this.getBoundingBox(null);
584
    }
585

    
586
    public void refreshDependence(IFFrame fant, IFFrame fnew) {
587
        if (fframeViewDependence.equals(fant)) {
588
            fframeViewDependence = (FFrameView) fnew;
589
            fframeViewDependence.refresh();           
590
        }
591
    }
592

    
593
    public void drawHandlers(Graphics2D g) {
594
        g.setColor(Color.gray);
595
        super.drawHandlers(g);
596
        g.setColor(Color.black);
597
    }
598

    
599
    public Rectangle2D getLastMoveRect() {
600
        return getBoundBox();
601
    }
602

    
603
    public ISymbol getSymbolLine() {
604
        return symbolLine;
605
    }
606

    
607
    public void setSymbolLine(ISymbol symbolLine) {
608
        this.symbolLine = (ILineSymbol) symbolLine;
609
    }
610

    
611
    public ISymbol getSymbolPoint() {
612
        return symbolPoint;
613
    }
614

    
615
    public void setSymbolPoint(ISymbol symbolPoint) {
616
        this.symbolPoint = (IMarkerSymbol) symbolPoint;
617
    }
618

    
619
    public Font getFont() {
620
        return font;
621
    }
622

    
623
    public void setFont(Font m_font) {
624
        this.font = m_font;
625
    }
626

    
627
    public int getFontSize() {
628
        return font.getSize();
629
    }
630

    
631
    /**
632
     * Defines whether a number of divisions is used to calculate the
633
     * location of grid lines,
634
     * or a distance (intervalX and intervalY) is used to
635
     * calculate them.
636
     * 
637
     * @param useNumDivisions One of {@link #FIXED_DISTANCE_MODE},
638
     * {@link #NUM_DIVISIONS_HORIZ_MODE} or {@link #NUM_DIVISIONS_HORIZ_MODE}.
639
     * @return
640
     */
641
    public void setUseNumDivisions(int mode) {
642
            this.useNumDivisions  = mode;
643
    }
644
    
645
    protected void updateIntervals() {
646
            if (fframeViewDependence.getMapContext()!=null
647
                            && fframeViewDependence.getMapContext().getViewPort()!=null) {
648
                    Envelope env = fframeViewDependence.getMapContext().getViewPort().getAdjustedEnvelope();
649
                    updateIntervals(env);
650
            }
651
    }
652
    
653
    protected void updateIntervals(Envelope env) {
654
            if (useNumDivisions==NUM_DIVISIONS_HORIZ_MODE) {
655
                    double division = IntervalUtils.roundIntervalDivision(env.getLength(0), numDivHoriz);
656
                    intervalX = division;
657
                    intervalY = division;
658
            }
659
            else if (useNumDivisions==NUM_DIVISIONS_VERT_MODE) {
660
                    double division = IntervalUtils.roundIntervalDivision(env.getLength(1), numDivVert);
661
                    intervalX = division;
662
                    intervalY = division;
663
            }
664
    }
665
    
666
    /**
667
     * Returns true if a number of divisions is used to calculate the
668
     * location of grid lines,
669
     * or false if a distance (intervalX and intervalY) is used to
670
     * calculate them.
671
     * 
672
     * @return  One of {@link #FIXED_DISTANCE_MODE},
673
     * {@link #NUM_DIVISIONS_HORIZ_MODE} or {@link #NUM_DIVISIONS_VERT_MODE}.
674
     */
675
    public int getUseNumDivisions() {
676
            return this.useNumDivisions;
677
    }
678
    
679
    public void setNumDivisionsHoriz(int nx) {
680
            this.numDivHoriz = nx;
681
    }
682
    
683
    public void setNumDivisionsVert(int ny) {
684
            this.numDivVert = ny;
685
    }
686
    
687
    public int getNumDivisionsHoriz() {
688
            return this.numDivHoriz;
689
    }
690
    
691
    public int getNumDivisionsVert() {
692
            return this.numDivVert;
693
    }
694
    
695
    public void setLabelFormat(DecimalFormat f) {
696
            this.labelFormat  = f;
697
    }
698
    
699
    public DecimalFormat  getLabelFormat() {
700
            return this.labelFormat;
701
    }
702

    
703
    /**
704
     * Sets the rotation of the labels corresponding to horizontal lines
705
     * 
706
     * @param labelRotation Label rotation, measured in arc degrees
707
     */
708
    public void setHorizLabelRotation(double labelRotation) {
709
            this.horizLabelRotation  = labelRotation;
710
    }
711
    
712
    /**
713
     * Sets the rotation of the labels corresponding to vertical lines
714
     * 
715
     * @param labelRotation Label rotation, measured in arc degrees
716
     */
717
    public void setVertLabelRotation(double labelRotation) {
718
            this.vertLabelRotation  = labelRotation;
719
    }
720
    
721
    /**
722
     * Gets the rotation of the labels corresponding to horizontal lines
723
     * 
724
     * @param labelRotation Label rotation, measured in arc degrees
725
     */
726
    public double getHorizLabelRotation() {
727
            return this.horizLabelRotation;
728
    }
729
    
730
    /**
731
     * Defines the alignment of the grid label compared with the
732
     * associated grid tick
733
     * 
734
     * @param anchor {@link RotatedTextUtils.ANCHOR_CORNER} or
735
     *   {@link RotatedTextUtils.ANCHOR_CENTER}
736
     */
737
    public int getLabelAnchor() {
738
            return this.labelAnchor;
739
    }
740
    
741
    /**
742
     * Gets the alignment of the grid labels. ANCHOR_CORNER aligns
743
     * the corner of the label with the grid tick, while ANCHOR_CENTER
744
     * aligns the label center with the grid tick.
745
     * 
746
     * @param anchor {@link RotatedTextUtils.ANCHOR_CORNER} or
747
     *   {@link RotatedTextUtils.ANCHOR_CENTER}
748
     */
749
    public void setLabelAnchor(int anchor) {
750
            // ensure a coherent value
751
            if (anchor==RotatedTextUtils.ANCHOR_CENTER) {
752
                    this.labelAnchor = anchor;
753
            }
754
            else {
755
                    this.labelAnchor = RotatedTextUtils.ANCHOR_CORNER;
756
            }
757
    }
758
    
759
    /**
760
     * Gets the rotation of the labels corresponding to vertical lines
761
     * 
762
     * @param labelRotation Label rotation, measured in arc degrees
763
     */
764
    public double getVertLabelRotation() {
765
            return this.vertLabelRotation;
766
    }
767
    
768
    public void print(Graphics2D g, AffineTransform at, Geometry shape,
769
        PrintAttributes properties) {
770
        draw(g, at, null, null);
771
    }
772

    
773
    public static void registerPersistent() {
774
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
775
        if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) {
776
            DynStruct definition =
777
                manager.addDefinition(FFrameGrid.class,
778
                    PERSISTENCE_DEFINITION_NAME,
779
                    "FFrameGrid persistence definition", null, null);
780

    
781
            definition
782
                .extend(manager
783
                    .getDefinition(AbstractFFrameViewDependence.PERSISTENCE_DEFINITION_NAME));
784

    
785
            definition.addDynFieldObject(SYMBOLLINE_FIELD)
786
                .setClassOfValue(ILineSymbol.class).setMandatory(true);
787
            definition.addDynFieldObject(SYMBOLPOINT_FIELD)
788
                .setClassOfValue(IMarkerSymbol.class).setMandatory(true);
789
            definition.addDynFieldObject(FONT_FIELD)
790
                .setClassOfValue(Font.class).setMandatory(true);
791
            definition.addDynFieldDouble(INTERVALX_FIELD).setMandatory(false);
792
            definition.addDynFieldDouble(INTERVALY_FIELD).setMandatory(false);
793
            definition.addDynFieldBoolean(ISLINE_FIELD).setMandatory(true);
794
            definition.addDynFieldInt(FONTSYZE_FIELD).setMandatory(true);
795
            definition.addDynFieldObject(TEXTCOLOR_FIELD)
796
                .setClassOfValue(Color.class).setMandatory(true);
797
            definition.addDynFieldInt(USE_NUM_DIVISIONS_FIELD).setMandatory(false);
798
            definition.addDynFieldInt(NUM_DIV_HORIZ_FIELD).setMandatory(false);
799
            definition.addDynFieldInt(NUM_DIV_VERT_FIELD).setMandatory(false);
800
            definition.addDynFieldObject(LABEL_FORMAT_FIELD)
801
            .setClassOfValue(DecimalFormat.class).setMandatory(false);
802
            definition.addDynFieldDouble(VERT_LABEL_ROTATION_FIELD).setMandatory(false);
803
            definition.addDynFieldDouble(HORIZ_LABEL_ROTATION_FIELD).setMandatory(false);
804
            definition.addDynFieldInt(LABEL_ANCHOR).setMandatory(false);
805
        }
806
    }
807

    
808
    
809
    @Override
810
    public void loadFromState(PersistentState state)
811
        throws PersistenceException {
812
        super.loadFromState(state);
813
        symbolLine = (ILineSymbol) state.get(SYMBOLLINE_FIELD);
814
        symbolPoint = (IMarkerSymbol) state.get(SYMBOLPOINT_FIELD);
815
        font = (Font) state.get(FONT_FIELD);
816
        intervalX = (Double) state.get(INTERVALX_FIELD);
817
        intervalY = (Double) state.get(INTERVALY_FIELD);
818
        isLine = state.getBoolean(ISLINE_FIELD);
819
        sizeFont = state.getInt(FONTSYZE_FIELD);
820
        textColor = (Color) state.get(TEXTCOLOR_FIELD);
821
        if (state.hasValue(USE_NUM_DIVISIONS_FIELD)) {
822
                useNumDivisions = state.getInt(USE_NUM_DIVISIONS_FIELD);
823
        }
824
        if (state.hasValue(NUM_DIV_HORIZ_FIELD)) {
825
                numDivHoriz = state.getInt(NUM_DIV_HORIZ_FIELD);        
826
        }
827
        if (state.hasValue(NUM_DIV_VERT_FIELD)) {
828
                numDivVert = state.getInt(NUM_DIV_VERT_FIELD);        
829
        }
830
        if (state.hasValue(LABEL_FORMAT_FIELD)) {
831
                labelFormat = (DecimalFormat) state.get(LABEL_FORMAT_FIELD);        
832
        }
833
        if (state.hasValue(VERT_LABEL_ROTATION_FIELD)) {
834
                vertLabelRotation = state.getDouble(VERT_LABEL_ROTATION_FIELD);
835
        }
836
        if (state.hasValue(HORIZ_LABEL_ROTATION_FIELD)) {
837
                horizLabelRotation = state.getDouble(HORIZ_LABEL_ROTATION_FIELD);
838
        }
839
        if (state.hasValue(LABEL_ANCHOR)) {
840
                labelAnchor = state.getInt(LABEL_ANCHOR);
841
        }
842
    }
843

    
844
    @Override
845
    public void saveToState(PersistentState state) throws PersistenceException {
846
        super.saveToState(state);
847
        state.set(SYMBOLLINE_FIELD, symbolLine);
848
        state.set(SYMBOLPOINT_FIELD, symbolPoint);
849
        state.set(FONT_FIELD, font);
850
        state.set(INTERVALX_FIELD, intervalX);
851
        state.set(INTERVALY_FIELD, intervalY);
852
        state.set(ISLINE_FIELD, isLine);
853
        state.set(FONTSYZE_FIELD, sizeFont);
854
        state.set(TEXTCOLOR_FIELD, textColor);
855
        state.set(USE_NUM_DIVISIONS_FIELD, useNumDivisions);
856
        state.set(NUM_DIV_HORIZ_FIELD, numDivHoriz);
857
        state.set(NUM_DIV_VERT_FIELD, numDivVert);
858
        state.set(LABEL_FORMAT_FIELD, labelFormat);
859
        state.set(VERT_LABEL_ROTATION_FIELD, vertLabelRotation);
860
        state.set(HORIZ_LABEL_ROTATION_FIELD, horizLabelRotation);
861
        state.set(LABEL_ANCHOR, labelAnchor);
862
    }
863
}