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 @ 41621

History | View | Annotate | Download (12.4 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

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

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

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

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

    
79
    private ConfigurableFeatureTableModel tableModel;
80

    
81
    private JScrollPane jScrollPane = null;
82

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
306
    private static class RowHeaderRenderer extends JButton implements ListCellRenderer {
307

    
308
        private JTable table = null;
309
        private final Dimension dimension = new Dimension();
310

    
311
        RowHeaderRenderer(JTable table) {
312
            JTableHeader header = table.getTableHeader();
313
            setOpaque(true);
314
            setBorder(UIManager.getBorder("TableHeader.cellBorder"));
315
            setHorizontalAlignment(CENTER);
316
            setForeground(header.getForeground());
317
            setBackground(header.getBackground());
318
            setFont(header.getFont());
319
            this.table = table;
320
            //                                               1234567
321
            Rectangle2D r = this.getFont().getStringBounds( "_______", new FontRenderContext(null,true,true));
322
            this.dimension.width = (int) r.getWidth();
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.dimension.height = this.table.getRowHeight(index);
329
            this.setPreferredSize(this.dimension);
330
            return this;
331
        }
332

    
333
    }
334

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