Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.fmap.control / src / main / java / org / gvsig / fmap / mapcontrol / dal / feature / swing / FeatureTablePanel.java @ 41830

History | View | Annotate | Download (12.6 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA 02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
/*
25
 * AUTHORS (In addition to CIT):
26
 * 2008 {DiSiD Technologies}  {Create a Table component for Features}
27
 */
28
package org.gvsig.fmap.mapcontrol.dal.feature.swing;
29

    
30
import java.awt.BorderLayout;
31
import java.awt.Component;
32
import java.awt.Dimension;
33
import java.awt.font.FontRenderContext;
34
import java.awt.geom.Rectangle2D;
35
import java.beans.PropertyChangeEvent;
36
import java.beans.PropertyChangeListener;
37
import javax.swing.AbstractListModel;
38
import javax.swing.JButton;
39

    
40
import javax.swing.JLabel;
41
import javax.swing.JList;
42
import javax.swing.JPanel;
43
import javax.swing.JScrollPane;
44
import javax.swing.JTable;
45
import javax.swing.ListCellRenderer;
46
import javax.swing.ListModel;
47
import javax.swing.SwingUtilities;
48
import javax.swing.UIManager;
49
import javax.swing.event.TableModelEvent;
50
import javax.swing.event.TableModelListener;
51
import javax.swing.table.JTableHeader;
52
import javax.swing.table.TableModel;
53
import javax.swing.text.StyleConstants;
54

    
55
import org.gvsig.fmap.dal.DataStoreNotification;
56
import org.gvsig.fmap.dal.exception.DataException;
57
import org.gvsig.fmap.dal.feature.Feature;
58
import org.gvsig.fmap.dal.feature.FeatureQuery;
59
import org.gvsig.fmap.dal.feature.FeatureStore;
60
import org.gvsig.fmap.mapcontrol.dal.feature.swing.table.ConfigurableFeatureTableModel;
61
import org.gvsig.fmap.mapcontrol.dal.feature.swing.table.FeatureTableConfigurationPanel;
62
import org.gvsig.i18n.Messages;
63
import org.gvsig.tools.exception.BaseException;
64
import org.gvsig.tools.observer.Observable;
65
import org.gvsig.tools.observer.Observer;
66
import org.slf4j.Logger;
67
import org.slf4j.LoggerFactory;
68

    
69
/**
70
 * Panel to show a table of Feature data.
71
 *
72
 * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
73
 */
74
public class FeatureTablePanel extends JPanel implements Observer {
75

    
76
    private static final Logger logger = LoggerFactory.getLogger(FeatureTablePanel.class);
77

    
78
    private static final long serialVersionUID = -9199073063283531216L;
79

    
80
    private ConfigurableFeatureTableModel tableModel;
81

    
82
    private JScrollPane jScrollPane = null;
83

    
84
    private FeatureTable table = null;
85
    private JPanel selectionPanel;
86
    private JLabel selectionLabel;
87

    
88
    /**
89
     * Constructs a Panel to show a table with the features of a FeatureStore.
90
     *
91
     * @param featureStore
92
     * to extract the features from
93
     * @throws BaseException
94
     * if there is an error reading data from the FeatureStore
95
     */
96
    public FeatureTablePanel(FeatureStore featureStore) throws BaseException {
97
        this(featureStore, true);
98
    }
99

    
100
    /**
101
     * Constructs a Panel to show a table with the features of a FeatureStore.
102
     *
103
     * @param featureStore
104
     * to extract the features from
105
     * @param isDoubleBuffered
106
     * a boolean, true for double-buffering, which uses additional
107
     * memory space to achieve fast, flicker-free updates
108
     * @throws BaseException
109
     * if there is an error reading data from the FeatureStore
110
     */
111
    public FeatureTablePanel(FeatureStore featureStore, boolean isDoubleBuffered)
112
            throws BaseException {
113
        this(featureStore, null, isDoubleBuffered);
114
    }
115

    
116
    /**
117
     * @throws BaseException
118
     *
119
     */
120
    public FeatureTablePanel(FeatureStore featureStore,
121
            FeatureQuery featureQuery) throws BaseException {
122
        this(featureStore, featureQuery, true);
123
    }
124

    
125
    /**
126
     * @param isDoubleBuffered
127
     * @throws BaseException
128
     */
129
    public FeatureTablePanel(FeatureStore featureStore,
130
            FeatureQuery featureQuery, boolean isDoubleBuffered)
131
            throws BaseException {
132
        this(createModel(featureStore, featureQuery));
133
    }
134

    
135
    public FeatureTablePanel(ConfigurableFeatureTableModel tableModel)
136
            throws DataException {
137
        this(tableModel, true);
138
    }
139

    
140
    public FeatureTablePanel(ConfigurableFeatureTableModel tableModel,
141
            boolean isDoubleBuffered) throws DataException {
142
        super(isDoubleBuffered);
143
        this.tableModel = tableModel;
144
        this.setLayout(new BorderLayout());
145
        this.add(getJScrollPane(), BorderLayout.CENTER);
146
        this.add(getSelectionPanel(), BorderLayout.SOUTH);
147
        tableModel.getFeatureStore().addObserver(this);
148
    }
149

    
150
    private JPanel getSelectionPanel() {
151
        if ( selectionPanel == null ) {
152
            selectionLabel = new JLabel();
153
            selectionLabel.setText(getFeatureSelectionSize() + " / "
154
                    + getTableModel().getHelper().getTotalSize() + " "
155
                    + Messages.getText("registros_seleccionados_total") + ".");
156
            selectionPanel = new JPanel();
157

    
158
            selectionPanel.add(selectionLabel, BorderLayout.EAST);
159
        }
160
        return selectionPanel;
161
    }
162

    
163
    private void updateSelection() {
164
        selectionLabel.setText(getFeatureSelectionSize() + " / "
165
                + getTableModel().getRowCount() + " "
166
                + Messages.getText("registros_seleccionados_total") + ".");
167
    }
168

    
169
    private long getFeatureSelectionSize() {
170
        try {
171
            return getFeatureStore().getFeatureSelection().getSize();
172
        } catch (DataException e) {
173
            throw new RuntimeException("Error updating selection information",
174
                    e);
175
        }
176
    }
177

    
178
    public JPanel createConfigurationPanel() {
179
        return new FeatureTableConfigurationPanel(tableModel);
180
    }
181

    
182
    /**
183
     * Returns the internal Table Model for the Features of the FeatureStore.
184
     *
185
     * @return the internal Table Model
186
     */
187
    public ConfigurableFeatureTableModel getTableModel() {
188
        return tableModel;
189
    }
190

    
191
    /**
192
     * Returns the {@link FeatureStore} of the {@link Feature}s being shown in
193
     * the table.
194
     *
195
     * @return the store of the features
196
     */
197
    public FeatureStore getFeatureStore() {
198
        return getTableModel().getFeatureStore();
199
    }
200

    
201
    /**
202
     * Returns the FeatureQuery used to get the Features.
203
     *
204
     * @return the FeatureQuery
205
     */
206
    public FeatureQuery getFeatureQuery() {
207
        return getTableModel().getFeatureQuery();
208
    }
209

    
210
    /**
211
     * Sets that the selected Features to be viewed first.
212
     */
213
    public void setSelectionUp(boolean selectionUp) {
214
        try {
215
            getTable().setSelectionUp(selectionUp);
216
        } catch (DataException e) {
217
            throw new RuntimeException("Error setting the selection up", e);
218
        }
219
    }
220

    
221
    private static ConfigurableFeatureTableModel createModel(
222
            FeatureStore featureStore, FeatureQuery featureQuery)
223
            throws BaseException {
224
        FeatureQuery query
225
                = featureQuery == null ? featureStore.createFeatureQuery()
226
                : featureQuery;
227

    
228
        return new ConfigurableFeatureTableModel(featureStore, query);
229
    }
230

    
231
    public FeatureTable getTable() throws DataException {
232
        if ( table == null ) {
233
            table = new FeatureTable(tableModel);
234
            // Change the selection model to link with the FeatureStore
235
            // selection
236
            // through the FeatureTableModel
237
            table.setRowSelectionAllowed(true);
238
            table.setColumnSelectionAllowed(false);
239
            // table.setSelectionModel(new FeatureSelectionModel(tableModel));
240
        }
241
        return table;
242
    }
243

    
244
    /**
245
     * This method initializes jScrollPane
246
     *
247
     * @return javax.swing.JScrollPane
248
     * @throws DataException
249
     */
250
    private JScrollPane getJScrollPane() throws DataException {
251
        if ( jScrollPane == null ) {
252
            FeatureTable theTable = getTable();
253
            jScrollPane = new JScrollPane();
254
            jScrollPane.setViewportView(theTable);
255
            createTheRowHeader();
256
            theTable.addPropertyChangeListener(new PropertyChangeListener() {
257
                public void propertyChange(PropertyChangeEvent pce) {
258
                    if( "RowHeight".equalsIgnoreCase(pce.getPropertyName())) {
259
                        // No he averigado como cambiar el ancho de las lineas
260
                        // ya creadas de la cabezera de lineas, asi que la
261
                        // reconstruyo entera cuando algo cambia.
262
                        createTheRowHeader();
263
                    }
264
                }
265
            });
266
            TableModel model = theTable.getModel();
267
            model.addTableModelListener(new TableModelListener() {
268
                public void tableChanged(TableModelEvent tme) {
269
                    // No he averigado como cambiar el ancho de las lineas
270
                    // ya creadas de la cabezera de lineas, asi que la
271
                    // reconstruyo entera cuando algo cambia.
272
                    createTheRowHeader();
273
                }
274
            });
275
        }
276
        return jScrollPane;
277
    }
278

    
279
    void createTheRowHeader() {
280
        // No se si ha sido paranoia o que, pero parece que si la recreo sin mas
281
        // a veces parece como si no la cambiase, asi que he probado a encolarlo 
282
        // en la cola de eventos de swing y parece que siempre funciona.
283
        //
284
        // Cuando se estan mostrando las geometrias, que cada linea tiene un ancho
285
        // distinto, se le llama muchisimas veces;
286
        // habria que evaluar retenerlas por ejemplo durante un segundo y solo 
287
        // recrearlo entonces.
288
        SwingUtilities.invokeLater(new Runnable() {
289

    
290
            public void run() {
291
                ListModel lm = new AbstractListModel() {
292
                    public int getSize() {
293
                        return table.getRowCount();
294
                    }
295

    
296
                    public Object getElementAt(int index) {
297
                        return String.valueOf(index + 1);
298
                    }
299
                };
300
                final JList rowHeader = new JList(lm);
301
                rowHeader.setBackground(table.getTableHeader().getBackground());
302
                rowHeader.setCellRenderer(new RowHeaderRenderer(table,rowHeader));
303
                jScrollPane.setRowHeaderView(rowHeader);
304
            }
305
        });
306
    }
307

    
308
    private static class RowHeaderRenderer extends JButton implements ListCellRenderer {
309
        private JTable table = null;
310
        private final Dimension dimension = new Dimension();
311
        private JList rowHeader;
312
        
313
        RowHeaderRenderer(JTable table,JList rowHeader) {
314
            JTableHeader header = table.getTableHeader();
315
            setOpaque(true);
316
            setBorder(UIManager.getBorder("TableHeader.cellBorder"));
317
            setHorizontalAlignment(CENTER);
318
            setForeground(header.getForeground());
319
            setBackground(header.getBackground());
320
            setFont(header.getFont());
321
            this.table = table;
322
            this.rowHeader = rowHeader;
323
        }
324

    
325
        public Component getListCellRendererComponent(JList list, Object value,
326
                int index, boolean isSelected, boolean cellHasFocus) {
327
            setText((value == null) ? "" : value.toString());
328
            this.setPreferredSize(null); // Fuerza recalcular el tama?o del boton
329
            this.dimension.height = this.table.getRowHeight(index);
330
            this.dimension.width = this.getPreferredSize().width+10;
331
            this.setPreferredSize(this.dimension);
332
            return this;
333
        }
334

    
335
    }
336

    
337
    public void update(Observable observable, Object notification) {
338
        // If selection changes from nothing selected to anything selected
339
        // or the reverse, update selection info
340
        if ( notification instanceof DataStoreNotification ) {
341
            String type = ((DataStoreNotification) notification).getType();
342
            if ( DataStoreNotification.SELECTION_CHANGE.equals(type) ) {
343
                updateSelection();
344
            }
345
        }
346
    }
347
    // public void valueChanged(ListSelectionEvent e) {
348
    // updateSelection();
349
    // updateUI();
350
    // }
351
    //
352
    // public void tableChanged(TableModelEvent e) {
353
    // updateSelection();
354
    // updateUI();
355
    // }
356
}