Statistics
| Revision:

root / tags / v2_0_0_Build_2051 / extensions / extWFS2 / src / org / gvsig / wfs / gui / panels / WFSSelectFeaturePanel.java @ 38727

History | View | Annotate | Download (37.7 KB)

1
package org.gvsig.wfs.gui.panels;
2

    
3
import java.awt.Color;
4
import java.awt.Component;
5
import java.awt.Graphics;
6
import java.awt.Point;
7
import java.awt.Rectangle;
8
import java.awt.event.MouseAdapter;
9
import java.awt.event.MouseEvent;
10
import java.text.Collator;
11
import java.util.Collections;
12
import java.util.Locale;
13
import java.util.Vector;
14

    
15
import javax.swing.DefaultListSelectionModel;
16
import javax.swing.JCheckBox;
17
import javax.swing.JComponent;
18
import javax.swing.JLabel;
19
import javax.swing.JPanel;
20
import javax.swing.JScrollPane;
21
import javax.swing.JTable;
22
import javax.swing.JTextField;
23
import javax.swing.ListSelectionModel;
24
import javax.swing.UIManager;
25
import javax.swing.event.DocumentEvent;
26
import javax.swing.event.DocumentListener;
27
import javax.swing.event.ListSelectionListener;
28
import javax.swing.plaf.basic.BasicTableHeaderUI;
29
import javax.swing.table.AbstractTableModel;
30
import javax.swing.table.DefaultTableCellRenderer;
31
import javax.swing.table.TableCellRenderer;
32
import javax.swing.table.TableColumn;
33
import javax.swing.table.TableColumnModel;
34
import javax.swing.table.TableModel;
35

    
36
import org.gvsig.andami.PluginServices;
37
import org.gvsig.andami.messages.NotificationManager;
38
import org.gvsig.gui.beans.panelGroup.IPanelGroup;
39
import org.gvsig.remoteclient.wfs.WFSFeatureField;
40
import org.gvsig.utils.StringComparator;
41
import org.gvsig.wfs.gui.panels.WFSSelectFeaturePanel.LayerTable.LayerTableModel;
42
import org.gvsig.wfs.gui.panels.model.WFSSelectedFeature;
43
import org.gvsig.wfs.gui.wizards.WFSWizard;
44

    
45

    
46
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
47
 *
48
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
49
 *
50
 * This program is free software; you can redistribute it and/or
51
 * modify it under the terms of the GNU General Public License
52
 * as published by the Free Software Foundation; either version 2
53
 * of the License, or (at your option) any later version.
54
 *
55
 * This program is distributed in the hope that it will be useful,
56
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
57
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
58
 * GNU General Public License for more details.
59
 *
60
 * You should have received a copy of the GNU General Public License
61
 * along with this program; if not, write to the Free Software
62
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
63
 *
64
 * For more information, contact:
65
 *
66
 *  Generalitat Valenciana
67
 *   Conselleria d'Infraestructures i Transport
68
 *   Av. Blasco Ib??ez, 50
69
 *   46010 VALENCIA
70
 *   SPAIN
71
 *
72
 *      +34 963862235
73
 *   gvsig@gva.es
74
 *      www.gvsig.gva.es
75
 *
76
 *    or
77
 *
78
 *   IVER T.I. S.A
79
 *   Salamanca 50
80
 *   46005 Valencia
81
 *   Spain
82
 *
83
 *   +34 963163400
84
 *   dac@iver.es
85
 */
86
/* CVS MESSAGES:
87
 *
88
 * $Id: WFSSelectFeaturePanel.java 18799 2008-02-12 16:53:03Z vcaballero $
89
 * $Log$
90
 * Revision 1.19  2007-09-19 16:14:50  jaume
91
 * removed unnecessary imports
92
 *
93
 * Revision 1.18  2007/03/15 13:34:16  ppiqueras
94
 * Eliminado mensaje de aviso no necesario.
95
 *
96
 * Revision 1.17  2007/03/05 13:49:42  ppiqueras
97
 * Si una capa WFS no tiene campos (y por tanto no tiene un campo obligatorio de tipo geometr?a), que avise al usuario y no permita que se intente cargar dicha capa.
98
 *
99
 * Revision 1.16  2007/02/22 12:25:09  ppiqueras
100
 * A?adidas tool tip text.
101
 *
102
 * Revision 1.15  2007/02/09 14:12:39  jorpiell
103
 * Soporte para WFS 1.1 y WFS-T
104
 *
105
 * Revision 1.14  2007/02/07 13:26:23  ppiqueras
106
 * Corregido bug: al seleccionar una feature, pero sin cerrar el di?logo, se retrocede y se conecta a otro servidor,  se manten?a la posici?n seleccionada en la tabla de features. Se ha solucionado haciendo que se quede deseleccionada toda la tabla de features.
107
 *
108
 * Revision 1.13  2007/01/23 13:12:43  ppiqueras
109
 * Corregido un peque?o bug: el ?rea de texto del nombre de la feature no debe ser editable, dado que si se edita no procesa el texto escrito.
110
 *
111
 * Revision 1.12  2007/01/15 14:16:22  ppiqueras
112
 * Corregido bug: no cargaba los campos al principio y adem?s se ejecutaba m?s de una vez.
113
 *
114
 * Revision 1.11  2006/12/15 13:57:34  ppiqueras
115
 * eliminado un import que sobraba
116
 *
117
 * Revision 1.10  2006/12/12 10:24:45  ppiqueras
118
 * Nueva funcionalidad: Pulsando doble 'click' sobre una capa de un servidor, se carga (igual que antes), pero adem?s se avanza a la siguiente pesta?a sin tener que pulsar el bot?n 'Siguiente'.
119
 *
120
 * Revision 1.9  2006/12/04 08:59:47  ppiqueras
121
 * Algunos bugs corregidos. A cambio hay 2 bugs relacionados que todav?a no han sido corregidos (ver PHPCollab) (los tiene asignados Jorge).
122
 *
123
 * Revision 1.8  2006/10/27 06:44:56  jorpiell
124
 * Se han cambiado algunas etiquetas de texto que sal?an recortadas
125
 *
126
 * Revision 1.7  2006/07/21 11:50:31  jaume
127
 * improved appearance
128
 *
129
 * Revision 1.6  2006/06/21 12:35:45  jorpiell
130
 * Se ha a?adido la ventana de propiedades. Esto implica a?adir listeners por todos los paneles. Adem?s no se muestra la geomatr?a en la lista de atributos y se muestran ?nicamnete los que se van a descargar
131
 *
132
 * Revision 1.5  2006/05/25 10:31:06  jorpiell
133
 * Como ha cambiado la forma de mostrar las capas (una tabla, en lugar de una lista), los paneles han tenido que ser modificados
134
 *
135
 * Revision 1.4  2006/05/23 08:09:39  jorpiell
136
 * Se ha cambiado la forma en la que se leian los valores seleccionados en los paneles y se ha cambiado el comportamiento de los botones
137
 *
138
 * Revision 1.3  2006/05/19 12:57:08  jorpiell
139
 * Modificados algunos paneles
140
 *
141
 * Revision 1.2  2006/04/20 16:38:24  jorpiell
142
 * Ahora mismo ya se puede hacer un getCapabilities y un getDescribeType de la capa seleccionada para ver los atributos a dibujar. Queda implementar el panel de opciones y hacer el getFeature().
143
 *
144
 *
145
 */
146

    
147

    
148
/**
149
 * <p>Panel where user can select a feature type to load as a WFS layer.</p>
150
 * 
151
 * @author Jorge Piera Llodr? (piera_jor@gva.es)
152
 * @author Pablo Piqueras Bartolom? (pablo.piqueras@iver.es)
153
 */
154
public class WFSSelectFeaturePanel extends AbstractWFSPanel {
155
        private static final long serialVersionUID = -3781080396069038450L;
156
        private JPanel featureListPanel = null;
157
        private JScrollPane jScrollPane = null;
158
        private LayerTable lstFeatures = null;
159
        private JTextField txtName = null;
160
        private JCheckBox chkExtendedNames = null;
161
        private JPanel layerNamePanel = null;
162
        private WFSSelectedFeature layerNode = null;
163
        private ListSelectionListener listSelectionListener = null;
164

    
165
        /**
166
         * Creates a new WFS select feature panel.
167
         */
168
        public WFSSelectFeaturePanel() {
169
                super();
170
                initialize();
171
        }
172

    
173
        /**
174
         * This method initializes coveragesListPanel
175
         *
176
         * @return javax.swing.JPanel
177
         */
178
        private JPanel getFeaturesListPanel() {
179
                if (featureListPanel == null) {
180
                        java.awt.GridBagConstraints gridBagConstraints;
181
                        featureListPanel = new JPanel();
182
                        featureListPanel.setLayout(new java.awt.GridBagLayout());
183
                        featureListPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(
184
                                        null, PluginServices.getText(this, "select_features"),
185
                                        javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
186
                                        javax.swing.border.TitledBorder.DEFAULT_POSITION, null, null));
187

    
188
                        gridBagConstraints = new java.awt.GridBagConstraints();
189
                        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
190
                        gridBagConstraints.weightx = 1.0;
191
                        gridBagConstraints.weighty = 1.0;
192
                        featureListPanel.add(getJScrollPane(), gridBagConstraints);
193
                }
194

    
195
                return featureListPanel;
196
        }
197

    
198
        /**
199
         * This method initializes jScrollPane
200
         *
201
         * @return javax.swing.JScrollPane
202
         */
203
        private JScrollPane getJScrollPane() {
204
                if (jScrollPane == null) {
205
                        jScrollPane = new JScrollPane();                
206
                        jScrollPane.setViewportView(getLstFeatures());
207
                        jScrollPane.setToolTipText(PluginServices.getText(jScrollPane, "feature_Selection_Info"));
208
                }
209

    
210
                return jScrollPane;
211
        }
212

    
213
        /**
214
         * This method initializes lstFeatures
215
         *
216
         * @return javax.swing.LayerTable
217
         */
218
        public LayerTable getLstFeatures() {
219
                if (lstFeatures == null) {
220
                        lstFeatures = new LayerTable();
221
                        lstFeatures.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
222
                        lstFeatures.getSelectionModel().addListSelectionListener(getListSelectionListener());
223
                        lstFeatures.setToolTipText(PluginServices.getText(lstFeatures, "feature_Selection_Info"));
224

    
225
                        // Double-click -> click the 'Next' button
226
                        lstFeatures.addMouseListener(new MouseAdapter() {
227
                                /*
228
                                 *  (non-Javadoc)
229
                                 * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
230
                                 */
231
                                public void mouseClicked(MouseEvent e) {
232
                                        if (e.getClickCount() == 2) {
233
                                                Object obj = getPanelGroup();
234

    
235
                                                if ((obj != null) && (obj instanceof WFSParamsPanel))
236
                                                        ((WFSParamsPanel)obj).doClickOnNextButton();
237
                                        }
238
                                }                        
239
                        });
240
                }
241

    
242
                return lstFeatures;
243
        }
244
        
245
    public int getSelectedFeaturesCount() {
246

    
247
        if (lstFeatures == null) {
248
            return 0;
249
        }
250
        
251
        ListSelectionModel m = lstFeatures.getSelectionModel();
252
        if (m == null || m.isSelectionEmpty()) {
253
            return 0;
254
        } else {
255
            int resp = 0;
256
            for (int i = m.getMinSelectionIndex();
257
                i <= m.getMaxSelectionIndex();
258
                i++) {
259

    
260
                if (m.isSelectedIndex(i)) {
261
                    resp++;
262
                }
263
            }
264
            return resp;
265
        }
266

    
267
    }
268

    
269
        /**
270
         * Creates the list selection listener for the layers list
271
         * 
272
         * @return the listener
273
         */
274
        private ListSelectionListener getListSelectionListener(){
275
                if (listSelectionListener == null){
276
                        listSelectionListener = new ListSelectionListener(){
277
                                public void valueChanged(javax.swing.event.ListSelectionEvent e) {
278
                                        DefaultListSelectionModel model = (DefaultListSelectionModel) e.getSource();
279
                                        LayerTableModel t_model = ((LayerTableModel)lstFeatures.getModel());
280
                                        if (t_model.isUpdatingSelection())
281
                                                return;
282

    
283
                                        // With this condition we force to execute the updating only when a row has been selected by the user
284
                                        if ((model.getMinSelectionIndex() > -1) && (e.getValueIsAdjusting() == false)) {
285
                                                // Indicate that now we are loading a new layer
286
                                                IPanelGroup panelGroup = getPanelGroup();
287

    
288
                                                if (panelGroup == null)
289
                                                        return;
290

    
291
                                                if (((WFSParamsPanel)panelGroup).getFilterPanel() == null)
292
                                                        return;
293
                        
294
                                                refreshData();
295
                                        }
296
                                        
297
                    // =============================================
298
                    // If zero selected, settings are invalid
299
                                        int n_sel = getSelectedFeaturesCount();
300
                                        if (n_sel == 0) {
301
                               Object obj = getPanelGroup();
302
                               if (obj != null && obj instanceof WFSParamsPanel) {
303
                                   obj = ((WFSParamsPanel) obj).getParent();
304
                                   if (obj instanceof WFSWizard) {
305
                                       ((WFSWizard) obj).callStateChanged(false); 
306
                                   }
307
                               }
308
                                        }
309
                                        // =============================================
310
                                }
311
                        };        
312
                }
313

    
314
                return listSelectionListener;
315
        }
316

    
317
        /**
318
         * This method initializes jTextField
319
         *
320
         * @return javax.swing.JTextField
321
         */
322
        public JTextField getTxtName() {
323
                if (txtName == null) {
324
                        txtName = new JTextField();
325
                        txtName.setBounds(6, 19, 472, 20);
326
                        txtName.setText(PluginServices.getText(this, "WFSLayer"));
327
                        txtName.setEditable(false);
328
                        txtName.setBackground(Color.WHITE);
329
                        txtName.setToolTipText(PluginServices.getText(txtName, "feature_to_load"));
330

    
331
                        txtName.getDocument().addDocumentListener(new DocumentListener() {
332
                                /*
333
                                 * (non-Javadoc)
334
                                 * @see javax.swing.event.DocumentListener#changedUpdate(javax.swing.event.DocumentEvent)
335
                                 */
336
                                public void changedUpdate(DocumentEvent e) {
337
                                }
338

    
339
                                /*
340
                                 * (non-Javadoc)
341
                                 * @see javax.swing.event.DocumentListener#insertUpdate(javax.swing.event.DocumentEvent)
342
                                 */
343
                                public void insertUpdate(DocumentEvent e) {
344
                                        IPanelGroup panelGroup = getPanelGroup();
345

    
346
                                        if (panelGroup == null)
347
                                                return;
348

    
349
                                        ((WFSParamsPanel)panelGroup).setApplicable(true);
350
                                }
351

    
352
                                /*
353
                                 * (non-Javadoc)
354
                                 * @see javax.swing.event.DocumentListener#removeUpdate(javax.swing.event.DocumentEvent)
355
                                 */
356
                                public void removeUpdate(DocumentEvent e) {
357
                                }
358
                        });
359
                }
360

    
361
                return txtName;
362
        }
363

    
364
        /**
365
         * This method initializes chkExtendedNames
366
         *
367
         * @return javax.swing.JCheckBox
368
         */
369
        private JCheckBox getChkExtendedNames() {
370
                if (chkExtendedNames == null) {
371
                        chkExtendedNames = new JCheckBox();
372
                        chkExtendedNames.setText(PluginServices.getText(this, "show_layer_names"));
373
                        chkExtendedNames.setBounds(10, 372, 382, 20);
374
                        chkExtendedNames.addItemListener(new java.awt.event.ItemListener() {
375
                                /*
376
                                 * (non-Javadoc)
377
                                 * @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent)
378
                                 */
379
                                public void itemStateChanged(java.awt.event.ItemEvent e) {
380
                                        boolean b = chkExtendedNames.isSelected();
381
                                        getLstFeatures().setShowLayerNames(b);
382
                                        getLstFeatures().repaint();
383
                                }
384
                        });
385
                }
386

    
387
                return chkExtendedNames;
388
        }
389

    
390
        /**
391
         * Set the selected layer node
392
         * 
393
         * @param layerNode the layer to select
394
         */
395
        public void setSelectedFeature(WFSSelectedFeature layerNode){
396
                int index = -1;
397

    
398
                for (int i=0; i<getLstFeatures().getRowCount(); i++){
399
                        WFSSelectedFeature node = (WFSSelectedFeature)getLstFeatures().getValueAt(i);
400

    
401
                        if (node != null && layerNode.getName().equals(node.getName())){
402
                                index = i;
403
                        }
404
                }
405

    
406
                if (index != -1){
407
                        getLstFeatures().changeSelection(index, 0, false, false);
408
                }
409
        }
410

    
411
        /**
412
         * Refresh the features list
413
         */
414
        public void refresh(WFSSelectedFeature layer) {
415
                // Unselects all features
416
                unselectAllFeatures();
417

    
418
                // Add the new features
419
                getLstFeatures().addFeatures(getSelectedFeatureManager().getLayerList());
420

    
421
                if (layer != null) {
422
                        layerNode = layer;
423
                        setLayerName(layer.getName());
424
                        setSelectedFeature(layer);                        
425
                }                
426
        }
427

    
428
        /**
429
         * Refreshes the wizard components data each time a feature
430
         * is selected. The <i>describeFeatureType</i> operation must be sent.
431
         */
432
        public void refreshData() {
433
                WFSSelectedFeature lyr = (WFSSelectedFeature)getLstFeatures().getSelectedValue();
434

    
435
                try {
436
                        getTxtName().setText(lyr.getTitle());
437
                } catch (NullPointerException e){
438
                        getTxtName().setText(PluginServices.getText(this,"default_name"));
439
                        NotificationManager.addError(PluginServices.getText(this,"default_name"), e);
440
                }
441

    
442
                IPanelGroup panelGroup = getPanelGroup();
443

    
444
                if (panelGroup == null)
445
                        return;
446

    
447
                ((WFSParamsPanel)panelGroup).refresh(lyr);
448

    
449
                repaint();
450
        }
451

    
452
        /**
453
         * This method initializes layerNamePanel
454
         *
455
         * @return javax.swing.JPanel
456
         */
457
        private JPanel getLayerNamePanel() {
458
                if (layerNamePanel == null) {
459
                        java.awt.GridBagConstraints gridBagConstraints;
460
                        layerNamePanel = new JPanel();
461
                        layerNamePanel.setLayout(new java.awt.GridBagLayout());
462
                        layerNamePanel.setBorder(javax.swing.BorderFactory.createTitledBorder(
463
                                        null, PluginServices.getText(this, "layer_name"),
464
                                        javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
465
                                        javax.swing.border.TitledBorder.DEFAULT_POSITION, null, null));                        
466
                        gridBagConstraints = new java.awt.GridBagConstraints();
467
                        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
468
                        gridBagConstraints.weightx = 1.0;
469
                        layerNamePanel.add(getTxtName(), gridBagConstraints);
470
                }
471

    
472
                return layerNamePanel;
473
        }
474

    
475
        /**
476
         * Gets the name of the layer (feature) selected.
477
         *
478
         * @return the layer name
479
         */
480
        public String getLayerName() {
481
                if ((WFSSelectedFeature)getLstFeatures().getSelectedValue() != null){
482
                        return ((WFSSelectedFeature)getLstFeatures().getSelectedValue()).getName();
483
                }
484
                return "";
485
        }
486

    
487
        /**
488
         * Gets the name space of the layer (feature) selected.
489
         *
490
         * @return the name space
491
         */
492
        public String getLayerNameSpace(){
493
                return ((WFSSelectedFeature)getLstFeatures().getSelectedValue()).getNameSpace();
494
        }
495

    
496
        /**
497
         * Gets the selected feature.
498
         * 
499
         * @return the selected feature
500
         */
501
        public WFSSelectedFeature getSelectedFeature() {
502
                WFSSelectedFeature selectedFeature = (WFSSelectedFeature)getLstFeatures().getSelectedValue();
503

    
504
                if (selectedFeature != null) {
505
                        layerNode = selectedFeature;
506
                }
507

    
508
                return layerNode;
509
        }
510

    
511
        /**
512
         * Sets the name of the feature selected.
513
         * 
514
         * @param name the name of the feature selected
515
         */
516
        public void setLayerName(String name) {
517
                getTxtName().setText(name);
518
        }
519

    
520
        /*
521
         * (non-Javadoc)
522
         * @see com.iver.cit.gvsig.gui.panels.AbstractWFSPanel#initialize()
523
         */
524
        protected void initialize() {
525
                setLabel(PluginServices.getText(this, "feature"));
526
                setLabelGroup(PluginServices.getText(this, "wfs"));
527
                java.awt.GridBagConstraints gridBagConstraints;
528
                this.setLayout(new java.awt.GridBagLayout());
529

    
530
                gridBagConstraints = new java.awt.GridBagConstraints();
531
                gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
532
                gridBagConstraints.weightx = 1.0;
533
                this.add(getLayerNamePanel(), gridBagConstraints);
534

    
535
                gridBagConstraints = new java.awt.GridBagConstraints();
536
                gridBagConstraints.gridx = 0;
537
                gridBagConstraints.gridy = 1;
538
                gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
539
                gridBagConstraints.weightx = 1.0;
540
                gridBagConstraints.weighty = 1.0;
541
                this.add(getFeaturesListPanel(), gridBagConstraints);
542

    
543
                gridBagConstraints = new java.awt.GridBagConstraints();
544
                gridBagConstraints.gridx = 0;
545
                gridBagConstraints.gridy = 2;
546
                gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
547
                gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
548
                gridBagConstraints.weightx = 1.0;
549
                this.add(getChkExtendedNames(), gridBagConstraints);                
550

    
551
        }
552

    
553
        /*
554
         * (non-Javadoc)
555
         * @see com.iver.cit.gvsig.gui.panels.AbstractWFSPanel#setReference(java.lang.Object)
556
         */
557
        public void setReference(Object ref) {
558
                super.setReference(ref);
559
                //                if (ref instanceof FLyrWFS){                        
560
                //                        getPanelGroup().setEnabledApplyButton(false);
561
                //                }                
562
        }        
563

    
564
        /**
565
         * Updates the list with no feature selected.
566
         */
567
        public void unselectAllFeatures() {
568
                // Reset the last row selection of the features table
569
                int numberOfFeatures = getLstFeatures().getRowCount();
570

    
571
                if (numberOfFeatures > 0) {                        
572
                        ListSelectionModel model = getLstFeatures().getSelectionModel();
573
                        model.removeSelectionInterval(0, numberOfFeatures - 1); // whatever row selection
574
                }
575
        }
576

    
577
        /**
578
         * Table with the information of all layers which could be selected from the server connected.
579
         * 
580
         * @author Pablo Piqueras Bartolom? (pablo.piqueras@iver.es)
581
         * @author Jorge Piera Llodr? (piera_jor@gva.es)
582
         */
583
        public class LayerTable extends JTable {
584
                private static final long serialVersionUID = 4700375945858283696L;
585
                private int headerSelected = -1; 
586

    
587
                /**
588
                 * Creates a new instance of <code>LayerTable</code>
589
                 */
590
                public LayerTable() {
591
                        super();
592

    
593
                        setModel(new LayerTableModel());
594

    
595
                        getTableHeader().setUI(new BasicTableHeaderSelectableUI());
596

    
597
                        getTableHeader().addMouseListener(new MouseAdapter() {
598
                                /*
599
                                 * (non-Javadoc)
600
                                 * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
601
                                 */
602
                                public void mouseClicked(MouseEvent e) {
603
                                        // Sorts according the selected column
604
                                        ((LayerTableModel)getModel()).sort(getTableHeader().getColumnModel().getColumnIndexAtX(e.getX()));
605
                                }
606

    
607
                                /*
608
                                 * (non-Javadoc)
609
                                 * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
610
                                 */
611
                                public void mousePressed(MouseEvent e) {
612
                                        headerSelected = getTableHeader().getColumnModel().getColumnIndexAtX(e.getX());
613
                                        getTableHeader().repaint();
614
                                }
615

    
616
                                /*
617
                                 * (non-Javadoc)
618
                                 * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
619
                                 */
620
                                public void mouseReleased(MouseEvent e) {
621
                                        headerSelected = -1;
622
                                }
623
                        });
624
                }
625

    
626
                /*
627
                 * (non-Javadoc)
628
                 * @see javax.swing.JTable#createDefaultColumnsFromModel()
629
                 */
630
                public void createDefaultColumnsFromModel() {
631
                        TableModel m = getModel();
632
                        if (m != null) {
633
                                // Remove any current columns
634
                                TableColumnModel cm = getColumnModel();
635
                                while (cm.getColumnCount() > 0) {
636
                                        cm.removeColumn(cm.getColumn(0));
637
                                }
638

    
639
                                // Create new columns from the data model info
640
                                for (int i = 0; i < m.getColumnCount(); i++) {
641
                                        TableColumn newColumn = new TableColumn(i);
642

    
643
                                        // Special renderer for supporting selection of a particular column header
644
                                        newColumn.setHeaderRenderer(new DefaultTableSelectableCellRenderer());
645
                                        addColumn(newColumn);
646
                                }
647
                        }
648
                }
649

    
650
                /**
651
                 * Gets the selected <i>WFS</i> layer.
652
                 * 
653
                 * @return node of the selected <i>WFS</i> layer
654
                 */
655
                public WFSSelectedFeature getSelectedValue() {
656
                        int selectedRow = getSelectedRow();
657
                        LayerTableModel model = (LayerTableModel)getModel();
658

    
659
                        return model.getLayerAt(selectedRow);
660
                }
661

    
662
                /**
663
                 * Gets the layer at a row position.
664
                 * 
665
                 * @return node of the selected <i>WFS</i> layer
666
                 */
667
                public WFSSelectedFeature getValueAt(int position) {
668
                        if (position < this.getRowCount()) {
669
                                LayerTableModel model = (LayerTableModel)getModel();
670

    
671
                                return model.getLayerAt(position);                        
672
                        }
673

    
674
                        return null;
675
                }
676

    
677
                /**
678
                 * Adds the available features to load as a <i>WFS</i> layer.
679
                 * 
680
                 * @param features available features
681
                 */
682
                public void addFeatures(WFSSelectedFeature[] features) {
683
                        LayerTableModel model = (LayerTableModel)getModel();
684
                        model.deleteAllRows();
685

    
686
                        for (int i=0 ; i < features.length ; i++){
687
                                model.addRow(features[i]);                        
688
                        }        
689
                }        
690

    
691
                /**
692
                 * Shows the names of the features.
693
                 * 
694
                 * @param showFeatureNameType The showLayerNames to set.
695
                 */
696
                public void setShowLayerNames(boolean showFeatureNameType) {
697
                        LayerTableModel model = (LayerTableModel)getModel();
698
                        model.setShowedFeatureNameType(showFeatureNameType);
699
                }
700

    
701
                /**
702
                 * Model of the <code>LayerTable</code> that stores the features available to load as a WFS layer.
703
                 * 
704
                 * @author Jorge Piera Llodr? (piera_jor@gva.es)
705
                 * @author Pablo Piqueras Bartolome (pablo.piqueras@iver.es)
706
                 */
707
                public class LayerTableModel extends AbstractTableModel {  
708
                        private static final long serialVersionUID = 2722138264867593508L;
709
                        private Vector<WFSSelectedFeature> layers = new Vector<WFSSelectedFeature>();
710
                        private boolean showFeatureNameType = false;
711
                        private WFSLayerStringComparator stringComparator;
712
                        private boolean updatingSelection;
713
                        private short previousColumnSorted;
714

    
715

    
716
                        /**
717
                         * Constructs an investment table model.
718
                         */
719
                        public LayerTableModel(){  
720
                                super();
721

    
722
                                // Alphabetical sort ordering support
723
                                updatingSelection = false;
724
                                previousColumnSorted = -1;
725
                                Collator collator = Collator.getInstance(new Locale("en_EN"));                
726
                                stringComparator = new WFSLayerStringComparator();
727
                                stringComparator.setLocaleRules(stringComparator.new LocaleRules(true, collator));
728
                                stringComparator.setCaseSensitive(false);
729
                                stringComparator.setAscendingOrdering(true);
730
                        }
731

    
732

    
733
                        /*
734
                         *  (non-Javadoc)
735
                         * @see javax.swing.table.TableModel#getRowCount()
736
                         */
737
                        public int getRowCount(){  
738
                                return layers.size();                
739
                        }
740

    
741
                        /*
742
                         *  (non-Javadoc)
743
                         * @see javax.swing.table.TableModel#getColumnCount()
744
                         */
745
                        public int getColumnCount(){  
746
                                return 2;
747
                        }
748

    
749
                        /*
750
                         *  (non-Javadoc)
751
                         * @see javax.swing.table.TableModel#getValueAt(int, int)
752
                         */
753
                        public Object getValueAt(int rowNumber, int columnNumber){  
754
                                if (rowNumber < layers.size()) {
755
                                        WFSSelectedFeature layer = (WFSSelectedFeature)layers.get(rowNumber);
756

    
757
                                        if (columnNumber == 0) {
758
                                                return getLayerName(layer);
759
                                        } else {
760
                                            if (layer.getGeometryField() != null){
761
                                                return PluginServices.getText(this, layer.getGeometryField().getType());
762
                                            }
763
                                                return "";
764
                                        }
765
                                } else {
766
                                        return "";
767
                                }
768
                        }        
769

    
770
                        /**
771
                         * Gets the layer name displaying the type name of the feature collection associated if it's needed.
772
                         * 
773
                         * @param layer a <i>WFS</i> layer 
774
                         * @return the layer name
775
                         */
776
                        private String getLayerName(WFSSelectedFeature layer){
777
                                if (showFeatureNameType){
778
                                        return "[" + layer.getName() + "] " + layer.getTitle(); 
779
                                } else {
780
                                        return layer.getTitle();
781
                                }
782
                        }
783

    
784
                        /**
785
                         * Gets the layer at the specified position.
786
                         * 
787
                         * @param rowNumber row position
788
                         * @return <i>WFS</i> layer node
789
                         */
790
                        public WFSSelectedFeature getLayerAt(int rowNumber){
791
                                try {
792
                                        if (rowNumber == -1)
793
                                                return null;
794

    
795
                                        return (WFSSelectedFeature)layers.get(rowNumber);
796
                                } catch (ArrayIndexOutOfBoundsException e) {
797
                                        NotificationManager.addError(e);
798
                                        return null;
799
                                }
800
                        }        
801

    
802
                        /**
803
                         * Adds a new layer to the table model, each table will be represented as a row.
804
                         *  
805
                         * @param layer a new <i>WFS</i> layer
806
                         */
807
                        public void addRow(WFSSelectedFeature layer){
808
                                layers.add(layer);
809
                                fireTableRowsInserted(getRowCount(), getRowCount());
810
                                fireTableRowsUpdated(0,getRowCount());
811
                        }
812

    
813
                        /**
814
                         * Deletes all the table rows.
815
                         */
816
                        public void deleteAllRows(){
817
                                layers.clear();
818
                                int rows = getRowCount();
819

    
820
                                if (rows >= 1){
821
                                        fireTableRowsDeleted(0, rows - 1);
822
                                }                
823
                        }        
824

    
825
                        /**
826
                         * Delete all the table rows
827
                         */
828
                        public void deleteRow(int rowPosition){
829
                                layers.remove(rowPosition);
830
                                fireTableRowsDeleted(rowPosition, rowPosition);
831
                                fireTableRowsUpdated(0,getRowCount());
832
                        }        
833

    
834
                        /*
835
                         *  (non-Javadoc)
836
                         * @see javax.swing.table.TableModel#getColumnName(int)
837
                         */
838
                        public String getColumnName(int columnIndex){
839
                                if (columnIndex == 0){
840
                                        return PluginServices.getText(this, "layerName");
841
                                }else{
842
                                        return PluginServices.getText(this, "layerType");
843
                                }
844
                        }
845

    
846
                        /**
847
                         * Gets if shows the feature name type.
848
                         * 
849
                         * @return <code>true</code> if shows the feature name type; <code>false</code> otherwise
850
                         */
851
                        public boolean isShowedFeatureNameType() {
852
                                return showFeatureNameType;
853
                        }
854

    
855
                        /**
856
                         * Gets if shows the feature name type.
857
                         * 
858
                         * @param showFeatureNameType <code>true</code> if shows the feature name type; <code>false</code> otherwise
859
                         */
860
                        public void setShowedFeatureNameType(boolean showFeatureNameType) {
861
                                this.showFeatureNameType = showFeatureNameType;
862

    
863
                                this.stringComparator.setShowFeatureNameType(showFeatureNameType);
864
                        }
865

    
866
                        /**
867
                         * Sorts the rows of the table alphabetically.
868
                         * 
869
                         * @param column index of the column to sort. In this table there are only 2 columns.
870
                         */
871
                        public void sort(int column) {
872
                                // Orders the layer alphabetically according the Spanish alphabetically rules 
873
                                switch(column) {
874
                                case 0:
875
                                        stringComparator.setColumn(WFSLayerStringComparator.LAYER_NAME);
876
                                        break;
877
                                case 1:
878
                                        stringComparator.setColumn(WFSLayerStringComparator.GEOMETRY_TYPE);
879
                                        break;
880
                                }
881

    
882
                                if (previousColumnSorted != column)
883
                                        stringComparator.setAscendingOrdering(true);
884

    
885
                                previousColumnSorted = (short) column;
886

    
887
                                WFSSelectedFeature layer = getSelectedValue();
888

    
889
                                Collections.sort(layers, stringComparator);
890

    
891
                                if (layer != null) {
892
                                        updatingSelection = true;
893
                                        unselectAllFeatures();
894
                                        int row = Collections.binarySearch(layers, layer, stringComparator);
895

    
896
                                        if (row != -1) {
897
                                                ListSelectionModel model = getSelectionModel();
898
                                                model.setLeadSelectionIndex(row);
899
                                        }
900

    
901
                                        updatingSelection = false;
902
                                }
903
                                stringComparator.setAscendingOrdering(!stringComparator.isAscendingOrdering());
904
                        }
905

    
906
                        /**
907
                         * Determines if now is updating the selection of the previous selected item.
908
                         * 
909
                         * @return <code>true</code> if now is updating the selection of the previous selected item; otherwise <code>false</code>
910
                         */
911
                        public boolean isUpdatingSelection() {
912
                                return updatingSelection;
913
                        }
914
                }
915

    
916
                /**
917
                 * <p>Enhances {@link BasicTableHeaderUI BasicTableHeaderUI} adding support for column head selection.</p>
918
                 * 
919
                 * @see BasicTableHeaderUI
920
                 *
921
                 * @version 29/01/2008
922
                 * @author Pablo Piqueras Bartolom? (pablo.piqueras@iver.es) 
923
                 */
924
                private class BasicTableHeaderSelectableUI extends BasicTableHeaderUI {
925
                        /**
926
                         * Creates a new BasicTableHeaderSelectableUI object
927
                         */
928
                        public BasicTableHeaderSelectableUI() {
929
                                super();
930
                        }
931

    
932
                        //
933
                        // Some Paint Methods and support re-implemented
934
                        //
935

    
936
                        /*
937
                         * (non-Javadoc)
938
                         * @see javax.swing.plaf.basic.BasicTableHeaderUI#paint(java.awt.Graphics, javax.swing.JComponent)
939
                         */
940
                        public void paint(Graphics g, JComponent c) {
941
                                if (header.getColumnModel().getColumnCount() <= 0) { 
942
                                        return; 
943
                                }
944

    
945
                                boolean ltr = header.getComponentOrientation().isLeftToRight();
946

    
947
                                Rectangle clip = g.getClipBounds(); 
948
                                Point left = clip.getLocation();
949
                                Point right = new Point( clip.x + clip.width - 1, clip.y );
950
                                TableColumnModel cm = header.getColumnModel(); 
951
                                int cMin = header.columnAtPoint( ltr ? left : right );
952
                                int cMax = header.columnAtPoint( ltr ? right : left );
953
                                // This should never happen. 
954
                                if (cMin == -1) {
955
                                        cMin =  0;
956
                                }
957
                                // If the table does not have enough columns to fill the view we'll get -1.
958
                                // Replace this with the index of the last column.
959
                                if (cMax == -1) {
960
                                        cMax = cm.getColumnCount()-1;  
961
                                }
962

    
963
                                TableColumn draggedColumn = header.getDraggedColumn(); 
964
                                int columnWidth;
965
                                Rectangle cellRect = header.getHeaderRect(ltr ? cMin : cMax); 
966
                                TableColumn aColumn;
967
                                if (ltr) {
968
                                        for(int column = cMin; column <= cMax ; column++) { 
969
                                                aColumn = cm.getColumn(column); 
970
                                                columnWidth = aColumn.getWidth();
971
                                                cellRect.width = columnWidth;
972
                                                if (aColumn != draggedColumn) {
973
                                                        paintCell(g, cellRect, column);
974
                                                } 
975
                                                cellRect.x += columnWidth;
976
                                        }
977
                                } else {
978
                                        for(int column = cMax; column >= cMin; column--) {
979
                                                aColumn = cm.getColumn(column);
980
                                                columnWidth = aColumn.getWidth();
981
                                                cellRect.width = columnWidth;
982
                                                if (aColumn != draggedColumn) {
983
                                                        paintCell(g, cellRect, column);
984
                                                }
985
                                                cellRect.x += columnWidth;
986
                                        }
987
                                } 
988

    
989
                                // Paint the dragged column if we are dragging. 
990
                                if (draggedColumn != null) { 
991
                                        int draggedColumnIndex = viewIndexForColumn(draggedColumn); 
992
                                        Rectangle draggedCellRect = header.getHeaderRect(draggedColumnIndex); 
993

    
994
                                        // Draw a gray well in place of the moving column. 
995
                                        g.setColor(header.getParent().getBackground());
996
                                        g.fillRect(draggedCellRect.x, draggedCellRect.y,
997
                                                        draggedCellRect.width, draggedCellRect.height);
998

    
999
                                        draggedCellRect.x += header.getDraggedDistance();
1000

    
1001
                                        // Fill the background. 
1002
                                        g.setColor(header.getBackground());
1003
                                        g.fillRect(draggedCellRect.x, draggedCellRect.y,
1004
                                                        draggedCellRect.width, draggedCellRect.height);
1005

    
1006
                                        paintCell(g, draggedCellRect, draggedColumnIndex);
1007
                                }
1008

    
1009
                                // Remove all components in the rendererPane. 
1010
                                rendererPane.removeAll(); 
1011
                        }
1012

    
1013
                        private void paintCell(Graphics g, Rectangle cellRect, int columnIndex) {
1014
                                Component component = getHeaderRenderer(columnIndex); 
1015
                                rendererPane.paintComponent(g, component, header, cellRect.x, cellRect.y,
1016
                                                cellRect.width, cellRect.height, true);
1017
                        }
1018

    
1019
                        private Component getHeaderRenderer(int columnIndex) { 
1020
                                TableColumn aColumn = header.getColumnModel().getColumn(columnIndex); 
1021
                                TableCellRenderer renderer = aColumn.getHeaderRenderer();
1022

    
1023
                                if (renderer == null) { 
1024
                                        renderer = header.getDefaultRenderer(); 
1025
                                }
1026

    
1027
                                if (headerSelected == columnIndex) {
1028
                                        headerSelected = -1;
1029
                                        return renderer.getTableCellRendererComponent(header.getTable(), aColumn.getHeaderValue(), true, false, -1, columnIndex);
1030
                                }
1031
                                else {
1032
                                        return renderer.getTableCellRendererComponent(header.getTable(), aColumn.getHeaderValue(), false, false, -1, columnIndex);
1033
                                }
1034
                        }
1035

    
1036
                        private int viewIndexForColumn(TableColumn aColumn) {
1037
                                TableColumnModel cm = header.getColumnModel();
1038

    
1039
                                for (int column = 0; column < cm.getColumnCount(); column++) {
1040
                                        if (cm.getColumn(column) == aColumn) {
1041
                                                return column;
1042
                                        }
1043
                                }
1044

    
1045
                                return -1;
1046
                        }
1047
                }
1048

    
1049
                /**
1050
                 * <p>Simulates the selection / unselection of the head of the column clicked.</p>
1051
                 * 
1052
                 * @version 29/01/2008
1053
                 * @author Pablo Piqueras Bartolom? (pablo.piqueras@iver.es) 
1054
                 */
1055
                private class DefaultTableSelectableCellRenderer extends DefaultTableCellRenderer {
1056
                        private static final long serialVersionUID = -3896516869747447668L;
1057

    
1058
                        /*
1059
                         * (non-Javadoc)
1060
                         * @see javax.swing.table.DefaultTableCellRenderer#getTableCellRendererComponent(javax.swing.JTable, java.lang.Object, boolean, boolean, int, int)
1061
                         */
1062
                        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
1063
                                Component comp = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
1064

    
1065
                                Color bgColor = getTableHeader().getBackground();
1066

    
1067
                                if (isSelected)
1068
                                        comp.setBackground(new Color(bgColor.getRed() - 10 , bgColor.getGreen() - 10, bgColor.getBlue() - 10));
1069
                                else
1070
                                        comp.setBackground(bgColor);
1071

    
1072
                                ((JLabel)comp).setText((value == null) ? "" : value.toString());
1073
                                ((JLabel)comp).setBorder(UIManager.getBorder("TableHeader.cellBorder"));
1074

    
1075
                                return comp;
1076
                        }
1077
                }
1078

    
1079
                /**
1080
                 * Compares two chain of characters alphabetically, bearing in mind the information of a WFS layer.
1081
                 * 
1082
                 * @version 24/01/2008
1083
                 * @author Pablo Piqueras Bartolom? (pablo.piqueras@iver.es) 
1084
                 */
1085
                private class WFSLayerStringComparator extends StringComparator {
1086
                        public static final short LAYER_NAME = 0;
1087
                        public static final short GEOMETRY_TYPE = 1;
1088

    
1089
                        protected short column = LAYER_NAME; // by default the first column
1090
                        protected boolean showFeatureNameType = false; // by default doesn't shows the feature name type
1091
                        protected boolean ascendingOrdering = true; // by default: ascending ordering
1092

    
1093
                        /*
1094
                         * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
1095
                         */
1096
                        public int compare(Object o1, Object o2) {
1097
                                String s1 = null, s2 = null;
1098

    
1099
                                switch(column) {
1100
                                case LAYER_NAME:
1101
                                        if (ascendingOrdering) {
1102
                                                s1 = o1.toString();
1103
                                                s2 = o2.toString();
1104
                                        }
1105
                                        else {
1106
                                                s1 = o2.toString();
1107
                                                s2 = o1.toString();
1108
                                        }
1109

    
1110
                                        if (showFeatureNameType) {
1111
                                                if (ascendingOrdering) {
1112
                                                        return super.compare(o1, o2);
1113
                                                }
1114
                                                else {
1115
                                                        return super.compare(o2, o1);
1116
                                                }
1117
                                        }
1118

    
1119
                                        // Only if "showFeatureNameType == true" :
1120
                                        int index = s1.indexOf(']');
1121

    
1122
                                        if (index > 0)
1123
                                                s1 = s1.substring(index, s1.length()).trim();
1124
                                        else
1125
                                                s1 = s1.trim();
1126

    
1127
                                        index = s2.indexOf(']');
1128

    
1129
                                        if (index > 0)
1130
                                                s2 = s2.substring(index, s2.length()).trim();
1131
                                        else
1132
                                                s2 = s2.trim();
1133

    
1134
                                        break;
1135
                                case GEOMETRY_TYPE:
1136
                                        WFSFeatureField gType = ((WFSSelectedFeature)o1).getGeometryField();
1137

    
1138
                                        if (gType == null)
1139
                                                s1 = "";
1140
                                        else
1141
                                                s1 = gType.getName();
1142

    
1143
                                        gType = ((WFSSelectedFeature)o2).getGeometryField();
1144

    
1145
                                        if (gType == null)
1146
                                                s2 = "";
1147
                                        else
1148
                                                s2 = gType.getName();
1149

    
1150
                                        if (ascendingOrdering)
1151
                                                return super.compare(s1, s2);
1152
                                        else
1153
                                                return super.compare(s2, s1);
1154
                                default:
1155
                                        return 0;
1156
                                }
1157

    
1158
                                // If localeRules is null -> use the default rules
1159
                                if (getLocaleRules() == null) {
1160
                                        if (isCaseSensitive()) {
1161
                                                return s1.compareTo(s2);
1162
                                        }
1163
                                        else {
1164
                                                return s1.compareToIgnoreCase(s2);
1165
                                        }
1166
                                }
1167
                                else {
1168
                                        if (getLocaleRules().isUseLocaleRules()) {
1169
                                                Collator collator = getLocaleRules().getCollator();
1170

    
1171
                                                if (isCaseSensitive()) {
1172
                                                        return collator.compare(s1, s2);
1173
                                                }
1174
                                                else {
1175
                                                        //return collator.compare(s1.toLowerCase(), s2.toLowerCase());
1176
                                                        return collator.compare(s1.toUpperCase(), s2.toUpperCase());
1177
                                                }
1178
                                        }
1179
                                        else {
1180
                                                if (isCaseSensitive()) {
1181
                                                        return s1.compareTo(s2);
1182
                                                }
1183
                                                else {
1184
                                                        return s1.compareToIgnoreCase(s2);
1185
                                                }
1186
                                        }
1187
                                }
1188
                        }
1189

    
1190
                        /**
1191
                         * Determines if the name of each element includes the type name.
1192
                         * 
1193
                         * @return <code>true</code> if the name of each element includes the type name; otherwise <code>false</code>
1194
                         */
1195
                        public boolean isShowFeatureNameType() {
1196
                                return showFeatureNameType;
1197
                        }
1198

    
1199
                        /**
1200
                         * Sets if the name of each element includes the type name.
1201
                         * 
1202
                         * @param showFeatureNameType <code>true</code> if the name of each element includes the type name; otherwise <code>false</code>
1203
                         */
1204
                        public void setShowFeatureNameType(boolean showFeatureNameType) {
1205
                                this.showFeatureNameType = showFeatureNameType;
1206
                        }
1207

    
1208
                        /**
1209
                         * <p>Sets which column well be alphabetically sort ordered.</p>
1210
                         * 
1211
                         * <p>There are two columns:
1212
                         *  <ul>
1213
                         *   <li><i>LAYER_NAME</i>: name of the layer.</li>
1214
                         *   <li><i>GEOMETRY_TYPE</i>: geometry type that layer is.</li>
1215
                         *  </ul>
1216
                         * </p>
1217
                         * 
1218
                         * @param column
1219
                         */
1220
                        public void setColumn(short column) {
1221
                                this.column = column;
1222
                        }
1223

    
1224
                        /**
1225
                         * <p>Sets if the alphabetical sort will be ascending or descending.</p>
1226
                         * 
1227
                         * @param b <code>true</code> if the alphabetical sort will be ascending, <code>false</code> if descending
1228
                         */
1229
                        public void setAscendingOrdering(boolean b) {
1230
                                ascendingOrdering = b;
1231
                        }
1232

    
1233
                        /**
1234
                         * <p>Determines if the alphabetical sort will be ascending or descending.</p>
1235
                         * 
1236
                         * @param b <code>true</code> if the alphabetical sort will be ascending, <code>false</code> if descending
1237
                         */
1238
                        public boolean isAscendingOrdering() {
1239
                                return ascendingOrdering;
1240
                        }
1241
                }
1242
        }
1243
}