Statistics
| Revision:

root / trunk / applications / appgvSIG / src / com / iver / cit / gvsig / project / documents / view / legend / gui / DotDensity.java @ 11297

History | View | Annotate | Download (19.3 KB)

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

    
42
/* CVS MESSAGES:
43
*
44
* $Id: DotDensity.java 11297 2007-04-20 07:54:39Z jaume $
45
* $Log$
46
* Revision 1.5  2007-04-20 07:54:39  jaume
47
* *** empty log message ***
48
*
49
* Revision 1.4  2007/04/20 07:24:56  jaume
50
* *** empty log message ***
51
*
52
* Revision 1.3  2007/04/17 06:53:46  bsanchez
53
* - Corregido fallo de Double.MIN_VALUE por Double.NEGATIVE_INFINITY comentado por Victor Olaya.
54
*
55
* Revision 1.2  2007/03/09 11:25:00  jaume
56
* Advanced symbology (start committing)
57
*
58
* Revision 1.1.2.4  2007/02/21 07:35:14  jaume
59
* *** empty log message ***
60
*
61
* Revision 1.1.2.3  2007/02/12 15:14:41  jaume
62
* refactored interval legend and added graduated symbol legend
63
*
64
* Revision 1.1.2.2  2007/02/09 11:00:03  jaume
65
* *** empty log message ***
66
*
67
* Revision 1.1.2.1  2007/01/26 13:49:03  jaume
68
* *** empty log message ***
69
*
70
* Revision 1.4  2006/11/17 13:53:45  cesar
71
* *** empty log message ***
72
*
73
* Revision 1.3  2006/11/17 12:50:36  jaume
74
* tama?o de punto defecto 2
75
*
76
* Revision 1.2  2006/11/15 12:57:31  jaume
77
* *** empty log message ***
78
*
79
* Revision 1.1  2006/11/14 11:10:27  jaume
80
* *** empty log message ***
81
*
82
*
83
*/
84
package com.iver.cit.gvsig.project.documents.view.legend.gui;
85

    
86
import java.awt.BorderLayout;
87
import java.awt.Color;
88
import java.awt.ComponentOrientation;
89
import java.awt.Dimension;
90
import java.awt.FlowLayout;
91
import java.awt.GridLayout;
92
import java.awt.LayoutManager;
93
import java.awt.event.ActionEvent;
94
import java.awt.event.ActionListener;
95
import java.awt.event.ItemEvent;
96
import java.awt.event.ItemListener;
97
import java.sql.Types;
98
import java.text.NumberFormat;
99

    
100
import javax.swing.BorderFactory;
101
import javax.swing.BoxLayout;
102
import javax.swing.ButtonGroup;
103
import javax.swing.ImageIcon;
104
import javax.swing.JComboBox;
105
import javax.swing.JLabel;
106
import javax.swing.JOptionPane;
107
import javax.swing.JPanel;
108
import javax.swing.JRadioButton;
109
import javax.swing.JSlider;
110
import javax.swing.JTextField;
111
import javax.swing.event.ChangeEvent;
112
import javax.swing.event.ChangeListener;
113

    
114
import org.gvsig.gui.beans.swing.GridBagLayoutPanel;
115

    
116
import com.hardcode.gdbms.engine.data.DataSource;
117
import com.hardcode.gdbms.engine.data.DataSourceFactory;
118
import com.hardcode.gdbms.engine.values.NumericValue;
119
import com.hardcode.gdbms.engine.values.ValueFactory;
120
import com.iver.andami.PluginServices;
121
import com.iver.andami.messages.NotificationManager;
122
import com.iver.cit.gvsig.fmap.core.FShape;
123
import com.iver.cit.gvsig.fmap.core.symbols.DotDensityFillSymbol;
124
import com.iver.cit.gvsig.fmap.core.symbols.ILineSymbol;
125
import com.iver.cit.gvsig.fmap.core.symbols.ISymbol;
126
import com.iver.cit.gvsig.fmap.core.symbols.MultiLayerFillSymbol;
127
import com.iver.cit.gvsig.fmap.core.symbols.SimpleFillSymbol;
128
import com.iver.cit.gvsig.fmap.layers.FLayer;
129
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
130
import com.iver.cit.gvsig.fmap.layers.SelectableDataSource;
131
import com.iver.cit.gvsig.fmap.rendering.DotDensityLegend;
132
import com.iver.cit.gvsig.fmap.rendering.Legend;
133
import com.iver.cit.gvsig.gui.panels.ColorChooserPanel;
134

    
135
/**
136
 *
137
 * @author jaume dominguez faus - jaume.dominguez@iver.es
138
 *
139
 */
140
public class DotDensity extends JPanel implements ILegendPanel {
141
        private FLyrVect layer;
142
        private JPanel northPanel = null;
143
        private GridBagLayoutPanel densityButtonsPanel = null;
144
        private JPanel pnlDensities = null;
145
        private JComboBox cmbLegendField = null;
146
        private JRadioButton rdBtnHigh = null;
147
        private JRadioButton rdBtnMedium = null;
148
        private JRadioButton rdBtnLow = null;
149
        private JTextField numDotSize = null;
150
        private double max, min, mean;
151
        private JTextField nmbrDotValue = null;
152
        private JLabel lblLabellingField = null;
153
        private DotDensityLegend legend;
154
        private String fieldName;
155
        private boolean initializing;
156

    
157
        private MyListener cmbAction = new MyListener();
158
        NumberFormat nf = NumberFormat.getInstance();
159

    
160
        {
161
                nf.setMaximumFractionDigits(3);
162
        }
163

    
164
        private class MyListener implements ItemListener, ActionListener {
165

    
166

    
167
                public void itemStateChanged(ItemEvent e) {
168
                        if (!initializing)
169
                                doIt();
170
                }
171

    
172
                public void actionPerformed(ActionEvent e) {
173
                        if (!initializing)
174
                                doIt();
175
                }
176

    
177
                private void doIt() {
178
                        int index = cmbLegendField.getSelectedIndex();
179
            try {
180
                SelectableDataSource sds = layer.getRecordset();
181

    
182
                if (index != -1) {
183
                    fieldName = (String) cmbLegendField.getSelectedItem();
184
                } else {
185
                    fieldName = (String) cmbLegendField.getItemAt(0);
186
                }
187

    
188
                String sql = "select "+fieldName+" from '"+sds.getName()+"';";
189

    
190
                DataSource recordset = sds.getDataSourceFactory().executeSQL(sql, DataSourceFactory.AUTOMATIC_OPENING );
191
                // TODO implement MAX() and MIN() functions in GDBMS!!!!!
192
                max = Double.NEGATIVE_INFINITY;
193
                min = Double.MAX_VALUE;
194
                for (int i = 0; i < sds.getRowCount(); i++) {
195
                    double value = ((NumericValue) recordset.getFieldValue(i,0)).doubleValue();
196
                    max = Math.max(max, value);
197
                    min = Math.min(min, value);
198
                }
199
                mean = (max+min) /2;
200
                buttonsListener.actionPerformed(null);
201

    
202
            } catch (Exception ex) {
203
                ex.printStackTrace();
204
            }
205
                }
206
        };
207
        private ActionListener buttonsListener = new ActionListener() {
208
            public void actionPerformed(ActionEvent e) {
209
                    if (getRdBtnHigh().isSelected()) {
210
                            getSldDensity().setValue(66);
211
                    } else if (getRdBtnLow().isSelected()) {
212
                            getSldDensity().setValue(33);
213
                    } else if (getRdBtnMedium().isSelected()) {
214
                            getSldDensity().setValue(50);
215
                    }
216
            }
217
    };
218
        private JPanel centerPanel = null;
219
        private JSlider sldDensity = null;
220

    
221
        private ChangeListener sldListener = new ChangeListener() {
222

    
223
                public void stateChanged(ChangeEvent e) {
224

    
225
                        // This is my messy statistic aggregation function
226
                        // TODO if I can, I'll have a look to my statistic books to figure out one better
227
                        int quantileIndex = getSldDensity().getValue();
228
                        final int topLimit = 98;
229
                        if (quantileIndex > topLimit)
230
                                quantileIndex = topLimit;
231
                        double quantileAmount = (max-min)/100;
232
                        nmbrDotValue.setText(nf.format(3*quantileAmount/Math.log(quantileIndex)));
233
                }
234

    
235
        };
236
        private ColorChooserPanel jcc;
237
        private ColorChooserPanel outlineColorChooserPanel;
238
        private Legend oldLegend;
239
        private JSymbolPreviewButton btnOutline;
240

    
241
        public DotDensity() {
242
        super();
243
        initialize();
244
    }
245

    
246
    /**
247
     * This method initializes this
248
     *
249
     */
250
    private void initialize() {
251
        this.setLayout(new BorderLayout());
252
        this.setSize(new java.awt.Dimension(492,278));
253
        this.add(getNorthPanel(), java.awt.BorderLayout.NORTH);
254

    
255
        this.add(getCenterPanel(), java.awt.BorderLayout.CENTER);
256
    }
257

    
258
    public void setData(FLayer lyr, Legend legend) {
259
        this.layer = (FLyrVect) lyr;
260
        this.oldLegend = legend;
261
        try {
262
                SelectableDataSource sds = layer.getRecordset();
263
                initializing = true; // silents events to the combo box
264
                cmbLegendField.removeAllItems();
265
                String[] fNames = sds.getFieldNames();
266
                for (int i = 0; i < fNames.length; i++) {
267
                        if (isNumericField(sds.getFieldType(i))) {
268
                                cmbLegendField.addItem(fNames[i]);
269
                        }
270
                }
271
                if (!(legend instanceof DotDensityLegend)) {
272
                        legend = new DotDensityLegend();
273
                        ((DotDensityLegend) legend).setFieldName((String) cmbLegendField.getItemAt(0));
274
                }
275

    
276
                DotDensityLegend theLegend = (DotDensityLegend) legend;
277

    
278
                initializing = false; // enables events to the combo box
279

    
280
                cmbLegendField.setSelectedItem(theLegend.getFieldName());
281
                try {
282
                        getDotColorChooserPanel().setColor(theLegend.getDotColor());
283
                } catch (NullPointerException npEx) {
284
                        getDotColorChooserPanel().setColor(Color.RED);
285
                }
286
                getBtnOutline().setSymbol(theLegend.getOutline());
287
                try {
288
                        double dotValue = theLegend.getDotValue();
289
                        if (dotValue <= 0)
290
                                dotValue = 100;
291
                        getNmbrDotValue().setText(String.valueOf(dotValue));
292
                } catch (NullPointerException npEx) {
293
                        getNmbrDotValue().setText(String.valueOf(max));
294
                }
295
                try {
296
                        double dotSize = theLegend.getDotSize();
297
                        if (dotSize <= 0)
298
                                dotSize = 2;
299
                        getNumDotSize().setText(String.valueOf(dotSize));
300
                } catch (NullPointerException npEx) {
301
                        getNumDotSize().setText(String.valueOf(3));
302
                }
303

    
304
        } catch (Exception e) {
305
                e.printStackTrace();
306
        }
307
    }
308

    
309
    private boolean isNumericField(int fieldType) {
310
        switch (fieldType) {
311
        case Types.BIGINT:
312
        case Types.DECIMAL:
313
        case Types.DOUBLE:
314
        case Types.FLOAT:
315
        case Types.INTEGER:
316
        case Types.NUMERIC:
317
        case Types.REAL:
318
        case Types.SMALLINT:
319
        case Types.TINYINT:
320
            return true;
321
        default:
322
            return false;
323
        }
324

    
325
    }
326

    
327
    public Legend getLegend() {
328
            try {
329
                        int shapeType = layer.getShapeType();
330

    
331
                    // shapeType should be always polygon
332
                    if (shapeType != FShape.POLYGON) {
333
                            NotificationManager.addError(PluginServices.getText(this, "cannot_apply_to_a_non_polygon_layer"), new Exception());
334
                    }
335

    
336
                    // check if the field exists (this is probably dead code)
337
                    SelectableDataSource sds;
338
                    sds = layer.getRecordset();
339
                    if (-1 == sds.getFieldIndexByName(fieldName))
340
                            return null;
341

    
342
                    // gather values
343
                    double dotValue;
344
                    double dotSize;
345
                    try {
346
                            dotValue = Double.parseDouble(nmbrDotValue.getText());
347
                    } catch (Exception e) {
348
                            dotValue = nf.parse(nmbrDotValue.getText()).doubleValue();
349
                    }
350
                    if (dotValue == 0)
351
                            dotValue = 1;
352
                    try {
353
                            dotSize = Double.parseDouble(numDotSize.getText());
354
                    } catch (Exception e) {
355
                            dotSize = nf.parse(numDotSize.getText()).doubleValue();
356
                    }
357

    
358
                    if (max/dotValue > 50000) {
359
                            int option = JOptionPane.showConfirmDialog(this,
360
                                            PluginServices.getText(this, "looks_like_too_low_value_for_this_field_may_cause_system_to_run_slow"),
361
                                            PluginServices.getText(this, "warning"),
362
                                            JOptionPane.OK_CANCEL_OPTION);
363
                            if (option        == JOptionPane.CANCEL_OPTION)
364
                                    return oldLegend;
365
                    }
366

    
367
                    // create the density symbol with the values set above
368
                    DotDensityFillSymbol densitySymbol = new DotDensityFillSymbol();
369
                    densitySymbol.setDotSize(dotSize);
370
                    densitySymbol.setDotColor(getDotColorChooserPanel().getColor());
371

    
372
                    // create a simple-fill symbol over which the dot density will be drawn
373
                    SimpleFillSymbol fillSymbol = new SimpleFillSymbol();
374
                    fillSymbol.setFillColor(Color.WHITE);
375
                    fillSymbol.setOutline((ILineSymbol) getBtnOutline().getSymbol());
376

    
377
                    // combine both the DotDensitySymbol and the SimpleFillSymbol in
378
                    // MultiLayerSymbol so they will be paint as a unique ISymbol
379
                    MultiLayerFillSymbol symbol = new MultiLayerFillSymbol();
380
                    symbol.setDescription(
381
                                    "DotDensitySymbol" + PluginServices.getText(this, "in_layer") +
382
                                    ": '"+layer.getName()+"'");
383
                    symbol.addLayer(fillSymbol);
384
                    symbol.addLayer(densitySymbol);
385

    
386
                    legend = new DotDensityLegend();
387
                    legend.addSymbol(ValueFactory.createValue("theSymbol"), symbol);
388
                    legend.setDefaultSymbol(symbol);
389
                    legend.setDotValue(dotValue);
390
                    legend.setFieldName(fieldName);
391

    
392

    
393
            } catch (Exception e) {
394
                    NotificationManager.addError(PluginServices.getText(this, "could_not_setup_legend")+".", e);
395
            }
396
            return legend;
397

    
398
    }
399

    
400
    /**
401
     * This method initializes centerPanel
402
     *
403
     * @return javax.swing.JPanel
404
     */
405
    private JPanel getNorthPanel() {
406
        if (northPanel == null) {
407
            lblLabellingField = new JLabel();
408
            lblLabellingField.setText(PluginServices.getText(this, "labelling_field")+".");
409
            northPanel = new JPanel(new FlowLayout(FlowLayout.LEADING,15,0));
410
            northPanel.add(lblLabellingField, null);
411
            northPanel.add(getCmbLegendField(), null);
412

    
413
        }
414
        return northPanel;
415
    }
416

    
417
    private ColorChooserPanel getDotColorChooserPanel() {
418
            if (jcc == null) {
419
                    jcc = new ColorChooserPanel() ;
420
                    jcc.setAlpha(255);
421
            }
422
            return jcc;
423
        }
424

    
425
        /**
426
     * This method initializes southPanel
427
     *
428
     * @return javax.swing.JPanel
429
     */
430
    private JPanel getDensityButtonsPanel() {
431
        if (densityButtonsPanel == null) {
432
                densityButtonsPanel = new GridBagLayoutPanel();
433
                LayoutManager layout = new FlowLayout(FlowLayout.LEADING, 0,0);
434
                JPanel aux = new JPanel(layout);
435
                aux.add(getNumDotSize());
436
                densityButtonsPanel.addComponent(
437
                                PluginServices.getText(this, "dot_size"), aux);
438
                aux = new JPanel(layout);
439
                aux.add(getNmbrDotValue());
440
            densityButtonsPanel.addComponent(
441
                            PluginServices.getText(this,"dot_value"), aux);
442
            aux = new JPanel(layout);
443
            aux.add(getDotColorChooserPanel());
444
            densityButtonsPanel.addComponent(
445
                            PluginServices.getText(this, "color"), aux);
446
            aux = new JPanel(layout);
447
            aux.add(getBtnOutline());
448
            densityButtonsPanel.addComponent(
449
                            PluginServices.getText(this, "outline_color"), aux);
450
        }
451
        return densityButtonsPanel;
452
    }
453

    
454
        private JSymbolPreviewButton getBtnOutline() {
455
                if (btnOutline == null) {
456
                        btnOutline = new JSymbolPreviewButton(FShape.LINE);
457
                        btnOutline.setPreferredSize(new Dimension(100, 35));
458
                }
459
                return btnOutline;
460
        }
461

    
462
        /**
463
     * This method initializes pnlDensities
464
     *
465
     * @return javax.swing.JPanel
466
     */
467
    private JPanel getPnlDensities() {
468
        if (pnlDensities == null) {
469
            pnlDensities = new JPanel(new BorderLayout(5,0));
470
            pnlDensities.setBorder(BorderFactory.createTitledBorder(null,
471
                                        PluginServices.getText(this, "densities")));
472
            JPanel aux2 = new JPanel();
473
            JPanel aux;
474
                        aux = new JPanel(new GridLayout(1,3));
475
            aux.add(new JLabel(PluginServices.getText(this, "high")));
476
            aux.add(new JLabel(PluginServices.getText(this, "medium")));
477
            aux.add(new JLabel(PluginServices.getText(this, "low")));
478

    
479
            aux2.add(aux);
480

    
481
                        aux = new JPanel(new GridLayout(1,3));
482
            aux.add(getRdBtnHigh());
483
            aux.add(getRdBtnMedium());
484
            aux.add(getRdBtnLow());
485

    
486
            aux2.add(aux);
487
            aux2.setLayout(new BoxLayout(aux2, BoxLayout.Y_AXIS));
488

    
489
            pnlDensities.add(aux2, BorderLayout.NORTH);
490
            pnlDensities.add(getSldDensity(), BorderLayout.CENTER);
491
            pnlDensities.add(getDensityButtonsPanel(), BorderLayout.SOUTH);
492

    
493
            ButtonGroup group = new ButtonGroup();
494
            group.add(getRdBtnHigh());
495
            group.add(getRdBtnLow());
496
            group.add(getRdBtnMedium());
497
            getRdBtnMedium().setSelected(true);
498
        }
499
        return pnlDensities;
500
    }
501

    
502

    
503
        /**
504
     * This method initializes cmbLegendField
505
     *
506
     * @return javax.swing.JComboBox
507
     */
508
    private JComboBox getCmbLegendField() {
509
        if (cmbLegendField == null) {
510
            cmbLegendField = new JComboBox();
511
            cmbLegendField.addActionListener(cmbAction);
512
        }
513
        return cmbLegendField;
514
    }
515

    
516
    /**
517
     * This method initializes rdBtnHigh
518
     *
519
     * @return javax.swing.JRadioButton
520
     */
521
    private JRadioButton getRdBtnHigh() {
522
        if (rdBtnHigh == null) {
523
            rdBtnHigh = new JRadioButton(new ImageIcon(
524
                            getClass().getClassLoader().
525
                                    getResource("images/high-density-sample.png")));
526
            rdBtnHigh.addActionListener(buttonsListener);
527
        }
528
        return rdBtnHigh;
529
    }
530

    
531
    /**
532
     * This method initializes rdBtnMedium
533
     *
534
     * @return javax.swing.JRadioButton
535
     */
536
    private JRadioButton getRdBtnMedium() {
537
        if (rdBtnMedium == null) {
538
            rdBtnMedium = new JRadioButton(new ImageIcon(
539
                            getClass().getClassLoader().
540
                                getResource("images/medium-density-sample.png")));
541
            rdBtnMedium.addActionListener(buttonsListener);
542
        }
543
        return rdBtnMedium;
544
    }
545

    
546
    /**
547
     * This method initializes rdBtnMax
548
     *
549
     * @return javax.swing.JRadioButton
550
     */
551
    private JRadioButton getRdBtnLow() {
552
        if (rdBtnLow == null) {
553
            rdBtnLow = new JRadioButton(new ImageIcon(
554
                            getClass().getClassLoader().
555
                                getResource("images/low-density-sample.png")));
556
            rdBtnLow.addActionListener(buttonsListener);
557
        }
558
        return rdBtnLow;
559
    }
560

    
561
    /**
562
     * This method initializes numDotSize
563
     *
564
     * @return de.ios.framework.swing.JNumberField
565
     */
566
    private JTextField getNumDotSize() {
567
        if (numDotSize == null) {
568
            numDotSize = new JTextField(4);
569
        }
570
        return numDotSize;
571
    }
572

    
573
        /**
574
         * This method initializes nmbrDotValue
575
         *
576
         * @return de.ios.framework.swing.JNumberField
577
         */
578
        private JTextField getNmbrDotValue() {
579
                if (nmbrDotValue == null) {
580
                        nmbrDotValue = new JTextField(15);
581

    
582
                }
583
                return nmbrDotValue;
584
        }
585

    
586
        /**
587
         * This method initializes centerPanel
588
         *
589
         * @return javax.swing.JPanel
590
         */
591
        private JPanel getCenterPanel() {
592
                if (centerPanel == null) {
593
                        centerPanel = new JPanel();
594
                        centerPanel.setLayout(new BorderLayout(5, 5));
595
                        centerPanel.add(getPnlDensities(), java.awt.BorderLayout.WEST);
596
                }
597
                return centerPanel;
598
        }
599

    
600
        /**
601
         * This method initializes sldDensity
602
         *
603
         * @return javax.swing.JSlider
604
         */
605
        private JSlider getSldDensity() {
606
                if (sldDensity == null) {
607
                        sldDensity = new JSlider();
608
                        sldDensity.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
609
                        sldDensity.addChangeListener(sldListener);
610
                }
611
                return sldDensity;
612
        }
613

    
614
        public String getDescription() {
615
                return PluginServices.getText(this,"Defines_a_dot_density_symbol_based_on_a_field_value") + ".";
616
        }
617

    
618
        public ISymbol getPreviewSymbol() {
619
                // TODO Implement it
620
                return null;
621
        }
622

    
623
        public Class getParentClass() {
624
                return Quantities.class;
625
        }
626

    
627
        public String getTitle() {
628
                return PluginServices.getText(this, "dot_density");
629
        }
630

    
631
        public JPanel getPanel() {
632
                return this;
633
        }
634

    
635
        public Class getLegendClass() {
636
                return DotDensityLegend.class;
637
        }
638

    
639
}  //  @jve:decl-index=0:visual-constraint="10,10"