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

History | View | Annotate | Download (13 KB)

1 40559 jjdelcerro
/**
2
 * gvSIG. Desktop Geographic Information System.
3 40435 jjdelcerro
 *
4 40559 jjdelcerro
 * Copyright (C) 2007-2013 gvSIG Association.
5 40435 jjdelcerro
 *
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 40559 jjdelcerro
 * as published by the Free Software Foundation; either version 3
9 40435 jjdelcerro
 * 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 41621 jjdelcerro
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 40435 jjdelcerro
 * 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 41621 jjdelcerro
 * MA 02110-1301, USA.
20 40435 jjdelcerro
 *
21 40559 jjdelcerro
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23 40435 jjdelcerro
 */
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 41611 jjdelcerro
import java.awt.Component;
32 41621 jjdelcerro
import java.awt.Dimension;
33
import java.beans.PropertyChangeEvent;
34
import java.beans.PropertyChangeListener;
35 41611 jjdelcerro
import javax.swing.AbstractListModel;
36
import javax.swing.JButton;
37 40435 jjdelcerro
import javax.swing.JLabel;
38 41611 jjdelcerro
import javax.swing.JList;
39 40435 jjdelcerro
import javax.swing.JPanel;
40
import javax.swing.JScrollPane;
41 41611 jjdelcerro
import javax.swing.JTable;
42
import javax.swing.ListCellRenderer;
43
import javax.swing.ListModel;
44 41621 jjdelcerro
import javax.swing.SwingUtilities;
45 41611 jjdelcerro
import javax.swing.UIManager;
46 41621 jjdelcerro
import javax.swing.event.TableModelEvent;
47
import javax.swing.event.TableModelListener;
48 41611 jjdelcerro
import javax.swing.table.JTableHeader;
49 41621 jjdelcerro
import javax.swing.table.TableModel;
50 40435 jjdelcerro
import org.gvsig.fmap.dal.DataStoreNotification;
51
import org.gvsig.fmap.dal.exception.DataException;
52
import org.gvsig.fmap.dal.feature.Feature;
53
import org.gvsig.fmap.dal.feature.FeatureQuery;
54
import org.gvsig.fmap.dal.feature.FeatureStore;
55
import org.gvsig.fmap.mapcontrol.dal.feature.swing.table.ConfigurableFeatureTableModel;
56
import org.gvsig.fmap.mapcontrol.dal.feature.swing.table.FeatureTableConfigurationPanel;
57
import org.gvsig.i18n.Messages;
58 46761 jjdelcerro
import org.gvsig.tools.ToolsLocator;
59 40435 jjdelcerro
import org.gvsig.tools.exception.BaseException;
60 46761 jjdelcerro
import org.gvsig.tools.i18n.I18nManager;
61 40435 jjdelcerro
import org.gvsig.tools.observer.Observable;
62
import org.gvsig.tools.observer.Observer;
63 41621 jjdelcerro
import org.slf4j.Logger;
64
import org.slf4j.LoggerFactory;
65 40435 jjdelcerro
66
/**
67
 * Panel to show a table of Feature data.
68 41621 jjdelcerro
 *
69 40435 jjdelcerro
 * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
70
 */
71
public class FeatureTablePanel extends JPanel implements Observer {
72
73 41621 jjdelcerro
    private static final Logger logger = LoggerFactory.getLogger(FeatureTablePanel.class);
74
75 40435 jjdelcerro
    private static final long serialVersionUID = -9199073063283531216L;
76
77
    private ConfigurableFeatureTableModel tableModel;
78
79
    private JScrollPane jScrollPane = null;
80
81
    private FeatureTable table = null;
82
    private JPanel selectionPanel;
83
    private JLabel selectionLabel;
84
85
    /**
86
     * Constructs a Panel to show a table with the features of a FeatureStore.
87 41621 jjdelcerro
     *
88 40435 jjdelcerro
     * @param featureStore
89 41621 jjdelcerro
     * to extract the features from
90 40435 jjdelcerro
     * @throws BaseException
91 41621 jjdelcerro
     * if there is an error reading data from the FeatureStore
92 40435 jjdelcerro
     */
93
    public FeatureTablePanel(FeatureStore featureStore) throws BaseException {
94
        this(featureStore, true);
95
    }
96
97
    /**
98
     * Constructs a Panel to show a table with the features of a FeatureStore.
99 41621 jjdelcerro
     *
100 40435 jjdelcerro
     * @param featureStore
101 41621 jjdelcerro
     * to extract the features from
102 40435 jjdelcerro
     * @param isDoubleBuffered
103 41621 jjdelcerro
     * a boolean, true for double-buffering, which uses additional
104
     * memory space to achieve fast, flicker-free updates
105 40435 jjdelcerro
     * @throws BaseException
106 41621 jjdelcerro
     * if there is an error reading data from the FeatureStore
107 40435 jjdelcerro
     */
108
    public FeatureTablePanel(FeatureStore featureStore, boolean isDoubleBuffered)
109 41621 jjdelcerro
            throws BaseException {
110 40435 jjdelcerro
        this(featureStore, null, isDoubleBuffered);
111
    }
112
113
    /**
114
     * @throws BaseException
115 41621 jjdelcerro
     *
116 40435 jjdelcerro
     */
117
    public FeatureTablePanel(FeatureStore featureStore,
118 41621 jjdelcerro
            FeatureQuery featureQuery) throws BaseException {
119 40435 jjdelcerro
        this(featureStore, featureQuery, true);
120
    }
121
122
    /**
123
     * @param isDoubleBuffered
124
     * @throws BaseException
125
     */
126
    public FeatureTablePanel(FeatureStore featureStore,
127 41621 jjdelcerro
            FeatureQuery featureQuery, boolean isDoubleBuffered)
128
            throws BaseException {
129 40435 jjdelcerro
        this(createModel(featureStore, featureQuery));
130
    }
131
132
    public FeatureTablePanel(ConfigurableFeatureTableModel tableModel)
133 41621 jjdelcerro
            throws DataException {
134 40435 jjdelcerro
        this(tableModel, true);
135
    }
136
137
    public FeatureTablePanel(ConfigurableFeatureTableModel tableModel,
138 41621 jjdelcerro
            boolean isDoubleBuffered) throws DataException {
139 40435 jjdelcerro
        super(isDoubleBuffered);
140
        this.tableModel = tableModel;
141
        this.setLayout(new BorderLayout());
142
        this.add(getJScrollPane(), BorderLayout.CENTER);
143
        this.add(getSelectionPanel(), BorderLayout.SOUTH);
144
        tableModel.getFeatureStore().addObserver(this);
145
    }
146
147
    private JPanel getSelectionPanel() {
148 41621 jjdelcerro
        if ( selectionPanel == null ) {
149 46761 jjdelcerro
            I18nManager i18n = ToolsLocator.getI18nManager();
150 40435 jjdelcerro
            selectionLabel = new JLabel();
151
            selectionLabel.setText(getFeatureSelectionSize() + " / "
152 41621 jjdelcerro
                    + getTableModel().getHelper().getTotalSize() + " "
153 46761 jjdelcerro
                    + i18n.getTranslation("registros_seleccionados_total") + ".");
154
            FeatureStore store = this.getTableModel().getFeatureStore();
155
            if( store!=null ) {
156
                selectionLabel.setToolTipText(
157
                    "<html>" +
158
                    i18n.getTranslation("_Table") + ": " + store.getName() +"<br>\n"+
159
                    "( "+store.getFullName() + " )" +
160
                    "</html>"
161
                );
162
            }
163 40435 jjdelcerro
            selectionPanel = new JPanel();
164
            selectionPanel.add(selectionLabel, BorderLayout.EAST);
165
        }
166
        return selectionPanel;
167
    }
168
169
    private void updateSelection() {
170 47421 fdiaz
            selectionLabel.setText(getFeatureSelectionSize() + " / "
171 41621 jjdelcerro
                + getTableModel().getRowCount() + " "
172
                + Messages.getText("registros_seleccionados_total") + ".");
173 40435 jjdelcerro
    }
174
175
    private long getFeatureSelectionSize() {
176
        try {
177
            return getFeatureStore().getFeatureSelection().getSize();
178
        } catch (DataException e) {
179
            throw new RuntimeException("Error updating selection information",
180 41621 jjdelcerro
                    e);
181 40435 jjdelcerro
        }
182
    }
183
184
    public JPanel createConfigurationPanel() {
185
        return new FeatureTableConfigurationPanel(tableModel);
186
    }
187
188
    /**
189
     * Returns the internal Table Model for the Features of the FeatureStore.
190 41621 jjdelcerro
     *
191 40435 jjdelcerro
     * @return the internal Table Model
192
     */
193
    public ConfigurableFeatureTableModel getTableModel() {
194
        return tableModel;
195
    }
196
197
    /**
198
     * Returns the {@link FeatureStore} of the {@link Feature}s being shown in
199
     * the table.
200 41621 jjdelcerro
     *
201 40435 jjdelcerro
     * @return the store of the features
202
     */
203
    public FeatureStore getFeatureStore() {
204
        return getTableModel().getFeatureStore();
205
    }
206
207
    /**
208
     * Returns the FeatureQuery used to get the Features.
209 41621 jjdelcerro
     *
210 40435 jjdelcerro
     * @return the FeatureQuery
211
     */
212
    public FeatureQuery getFeatureQuery() {
213
        return getTableModel().getFeatureQuery();
214
    }
215
216
    /**
217
     * Sets that the selected Features to be viewed first.
218
     */
219
    public void setSelectionUp(boolean selectionUp) {
220
        try {
221
            getTable().setSelectionUp(selectionUp);
222
        } catch (DataException e) {
223
            throw new RuntimeException("Error setting the selection up", e);
224
        }
225
    }
226
227
    private static ConfigurableFeatureTableModel createModel(
228 41621 jjdelcerro
            FeatureStore featureStore, FeatureQuery featureQuery)
229
            throws BaseException {
230
        FeatureQuery query
231
                = featureQuery == null ? featureStore.createFeatureQuery()
232 40435 jjdelcerro
                : featureQuery;
233
234
        return new ConfigurableFeatureTableModel(featureStore, query);
235
    }
236
237
    public FeatureTable getTable() throws DataException {
238 41621 jjdelcerro
        if ( table == null ) {
239 40435 jjdelcerro
            table = new FeatureTable(tableModel);
240
            // Change the selection model to link with the FeatureStore
241
            // selection
242
            // through the FeatureTableModel
243
            table.setRowSelectionAllowed(true);
244
            table.setColumnSelectionAllowed(false);
245
            // table.setSelectionModel(new FeatureSelectionModel(tableModel));
246
        }
247
        return table;
248
    }
249
250
    /**
251
     * This method initializes jScrollPane
252 41621 jjdelcerro
     *
253 40435 jjdelcerro
     * @return javax.swing.JScrollPane
254
     * @throws DataException
255
     */
256
    private JScrollPane getJScrollPane() throws DataException {
257 41621 jjdelcerro
        if ( jScrollPane == null ) {
258 41611 jjdelcerro
            FeatureTable theTable = getTable();
259 40435 jjdelcerro
            jScrollPane = new JScrollPane();
260 41611 jjdelcerro
            jScrollPane.setViewportView(theTable);
261 41621 jjdelcerro
            createTheRowHeader();
262
            theTable.addPropertyChangeListener(new PropertyChangeListener() {
263
                public void propertyChange(PropertyChangeEvent pce) {
264
                    if( "RowHeight".equalsIgnoreCase(pce.getPropertyName())) {
265
                        // No he averigado como cambiar el ancho de las lineas
266
                        // ya creadas de la cabezera de lineas, asi que la
267
                        // reconstruyo entera cuando algo cambia.
268
                        createTheRowHeader();
269
                    }
270
                }
271
            });
272
            TableModel model = theTable.getModel();
273
            model.addTableModelListener(new TableModelListener() {
274
                public void tableChanged(TableModelEvent tme) {
275
                    // No he averigado como cambiar el ancho de las lineas
276
                    // ya creadas de la cabezera de lineas, asi que la
277
                    // reconstruyo entera cuando algo cambia.
278
                    createTheRowHeader();
279
                }
280
            });
281 40435 jjdelcerro
        }
282
        return jScrollPane;
283
    }
284
285 41621 jjdelcerro
    void createTheRowHeader() {
286
        // No se si ha sido paranoia o que, pero parece que si la recreo sin mas
287
        // a veces parece como si no la cambiase, asi que he probado a encolarlo
288
        // en la cola de eventos de swing y parece que siempre funciona.
289
        //
290
        // Cuando se estan mostrando las geometrias, que cada linea tiene un ancho
291
        // distinto, se le llama muchisimas veces;
292
        // habria que evaluar retenerlas por ejemplo durante un segundo y solo
293
        // recrearlo entonces.
294
        SwingUtilities.invokeLater(new Runnable() {
295
296
            public void run() {
297
                ListModel lm = new AbstractListModel() {
298
                    public int getSize() {
299
                        return table.getRowCount();
300
                    }
301
302
                    public Object getElementAt(int index) {
303
                        return String.valueOf(index + 1);
304
                    }
305
                };
306
                final JList rowHeader = new JList(lm);
307 41707 jjdelcerro
                rowHeader.setBackground(table.getTableHeader().getBackground());
308 41830 jjdelcerro
                rowHeader.setCellRenderer(new RowHeaderRenderer(table,rowHeader));
309 41621 jjdelcerro
                jScrollPane.setRowHeaderView(rowHeader);
310
            }
311
        });
312
    }
313
314 41611 jjdelcerro
    private static class RowHeaderRenderer extends JButton implements ListCellRenderer {
315 41621 jjdelcerro
        private JTable table = null;
316
        private final Dimension dimension = new Dimension();
317 41830 jjdelcerro
        private JList rowHeader;
318
319
        RowHeaderRenderer(JTable table,JList rowHeader) {
320 41621 jjdelcerro
            JTableHeader header = table.getTableHeader();
321
            setOpaque(true);
322
            setBorder(UIManager.getBorder("TableHeader.cellBorder"));
323
            setHorizontalAlignment(CENTER);
324
            setForeground(header.getForeground());
325
            setBackground(header.getBackground());
326
            setFont(header.getFont());
327
            this.table = table;
328 41830 jjdelcerro
            this.rowHeader = rowHeader;
329 41611 jjdelcerro
        }
330
331
        public Component getListCellRendererComponent(JList list, Object value,
332 41621 jjdelcerro
                int index, boolean isSelected, boolean cellHasFocus) {
333
            setText((value == null) ? "" : value.toString());
334 41830 jjdelcerro
            this.setPreferredSize(null); // Fuerza recalcular el tama?o del boton
335 41621 jjdelcerro
            this.dimension.height = this.table.getRowHeight(index);
336 41830 jjdelcerro
            this.dimension.width = this.getPreferredSize().width+10;
337 41621 jjdelcerro
            this.setPreferredSize(this.dimension);
338
            return this;
339 41611 jjdelcerro
        }
340 41621 jjdelcerro
341 41611 jjdelcerro
    }
342
343 40435 jjdelcerro
    public void update(Observable observable, Object notification) {
344
        // If selection changes from nothing selected to anything selected
345
        // or the reverse, update selection info
346 41621 jjdelcerro
        if ( notification instanceof DataStoreNotification ) {
347 40435 jjdelcerro
            String type = ((DataStoreNotification) notification).getType();
348 41621 jjdelcerro
            if ( DataStoreNotification.SELECTION_CHANGE.equals(type) ) {
349 40435 jjdelcerro
                updateSelection();
350
            }
351
        }
352
    }
353
    // public void valueChanged(ListSelectionEvent e) {
354
    // updateSelection();
355
    // updateUI();
356
    // }
357
    //
358
    // public void tableChanged(TableModelEvent e) {
359
    // updateSelection();
360
    // updateUI();
361
    // }
362
}