Statistics
| Revision:

root / trunk / extensions / extArcims / src / es / prodevelop / cit / gvsig / arcims / gui / panels / LayerScaleDrawPanel.java @ 10667

History | View | Annotate | Download (16.1 KB)

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

    
45
import com.iver.andami.PluginServices;
46

    
47
import es.prodevelop.cit.gvsig.arcims.fmap.layers.LayerScaleData;
48
import es.prodevelop.cit.gvsig.arcims.gui.dialogs.LayerScaleDialog;
49

    
50
import java.awt.BasicStroke;
51
import java.awt.Color;
52
import java.awt.Font;
53
import java.awt.FontMetrics;
54
import java.awt.Graphics;
55
import java.awt.Graphics2D;
56
import java.awt.Stroke;
57
import java.awt.geom.AffineTransform;
58

    
59
import java.util.Vector;
60

    
61
import javax.swing.JLabel;
62
import javax.swing.JPanel;
63

    
64

    
65
/**
66
 * This is the 'canvas' where layer scale limits status is
67
 * painted.
68
 *
69
 * @author jldominguez
70
 *
71
 */
72
public class LayerScaleDrawPanel extends JPanel {
73
    private static final long serialVersionUID = 0;
74
    private LayerScaleDialog parentDialog;
75
    private Vector layerLabelsVector = new Vector();
76
    private Vector layerInfo = new Vector();
77
    private float currentScale;
78
    private int dpi = 96;
79
    private String fontName = "Dialog";
80
    private rulerItem[] rulerItems;
81

    
82
    // ----------------------------------------------------------------------------
83
    private double minScale = 500.0;
84
    private double maxScale = 10000000.0;
85
    private int minScaleX = 93; //88; // +- 8 for less than and more than
86
    private int maxScaleX = 762;
87
    private int margin = 8;
88
    private int rowHeight = 12;
89
    private int rowSep = 15;
90
    private int parentDialogMinLimitForNormalTitle = 485;
91
    private int parentDialogMinLimitForShortTitle = 350;
92
    private Color carrilColor = new Color(219, 219, 219);
93
    private Color scaleLineColor = new Color(199, 106, 191);
94

    
95
    // ----------------------------------------------------------------------------
96
    private double logDist = Math.log(maxScale) - Math.log(minScale);
97
    private String title = "";
98
    private double medScale;
99
    private JLabel updateLabel;
100

    
101
    /**
102
     * @param info this vector contains the layers' scale info
103
     */
104
    public LayerScaleDrawPanel(Vector info, LayerScaleDialog dlg, JLabel ulabel) {
105
        super();
106
        parentDialog = dlg;
107
        updateLabel = ulabel;
108

    
109
        LayerScaleData theInfo;
110
        LayerLabel ll;
111
        currentScale = (float) 1.0;
112
        setBackground(Color.WHITE);
113
        setLayout(null);
114
        layerInfo = invertedVector(info);
115

    
116
        int size = info.size();
117

    
118
        for (int i = 0; i < size; i++) {
119
            theInfo = (LayerScaleData) layerInfo.get(i);
120
            ll = new LayerLabel(theInfo.getName(), theInfo.getId());
121
            ll.setBounds(5, indexDomainToYDomain(i), getLabelsWidth(), rowHeight);
122
            layerLabelsVector.add(ll);
123
            add(ll);
124
        }
125

    
126
        rulerItems = getRulerItems();
127
        medScale = Math.sqrt(maxScale * minScale);
128
        medScale = Math.sqrt(medScale * minScale);
129
    }
130

    
131
    public void resetInfo(Vector info) {
132
        layerLabelsVector.removeAllElements();
133
        removeAll();
134

    
135
        layerInfo = info;
136

    
137
        LayerScaleData theInfo;
138
        LayerLabel ll;
139
        int size = info.size();
140

    
141
        for (int i = 0; i < size; i++) {
142
            theInfo = (LayerScaleData) layerInfo.get(i);
143
            ll = new LayerLabel(theInfo.getName(), theInfo.getId());
144
            ll.setBounds(5, indexDomainToYDomain((size - 1) - i),
145
                getLabelsWidth(), rowHeight);
146
            layerLabelsVector.add(ll);
147
            add(ll);
148
        }
149
    }
150

    
151
    private Vector invertedVector(Vector v) {
152
        Vector res = new Vector();
153

    
154
        for (int i = (v.size() - 1); i >= 0; i--) {
155
            res.add(v.get(i));
156
        }
157

    
158
        return res;
159
    }
160

    
161
    /**
162
     * Sets current scale (it is represented as a vertical line)
163
     * @param s
164
     */
165
    public void setCurrentScale(double s) {
166
        currentScale = (float) s;
167
        updateLabel.setText(PluginServices.getText(this, "Escala") + "  1 : " +
168
            LayerScaleDialog.getFormattedInteger(Math.round(currentScale)));
169
    }
170

    
171
    public void setCurrentScale(float s) {
172
        currentScale = s;
173
        updateLabel.setText(PluginServices.getText(this, "Escala") + "  1 : " +
174
            LayerScaleDialog.getFormattedInteger(Math.round(currentScale)));
175
    }
176

    
177
    public float getCurrentScale() {
178
        return currentScale;
179
    }
180

    
181
    private int getLabelsWidth() {
182
        return minScaleX - margin - 5;
183
    }
184

    
185
    public void paint(Graphics g) {
186
        super.paint(g);
187

    
188
        Graphics2D g2d = (Graphics2D) g;
189

    
190
        System.err.println("WIDTH = " + getWidth());
191
        maxScaleX = getWidth() - 20;
192

    
193
        if (getParentWidth() < parentDialogMinLimitForNormalTitle) {
194
            if (getParentWidth() < parentDialogMinLimitForShortTitle) {
195
                setEmptyTitle();
196
            }
197
            else {
198
                setShortTitle();
199
            }
200
        }
201
        else {
202
            setNormalTitle();
203
        }
204

    
205
        drawTitle(g2d);
206

    
207
        g2d.setStroke(new BasicStroke(1));
208
        g2d.setFont(new Font(fontName, Font.PLAIN, 12));
209

    
210
        int size = layerInfo.size();
211

    
212
        for (int i = 0; i < size; i++) {
213
            LayerScaleData info = (LayerScaleData) layerInfo.get(i);
214

    
215
            int x_min;
216
            int y_min;
217
            int w;
218
            int x_max = this.scaleDomainToXDomain(Math.pow(10.0, 9.0));
219

    
220
            x_min = scaleDomainToXDomain(info.getMinSc());
221
            w = scaleDomainToXDomain(info.getMaxSc()) - x_min;
222
            // y_min = indexDomainToYDomain(i);
223
            
224
            y_min = indexDomainToYDomain((size - 1) - i);
225

    
226
            g2d.setColor(carrilColor);
227
            g2d.fillRect((minScaleX - margin), y_min,
228
                x_max - (minScaleX - margin), rowHeight);
229

    
230
            g2d.setColor(info.getColor(currentScale));
231
            g2d.fillRect(x_min, y_min, w, rowHeight);
232

    
233
            g2d.setColor(Color.BLACK);
234
        }
235

    
236
        drawRuler(g2d, size);
237
        drawCurrentScale(g2d, size);
238

    
239
        int x = Math.min(getWidth() - 136,
240
                ((getParentWidth() - parentDialogMinLimitForNormalTitle) / 2) +
241
                (parentDialogMinLimitForNormalTitle - 136));
242
        drawLegend(g2d, x, 10);
243
    }
244

    
245
    private void setEmptyTitle() {
246
        title = "";
247
    }
248

    
249
    private void setNormalTitle() {
250
        title = PluginServices.getText(this, "scale_limits_status");
251
    }
252

    
253
    private void setShortTitle() {
254
        title = PluginServices.getText(this, "scale_limits");
255
    }
256

    
257
    private void drawTitle(Graphics2D g) {
258
        g.setColor(Color.GRAY);
259
        g.setFont(new Font(fontName, Font.BOLD, 20));
260
        g.drawString(title, 20, 55);
261
    }
262

    
263
    private void drawRuler(Graphics2D g, int i) {
264
        g.setColor(Color.DARK_GRAY);
265

    
266
        int x_min = this.scaleDomainToXDomain(minScale - 1.0);
267
        int x_max = this.scaleDomainToXDomain(maxScale + 1.0);
268
        int y = this.indexDomainToYDomain(0) - 10;
269
        int offsetFromTagsToRuler = 8;
270

    
271
        g.drawLine(x_min, y, x_max, y);
272

    
273
        // arrows
274
        int[] xp = { x_min - 2, x_min + 5, x_min + 5 };
275
        int[] yp = { y, y - 3, y + 3 };
276
        g.fillPolygon(xp, yp, 3);
277

    
278
        int[] x2p = { x_max + 2, x_max - 5, x_max - 5 };
279
        g.fillPolygon(x2p, yp, 3);
280

    
281
        // ---------------- scale label -------------------------
282
        g.setFont(new Font(fontName, Font.BOLD, 12));
283
        g.drawString(PluginServices.getText(this, "the_scale"), 20, y - 44);
284
        g.drawString("(DPI = " + dpi + ")", 20, (y + 12) - 44);
285
        g.setFont(new Font(fontName, Font.PLAIN, 12));
286

    
287
        // ------------------------------------------------------
288
        rulerItem ruIt;
289

    
290
        g.drawString("1:", scaleDomainToXDomain(minScale) - 30,
291
            y - offsetFromTagsToRuler);
292

    
293
        AffineTransform oldt = g.getTransform();
294
        AffineTransform newt;
295
        AffineTransform rott;
296
        AffineTransform trat;
297
        double angulo = -65.0;
298

    
299
        for (int ind = 0; ind < rulerItems.length; ind++) {
300
            ruIt = this.rulerItems[ind];
301
            g.drawLine(ruIt.getScaleInXDomain(), y - 3,
302
                ruIt.getScaleInXDomain(), y + 3);
303

    
304
            int strx = ruIt.getScaleInXDomain();
305
            int stry = y - offsetFromTagsToRuler;
306
            trat = AffineTransform.getTranslateInstance(1.0 * strx, 1.0 * stry);
307
            rott = AffineTransform.getRotateInstance((angulo * 3.1415926) / 180.0);
308
            newt = (AffineTransform) oldt.clone();
309
            newt.concatenate(trat);
310
            newt.concatenate(rott);
311
            g.setTransform(newt);
312
            g.drawString(ruIt.getTag(), 0, 0);
313
            g.setTransform(oldt);
314
        }
315
    }
316

    
317
    private int indexDomainToYDomain(int i) {
318
        return Math.round((float) (158.0 + (rowSep * i)));
319
    }
320

    
321
    private int scaleDomainToXDomain(double d) {
322
        if (d < minScale) {
323
            return minScaleX - margin;
324
        }
325

    
326
        if (d > maxScale) {
327
            return maxScaleX + margin;
328
        }
329

    
330
        double dist = Math.log(d) - Math.log(minScale);
331

    
332
        return Math.round((float) ((1.0 * minScaleX) +
333
            ((dist * (maxScaleX - minScaleX)) / logDist)));
334
    }
335

    
336
    private void drawCurrentScale(Graphics2D g, int i) {
337
        int footLength = 90;
338
        int x = this.scaleDomainToXDomain(currentScale);
339
        int y_min = indexDomainToYDomain(0) - 10;
340
        int y_max = indexDomainToYDomain(layerInfo.size()) + 18;
341

    
342
        Stroke old = g.getStroke();
343
        g.setStroke(new BasicStroke(1));
344
        g.setColor(scaleLineColor);
345
        g.drawLine(x, y_min, x, y_max);
346

    
347
        // little square
348
        int[] xp = { x - 1, x + 2, x + 2, x - 1 };
349
        int[] yp = { y_min - 1, y_min - 1, y_min + 2, y_min + 2 };
350
        g.fillPolygon(xp, yp, 4);
351

    
352
        if (currentScale > medScale) { // label to the left
353
            g.drawLine(x, y_max, x - footLength, y_max);
354
            g.setColor(LayerScaleData.darker(scaleLineColor));
355
            g.setFont(new Font(fontName, Font.BOLD, 12));
356
            g.drawString(PluginServices.getText(this, "current_scale"),
357
                x - footLength, y_max - 4);
358
        }
359
        else { // label to the right
360
            g.drawLine(x, y_max, x + 10, y_max);
361
            g.setColor(LayerScaleData.darker(scaleLineColor));
362
            g.setFont(new Font(fontName, Font.BOLD, 12));
363
            g.drawString(PluginServices.getText(this, "current_scale"), x + 15,
364
                y_max + 4);
365
        }
366

    
367
        g.setFont(new Font(fontName, Font.PLAIN, 12));
368
        g.setStroke(old);
369
    }
370

    
371
    private void drawLegend(Graphics2D g, int orx, int ory) {
372
        // width = 2 * margin + 2 * sampleW + labelW = 126 
373
        // height = 2 * margin + 4 * rowSep = 76
374
        int sampleW = 25;
375
        int margin = 8;
376
        int labelW = 60;
377

    
378
        // -----------------------------------------
379
        int correction = -2;
380
        int smpx = orx + margin + labelW;
381
        int smpy = ory + margin + (2 * rowSep) + (rowSep - rowHeight);
382
        int auxx;
383
        int auxy;
384

    
385
        g.setFont(new Font(fontName, Font.PLAIN, 12));
386

    
387
        auxx = orx + margin;
388
        auxy = ory + (2 * rowSep) + margin;
389
        g.setColor(Color.GRAY);
390
        g.drawString(PluginServices.getText(this, "type"), auxx,
391
            auxy + correction);
392

    
393
        auxy = auxy + rowSep;
394
        g.setColor(Color.BLACK);
395
        g.drawString(PluginServices.getText(this, "vectorial"), auxx, auxy);
396

    
397
        auxy = auxy + rowSep;
398
        g.drawString(PluginServices.getText(this, "raster"), auxx, auxy);
399

    
400
        auxx = orx + margin + labelW;
401
        auxy = ory + rowSep + margin;
402
        g.setColor(Color.GRAY);
403
        g.drawString(PluginServices.getText(this, "visible"), auxx,
404
            auxy + correction);
405

    
406
        auxy = auxy + rowSep;
407
        g.setFont(new Font(fontName, Font.PLAIN, 10));
408
        g.setColor(Color.BLACK);
409
        g.drawString(PluginServices.getText(this, "YES"), auxx,
410
            auxy + correction);
411

    
412
        auxx = auxx + sampleW;
413
        g.drawString(PluginServices.getText(this, "NO"), auxx, auxy +
414
            correction);
415

    
416
        // --------- samples ---------------------
417
        g.setColor(LayerScaleData.featYesColor);
418
        g.fillRect(smpx, smpy, sampleW, rowHeight);
419

    
420
        g.setColor(LayerScaleData.featNoColor);
421
        g.fillRect(smpx + sampleW, smpy, sampleW, rowHeight);
422

    
423
        g.setColor(LayerScaleData.imagYesColor);
424
        g.fillRect(smpx, smpy + rowSep, sampleW, rowHeight);
425

    
426
        g.setColor(LayerScaleData.imagNoColor);
427
        g.fillRect(smpx + sampleW, smpy + rowSep, sampleW, rowHeight);
428

    
429
        g.setColor(Color.BLACK);
430
        g.drawRect(orx, ory, (2 * margin) + (2 * sampleW) + labelW,
431
            (2 * margin) + (4 * rowSep));
432

    
433
        // ------------------------------------------
434
    }
435

    
436
    //        public void setLayerInfo(Vector v) {
437
    //                layerInfo = invertedVector(v);
438
    //        }
439
    public void setDpi(int dpi) {
440
        this.dpi = dpi;
441
    }
442

    
443
    /**
444
     *
445
     * @return Scale items shown on ruler
446
     */
447
    private rulerItem[] getRulerItems() {
448
        rulerItem[] ri = new rulerItem[12];
449
        ri[0] = new rulerItem(500);
450
        ri[1] = new rulerItem(2000);
451
        ri[2] = new rulerItem(5000);
452
        ri[3] = new rulerItem(10000);
453
        ri[4] = new rulerItem(25000);
454
        ri[5] = new rulerItem(50000);
455
        ri[6] = new rulerItem(100000);
456
        ri[7] = new rulerItem(250000);
457
        ri[8] = new rulerItem(500000);
458
        ri[9] = new rulerItem(1000000);
459
        ri[10] = new rulerItem(5000000);
460
        ri[11] = new rulerItem(10000000); // must be the same as 'private double maxScale'
461

    
462
        return ri;
463
    }
464

    
465
    private int getParentWidth() {
466
        if (parentDialog == null) {
467
            return parentDialogMinLimitForNormalTitle;
468
        }
469
        else {
470
            return parentDialog.getWidth();
471
        }
472
    }
473

    
474
    /**
475
     * Utility class used to allow tool tips.
476
     *
477
     * @author jldominguez
478
     *
479
     */
480
    public class LayerLabel extends JLabel {
481
        private static final long serialVersionUID = 0;
482
        private String theName = "";
483
        private String theId = "";
484

    
485
        public LayerLabel(String name, String id) {
486
            theName = name;
487
            theId = id;
488
            setToolTipText(toolTipString());
489
            setText(toString());
490
            setFont(new Font(fontName, Font.BOLD, 12));
491
        }
492

    
493
        public String toString() {
494
            if (theName.length() < 19) {
495
                return theName;
496
            }
497

    
498
            return theName.substring(0, 16) + "...";
499
        }
500

    
501
        public String toolTipString() {
502
            return "[" + theId + "] " + theName;
503
        }
504
    }
505

    
506
    private class rulerItem {
507
        private int scale;
508

    
509
        public rulerItem(int sc) {
510
            scale = sc;
511
        }
512

    
513
        public String getTag() {
514
            return intToAbbrev(scale);
515
        }
516

    
517
        public int getScale() {
518
            return scale;
519
        }
520

    
521
        public int getScaleInXDomain() {
522
            return scaleDomainToXDomain(1.0 * scale);
523
        }
524

    
525
        public int xAxisOffset() {
526
            return (getTag().length() * 4) + 3;
527
        }
528

    
529
        private String intToAbbrev(int n) {
530
            if (n >= 1000000) {
531
                return String.valueOf(n / 1000000) + " M";
532
            }
533

    
534
            return String.valueOf(n);
535
        }
536
    }
537
}