Revision 32592

View differences:

branches/v2_0_0_prep/extensions/org.gvsig.arcims.feature.extension/src/main/java/org/gvsig/arcims/feature/gui/panels/LayerScaleDrawPanel.java
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 org.gvsig.arcims.feature.gui.panels;
44

  
45
import java.awt.BasicStroke;
46
import java.awt.Color;
47
import java.awt.Font;
48
import java.awt.Graphics;
49
import java.awt.Graphics2D;
50
import java.awt.Stroke;
51
import java.awt.geom.AffineTransform;
52
import java.util.Vector;
53

  
54
import javax.swing.JLabel;
55
import javax.swing.JPanel;
56

  
57
import org.gvsig.andami.PluginServices;
58
import org.gvsig.arcims.feature.fmap.layers.LayerScaleData;
59
import org.gvsig.arcims.feature.gui.dialogs.LayerScaleDialog;
60

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

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

  
90
	// ----------------------------------------------------------------------------
91
	private double logDist = Math.log(maxScale) - Math.log(minScale);
92
	private String title = "";
93
	private double medScale;
94
	private JLabel updateLabel;
95

  
96
	/**
97
	 * @param info
98
	 *            this vector contains the layers' scale info
99
	 */
100
	public LayerScaleDrawPanel(Vector info, LayerScaleDialog dlg, JLabel ulabel) {
101
		super();
102
		parentDialog = dlg;
103
		updateLabel = ulabel;
104

  
105
		LayerScaleData theInfo;
106
		LayerLabel ll;
107
		currentScale = (float) 1.0;
108
		setBackground(Color.WHITE);
109
		setLayout(null);
110

  
111
		// layerInfo = invertedVector(info);
112
		layerInfo = copyVector(info, true);
113

  
114
		int size = info.size();
115

  
116
		for (int i = 0; i < size; i++) {
117
			theInfo = (LayerScaleData) layerInfo.get(i);
118
			ll = new LayerLabel(theInfo.getName(), theInfo.getId());
119

  
120
			ll.setBounds(5, indexDomainToYDomain(i), getLabelsWidth(),
121
					rowHeight);
122
			// ll.setBounds(5, indexDomainToYDomain((size - 1) - i),
123
			// getLabelsWidth(), rowHeight);
124

  
125
			layerLabelsVector.add(ll);
126
			add(ll);
127
		}
128

  
129
		layerInfo = copyVector(layerInfo, true);
130

  
131
		rulerItems = getRulerItems();
132
		medScale = Math.sqrt(maxScale * minScale);
133
		medScale = Math.sqrt(medScale * minScale);
134
	}
135

  
136
	/**
137
	 * 
138
	 * @param info
139
	 */
140
	public void resetInfo(Vector info) {
141
		layerLabelsVector.removeAllElements();
142
		removeAll();
143

  
144
		layerInfo = info;
145

  
146
		LayerScaleData theInfo;
147
		LayerLabel ll;
148
		int size = info.size();
149

  
150
		for (int i = 0; i < size; i++) {
151
			theInfo = (LayerScaleData) layerInfo.get(i);
152
			ll = new LayerLabel(theInfo.getName(), theInfo.getId());
153
			ll.setBounds(5, indexDomainToYDomain((size - 1) - i),
154
					getLabelsWidth(), rowHeight);
155
			layerLabelsVector.add(ll);
156
			add(ll);
157
		}
158
	}
159

  
160
	/**
161
	 * 
162
	 * @param v
163
	 * @param inverted
164
	 * @return
165
	 */
166
	private Vector copyVector(Vector v, boolean inverted) {
167
		Vector res = new Vector();
168

  
169
		if (inverted) {
170
			for (int i = (v.size() - 1); i >= 0; i--)
171
				res.add(v.get(i));
172
		} else {
173
			for (int i = 0; i < v.size(); i++)
174
				res.add(v.get(i));
175
		}
176

  
177
		return res;
178
	}
179

  
180
	/**
181
	 * Sets current scale (it is represented as a vertical line)
182
	 * 
183
	 * @param s
184
	 */
185
	public void setCurrentScale(double s) {
186
		currentScale = (float) s;
187
		updateLabel.setText(PluginServices.getText(this, "Escala")
188
				+ "  1 : "
189
				+ LayerScaleDialog
190
						.getFormattedInteger(Math.round(currentScale)));
191
	}
192

  
193
	/**
194
	 * 
195
	 * @param s
196
	 */
197
	public void setCurrentScale(float s) {
198
		currentScale = s;
199
		updateLabel.setText(PluginServices.getText(this, "Escala")
200
				+ "  1 : "
201
				+ LayerScaleDialog
202
						.getFormattedInteger(Math.round(currentScale)));
203
	}
204

  
205
	/**
206
	 * 
207
	 * @return
208
	 */
209
	public float getCurrentScale() {
210
		return currentScale;
211
	}
212

  
213
	private int getLabelsWidth() {
214
		return minScaleX - margin - 5;
215
	}
216

  
217
	public void paint(Graphics g) {
218
		super.paint(g);
219

  
220
		Graphics2D g2d = (Graphics2D) g;
221

  
222
		maxScaleX = getWidth() - 20;
223

  
224
		if (getParentWidth() < parentDialogMinLimitForNormalTitle) {
225
			if (getParentWidth() < parentDialogMinLimitForShortTitle) {
226
				setEmptyTitle();
227
			} else {
228
				setShortTitle();
229
			}
230
		} else {
231
			setNormalTitle();
232
		}
233

  
234
		drawTitle(g2d);
235

  
236
		g2d.setStroke(new BasicStroke(1));
237
		g2d.setFont(new Font(fontName, Font.PLAIN, 12));
238

  
239
		int size = layerInfo.size();
240

  
241
		for (int i = 0; i < size; i++) {
242
			LayerScaleData info = (LayerScaleData) layerInfo.get(i);
243

  
244
			int x_min;
245
			int y_min;
246
			int w;
247
			int x_max = this.scaleDomainToXDomain(Math.pow(10.0, 9.0));
248

  
249
			x_min = scaleDomainToXDomain(info.getMinSc());
250
			w = scaleDomainToXDomain(info.getMaxSc()) - x_min;
251
			// y_min = indexDomainToYDomain(i);
252

  
253
			y_min = indexDomainToYDomain((size - 1) - i);
254

  
255
			g2d.setColor(carrilColor);
256
			g2d.fillRect((minScaleX - margin), y_min, x_max
257
					- (minScaleX - margin), rowHeight);
258

  
259
			g2d.setColor(info.getColor(currentScale));
260
			g2d.fillRect(x_min, y_min, w, rowHeight);
261

  
262
			g2d.setColor(Color.BLACK);
263
		}
264

  
265
		drawRuler(g2d, size);
266
		drawCurrentScale(g2d, size);
267

  
268
		int x = Math.min(getWidth() - 136,
269
				((getParentWidth() - parentDialogMinLimitForNormalTitle) / 2)
270
						+ (parentDialogMinLimitForNormalTitle - 136));
271
		drawLegend(g2d, x, 10);
272
	}
273

  
274
	private void setEmptyTitle() {
275
		title = "";
276
	}
277

  
278
	private void setNormalTitle() {
279
		title = PluginServices.getText(this, "scale_limits_status");
280
	}
281

  
282
	private void setShortTitle() {
283
		title = PluginServices.getText(this, "scale_limits");
284
	}
285

  
286
	private void drawTitle(Graphics2D g) {
287
		g.setColor(Color.GRAY);
288
		g.setFont(new Font(fontName, Font.BOLD, 20));
289
		g.drawString(title, 20, 55);
290
	}
291

  
292
	private void drawRuler(Graphics2D g, int i) {
293
		g.setColor(Color.DARK_GRAY);
294

  
295
		int x_min = this.scaleDomainToXDomain(minScale - 1.0);
296
		int x_max = this.scaleDomainToXDomain(maxScale + 1.0);
297
		int y = this.indexDomainToYDomain(0) - 10;
298
		int offsetFromTagsToRuler = 8;
299

  
300
		g.drawLine(x_min, y, x_max, y);
301

  
302
		// arrows
303
		int[] xp = { x_min - 2, x_min + 5, x_min + 5 };
304
		int[] yp = { y, y - 3, y + 3 };
305
		g.fillPolygon(xp, yp, 3);
306

  
307
		int[] x2p = { x_max + 2, x_max - 5, x_max - 5 };
308
		g.fillPolygon(x2p, yp, 3);
309

  
310
		// ---------------- scale label -------------------------
311
		g.setFont(new Font(fontName, Font.BOLD, 12));
312
		g.drawString(PluginServices.getText(this, "the_scale"), 20, y - 44);
313
		g.drawString("(DPI = " + dpi + ")", 20, (y + 12) - 44);
314
		g.setFont(new Font(fontName, Font.PLAIN, 12));
315

  
316
		// ------------------------------------------------------
317
		rulerItem ruIt;
318

  
319
		g.drawString("1:", scaleDomainToXDomain(minScale) - 30, y
320
				- offsetFromTagsToRuler);
321

  
322
		AffineTransform oldt = g.getTransform();
323
		AffineTransform newt;
324
		AffineTransform rott;
325
		AffineTransform trat;
326
		double angulo = -65.0;
327

  
328
		for (int ind = 0; ind < rulerItems.length; ind++) {
329
			ruIt = this.rulerItems[ind];
330
			g.drawLine(ruIt.getScaleInXDomain(), y - 3, ruIt
331
					.getScaleInXDomain(), y + 3);
332

  
333
			int strx = ruIt.getScaleInXDomain();
334
			int stry = y - offsetFromTagsToRuler;
335
			trat = AffineTransform.getTranslateInstance(1.0 * strx, 1.0 * stry);
336
			rott = AffineTransform
337
					.getRotateInstance((angulo * 3.1415926) / 180.0);
338
			newt = (AffineTransform) oldt.clone();
339
			newt.concatenate(trat);
340
			newt.concatenate(rott);
341
			g.setTransform(newt);
342
			g.drawString(ruIt.getTag(), 0, 0);
343
			g.setTransform(oldt);
344
		}
345
	}
346

  
347
	private int indexDomainToYDomain(int i) {
348
		return Math.round((float) (158.0 + (rowSep * i)));
349
	}
350

  
351
	private int scaleDomainToXDomain(double d) {
352
		if (d < minScale) {
353
			return minScaleX - margin;
354
		}
355

  
356
		if (d > maxScale) {
357
			return maxScaleX + margin;
358
		}
359

  
360
		double dist = Math.log(d) - Math.log(minScale);
361

  
362
		return Math
363
				.round((float) ((1.0 * minScaleX) + ((dist * (maxScaleX - minScaleX)) / logDist)));
364
	}
365

  
366
	private void drawCurrentScale(Graphics2D g, int i) {
367
		int footLength = 90;
368
		int x = this.scaleDomainToXDomain(currentScale);
369
		int y_min = indexDomainToYDomain(0) - 10;
370
		int y_max = indexDomainToYDomain(layerInfo.size()) + 18;
371

  
372
		Stroke old = g.getStroke();
373
		g.setStroke(new BasicStroke(1));
374
		g.setColor(scaleLineColor);
375
		g.drawLine(x, y_min, x, y_max);
376

  
377
		// little square
378
		int[] xp = { x - 1, x + 2, x + 2, x - 1 };
379
		int[] yp = { y_min - 1, y_min - 1, y_min + 2, y_min + 2 };
380
		g.fillPolygon(xp, yp, 4);
381

  
382
		if (currentScale > medScale) { // label to the left
383
			g.drawLine(x, y_max, x - footLength, y_max);
384
			g.setColor(LayerScaleData.darker(scaleLineColor));
385
			g.setFont(new Font(fontName, Font.BOLD, 12));
386
			g.drawString(PluginServices.getText(this, "current_scale"), x
387
					- footLength, y_max - 4);
388
		} else { // label to the right
389
			g.drawLine(x, y_max, x + 10, y_max);
390
			g.setColor(LayerScaleData.darker(scaleLineColor));
391
			g.setFont(new Font(fontName, Font.BOLD, 12));
392
			g.drawString(PluginServices.getText(this, "current_scale"), x + 15,
393
					y_max + 4);
394
		}
395

  
396
		g.setFont(new Font(fontName, Font.PLAIN, 12));
397
		g.setStroke(old);
398
	}
399

  
400
	private void drawLegend(Graphics2D g, int orx, int ory) {
401
		// width = 2 * margin + 2 * sampleW + labelW = 126
402
		// height = 2 * margin + 4 * rowSep = 76
403
		int sampleW = 25;
404
		int margin = 8;
405
		int labelW = 60;
406

  
407
		// -----------------------------------------
408
		int correction = -2;
409
		int smpx = orx + margin + labelW;
410
		int smpy = ory + margin + (2 * rowSep) + (rowSep - rowHeight);
411
		int auxx;
412
		int auxy;
413

  
414
		g.setFont(new Font(fontName, Font.PLAIN, 12));
415

  
416
		auxx = orx + margin;
417
		auxy = ory + (2 * rowSep) + margin;
418
		g.setColor(Color.GRAY);
419
		g.drawString(PluginServices.getText(this, "type"), auxx, auxy
420
				+ correction);
421

  
422
		auxy = auxy + rowSep;
423
		g.setColor(Color.BLACK);
424
		g.drawString(PluginServices.getText(this, "vectorial"), auxx, auxy);
425

  
426
		auxy = auxy + rowSep;
427
		g.drawString(PluginServices.getText(this, "raster"), auxx, auxy);
428

  
429
		auxx = orx + margin + labelW;
430
		auxy = ory + rowSep + margin;
431
		g.setColor(Color.GRAY);
432
		g.drawString(PluginServices.getText(this, "visible"), auxx, auxy
433
				+ correction);
434

  
435
		auxy = auxy + rowSep;
436
		g.setFont(new Font(fontName, Font.PLAIN, 10));
437
		g.setColor(Color.BLACK);
438
		g.drawString(PluginServices.getText(this, "YES"), auxx, auxy
439
				+ correction);
440

  
441
		auxx = auxx + sampleW;
442
		g.drawString(PluginServices.getText(this, "NO"), auxx, auxy
443
				+ correction);
444

  
445
		// --------- samples ---------------------
446
		g.setColor(LayerScaleData.featYesColor);
447
		g.fillRect(smpx, smpy, sampleW, rowHeight);
448

  
449
		g.setColor(LayerScaleData.featNoColor);
450
		g.fillRect(smpx + sampleW, smpy, sampleW, rowHeight);
451

  
452
		g.setColor(LayerScaleData.imagYesColor);
453
		g.fillRect(smpx, smpy + rowSep, sampleW, rowHeight);
454

  
455
		g.setColor(LayerScaleData.imagNoColor);
456
		g.fillRect(smpx + sampleW, smpy + rowSep, sampleW, rowHeight);
457

  
458
		g.setColor(Color.BLACK);
459
		g.drawRect(orx, ory, (2 * margin) + (2 * sampleW) + labelW,
460
				(2 * margin) + (4 * rowSep));
461

  
462
		// ------------------------------------------
463
	}
464

  
465
	// public void setLayerInfo(Vector v) {
466
	// layerInfo = invertedVector(v);
467
	// }
468
	public void setDpi(int dpi) {
469
		this.dpi = dpi;
470
	}
471

  
472
	/**
473
	 * 
474
	 * @return Scale items shown on ruler
475
	 */
476
	private rulerItem[] getRulerItems() {
477
		rulerItem[] ri = new rulerItem[12];
478
		ri[0] = new rulerItem(500);
479
		ri[1] = new rulerItem(2000);
480
		ri[2] = new rulerItem(5000);
481
		ri[3] = new rulerItem(10000);
482
		ri[4] = new rulerItem(25000);
483
		ri[5] = new rulerItem(50000);
484
		ri[6] = new rulerItem(100000);
485
		ri[7] = new rulerItem(250000);
486
		ri[8] = new rulerItem(500000);
487
		ri[9] = new rulerItem(1000000);
488
		ri[10] = new rulerItem(5000000);
489
		ri[11] = new rulerItem(10000000); // must be the same as 'private double
490
											// maxScale'
491

  
492
		return ri;
493
	}
494

  
495
	private int getParentWidth() {
496
		if (parentDialog == null) {
497
			return parentDialogMinLimitForNormalTitle;
498
		} else {
499
			return parentDialog.getWidth();
500
		}
501
	}
502

  
503
	/**
504
	 * Utility class used to allow tool tips.
505
	 * 
506
	 * @author jldominguez
507
	 * 
508
	 */
509
	public class LayerLabel extends JLabel {
510
		private static final long serialVersionUID = 0;
511
		private String theName = "";
512
		private String theId = "";
513

  
514
		public LayerLabel(String name, String id) {
515
			theName = name;
516
			theId = id;
517
			setToolTipText(toolTipString());
518
			setText(toString());
519
			setFont(new Font(fontName, Font.BOLD, 12));
520
		}
521

  
522
		public String toString() {
523
			if (theName.length() < 19) {
524
				return theName;
525
			}
526

  
527
			return theName.substring(0, 16) + "...";
528
		}
529

  
530
		public String toolTipString() {
531
			return "[" + theId + "] " + theName;
532
		}
533
	}
534

  
535
	private class rulerItem {
536
		private int scale;
537

  
538
		public rulerItem(int sc) {
539
			scale = sc;
540
		}
541

  
542
		public String getTag() {
543
			return intToAbbrev(scale);
544
		}
545

  
546
		public int getScale() {
547
			return scale;
548
		}
549

  
550
		public int getScaleInXDomain() {
551
			return scaleDomainToXDomain(1.0 * scale);
552
		}
553

  
554
		public int xAxisOffset() {
555
			return (getTag().length() * 4) + 3;
556
		}
557

  
558
		private String intToAbbrev(int n) {
559
			if (n >= 1000000) {
560
				return String.valueOf(n / 1000000) + " M";
561
			}
562

  
563
			return String.valueOf(n);
564
		}
565
	}
566
}

Also available in: Unified diff