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 / FeatureTable.java @ 41821

History | View | Annotate | Download (10.8 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.Color;
31
import java.awt.Component;
32
import java.sql.Timestamp;
33
import java.util.Date;
34

    
35
import javax.swing.JTable;
36
import javax.swing.event.ChangeEvent;
37
import javax.swing.event.TableModelEvent;
38
import javax.swing.table.TableCellRenderer;
39
import javax.swing.table.TableColumn;
40
import javax.swing.table.TableColumnModel;
41
import javax.swing.table.TableModel;
42

    
43
import org.gvsig.fmap.dal.exception.DataException;
44
import org.gvsig.fmap.dal.feature.Feature;
45
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
46
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
47
import org.gvsig.fmap.geom.Geometry;
48
import org.gvsig.fmap.mapcontrol.dal.feature.swing.table.ConfigurableFeatureTableModel;
49
import org.gvsig.fmap.mapcontrol.dal.feature.swing.table.FeatureCellRenderer;
50
import org.gvsig.fmap.mapcontrol.dal.feature.swing.table.FeatureTableModel;
51
import org.gvsig.fmap.mapcontrol.dal.feature.swing.table.FormattedCellEditor;
52
import org.gvsig.fmap.mapcontrol.dal.feature.swing.table.FormattedCellRenderer;
53
import org.gvsig.fmap.mapcontrol.dal.feature.swing.table.GeometryWKTCellEditor;
54
import org.gvsig.fmap.mapcontrol.dal.feature.swing.table.GeometryWKTCellRenderer;
55
import org.gvsig.fmap.mapcontrol.dal.feature.swing.table.JToggleButtonHeaderCellRenderer;
56
import org.gvsig.fmap.mapcontrol.dal.feature.swing.table.notification.ColumnHeaderSelectionChangeNotification;
57
import org.gvsig.tools.observer.Observable;
58
import org.gvsig.tools.observer.Observer;
59
import org.slf4j.Logger;
60
import org.slf4j.LoggerFactory;
61

    
62
/**
63
 * Table extension to show Feature values.
64
 *
65
 * It's based on the usage of a FeatureTableModel, and adds renderers for
66
 * Geometry and Feature cell values.
67
 *
68
 * Observers are notified about column header selection changes, with a
69
 * {@link ColumnHeaderSelectionChangeNotification}.
70
 *
71
 * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
72
 */
73
public class FeatureTable extends JTable implements Observer, Observable {
74

    
75
    private static final Logger logger = LoggerFactory.getLogger(FeatureTable.class);
76
    /**
77
     * Generated Serial UID
78
     */
79
    private static final long serialVersionUID = -6139395189283163964L;
80

    
81
    
82
    private final FeatureTableModel featureTableModel;
83
    private JToggleButtonHeaderCellRenderer headerCellRenderer;
84

    
85
        private static final int COLUMN_HEADER_MARGIN = 8;
86

    
87
        private static final int COLUMN_HEADER_MIN_WIDTH = 50;
88

    
89
    /**
90
     * Creates a new FeatureTable with a {@link FeatureTableModel}.
91
     *
92
     * @param featureTableModel
93
     *            the table model to get data to be shown on the table
94
     * @throws DataException
95
     *             if there is an error while loading the Features to show
96
     * @see JTable#JTable(TableModel)
97
     */
98
    public FeatureTable(FeatureTableModel featureTableModel)
99
            throws DataException {
100
        super(featureTableModel);
101
        this.featureTableModel = featureTableModel;
102
        init();
103
    }
104

    
105
    /**
106
     * Creates a new FeatureTable with a {@link FeatureTableModel}.
107
     *
108
     * @param featureTableModel
109
     *            the table model to get data to be shown on the table
110
     * @param cm
111
     *            the table column model to use
112
     * @throws DataException
113
     *             if there is an error while loading the Features to show
114
     * @see JTable#JTable(TableModel, TableColumnModel)
115
     */
116
    public FeatureTable(FeatureTableModel featureTableModel, TableColumnModel cm)
117
            throws DataException {
118
        super(featureTableModel, cm);
119
        this.featureTableModel = featureTableModel;
120
        init();
121
    }
122

    
123
    public void update(Observable observable, Object notification) {
124
        if (notification instanceof FeatureStoreNotification) {
125
            FeatureStoreNotification fsNotification = (FeatureStoreNotification) notification;
126
            String type = fsNotification.getType();
127
            // If the selection has changed, repaint the table to show the new
128
            // selected rows
129
            if (FeatureStoreNotification.SELECTION_CHANGE.equals(type)) {
130
                repaint();
131
            }
132

    
133
            /*
134
             * This is necessary to let Swing know
135
             * that editing (in terms of Swing, not gvsig editing)
136
             * must be cancelled because the deleted row
137
             * is perhaps the row that was being edited
138
             */
139
            if (FeatureStoreNotification.BEFORE_DELETE.equals(type)) {
140
                if (this.isEditing()) {
141
                    ChangeEvent che = new ChangeEvent(this);
142
                    this.editingCanceled(che);
143
                }
144
            }
145
        }
146
    }
147

    
148
    /**
149
     * Returns the FeatureAttributeDescriptor related to the selected columns.
150
     *
151
     * @return an array of FeatureAttributeDescriptor
152
     *
153
     * @see org.gvsig.fmap.mapcontrol.dal.feature.swing.table.JToggleButtonHeaderCellRenderer#getSelectedColumns()
154
     */
155
    public FeatureAttributeDescriptor[] getSelectedColumnsAttributeDescriptor() {
156
        int[] columns = headerCellRenderer.getSelectedColumns();
157
        FeatureAttributeDescriptor[] descriptors = new FeatureAttributeDescriptor[columns.length];
158

    
159
        for (int i = 0; i < descriptors.length; i++) {
160
            descriptors[i] = featureTableModel
161
                    .getDescriptorForColumn(columns[i]);
162
        }
163

    
164
        return descriptors;
165
    }
166

    
167
    public void addObserver(Observer observer) {
168
        headerCellRenderer.addObserver(observer);
169
    }
170

    
171
    public void deleteObserver(Observer observer) {
172
        headerCellRenderer.deleteObserver(observer);
173
    }
174

    
175
    public void deleteObservers() {
176
        headerCellRenderer.deleteObservers();
177
    }
178

    
179
        /**
180
         * Sets that the selected Features to be viewed first.
181
         */
182
        public void setSelectionUp(boolean selectionUp) {
183
                ((FeatureTableModel) getModel()).setSelectionUp(selectionUp);
184
                scrollRectToVisible(getCellRect(0, 0, true));
185
        }
186

    
187
    // @Override
188
    // public void tableChanged(TableModelEvent e) {
189
    // super.tableChanged(e);
190
    // if (headerCellRenderer != null) {
191
    // headerCellRenderer.deselectAll();
192
    // }
193
    // }
194

    
195
    @Override
196
    protected void initializeLocalVars() {
197
        super.initializeLocalVars();
198
        // Add a cell renderer for Geometries and Features
199
        setDefaultRenderer(Geometry.class, new GeometryWKTCellRenderer());
200
        setDefaultEditor(Geometry.class, new GeometryWKTCellEditor());
201
        setDefaultRenderer(Feature.class, new FeatureCellRenderer());
202

    
203
        if( this.getModel() instanceof ConfigurableFeatureTableModel ) {
204
            ConfigurableFeatureTableModel model = (ConfigurableFeatureTableModel)this.getModel();
205
            setDefaultRenderer(Double.class, new FormattedCellRenderer(model));
206
            setDefaultRenderer(Float.class, new FormattedCellRenderer(model));
207
            setDefaultRenderer(Integer.class, new FormattedCellRenderer(model));
208
            setDefaultRenderer(Long.class, new FormattedCellRenderer(model));
209
            setDefaultRenderer(Date.class, new FormattedCellRenderer(model));
210
            setDefaultEditor(Double.class, new FormattedCellEditor(model));
211
            setDefaultEditor(Float.class, new FormattedCellEditor(model));
212
            setDefaultEditor(Integer.class, new FormattedCellEditor(model));
213
            setDefaultEditor(Long.class, new FormattedCellEditor(model));
214
            setDefaultEditor(Date.class, new FormattedCellEditor(model));
215
        }
216

    
217
        // Set the selected row colors
218
        setSelectionForeground(Color.blue);
219
        setSelectionBackground(Color.yellow);
220
    }
221

    
222
    /**
223
     * Initializes the table GUI.
224
     */
225
    private void init() throws DataException {
226
                setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
227

    
228
        featureTableModel.getFeatureStore().addObserver(this);
229
        // Change the selection model to link with the FeatureStore selection
230
        // through the FeatureTableModel
231
        setRowSelectionAllowed(true);
232
        setColumnSelectionAllowed(false);
233
                setSelectionModel(new FeatureSelectionModel(featureTableModel));
234

    
235
                headerCellRenderer = new JToggleButtonHeaderCellRenderer(this);
236
                getTableHeader().setDefaultRenderer(headerCellRenderer);
237

    
238
                TableColumnModel tcmodel = getColumnModel();
239
                for (int i = 0; i < tcmodel.getColumnCount(); i++) {
240
                        TableColumn col = tcmodel.getColumn(i);
241
                        // Get width of column header
242
                        TableCellRenderer renderer = col.getHeaderRenderer();
243
                        if (renderer == null) {
244
                                renderer = getTableHeader().getDefaultRenderer();
245
                        }
246
                        Component comp =
247
                                        renderer.getTableCellRendererComponent(this,
248
                                                        col.getHeaderValue(), false, false, 0, i);
249
                        int width = comp.getPreferredSize().width;
250
                        width =
251
                                        width < COLUMN_HEADER_MIN_WIDTH ? COLUMN_HEADER_MIN_WIDTH
252
                                                        : width;
253
                        col.setPreferredWidth(width + 2 * COLUMN_HEADER_MARGIN);
254
                }
255
    }
256

    
257
    /**
258
     * Returns the number of selected columns.
259
     *
260
     * @return the number of selected columns, 0 if no columns are selected
261
     */
262
    public int getSelectedColumnCount() {
263
        return headerCellRenderer.getSelectedColumns().length;
264
    }
265

    
266
    public void tableChanged(TableModelEvent e) {
267
        // Clear the header selection
268
        if (e != null && e.getFirstRow() == TableModelEvent.HEADER_ROW
269
            && headerCellRenderer != null) {
270
            headerCellRenderer.deselectAll();
271
        }
272

    
273
        super.tableChanged(e);
274
    }
275

    
276
    public Class<?> getColumnClass(int column) {
277
        Class resp = super.getColumnClass(column);
278
        if (Timestamp.class.isAssignableFrom(resp)) {
279
            return Object.class;
280
        } else {
281
            return resp;
282
        }
283
    }
284

    
285
    @Override
286
    public int getSelectedRowCount() {
287
        try {
288
            return (int) this.featureTableModel.getFeatureStore().getFeatureSelection().getSelectedCount();
289
        } catch (DataException ex) {
290
            logger.error("Can't calculate selected rows in table.", ex);
291
            return 0;
292
        }
293
    }
294

    
295

    
296
}