Revision 22867

View differences:

trunk/extensions/extSymbology/src/org/gvsig/symbology/gui/layerproperties/ProportionalSymbols.java
1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2005 IVER T.I. 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
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41
package org.gvsig.symbology.gui.layerproperties;
42

  
43
import java.awt.BorderLayout;
44
import java.awt.Color;
45
import java.awt.Dimension;
46
import java.awt.FlowLayout;
47
import java.awt.event.ActionEvent;
48
import java.awt.event.ActionListener;
49
import java.sql.Types;
50

  
51
import javax.swing.BorderFactory;
52
import javax.swing.DefaultComboBoxModel;
53
import javax.swing.ImageIcon;
54
import javax.swing.JComboBox;
55
import javax.swing.JLabel;
56
import javax.swing.JPanel;
57

  
58
import org.apache.log4j.Logger;
59
import org.gvsig.gui.beans.swing.GridBagLayoutPanel;
60
import org.gvsig.gui.beans.swing.JBlank;
61
import org.gvsig.gui.beans.swing.JIncrementalNumberField;
62
import org.gvsig.symbology.fmap.rendering.ProportionalSymbolsLegend;
63
import org.gvsig.symbology.fmap.symbols.MarkerFillSymbol;
64

  
65
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
66
import com.hardcode.gdbms.engine.data.DataSource;
67
import com.hardcode.gdbms.engine.values.Value;
68
import com.hardcode.gdbms.engine.values.ValueFactory;
69
import com.iver.andami.PluginServices;
70
import com.iver.andami.messages.NotificationManager;
71
import com.iver.cit.gvsig.fmap.core.FShape;
72
import com.iver.cit.gvsig.fmap.core.SymbologyFactory;
73
import com.iver.cit.gvsig.fmap.core.styles.IMarkerFillPropertiesStyle;
74
import com.iver.cit.gvsig.fmap.core.symbols.ILineSymbol;
75
import com.iver.cit.gvsig.fmap.core.symbols.IMarkerSymbol;
76
import com.iver.cit.gvsig.fmap.core.symbols.ISymbol;
77
import com.iver.cit.gvsig.fmap.core.symbols.SimpleLineSymbol;
78
import com.iver.cit.gvsig.fmap.core.symbols.SimpleMarkerSymbol;
79
import com.iver.cit.gvsig.fmap.layers.FLayer;
80
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
81
import com.iver.cit.gvsig.fmap.layers.layerOperations.AlphanumericData;
82
import com.iver.cit.gvsig.fmap.layers.layerOperations.ClassifiableVectorial;
83
import com.iver.cit.gvsig.fmap.rendering.ILegend;
84
import com.iver.cit.gvsig.project.documents.view.legend.gui.ILegendPanel;
85
import com.iver.cit.gvsig.project.documents.view.legend.gui.JSymbolPreviewButton;
86
import com.iver.cit.gvsig.project.documents.view.legend.gui.Quantities;
87

  
88

  
89
/**
90
 * Implements the panel for the legend of proportional symbols.In the interface will be 
91
 * options to select the value field, the normalization field (if the user wants to use it) and 
92
 * options to select the symbol an its minimum and maximum size.
93
 * 
94
 * Also there will be possible to select a background symbol (only when the shapetype of the layer is
95
 * polygonal). 
96
 * 
97
 * @author jaume dominguez faus - jaume.dominguez@iver.es
98
 */
99
public class ProportionalSymbols extends JPanel implements ILegendPanel{
100
	private static final long serialVersionUID = 7394720230276170902L;
101
	private JPanel symbolPanel;
102
	private JPanel backgroundPanel;
103
	private JSymbolPreviewButton tmplateSymbol;
104
	private JSymbolPreviewButton backSymbol;
105
	private JComboBox cmbValue;
106
	private JComboBox cmbNormalization;
107
	private JIncrementalNumberField txtMinSize;
108
	private JIncrementalNumberField txtMaxSize;
109
	private static Logger logger = Logger.getLogger(ProportionalSymbols.class.getName());
110
	private ClassifiableVectorial myLayer;
111
	private ProportionalSymbolsLegend theLegend;
112
	private String[] fieldNames;
113
	private int templateShapeType = 0 ;
114
	private String noNormalization = PluginServices.getText(this, "none");
115
	private boolean useNormalization = true;
116

  
117
	/**
118
	 * Default constructor
119
	 */
120
	public ProportionalSymbols() {
121
		initialize();
122
	}
123

  
124
	/**
125
	 * This method initializes this
126
	 */
127
	private void initialize() {
128

  
129
		setLayout(new BorderLayout());
130
		JPanel aux = new JPanel(new BorderLayout());
131

  
132
		JPanel fieldsPanel = new JPanel(new FlowLayout());
133
		fieldsPanel.setBorder(BorderFactory.
134
				createTitledBorder(null,
135
						PluginServices.getText(this, "fields")));
136
		fieldsPanel.setPreferredSize(new Dimension(300,60));
137

  
138
		cmbValue = new JComboBox();
139
		cmbValue.setActionCommand("VALUE_SELECTED");
140

  
141
		cmbNormalization = new JComboBox();
142
		cmbNormalization.setActionCommand("NORMALIZATION_SELECTED");
143

  
144
		fieldsPanel.add(new JLabel(PluginServices.getText(this, "value")+":" ));
145
		fieldsPanel.add(cmbValue);
146

  
147
		fieldsPanel.add(new JLabel(PluginServices.getText(this, "normalization")+":" ));
148
		fieldsPanel.add(cmbNormalization);
149

  
150

  
151
		symbolPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 3,2));
152
		symbolPanel.setBorder(BorderFactory.
153
				createTitledBorder(null,
154
						PluginServices.getText(this, "symbol")));
155

  
156
		GridBagLayoutPanel aux2 = new GridBagLayoutPanel();
157
		aux2.addComponent(new JLabel(PluginServices.getText(this, "size")));
158
		aux2.addComponent(new JBlank(10,10));
159
		aux2.addComponent(PluginServices.getText(this, "from")+":",
160
				getTxtMinSize());
161
		aux2.addComponent(PluginServices.getText(this, "to")+":",
162
				getTxtMaxSize());
163

  
164
		JPanel templatePanel = new JPanel();
165
		templatePanel.setBorder(BorderFactory.createTitledBorder(null,
166
				PluginServices.getText(this, "template")));
167
		templatePanel.add(getTemplSymbol());
168
		symbolPanel.add(new JBlank(10,10));
169
		symbolPanel.add(aux2);
170
		symbolPanel.add(new JBlank(10,10));
171
		symbolPanel.add(templatePanel);
172

  
173
		aux.add(fieldsPanel, BorderLayout.NORTH);
174
		aux.add(symbolPanel, BorderLayout.CENTER);
175
		
176
		this.add(aux, BorderLayout.CENTER);
177

  
178
		cmbValue.addActionListener(action);
179
		cmbNormalization.addActionListener(action);
180
		tmplateSymbol.addActionListener(action);
181
	}
182
	/**
183
	 * Creates the panel where the button for the background symbol will be placed
184
	 *
185
	 * @return JPanel panel
186
	 */
187

  
188
	private JPanel getBackgroundPanel() {
189
		backgroundPanel = new JPanel();
190
		backgroundPanel.setBorder(BorderFactory.createTitledBorder(null,
191
				PluginServices.getText(this, "background")));
192
		backgroundPanel.add(getBtnBackground());
193
		return backgroundPanel;
194
	}
195
	/**
196
	 * Creates a JIncrementalNumberField which is used to select the maximum size for the symbol
197
	 *  
198
	 * @return JIncrementalNumberField
199
	 */
200
	private JIncrementalNumberField getTxtMaxSize() {
201
		if (txtMaxSize == null) {
202
			txtMaxSize = new JIncrementalNumberField(String.valueOf(25), 7,0,100,1);
203
			txtMaxSize.addActionListener(action);
204
		}
205
		return txtMaxSize;
206
	}
207
	/**
208
	 * Creates a JIncrementalNumberField which is used to select the minimum size for the symbol
209
	 *  
210
	 * @return JIncrementalNumberField
211
	 */
212
	private JIncrementalNumberField getTxtMinSize() {
213
		if (txtMinSize == null) {
214
			txtMinSize = new JIncrementalNumberField(String.valueOf(3), 7,0,100,1);
215
			txtMinSize.addActionListener(action);
216
		}
217
		return txtMinSize;
218
	}
219
	/**
220
	 * Creates a JSymbolPreviewButton which is used to select the template symbol
221
	 *  
222
	 * @return JSymbolPreviewButton
223
	 */
224
	private JSymbolPreviewButton getTemplSymbol() {
225

  
226
		if (tmplateSymbol == null) {
227
			int templateShapeType = (this.templateShapeType == FShape.POLYGON) ? FShape.POINT : this.templateShapeType; 
228
			tmplateSymbol = new JSymbolPreviewButton(templateShapeType);
229
		}	
230
		tmplateSymbol.setPreferredSize(new Dimension(100, 45));
231
		return tmplateSymbol;
232
	}
233
	/**
234
	 * Creates a JSymbolPreviewButton which is used to select the background symbol
235
	 *  
236
	 * @return JSymbolPreviewButton
237
	 */
238
	private JSymbolPreviewButton getBtnBackground() {
239
		if (backSymbol == null) { 
240
			backSymbol = new JSymbolPreviewButton(FShape.POLYGON);
241
			backSymbol.setPreferredSize(new Dimension(100, 45));
242
		}
243
		return backSymbol;
244
	}
245
	/**
246
	 * Creates a new symbol of an specific shapetype with a concrete size
247
	 * 
248
	 * @param shapeType
249
	 * @param size
250
	 * 
251
	 * @return ISymbol symbol created
252
	 */
253
	private ISymbol newSymbol(int shapeType, double size) {
254
		if (getTemplSymbol().getSymbol() == null) {
255
			ISymbol templateSymbol;
256
			switch (shapeType) {
257
			case FShape.POINT:
258
			case FShape.POLYGON:
259
				templateSymbol = new SimpleMarkerSymbol();
260
				((SimpleMarkerSymbol) templateSymbol).setSize(size);
261
				((SimpleMarkerSymbol) templateSymbol).setColor(Color.DARK_GRAY);
262
				break;
263

  
264
			case FShape.LINE:
265
				templateSymbol = new SimpleLineSymbol();
266
				((SimpleLineSymbol) templateSymbol).setLineWidth(size);
267
				((SimpleLineSymbol) templateSymbol).setLineColor(Color.DARK_GRAY);
268
				break;
269
			default:
270
				throw new Error("Unknown symbol type");
271
			}
272
			getTemplSymbol().setSymbol(templateSymbol);
273
			return newSymbol(shapeType, size);
274
		} else {
275
			// clone symbol
276
			ISymbol mySymbol = SymbologyFactory.createSymbolFromXML(
277
					getTemplSymbol().getSymbol().getXMLEntity(), null);
278

  
279
			if (mySymbol instanceof ILineSymbol) {
280
				ILineSymbol lSym = (ILineSymbol) mySymbol;
281
				lSym.setLineWidth(size);
282

  
283
			}
284
			if (mySymbol instanceof IMarkerSymbol) {
285
				IMarkerSymbol mSym = (IMarkerSymbol) mySymbol;
286
				mSym.setSize(size);
287
				if (shapeType == FShape.POLYGON) {
288
					// this is to allow using in Polygon layers
289
					MarkerFillSymbol fillSymbol = new MarkerFillSymbol();
290
					fillSymbol.setOutline(null);
291
					fillSymbol.setFillColor(null);
292
					fillSymbol.getMarkerFillProperties().
293
					setFillStyle(IMarkerFillPropertiesStyle.SINGLE_CENTERED_SYMBOL);
294
					fillSymbol.setMarker(mSym);
295
				}
296
			}
297
			return mySymbol;
298
		}
299
	}
300

  
301
	/**
302
	 * Fills the comboboxes that are placed in the panel with the classifying field names of the layer 
303
	 * which contain numerical information
304
	 *   
305
	 */
306
	private void fillFieldNames() {
307
		DataSource rs;
308

  
309
		try {
310
			rs = ((AlphanumericData) myLayer).getRecordset();
311
			logger.debug("rs.start()");
312
			rs.start();
313

  
314
			int cont = 0;
315
			for (int i = 0; i < rs.getFieldCount(); i++) {
316
				if(isNumericField(rs.getFieldType(i)))
317
					cont++;
318
			}
319
			String[] nomFields = new String[cont];
320

  
321
			cont = 0;
322
			for (int i = 0; i < rs.getFieldCount(); i++) {
323
				if (isNumericField(rs.getFieldType(i))) {
324
					nomFields[cont] = rs.getFieldName(i).trim();
325
					cont++;
326
				}
327
			}
328

  
329
			rs.stop();
330
			this.fieldNames = nomFields;
331

  
332
			DefaultComboBoxModel cMValue = new DefaultComboBoxModel(this.fieldNames);
333
			DefaultComboBoxModel cMNormalization = new DefaultComboBoxModel(this.fieldNames);
334
			cmbValue.setModel(cMValue);
335
			cmbNormalization.setModel(cMNormalization);
336
			cmbNormalization.addItem(noNormalization);
337

  
338
		} catch (ReadDriverException e) {
339
			NotificationManager.addError(PluginServices.getText(this, "recovering_recordset"), e);
340
		}
341
	}
342

  
343

  
344
	public void setData(FLayer lyr, ILegend legend) {
345

  
346
		this.myLayer = (ClassifiableVectorial) lyr;
347

  
348
		fillFieldNames();
349

  
350
		try {
351
			templateShapeType = (this.myLayer.getShapeType() == FShape.POLYGON) ? FShape.POINT : this.myLayer.getShapeType();
352
			getTemplSymbol().setShapeType(templateShapeType);
353

  
354
			if(myLayer.getShapeType() == FShape.POLYGON && backgroundPanel == null)
355
				symbolPanel.add(getBackgroundPanel());
356

  
357
		} catch (ReadDriverException e) {
358
			NotificationManager.addError(PluginServices.getText(this, "error accessing to the layer"), e);
359
		} 
360

  
361
		if (ProportionalSymbolsLegend.class.equals(legend.getClass())) {
362

  
363
			theLegend = (ProportionalSymbolsLegend) legend;
364
			cmbValue.setSelectedItem(theLegend.getClassifyingFieldNames()[0]);
365
			ISymbol defSymbol = theLegend.getDefaultSymbol();
366
			
367
			if(((ProportionalSymbolsLegend) theLegend).getUseNormalization())
368
				cmbNormalization.setSelectedItem(theLegend.getClassifyingFieldNames()[1]);
369
			else cmbNormalization.setSelectedItem(noNormalization);
370

  
371
			txtMaxSize.setDouble(theLegend.getMaxSize());
372
			txtMinSize.setDouble(theLegend.getMinSize());
373
			
374
			getTemplSymbol().setSymbol(defSymbol);
375

  
376
			if(((ProportionalSymbolsLegend) theLegend).getBackgroundSymbol() != null)
377
				getBtnBackground().setSymbol(((ProportionalSymbolsLegend) theLegend).getBackgroundSymbol());
378
			
379
			action.actionPerformed(new ActionEvent(txtMinSize, 0, "no_hace_falta"));
380

  
381
		} else {
382

  
383
			theLegend = new ProportionalSymbolsLegend();
384
			theLegend.setTemplateShapeType(templateShapeType);
385
			theLegend.setDefaultSymbol(newSymbol(templateShapeType, templateShapeType == FShape.LINE ? 3 : 10));
386
			getTemplSymbol().setSymbol(theLegend.getDefaultSymbol());
387
			if(templateShapeType == FShape.LINE) {
388
				txtMinSize.setDouble(3);
389
				txtMaxSize.setDouble(3);
390
			}
391

  
392
			else {
393
				txtMinSize.setDouble(10);
394
				txtMaxSize.setDouble(10);
395
			}
396
		}
397

  
398
	}
399

  
400

  
401
	public ILegend getLegend() {
402

  
403
		String[] fieldNames = new String[2];
404
		fieldNames[0]= cmbValue.getSelectedItem().toString();
405

  
406
		if(!useNormalization)
407
			fieldNames[1]= fieldNames[0];
408
		else fieldNames[1]= cmbNormalization.getSelectedItem().toString();
409

  
410
		ProportionalSymbolsLegend l = new ProportionalSymbolsLegend();
411

  
412
		l.setTemplateShapeType(templateShapeType);
413
		l.setValueField(cmbValue.getSelectedItem().toString());
414
		l.setNormalizationField(cmbNormalization.getSelectedItem().toString());
415
		l.setUseNormalization(useNormalization);
416

  
417
		l.setMinSize(txtMinSize.getDouble());
418
		l.setMaxSize(txtMaxSize.getDouble());
419

  
420
		ISymbol symbol = getTemplSymbol().getSymbol();
421
		symbol.setDescription(getSymbolDescription());
422
		l.setDefaultSymbol(symbol);
423
		l.addSymbol(ValueFactory.createValue("defaultSymbol"), symbol);
424

  
425
		l.setBackgroundSymbol(getBtnBackground().getSymbol());
426
		l.setClassifyingFieldNames(fieldNames);
427

  
428
		DataSource recordSet = null;
429

  
430

  
431
		try {
432
			recordSet = ((AlphanumericData) myLayer).getRecordset();
433

  
434
			for (int i = 0; i < fieldNames.length; i++) {
435
				double min = 0, max = 0;
436

  
437
				for (int j = 0; j < recordSet.getRowCount(); j++) {
438
					Value val = recordSet.getFieldValue(j, recordSet.getFieldIndexByName(fieldNames[i]));
439
					double dob = Double.valueOf(val.toString());
440
					if (dob < min) min = dob;
441
					if (dob > max) max = dob;
442
				}
443
				if(i == 0) {
444
					l.setMinFeature(min);
445
					l.setMaxFeature(max);
446
				}
447
			}
448

  
449
		} catch (ReadDriverException e) {
450
			NotificationManager.addError("error_accessing_to_the_layer",e);
451
		}
452

  
453
		return l;
454
	}
455
	/**
456
	 * Creates the String which will be the description of the symbol. If the selected normalization field  
457
	 * is not "None", then the String created will have this structure ValueField/NormalizationField. Else, 
458
	 * if the user select "None" for the normalization field,the string will show the ValueField only.
459
	 * 
460
	 * @return String	description for the symbol
461
	 */
462

  
463
	private String getSymbolDescription() {
464
		String description = "";
465

  
466
		if (cmbValue.getSelectedItem() != null)
467
			description += cmbValue.getSelectedItem().toString();
468
		if (cmbNormalization.getSelectedItem().toString().compareTo(noNormalization) != 0 )
469
			description += " / "+cmbNormalization.getSelectedItem().toString();
470

  
471
		return description;
472
	}
473

  
474
	public String getDescription() {
475
		return PluginServices.getText(this, "draw_quantities_using_symbol_size_to_show_exact_values");
476
	}
477

  
478
	public ImageIcon getIcon() {
479
		// TODO Implement it
480
		return null;
481
	}
482

  
483
	public Class getParentClass() {
484
		return Quantities.class;
485
	}
486

  
487
	public String getTitle() {
488
		return PluginServices.getText(this, "proportional_symbols");
489
	}
490

  
491
	public Class getLegendClass() {
492
		return ProportionalSymbolsLegend.class;
493
	}
494
	/**
495
	 * Checks if an specific field contains numerical data
496
	 * 
497
	 * @param fieldType	index of the field
498
	 * 
499
	 * @return boolean	true or false depending on the type of data (numerical or not)
500
	 */
501
	private boolean isNumericField(int fieldType) {
502
		switch (fieldType) {
503
		case Types.BIGINT:
504
		case Types.DECIMAL:
505
		case Types.DOUBLE:
506
		case Types.FLOAT:
507
		case Types.INTEGER:
508
		case Types.NUMERIC:
509
		case Types.REAL:
510
		case Types.SMALLINT:
511
		case Types.TINYINT:
512
			return true;
513
		default:
514
			return false;
515
		}
516

  
517
	}
518
	public boolean isSuitableFor(FLayer layer) {
519
		FLyrVect lVect = (FLyrVect) layer;
520
		try {
521
			return lVect.getShapeType() != FShape.MULTI;
522
		} catch (ReadDriverException e) {
523
			return false;
524
		}
525
	}
526

  
527

  
528
	public JPanel getPanel() {
529
		return this;
530
	}
531

  
532

  
533
	private ActionListener action = new ActionListener() {
534

  
535
		public void actionPerformed(ActionEvent e) {
536

  
537
			if (e.getSource().equals(cmbValue)) {
538
				JComboBox cb = (JComboBox) e.getSource();
539
				theLegend.setValueField(cb.getSelectedItem().toString());
540
			}
541
			if (e.getSource().equals(cmbNormalization)) {
542
				JComboBox cb = (JComboBox) e.getSource();
543
				if(cb.getSelectedItem().toString().compareTo(noNormalization) == 0) {
544
					useNormalization = false;
545
					theLegend.setNormalizationField(cmbValue.getSelectedItem().toString());
546
				}
547
				else {
548
					useNormalization = true;
549
					theLegend.setNormalizationField(cb.getSelectedItem().toString());
550
				}
551
				theLegend.setUseNormalization(useNormalization);
552
			}
553
			if (e.getSource().equals(txtMinSize)) {				
554
				ISymbol sym = tmplateSymbol.getSymbol();
555
				if(sym != null) {
556
					if(sym instanceof ILineSymbol) {
557
						ILineSymbol line = (ILineSymbol)sym;
558
						line.setLineWidth(txtMinSize.getDouble());
559
						tmplateSymbol.setSymbol(line);
560
					}
561

  
562
					if(sym instanceof IMarkerSymbol) {
563
						IMarkerSymbol point = (IMarkerSymbol)sym;
564
						point.setSize(txtMinSize.getDouble());
565
						tmplateSymbol.setSymbol(point);
566
					}
567
					tmplateSymbol.repaint();
568
				}
569

  
570
				if(txtMaxSize.getDouble() < txtMinSize.getDouble())
571
					txtMaxSize.setDouble(txtMinSize.getDouble());
572
			}
573
			if(e.getSource().equals(txtMaxSize)) {
574
				if(txtMaxSize.getDouble() < txtMinSize.getDouble())
575
					txtMinSize.setDouble(txtMaxSize.getDouble());
576
			}
577
			if(e.getSource().equals(tmplateSymbol)) {
578
				ISymbol sym = tmplateSymbol.getSymbol();
579
				if(sym != null) {
580
					if(sym instanceof ILineSymbol) {
581
						ILineSymbol line = (ILineSymbol)sym;
582
						txtMinSize.setDouble(((int)line.getLineWidth()));
583
						txtMaxSize.setDouble(((int)line.getLineWidth()));
584
					}
585

  
586
					if(sym instanceof IMarkerSymbol) {
587
						IMarkerSymbol point = (IMarkerSymbol)sym;
588
						txtMinSize.setDouble(((int)point.getSize()));
589
						txtMaxSize.setDouble(((int)point.getSize()));
590
					}	
591
				}
592
			}
593
		}
594
	};
595

  
596
}
1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2005 IVER T.I. 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
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41
package org.gvsig.symbology.gui.layerproperties;
42

  
43
import java.awt.BorderLayout;
44
import java.awt.Color;
45
import java.awt.Dimension;
46
import java.awt.FlowLayout;
47
import java.awt.event.ActionEvent;
48
import java.awt.event.ActionListener;
49
import java.sql.Types;
50

  
51
import javax.swing.BorderFactory;
52
import javax.swing.DefaultComboBoxModel;
53
import javax.swing.ImageIcon;
54
import javax.swing.JComboBox;
55
import javax.swing.JLabel;
56
import javax.swing.JPanel;
57

  
58
import org.apache.log4j.Logger;
59
import org.gvsig.gui.beans.swing.GridBagLayoutPanel;
60
import org.gvsig.gui.beans.swing.JBlank;
61
import org.gvsig.gui.beans.swing.JIncrementalNumberField;
62
import org.gvsig.symbology.fmap.rendering.ProportionalSymbolsLegend;
63
import org.gvsig.symbology.fmap.symbols.MarkerFillSymbol;
64

  
65
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
66
import com.hardcode.gdbms.engine.data.DataSource;
67
import com.hardcode.gdbms.engine.values.Value;
68
import com.hardcode.gdbms.engine.values.ValueFactory;
69
import com.iver.andami.PluginServices;
70
import com.iver.andami.messages.NotificationManager;
71
import com.iver.cit.gvsig.fmap.core.FShape;
72
import com.iver.cit.gvsig.fmap.core.SymbologyFactory;
73
import com.iver.cit.gvsig.fmap.core.styles.IMarkerFillPropertiesStyle;
74
import com.iver.cit.gvsig.fmap.core.symbols.ILineSymbol;
75
import com.iver.cit.gvsig.fmap.core.symbols.IMarkerSymbol;
76
import com.iver.cit.gvsig.fmap.core.symbols.ISymbol;
77
import com.iver.cit.gvsig.fmap.core.symbols.SimpleLineSymbol;
78
import com.iver.cit.gvsig.fmap.core.symbols.SimpleMarkerSymbol;
79
import com.iver.cit.gvsig.fmap.layers.FLayer;
80
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
81
import com.iver.cit.gvsig.fmap.layers.SelectableDataSource;
82
import com.iver.cit.gvsig.fmap.layers.layerOperations.AlphanumericData;
83
import com.iver.cit.gvsig.fmap.layers.layerOperations.ClassifiableVectorial;
84
import com.iver.cit.gvsig.fmap.rendering.ILegend;
85
import com.iver.cit.gvsig.project.documents.view.legend.gui.ILegendPanel;
86
import com.iver.cit.gvsig.project.documents.view.legend.gui.JSymbolPreviewButton;
87
import com.iver.cit.gvsig.project.documents.view.legend.gui.Quantities;
88

  
89

  
90
/**
91
 * Implements the panel for the legend of proportional symbols.In the interface will be
92
 * options to select the value field, the normalization field (if the user wants to use it) and
93
 * options to select the symbol an its minimum and maximum size.
94
 *
95
 * Also there will be possible to select a background symbol (only when the shapetype of the layer is
96
 * polygonal).
97
 *
98
 * @author jaume dominguez faus - jaume.dominguez@iver.es
99
 */
100
public class ProportionalSymbols extends JPanel implements ILegendPanel{
101
	private static final long serialVersionUID = 7394720230276170902L;
102
	private JPanel symbolPanel;
103
	private JPanel backgroundPanel;
104
	private JSymbolPreviewButton tmplateSymbol;
105
	private JSymbolPreviewButton backSymbol;
106
	private JComboBox cmbValue;
107
	private JComboBox cmbNormalization;
108
	private JIncrementalNumberField txtMinSize;
109
	private JIncrementalNumberField txtMaxSize;
110
	private static Logger logger = Logger.getLogger(ProportionalSymbols.class.getName());
111
	private ClassifiableVectorial myLayer;
112
	private ProportionalSymbolsLegend auxLegend;
113
	private ProportionalSymbolsLegend theLegend;
114
	private String[] fieldNames;
115
	private int templateShapeType = 0 ;
116
	private String noNormalization = PluginServices.getText(this, "none");
117
	private boolean useNormalization = true;
118

  
119
	/**
120
	 * Default constructor
121
	 */
122
	public ProportionalSymbols() {
123
		initialize();
124
	}
125

  
126
	/**
127
	 * This method initializes this
128
	 */
129
	private void initialize() {
130

  
131
		setLayout(new BorderLayout());
132
		JPanel aux = new JPanel(new BorderLayout());
133

  
134
		JPanel fieldsPanel = new JPanel(new FlowLayout());
135
		fieldsPanel.setBorder(BorderFactory.
136
				createTitledBorder(null,
137
						PluginServices.getText(this, "fields")));
138
		fieldsPanel.setPreferredSize(new Dimension(300,60));
139

  
140
		cmbValue = new JComboBox();
141
		cmbValue.setActionCommand("VALUE_SELECTED");
142

  
143
		cmbNormalization = new JComboBox();
144
		cmbNormalization.setActionCommand("NORMALIZATION_SELECTED");
145

  
146
		fieldsPanel.add(new JLabel(PluginServices.getText(this, "value")+":" ));
147
		fieldsPanel.add(cmbValue);
148

  
149
		fieldsPanel.add(new JLabel(PluginServices.getText(this, "normalization")+":" ));
150
		fieldsPanel.add(cmbNormalization);
151

  
152

  
153
		symbolPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 3,2));
154
		symbolPanel.setBorder(BorderFactory.
155
				createTitledBorder(null,
156
						PluginServices.getText(this, "symbol")));
157

  
158
		GridBagLayoutPanel aux2 = new GridBagLayoutPanel();
159
		aux2.addComponent(new JLabel(PluginServices.getText(this, "size")));
160
		aux2.addComponent(new JBlank(10,10));
161
		aux2.addComponent(PluginServices.getText(this, "from")+":",
162
				getTxtMinSize());
163
		aux2.addComponent(PluginServices.getText(this, "to")+":",
164
				getTxtMaxSize());
165

  
166
		JPanel templatePanel = new JPanel();
167
		templatePanel.setBorder(BorderFactory.createTitledBorder(null,
168
				PluginServices.getText(this, "template")));
169
		templatePanel.add(getTemplSymbol());
170
		symbolPanel.add(new JBlank(10,10));
171
		symbolPanel.add(aux2);
172
		symbolPanel.add(new JBlank(10,10));
173
		symbolPanel.add(templatePanel);
174

  
175
		aux.add(fieldsPanel, BorderLayout.NORTH);
176
		aux.add(symbolPanel, BorderLayout.CENTER);
177

  
178
		this.add(aux, BorderLayout.CENTER);
179

  
180
		cmbValue.addActionListener(action);
181
		cmbNormalization.addActionListener(action);
182
		tmplateSymbol.addActionListener(action);
183
	}
184
	/**
185
	 * Creates the panel where the button for the background symbol will be placed
186
	 *
187
	 * @return JPanel panel
188
	 */
189

  
190
	private JPanel getBackgroundPanel() {
191
		backgroundPanel = new JPanel();
192
		backgroundPanel.setBorder(BorderFactory.createTitledBorder(null,
193
				PluginServices.getText(this, "background")));
194
		backgroundPanel.add(getBtnBackground());
195
		return backgroundPanel;
196
	}
197
	/**
198
	 * Creates a JIncrementalNumberField which is used to select the maximum size for the symbol
199
	 *
200
	 * @return JIncrementalNumberField
201
	 */
202
	private JIncrementalNumberField getTxtMaxSize() {
203
		if (txtMaxSize == null) {
204
			txtMaxSize = new JIncrementalNumberField(String.valueOf(25), 7,0,100,1);
205
			txtMaxSize.addActionListener(action);
206
		}
207
		return txtMaxSize;
208
	}
209
	/**
210
	 * Creates a JIncrementalNumberField which is used to select the minimum size for the symbol
211
	 *
212
	 * @return JIncrementalNumberField
213
	 */
214
	private JIncrementalNumberField getTxtMinSize() {
215
		if (txtMinSize == null) {
216
			txtMinSize = new JIncrementalNumberField(String.valueOf(3), 7,0,100,1);
217
			txtMinSize.addActionListener(action);
218
		}
219
		return txtMinSize;
220
	}
221
	/**
222
	 * Creates a JSymbolPreviewButton which is used to select the template symbol
223
	 *
224
	 * @return JSymbolPreviewButton
225
	 */
226
	private JSymbolPreviewButton getTemplSymbol() {
227

  
228
		if (tmplateSymbol == null) {
229
			int templateShapeType = (this.templateShapeType == FShape.POLYGON) ? FShape.POINT : this.templateShapeType;
230
			tmplateSymbol = new JSymbolPreviewButton(templateShapeType);
231
		}
232
		tmplateSymbol.setPreferredSize(new Dimension(100, 45));
233
		return tmplateSymbol;
234
	}
235
	/**
236
	 * Creates a JSymbolPreviewButton which is used to select the background symbol
237
	 *
238
	 * @return JSymbolPreviewButton
239
	 */
240
	private JSymbolPreviewButton getBtnBackground() {
241
		if (backSymbol == null) {
242
			backSymbol = new JSymbolPreviewButton(FShape.POLYGON);
243
			backSymbol.setPreferredSize(new Dimension(100, 45));
244
		}
245
		return backSymbol;
246
	}
247
	/**
248
	 * Creates a new symbol of an specific shapetype with a concrete size
249
	 *
250
	 * @param shapeType
251
	 * @param size
252
	 *
253
	 * @return ISymbol symbol created
254
	 */
255
	private ISymbol newSymbol(int shapeType, double size) {
256
		if (getTemplSymbol().getSymbol() == null) {
257
			ISymbol templateSymbol;
258
			switch (shapeType) {
259
			case FShape.POINT:
260
			case FShape.POLYGON:
261
				templateSymbol = new SimpleMarkerSymbol();
262
				((SimpleMarkerSymbol) templateSymbol).setSize(size);
263
				((SimpleMarkerSymbol) templateSymbol).setColor(Color.DARK_GRAY);
264
				break;
265

  
266
			case FShape.LINE:
267
				templateSymbol = new SimpleLineSymbol();
268
				((SimpleLineSymbol) templateSymbol).setLineWidth(size);
269
				((SimpleLineSymbol) templateSymbol).setLineColor(Color.DARK_GRAY);
270
				break;
271
			default:
272
				throw new Error("Unknown symbol type");
273
			}
274
			getTemplSymbol().setSymbol(templateSymbol);
275
			return newSymbol(shapeType, size);
276
		} else {
277
			// clone symbol
278
			ISymbol mySymbol = SymbologyFactory.createSymbolFromXML(
279
					getTemplSymbol().getSymbol().getXMLEntity(), null);
280

  
281
			if (mySymbol instanceof ILineSymbol) {
282
				ILineSymbol lSym = (ILineSymbol) mySymbol;
283
				lSym.setLineWidth(size);
284

  
285
			}
286
			if (mySymbol instanceof IMarkerSymbol) {
287
				IMarkerSymbol mSym = (IMarkerSymbol) mySymbol;
288
				mSym.setSize(size);
289
				if (shapeType == FShape.POLYGON) {
290
					// this is to allow using in Polygon layers
291
					MarkerFillSymbol fillSymbol = new MarkerFillSymbol();
292
					fillSymbol.setOutline(null);
293
					fillSymbol.setFillColor(null);
294
					fillSymbol.getMarkerFillProperties().
295
					setFillStyle(IMarkerFillPropertiesStyle.SINGLE_CENTERED_SYMBOL);
296
					fillSymbol.setMarker(mSym);
297
				}
298
			}
299
			return mySymbol;
300
		}
301
	}
302

  
303
	/**
304
	 * Fills the comboboxes that are placed in the panel with the classifying field names of the layer
305
	 * which contain numerical information
306
	 *
307
	 */
308
	private void fillFieldNames() {
309
		DataSource rs;
310

  
311
		try {
312
			rs = ((AlphanumericData) myLayer).getRecordset();
313
			logger.debug("rs.start()");
314
			rs.start();
315

  
316
			int cont = 0;
317
			for (int i = 0; i < rs.getFieldCount(); i++) {
318
				if(isNumericField(rs.getFieldType(i)))
319
					cont++;
320
			}
321
			String[] nomFields = new String[cont];
322

  
323
			cont = 0;
324
			for (int i = 0; i < rs.getFieldCount(); i++) {
325
				if (isNumericField(rs.getFieldType(i))) {
326
					nomFields[cont] = rs.getFieldName(i).trim();
327
					cont++;
328
				}
329
			}
330

  
331
			rs.stop();
332
			this.fieldNames = nomFields;
333

  
334
			DefaultComboBoxModel cMValue = new DefaultComboBoxModel(this.fieldNames);
335
			DefaultComboBoxModel cMNormalization = new DefaultComboBoxModel(this.fieldNames);
336
			cmbValue.setModel(cMValue);
337
			cmbNormalization.setModel(cMNormalization);
338
			cmbNormalization.addItem(noNormalization);
339

  
340
		} catch (ReadDriverException e) {
341
			NotificationManager.addError(PluginServices.getText(this, "recovering_recordset"), e);
342
		}
343
	}
344

  
345

  
346
	public void setData(FLayer lyr, ILegend legend) {
347

  
348
		this.myLayer = (ClassifiableVectorial) lyr;
349

  
350
		fillFieldNames();
351

  
352
		try {
353
			templateShapeType = (this.myLayer.getShapeType() == FShape.POLYGON) ? FShape.POINT : this.myLayer.getShapeType();
354
			getTemplSymbol().setShapeType(templateShapeType);
355

  
356
			if(myLayer.getShapeType() == FShape.POLYGON && backgroundPanel == null)
357
				symbolPanel.add(getBackgroundPanel());
358

  
359
		} catch (ReadDriverException e) {
360
			NotificationManager.addError(PluginServices.getText(this, "error accessing to the layer"), e);
361
		}
362

  
363
		if (ProportionalSymbolsLegend.class.equals(legend.getClass())) {
364

  
365
			auxLegend = (ProportionalSymbolsLegend) legend;
366
			cmbValue.setSelectedItem(auxLegend.getClassifyingFieldNames()[0]);
367
			ISymbol defSymbol = auxLegend.getDefaultSymbol();
368

  
369
			if(((ProportionalSymbolsLegend) auxLegend).getUseNormalization())
370
				cmbNormalization.setSelectedItem(auxLegend.getClassifyingFieldNames()[1]);
371
			else cmbNormalization.setSelectedItem(noNormalization);
372

  
373
			txtMaxSize.setDouble(auxLegend.getMaxSize());
374
			txtMinSize.setDouble(auxLegend.getMinSize());
375

  
376
			getTemplSymbol().setSymbol(defSymbol);
377

  
378
			if(((ProportionalSymbolsLegend) auxLegend).getBackgroundSymbol() != null)
379
				getBtnBackground().setSymbol(((ProportionalSymbolsLegend) auxLegend).getBackgroundSymbol());
380

  
381
			action.actionPerformed(new ActionEvent(txtMinSize, 0, "no_hace_falta"));
382

  
383
		} else {
384

  
385
			auxLegend = new ProportionalSymbolsLegend();
386
			auxLegend.setTemplateShapeType(templateShapeType);
387
			auxLegend.setDefaultSymbol(newSymbol(templateShapeType, templateShapeType == FShape.LINE ? 3 : 10));
388
			getTemplSymbol().setSymbol(auxLegend.getDefaultSymbol());
389
			if(templateShapeType == FShape.LINE) {
390
				txtMinSize.setDouble(3);
391
				txtMaxSize.setDouble(3);
392
			}
393

  
394
			else {
395
				txtMinSize.setDouble(10);
396
				txtMaxSize.setDouble(10);
397
			}
398
		}
399

  
400
	}
401

  
402

  
403
	public ILegend getLegend() {
404
		theLegend = new ProportionalSymbolsLegend();
405

  
406
		String[] fieldNames = new String[2];
407
		fieldNames[0]= cmbValue.getSelectedItem().toString();
408

  
409
		if(!useNormalization)
410
			fieldNames[1]= fieldNames[0];
411
		else fieldNames[1]= cmbNormalization.getSelectedItem().toString();
412

  
413
		auxLegend.setTemplateShapeType(templateShapeType);
414
		auxLegend.setValueField(cmbValue.getSelectedItem().toString());
415
		auxLegend.setNormalizationField(cmbNormalization.getSelectedItem().toString());
416
		auxLegend.setUseNormalization(useNormalization);
417

  
418
		auxLegend.setMinSize(txtMinSize.getDouble());
419
		auxLegend.setMaxSize(txtMaxSize.getDouble());
420

  
421
		ISymbol symbol = getTemplSymbol().getSymbol();
422
		symbol.setDescription(getSymbolDescription());
423
		auxLegend.setDefaultSymbol(symbol);
424
		auxLegend.addSymbol(ValueFactory.createValue("defaultSymbol"), symbol);
425

  
426
		auxLegend.setBackgroundSymbol(getBtnBackground().getSymbol());
427
		auxLegend.setClassifyingFieldNames(fieldNames);
428

  
429
		DataSource recordSet = null;
430

  
431

  
432
		try {
433
			recordSet = ((AlphanumericData) myLayer).getRecordset();
434

  
435
			for (int i = 0; i < fieldNames.length; i++) {
436
				double min = 0, max = 0;
437

  
438
				for (int j = 0; j < recordSet.getRowCount(); j++) {
439
					Value val = recordSet.getFieldValue(j, recordSet.getFieldIndexByName(fieldNames[i]));
440
					double dob = Double.valueOf(val.toString());
441
					if (dob < min) min = dob;
442
					if (dob > max) max = dob;
443
				}
444
				if(i == 0) {
445
					auxLegend.setMinFeature(min);
446
					auxLegend.setMaxFeature(max);
447
				}
448
			}
449

  
450
		} catch (ReadDriverException e) {
451
			NotificationManager.addError("error_accessing_to_the_layer",e);
452
		}
453
		theLegend = auxLegend;
454

  
455
		return theLegend;
456
	}
457
	/**
458
	 * Creates the String which will be the description of the symbol. If the selected normalization field
459
	 * is not "None", then the String created will have this structure ValueField/NormalizationField. Else,
460
	 * if the user select "None" for the normalization field,the string will show the ValueField only.
461
	 *
462
	 * @return String	description for the symbol
463
	 */
464

  
465
	private String getSymbolDescription() {
466
		String description = "";
467

  
468
		if (cmbValue.getSelectedItem() != null)
469
			description += cmbValue.getSelectedItem().toString();
470
		if (cmbNormalization.getSelectedItem().toString().compareTo(noNormalization) != 0 )
471
			description += " / "+cmbNormalization.getSelectedItem().toString();
472

  
473
		return description;
474
	}
475

  
476
	public String getDescription() {
477
		return PluginServices.getText(this, "draw_quantities_using_symbol_size_to_show_exact_values");
478
	}
479

  
480
	public ImageIcon getIcon() {
481
		// TODO Implement it
482
		return null;
483
	}
484

  
485
	public Class getParentClass() {
486
		return Quantities.class;
487
	}
488

  
489
	public String getTitle() {
490
		return PluginServices.getText(this, "proportional_symbols");
491
	}
492

  
493
	public Class getLegendClass() {
494
		return ProportionalSymbolsLegend.class;
495
	}
496
	/**
497
	 * Checks if an specific field contains numerical data
498
	 *
499
	 * @param fieldType	index of the field
500
	 *
501
	 * @return boolean	true or false depending on the type of data (numerical or not)
502
	 */
503
	private boolean isNumericField(int fieldType) {
504
		switch (fieldType) {
505
		case Types.BIGINT:
506
		case Types.DECIMAL:
507
		case Types.DOUBLE:
508
		case Types.FLOAT:
509
		case Types.INTEGER:
510
		case Types.NUMERIC:
511
		case Types.REAL:
512
		case Types.SMALLINT:
513
		case Types.TINYINT:
514
			return true;
515
		default:
516
			return false;
517
		}
518

  
519
	}
520
	public boolean isSuitableFor(FLayer layer) {
521
		if (layer instanceof FLyrVect) {
522
			FLyrVect lyr = (FLyrVect) layer;
523
			try {
524
				if (lyr.getShapeType() == FShape.MULTI)
525
					return false;
526

  
527
				SelectableDataSource sds;
528
				sds = ((FLyrVect) layer).getRecordset();
529
				String[] fNames = sds.getFieldNames();
530
				for (int i = 0; i < fNames.length; i++) {
531
					if (isNumericField(sds.getFieldType(i))) {
532
						return true;
533
					}
534
				}
535
			} catch (ReadDriverException e) {
536
				return false;
537
			}
538
		}
539
		return false;
540
	}
541

  
542

  
543
	public JPanel getPanel() {
544
		return this;
545
	}
546

  
547

  
548
	private ActionListener action = new ActionListener() {
549

  
550
		public void actionPerformed(ActionEvent e) {
551

  
552
			if (e.getSource().equals(cmbValue)) {
553
				JComboBox cb = (JComboBox) e.getSource();
554
				auxLegend.setValueField(cb.getSelectedItem().toString());
555
			}
556
			if (e.getSource().equals(cmbNormalization)) {
557
				JComboBox cb = (JComboBox) e.getSource();
558
				if(cb.getSelectedItem().toString().compareTo(noNormalization) == 0) {
559
					useNormalization = false;
560
					auxLegend.setNormalizationField(cmbValue.getSelectedItem().toString());
561
				}
562
				else {
563
					useNormalization = true;
564
					auxLegend.setNormalizationField(cb.getSelectedItem().toString());
565
				}
566
				auxLegend.setUseNormalization(useNormalization);
567
			}
568
			if (e.getSource().equals(txtMinSize)) {
569
//				ISymbol sym = tmplateSymbol.getSymbol();
570
//				if(sym != null) {
571
//					if(sym instanceof ILineSymbol) {
572
//						ILineSymbol line = (ILineSymbol)sym;
573
//						line.setLineWidth(txtMinSize.getDouble());
574
//						tmplateSymbol.setSymbol(line);
575
//					}
576
//
577
//					if(sym instanceof IMarkerSymbol) {
578
//						IMarkerSymbol point = (IMarkerSymbol)sym;
579
//						point.setSize(txtMinSize.getDouble());
580
//						tmplateSymbol.setSymbol(point);
581
//					}
582
//					tmplateSymbol.repaint();
583
//				}
584

  
585
				if(txtMaxSize.getDouble() < txtMinSize.getDouble())
586
					txtMaxSize.setDouble(txtMinSize.getDouble());
587
			}
588
			if(e.getSource().equals(txtMaxSize)) {
589
				if(txtMaxSize.getDouble() < txtMinSize.getDouble())
590
					txtMinSize.setDouble(txtMaxSize.getDouble());
591
			}
592
			if(e.getSource().equals(tmplateSymbol)) {
593
				ISymbol sym = tmplateSymbol.getSymbol();
594
				if(sym != null) {
595
					if(sym instanceof ILineSymbol) {
596
						ILineSymbol line = (ILineSymbol)sym;
597
						txtMinSize.setDouble(((int)line.getLineWidth()));
598
						txtMaxSize.setDouble(((int)line.getLineWidth()));
599
					}
600

  
601
					if(sym instanceof IMarkerSymbol) {
602
						IMarkerSymbol point = (IMarkerSymbol)sym;
603
						txtMinSize.setDouble(((int)point.getSize()));
604
						txtMaxSize.setDouble(((int)point.getSize()));
605
					}
606
				}
607
			}
608
		}
609
	};
610

  
611
}

Also available in: Unified diff