svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.swing / org.gvsig.fmap.dal.swing.impl / src / main / java / org / gvsig / fmap / dal / swing / impl / featuretable / table / DefaultFeatureTableModel.java @ 42806
History | View | Annotate | Download (30.9 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 | * 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 | 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 | 42775 | jjdelcerro | package org.gvsig.fmap.dal.swing.impl.featuretable.table; |
26 | |||
27 | import java.awt.event.ActionEvent; |
||
28 | import java.awt.event.ActionListener; |
||
29 | 40435 | jjdelcerro | import java.security.InvalidParameterException; |
30 | 41699 | jjdelcerro | import java.text.SimpleDateFormat; |
31 | 40435 | jjdelcerro | import java.util.ArrayList; |
32 | import java.util.HashMap; |
||
33 | import java.util.Iterator; |
||
34 | import java.util.List; |
||
35 | 41699 | jjdelcerro | import java.util.Locale; |
36 | 40435 | jjdelcerro | import java.util.Map; |
37 | 42806 | fdiaz | |
38 | 42775 | jjdelcerro | import javax.swing.SwingUtilities; |
39 | import javax.swing.Timer; |
||
40 | 40435 | jjdelcerro | import javax.swing.event.TableModelEvent; |
41 | 42775 | jjdelcerro | import javax.swing.table.AbstractTableModel; |
42 | 40435 | jjdelcerro | |
43 | 42806 | fdiaz | import org.slf4j.Logger; |
44 | import org.slf4j.LoggerFactory; |
||
45 | |||
46 | 40435 | jjdelcerro | import org.gvsig.fmap.dal.DataTypes; |
47 | 42775 | jjdelcerro | import org.gvsig.fmap.dal.exception.DataException; |
48 | 40435 | jjdelcerro | import org.gvsig.fmap.dal.feature.EditableFeature; |
49 | import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor; |
||
50 | import org.gvsig.fmap.dal.feature.Feature; |
||
51 | import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor; |
||
52 | import org.gvsig.fmap.dal.feature.FeatureQuery; |
||
53 | import org.gvsig.fmap.dal.feature.FeatureQueryOrder; |
||
54 | 42775 | jjdelcerro | import org.gvsig.fmap.dal.feature.FeatureSelection; |
55 | 40435 | jjdelcerro | import org.gvsig.fmap.dal.feature.FeatureStore; |
56 | 42775 | jjdelcerro | import org.gvsig.fmap.dal.feature.FeatureStoreNotification; |
57 | 40435 | jjdelcerro | import org.gvsig.fmap.dal.feature.FeatureType; |
58 | 42775 | jjdelcerro | import org.gvsig.fmap.dal.feature.exception.ConcurrentDataModificationException; |
59 | import org.gvsig.fmap.dal.feature.paging.FeaturePagingHelper; |
||
60 | 42806 | fdiaz | import org.gvsig.fmap.dal.swing.impl.featuretable.table.renders.GetFeatureAtException; |
61 | 40435 | jjdelcerro | import org.gvsig.tools.exception.BaseException; |
62 | 42775 | jjdelcerro | import org.gvsig.tools.observer.ComplexNotification; |
63 | import org.gvsig.tools.observer.ComplexObserver; |
||
64 | import org.gvsig.tools.observer.Observable; |
||
65 | 40435 | jjdelcerro | |
66 | 42775 | jjdelcerro | public class DefaultFeatureTableModel extends AbstractTableModel implements org.gvsig.fmap.dal.swing.FeatureTableModel, ComplexObserver { |
67 | 40435 | jjdelcerro | |
68 | private static final long serialVersionUID = -8223987814719746492L; |
||
69 | 42806 | fdiaz | |
70 | 42775 | jjdelcerro | private static final Logger logger = LoggerFactory.getLogger(DefaultFeatureTableModel.class); |
71 | 40435 | jjdelcerro | |
72 | private List<String> columnNames; |
||
73 | |||
74 | private List<String> visibleColumnNames; |
||
75 | |||
76 | private List<String> visibleColumnNamesOriginal; |
||
77 | |||
78 | private Map<String, String> name2Alias; |
||
79 | |||
80 | private Map<String, String> name2AliasOriginal; |
||
81 | |||
82 | 41699 | jjdelcerro | private Map<String,String> patterns = null; |
83 | |||
84 | 42806 | fdiaz | private Locale localeOfData; |
85 | 42775 | jjdelcerro | |
86 | private final FeaturePagingHelper featurePager; |
||
87 | |||
88 | /** Used to know if a modification in the FeatureStore is created by us. */
|
||
89 | private EditableFeature editableFeature;
|
||
90 | |||
91 | private boolean selectionLocked=false; |
||
92 | 42806 | fdiaz | |
93 | 42775 | jjdelcerro | private final DelayAction delayAction = new DelayAction(); |
94 | |||
95 | |||
96 | public DefaultFeatureTableModel(FeaturePagingHelper featurePager) {
|
||
97 | this.featurePager = featurePager;
|
||
98 | 41699 | jjdelcerro | this.localeOfData = Locale.getDefault(); |
99 | 42775 | jjdelcerro | this.initialize();
|
100 | 40435 | jjdelcerro | } |
101 | |||
102 | 42775 | jjdelcerro | private void initialize() { |
103 | this.getFeatureStore().addObserver(this); |
||
104 | 42806 | fdiaz | |
105 | 42775 | jjdelcerro | int columns = this.getOriginalColumnCount(); |
106 | |||
107 | // Initilize visible columns
|
||
108 | columnNames = new ArrayList<>(columns); |
||
109 | visibleColumnNames = new ArrayList<>(columns); |
||
110 | for (int i = 0; i < columns; i++) { |
||
111 | FeatureAttributeDescriptor descriptor = this.getInternalColumnDescriptor(i);
|
||
112 | String columnName = descriptor.getName();
|
||
113 | columnNames.add(columnName); |
||
114 | |||
115 | // By default, geometry columns will not be visible
|
||
116 | if (descriptor.getType() != DataTypes.GEOMETRY) {
|
||
117 | visibleColumnNames.add(columnName); |
||
118 | } |
||
119 | } |
||
120 | visibleColumnNamesOriginal = new ArrayList<>(visibleColumnNames); |
||
121 | 42806 | fdiaz | |
122 | 42775 | jjdelcerro | // Initialize alias
|
123 | name2Alias = new HashMap<>(columns); |
||
124 | name2AliasOriginal = new HashMap<>(columns); |
||
125 | |||
126 | initializeFormatingPatterns(); |
||
127 | updatePagerWithHiddenColums(); |
||
128 | 40435 | jjdelcerro | } |
129 | |||
130 | 42775 | jjdelcerro | private void initializeFormatingPatterns() { |
131 | int columns = this.getOriginalColumnCount(); |
||
132 | 42806 | fdiaz | |
133 | 42775 | jjdelcerro | this.patterns = new HashMap<>(); |
134 | for (int i = 0; i < columns; i++) { |
||
135 | FeatureAttributeDescriptor descriptor = this.getInternalColumnDescriptor(i);
|
||
136 | String columnName = descriptor.getName();
|
||
137 | switch(descriptor.getDataType().getType()) {
|
||
138 | case DataTypes.BYTE:
|
||
139 | case DataTypes.INT:
|
||
140 | case DataTypes.LONG:
|
||
141 | String defaultIntegerPattern = "#,##0"; |
||
142 | this.patterns.put(columnName,defaultIntegerPattern);
|
||
143 | break;
|
||
144 | case DataTypes.DOUBLE:
|
||
145 | String defaultDoublePattern = "#,##0.0000000000"; |
||
146 | this.patterns.put(columnName,defaultDoublePattern);
|
||
147 | break;
|
||
148 | case DataTypes.FLOAT:
|
||
149 | String defaultFloatPattern = "#,##0.0000"; |
||
150 | this.patterns.put(columnName,defaultFloatPattern);
|
||
151 | break;
|
||
152 | case DataTypes.DATE:
|
||
153 | String defaultDatePattern = new SimpleDateFormat().toPattern(); |
||
154 | this.patterns.put(columnName,defaultDatePattern);
|
||
155 | break;
|
||
156 | default:
|
||
157 | this.patterns.put(columnName,null); |
||
158 | } |
||
159 | } |
||
160 | 42806 | fdiaz | |
161 | 42775 | jjdelcerro | } |
162 | 42806 | fdiaz | |
163 | 42775 | jjdelcerro | private void updatePagerWithHiddenColums() { |
164 | FeatureQuery query = this.getFeaturePager().getFeatureQuery();
|
||
165 | if (this.getFeaturePager().getFeatureStore().isEditing()) { |
||
166 | if (query.hasConstantsAttributeNames()) {
|
||
167 | query.clearConstantsAttributeNames(); |
||
168 | } |
||
169 | } else {
|
||
170 | query.setConstantsAttributeNames(this.getHiddenColumnNames());
|
||
171 | } |
||
172 | try {
|
||
173 | this.getFeaturePager().reload();
|
||
174 | } catch (BaseException ex) {
|
||
175 | logger.warn("Can't reload paging-helper.", ex);
|
||
176 | } |
||
177 | } |
||
178 | 42806 | fdiaz | |
179 | 40435 | jjdelcerro | @Override
|
180 | 42775 | jjdelcerro | public FeaturePagingHelper getFeaturePager() {
|
181 | return this.featurePager; |
||
182 | } |
||
183 | 42806 | fdiaz | |
184 | 42775 | jjdelcerro | @Override
|
185 | public FeatureQuery getFeatureQuery() {
|
||
186 | return this.getFeaturePager().getFeatureQuery(); |
||
187 | } |
||
188 | |||
189 | @Override
|
||
190 | public FeatureType getFeatureType() {
|
||
191 | return this.getFeaturePager().getFeatureType(); |
||
192 | } |
||
193 | 42806 | fdiaz | |
194 | 42775 | jjdelcerro | @Override
|
195 | public FeatureStore getFeatureStore() {
|
||
196 | return this.getFeaturePager().getFeatureStore(); |
||
197 | } |
||
198 | |||
199 | @Override
|
||
200 | 40435 | jjdelcerro | public int getColumnCount() { |
201 | return visibleColumnNames.size();
|
||
202 | } |
||
203 | |||
204 | public int getOriginalColumnCount() { |
||
205 | 42775 | jjdelcerro | FeatureType featureType = getFeatureType(); |
206 | return featureType.size();
|
||
207 | 40435 | jjdelcerro | } |
208 | |||
209 | @Override
|
||
210 | public String getColumnName(int column) { |
||
211 | 42775 | jjdelcerro | String columName = getOriginalColumnName(column);
|
212 | return this.getColumnAlias(columName); |
||
213 | 40435 | jjdelcerro | } |
214 | |||
215 | @Override
|
||
216 | public Class<?> getColumnClass(int columnIndex) { |
||
217 | int originalIndex = getOriginalColumnIndex(columnIndex);
|
||
218 | 42806 | fdiaz | |
219 | 42775 | jjdelcerro | // Return the class of the FeatureAttributeDescriptor for the value
|
220 | FeatureAttributeDescriptor attributeDesc = this.getInternalColumnDescriptor(originalIndex);
|
||
221 | if (attributeDesc == null) { |
||
222 | return super.getColumnClass(originalIndex); |
||
223 | } |
||
224 | Class<?> clazz = attributeDesc.getObjectClass();
|
||
225 | return (clazz == null ? super.getColumnClass(originalIndex) : clazz); |
||
226 | 40435 | jjdelcerro | } |
227 | |||
228 | @Override
|
||
229 | 42775 | jjdelcerro | public FeatureAttributeDescriptor getColumnDescriptor(int columnIndex) { |
230 | 40435 | jjdelcerro | int originalIndex = getOriginalColumnIndex(columnIndex);
|
231 | 42775 | jjdelcerro | return this.getInternalColumnDescriptor(originalIndex); |
232 | 40435 | jjdelcerro | } |
233 | 42806 | fdiaz | |
234 | 42775 | jjdelcerro | protected FeatureAttributeDescriptor getInternalColumnDescriptor(int columnIndex) { |
235 | FeatureType featureType = getFeatureType(); |
||
236 | if( featureType == null ) { |
||
237 | return null; |
||
238 | } |
||
239 | return featureType.getAttributeDescriptor(columnIndex);
|
||
240 | } |
||
241 | 40435 | jjdelcerro | |
242 | 42775 | jjdelcerro | @Override
|
243 | 40435 | jjdelcerro | public String getOriginalColumnName(int column) { |
244 | 42775 | jjdelcerro | return getInternalColumnDescriptor(column).getName();
|
245 | 40435 | jjdelcerro | } |
246 | |||
247 | 42775 | jjdelcerro | @Override
|
248 | public void setColumnVisible(String name, boolean visible) { |
||
249 | 40435 | jjdelcerro | if (!columnNames.contains(name)) {
|
250 | throw new InvalidParameterException(name); // FIXME |
||
251 | } |
||
252 | 42775 | jjdelcerro | if( visible ) {
|
253 | if ( !visibleColumnNames.contains(name) ) {
|
||
254 | visibleColumnNames.add(name); |
||
255 | setVisibleColumns(visibleColumnNames); |
||
256 | } |
||
257 | 40435 | jjdelcerro | } else {
|
258 | 42775 | jjdelcerro | if ( visibleColumnNames.contains(name) ) {
|
259 | visibleColumnNames.remove(name); |
||
260 | setVisibleColumns(visibleColumnNames); |
||
261 | fireTableStructureChanged(); |
||
262 | } |
||
263 | 40435 | jjdelcerro | } |
264 | } |
||
265 | |||
266 | public void setFeatureType(FeatureType featureType) { |
||
267 | // Check if there is a new column name
|
||
268 | 42775 | jjdelcerro | List<String> newColumns = new ArrayList<>(); |
269 | List<String> renamedColumnsNewName = new ArrayList<>(); |
||
270 | 42806 | fdiaz | |
271 | 40435 | jjdelcerro | Iterator<FeatureAttributeDescriptor> attrIter = featureType.iterator();
|
272 | 42775 | jjdelcerro | FeatureAttributeDescriptor fad ; |
273 | EditableFeatureAttributeDescriptor efad ; |
||
274 | 42806 | fdiaz | |
275 | 40435 | jjdelcerro | String colName;
|
276 | while (attrIter.hasNext()) {
|
||
277 | fad = attrIter.next(); |
||
278 | colName = fad.getName(); |
||
279 | if (!columnNames.contains(colName)) {
|
||
280 | if (fad instanceof EditableFeatureAttributeDescriptor) { |
||
281 | 42806 | fdiaz | efad = (EditableFeatureAttributeDescriptor) fad; |
282 | 40435 | jjdelcerro | /*
|
283 | * If editable att descriptor,
|
||
284 | * check original name
|
||
285 | */
|
||
286 | if (efad.getOriginalName() != null) { |
||
287 | if (!columnNames.contains(efad.getOriginalName())) {
|
||
288 | /*
|
||
289 | * Check with original name but add current name
|
||
290 | */
|
||
291 | newColumns.add(colName); |
||
292 | } else {
|
||
293 | /*
|
||
294 | * List of new names of renamed columns
|
||
295 | */
|
||
296 | renamedColumnsNewName.add(colName); |
||
297 | } |
||
298 | } else {
|
||
299 | newColumns.add(colName); |
||
300 | } |
||
301 | } else {
|
||
302 | newColumns.add(colName); |
||
303 | } |
||
304 | } |
||
305 | } |
||
306 | |||
307 | // Update column names
|
||
308 | columnNames.clear(); |
||
309 | @SuppressWarnings("unchecked") |
||
310 | Iterator<FeatureAttributeDescriptor> visibleAttrIter =
|
||
311 | featureType.iterator(); |
||
312 | while (visibleAttrIter.hasNext()) {
|
||
313 | fad = visibleAttrIter.next(); |
||
314 | colName = fad.getName(); |
||
315 | columnNames.add(colName); |
||
316 | //If the column is added has to be visible
|
||
317 | if (!visibleColumnNames.contains(colName)) {
|
||
318 | |||
319 | 41093 | jldominguez | if (((newColumns.contains(colName)
|
320 | || renamedColumnsNewName.contains(colName))) |
||
321 | && |
||
322 | fad.getType() != DataTypes.GEOMETRY) { |
||
323 | 40435 | jjdelcerro | // Add new columns and renamed
|
324 | visibleColumnNames.add(colName); |
||
325 | visibleColumnNamesOriginal.add(colName); |
||
326 | } |
||
327 | /*
|
||
328 | if (renamedColumnsNewName.contains(colName)) {
|
||
329 | // Add renamed
|
||
330 | insertWhereOldName(visibleColumnNames, colName, fad);
|
||
331 | insertWhereOldName(visibleColumnNamesOriginal, colName, fad);
|
||
332 | }
|
||
333 | */
|
||
334 | } |
||
335 | } |
||
336 | |||
337 | // remove from visible columns removed columns
|
||
338 | visibleColumnNames = intersectKeepOrder(columnNames, visibleColumnNames); |
||
339 | // instead of: visibleColumnNames.retainAll(columnNames);
|
||
340 | |||
341 | visibleColumnNamesOriginal = intersectKeepOrder(columnNames, visibleColumnNamesOriginal); |
||
342 | // instead of: visibleColumnNamesOriginal.retainAll(columnNames);
|
||
343 | |||
344 | // remove from alias map removed columns
|
||
345 | name2Alias.keySet().retainAll(columnNames); |
||
346 | name2AliasOriginal.keySet().retainAll(columnNames); |
||
347 | |||
348 | 42806 | fdiaz | initializeFormatingPatterns(); |
349 | |||
350 | 42775 | jjdelcerro | getFeatureQuery().setFeatureType(featureType); |
351 | reloadFeatures(); |
||
352 | //Selection must be locked to avoid losing it when the table is refreshed
|
||
353 | selectionLocked=true;
|
||
354 | //The table is refreshed
|
||
355 | try {
|
||
356 | fireTableStructureChanged(); |
||
357 | } catch (Exception e) { |
||
358 | logger.warn("Couldn't reload changed table");
|
||
359 | }finally{
|
||
360 | //The locked selection is unlocked.
|
||
361 | selectionLocked=false;
|
||
362 | 42806 | fdiaz | } |
363 | 40435 | jjdelcerro | |
364 | } |
||
365 | |||
366 | 42775 | jjdelcerro | private void reloadFeatures() { |
367 | try {
|
||
368 | this.getFeaturePager().reload();
|
||
369 | } catch (BaseException ex) {
|
||
370 | throw new FeaturesDataReloadException(ex); |
||
371 | } |
||
372 | } |
||
373 | 42806 | fdiaz | |
374 | 40435 | jjdelcerro | /**
|
375 | * keeps order of first parameter
|
||
376 | 42806 | fdiaz | *
|
377 | 40435 | jjdelcerro | * @param lista
|
378 | * @param listb
|
||
379 | * @return
|
||
380 | */
|
||
381 | private List<String> intersectKeepOrder(List<String> lista, List<String> listb) { |
||
382 | 42806 | fdiaz | |
383 | 42775 | jjdelcerro | List<String> resp = new ArrayList<>(); |
384 | 40435 | jjdelcerro | resp.addAll(lista); |
385 | resp.retainAll(listb); |
||
386 | return resp;
|
||
387 | } |
||
388 | |||
389 | public void setVisibleColumns(List<String> names) { |
||
390 | // Recreate the visible column names list
|
||
391 | 42806 | fdiaz | // to maintain the original order
|
392 | 42775 | jjdelcerro | visibleColumnNames = new ArrayList<>(names.size()); |
393 | 40435 | jjdelcerro | for (int i = 0; i < columnNames.size(); i++) { |
394 | String columnName = columnNames.get(i);
|
||
395 | if (names.contains(columnName)) {
|
||
396 | visibleColumnNames.add(columnName); |
||
397 | } |
||
398 | } |
||
399 | 42775 | jjdelcerro | updatePagerWithHiddenColums(); |
400 | 40435 | jjdelcerro | fireTableStructureChanged(); |
401 | } |
||
402 | |||
403 | 41212 | jjdelcerro | protected String[] getHiddenColumnNames() { |
404 | List<String> hiddenColumns = new ArrayList<String>(); |
||
405 | hiddenColumns.addAll(columnNames); |
||
406 | 42806 | fdiaz | |
407 | 41212 | jjdelcerro | for (int i = 0; i < visibleColumnNames.size(); i++) { |
408 | String columnName = visibleColumnNames.get(i);
|
||
409 | hiddenColumns.remove(columnName); |
||
410 | } |
||
411 | if( hiddenColumns.size()<1 ) { |
||
412 | return null; |
||
413 | } |
||
414 | return (String[]) hiddenColumns.toArray(new String[hiddenColumns.size()]); |
||
415 | } |
||
416 | 42806 | fdiaz | |
417 | 40435 | jjdelcerro | /**
|
418 | * Changes all columns to be visible.
|
||
419 | */
|
||
420 | public void setAllVisible() { |
||
421 | visibleColumnNames.clear(); |
||
422 | visibleColumnNames.addAll(columnNames); |
||
423 | fireTableStructureChanged(); |
||
424 | } |
||
425 | |||
426 | 42775 | jjdelcerro | @Override
|
427 | public void setColumnOrder(String name, boolean ascending) |
||
428 | 40435 | jjdelcerro | throws BaseException {
|
429 | 42775 | jjdelcerro | FeatureQueryOrder order = this.getFeatureQuery().getOrder();
|
430 | 40435 | jjdelcerro | if (order == null) { |
431 | order = new FeatureQueryOrder();
|
||
432 | 42775 | jjdelcerro | this.getFeatureQuery().setOrder(order);
|
433 | 40435 | jjdelcerro | } |
434 | order.clear(); |
||
435 | order.add(name, ascending); |
||
436 | 42775 | jjdelcerro | this.getFeaturePager().reload();
|
437 | fireTableChanged(new TableModelEvent(this, 0, this.getRowCount() - 1)); |
||
438 | 40435 | jjdelcerro | } |
439 | |||
440 | @Override
|
||
441 | 42775 | jjdelcerro | public int getRowCount() { |
442 | // Return the total size of the collection
|
||
443 | // If the size is bigger than INTEGER.MAX_VALUE, return that instead
|
||
444 | try {
|
||
445 | long totalSize = this.getFeaturePager().getTotalSize(); |
||
446 | if (totalSize > Integer.MAX_VALUE) { |
||
447 | return Integer.MAX_VALUE; |
||
448 | } else {
|
||
449 | return (int) totalSize; |
||
450 | } |
||
451 | } catch (ConcurrentDataModificationException e) {
|
||
452 | logger.debug("Error while getting the total size of the set", e);
|
||
453 | return 0; |
||
454 | } |
||
455 | 40435 | jjdelcerro | } |
456 | |||
457 | 42775 | jjdelcerro | @Override
|
458 | public boolean isColumnVisible(String name) { |
||
459 | 40435 | jjdelcerro | return visibleColumnNames.contains(name);
|
460 | } |
||
461 | |||
462 | 42775 | jjdelcerro | @Override
|
463 | public String getColumnAlias(String name) { |
||
464 | String alias = name2Alias.get(name);
|
||
465 | return alias == null ? name : alias; |
||
466 | 40435 | jjdelcerro | } |
467 | |||
468 | 42775 | jjdelcerro | @Override
|
469 | public void setColumnAlias(String name, String alias) { |
||
470 | name2Alias.put(name, alias); |
||
471 | fireTableStructureChanged(); |
||
472 | 40435 | jjdelcerro | } |
473 | |||
474 | 42775 | jjdelcerro | @Override
|
475 | 41707 | jjdelcerro | public int getOriginalColumnIndex(int columnIndex) { |
476 | 40435 | jjdelcerro | String columnName = visibleColumnNames.get(columnIndex);
|
477 | return columnNames.indexOf(columnName);
|
||
478 | } |
||
479 | |||
480 | @Override
|
||
481 | 42775 | jjdelcerro | public Object getValueAt(int rowIndex, int columnIndex) { |
482 | // Get the Feature at row "rowIndex", and return the value of the
|
||
483 | // attribute at "columnIndex"
|
||
484 | Feature feature = getFeatureAt(rowIndex); |
||
485 | return feature == null ? null : getFeatureValue(feature, columnIndex); |
||
486 | } |
||
487 | 42806 | fdiaz | |
488 | 42775 | jjdelcerro | @Override
|
489 | public Feature getFeatureAt(int rowIndex) { |
||
490 | try {
|
||
491 | return this.getFeaturePager().getFeatureAt(rowIndex); |
||
492 | } catch (BaseException ex) {
|
||
493 | throw new GetFeatureAtException(rowIndex, ex); |
||
494 | } |
||
495 | 42806 | fdiaz | } |
496 | |||
497 | 40435 | jjdelcerro | protected Object getFeatureValue(Feature feature, int columnIndex) { |
498 | int realColumnIndex = getOriginalColumnIndex(columnIndex);
|
||
499 | 42775 | jjdelcerro | return feature.get(realColumnIndex);
|
500 | 40435 | jjdelcerro | } |
501 | |||
502 | protected EditableFeature setFeatureValue(Feature feature, int columnIndex, |
||
503 | Object value) {
|
||
504 | int realColumnIndex = getOriginalColumnIndex(columnIndex);
|
||
505 | 42775 | jjdelcerro | EditableFeature editableFeature = feature.getEditable(); |
506 | editableFeature.set(realColumnIndex, value); |
||
507 | return editableFeature;
|
||
508 | 40435 | jjdelcerro | } |
509 | 42775 | jjdelcerro | |
510 | 42806 | fdiaz | |
511 | 40435 | jjdelcerro | public void acceptChanges() { |
512 | 42775 | jjdelcerro | visibleColumnNamesOriginal = new ArrayList<>(visibleColumnNames); |
513 | name2AliasOriginal = new HashMap<>(name2Alias); |
||
514 | 40435 | jjdelcerro | } |
515 | 42806 | fdiaz | |
516 | 40435 | jjdelcerro | public void cancelChanges() { |
517 | 42775 | jjdelcerro | visibleColumnNames = new ArrayList<>(visibleColumnNamesOriginal); |
518 | name2Alias = new HashMap<>(name2AliasOriginal); |
||
519 | 40435 | jjdelcerro | fireTableStructureChanged(); |
520 | } |
||
521 | 41699 | jjdelcerro | |
522 | 42806 | fdiaz | |
523 | 42775 | jjdelcerro | @Override
|
524 | public String getColumnFormattingPattern(int column) { |
||
525 | 41699 | jjdelcerro | String columnName = this.visibleColumnNames.get(column); |
526 | 42775 | jjdelcerro | return this.getColumnFormattingPattern(columnName); |
527 | 41699 | jjdelcerro | } |
528 | 42806 | fdiaz | |
529 | 42775 | jjdelcerro | @Override
|
530 | public String getColumnFormattingPattern(String columnName) { |
||
531 | 41707 | jjdelcerro | String pattern = this.patterns.get(columnName); |
532 | return pattern;
|
||
533 | 41699 | jjdelcerro | } |
534 | 42806 | fdiaz | |
535 | 42775 | jjdelcerro | @Override
|
536 | public void setColumnFormattingPattern(String columnName, String pattern) { |
||
537 | 41699 | jjdelcerro | this.patterns.put(columnName,pattern);
|
538 | } |
||
539 | 42806 | fdiaz | |
540 | 42775 | jjdelcerro | @Override
|
541 | 41699 | jjdelcerro | public Locale getLocaleOfData() { |
542 | return this.localeOfData; |
||
543 | } |
||
544 | 42806 | fdiaz | |
545 | 42775 | jjdelcerro | @Override
|
546 | 41699 | jjdelcerro | public void setLocaleOfData(Locale locale) { |
547 | this.localeOfData = locale;
|
||
548 | } |
||
549 | 42806 | fdiaz | |
550 | 42775 | jjdelcerro | public boolean isSelectionLocked() { |
551 | return selectionLocked;
|
||
552 | 42806 | fdiaz | } |
553 | 41699 | jjdelcerro | |
554 | 42775 | jjdelcerro | @Override
|
555 | public boolean isSelectionUp() { |
||
556 | return this.getFeaturePager().isSelectionUp(); |
||
557 | 42806 | fdiaz | } |
558 | 42775 | jjdelcerro | |
559 | @Override
|
||
560 | public void setSelectionUp(boolean selectionUp) { |
||
561 | this.getFeaturePager().setSelectionUp(selectionUp);
|
||
562 | fireTableChanged(new TableModelEvent(this, 0, getRowCount() - 1)); |
||
563 | } |
||
564 | 42806 | fdiaz | |
565 | 42775 | jjdelcerro | private class DelayAction extends Timer implements ActionListener, Runnable { |
566 | private static final int STATE_NONE = 0; |
||
567 | private static final int STATE_NEED_RELOADALL = 1; |
||
568 | private static final int STATE_NEED_RELOAD_IF_FEATURE_COUNT_CHANGED = 2; |
||
569 | private static final int STATE_NEED_RELOAD_IF_FEATURE_UPDATED = 4; |
||
570 | private static final int STATE_NEED_RELOAD_IF_FEATURE_TYPE_CHANGED = 8; |
||
571 | private static final int STATE_NEED_RELOAD_FEATURE_TYPE = 16; |
||
572 | private static final int STATE_NEED_SELECTION_UP = 32; |
||
573 | private static final int STATE_NEED_RELOAD_ALL_FEATURES=64; |
||
574 | 42806 | fdiaz | |
575 | 42775 | jjdelcerro | private static final long serialVersionUID = -5692569125344166705L; |
576 | |||
577 | private int state = STATE_NONE; |
||
578 | private Feature feature;
|
||
579 | private FeatureType featureType;
|
||
580 | private boolean isSelecctionUp; |
||
581 | |||
582 | public DelayAction() {
|
||
583 | super(1000,null); |
||
584 | this.setRepeats(false); |
||
585 | this.reset();
|
||
586 | this.addActionListener(this); |
||
587 | } |
||
588 | |||
589 | private void reset() { |
||
590 | this.state = STATE_NONE;
|
||
591 | this.isSelecctionUp = false; |
||
592 | this.feature = null; |
||
593 | this.featureType = null; |
||
594 | } |
||
595 | |||
596 | public void actionPerformed(ActionEvent ae) { |
||
597 | this.run();
|
||
598 | } |
||
599 | |||
600 | public void run() { |
||
601 | if( !SwingUtilities.isEventDispatchThread() ) { |
||
602 | SwingUtilities.invokeLater(this); |
||
603 | return;
|
||
604 | } |
||
605 | this.stop();
|
||
606 | logger.info("DelayAction.run["+this.state+"] begin"); |
||
607 | switch(this.state) { |
||
608 | case STATE_NEED_RELOADALL:
|
||
609 | reloadAll(); |
||
610 | break;
|
||
611 | case STATE_NEED_RELOAD_IF_FEATURE_COUNT_CHANGED:
|
||
612 | reloadIfFeatureCountChanged(feature); |
||
613 | break;
|
||
614 | case STATE_NEED_RELOAD_IF_FEATURE_UPDATED:
|
||
615 | reloadIfFeatureUpdated(feature); |
||
616 | break;
|
||
617 | case STATE_NEED_RELOAD_IF_FEATURE_TYPE_CHANGED:
|
||
618 | reloadIfTypeChanged(featureType); |
||
619 | break;
|
||
620 | case STATE_NEED_RELOAD_FEATURE_TYPE:
|
||
621 | reloadFeatureType(); |
||
622 | updatePagerWithHiddenColums(); |
||
623 | break;
|
||
624 | case STATE_NEED_RELOAD_ALL_FEATURES:
|
||
625 | reloadFeatures(); |
||
626 | fireTableChanged(new TableModelEvent(DefaultFeatureTableModel.this, 0, getRowCount())); |
||
627 | break;
|
||
628 | case STATE_NEED_SELECTION_UP:
|
||
629 | case STATE_NONE:
|
||
630 | default:
|
||
631 | break;
|
||
632 | } |
||
633 | if( isSelecctionUp ) {
|
||
634 | getFeaturePager().setSelectionUp(true);
|
||
635 | } |
||
636 | this.reset();
|
||
637 | logger.info("DelayAction.run["+this.state+"] end"); |
||
638 | } |
||
639 | |||
640 | public void nextState(int nextstate) { |
||
641 | this.nextState(nextstate, null, null); |
||
642 | } |
||
643 | |||
644 | public void nextState(int nextstate, Feature feature) { |
||
645 | this.nextState(nextstate, feature, null); |
||
646 | } |
||
647 | |||
648 | public void nextState(int nextstate, FeatureType featureType) { |
||
649 | this.nextState(nextstate, null, featureType); |
||
650 | } |
||
651 | |||
652 | public void nextState(int nextstate, Feature feature, FeatureType featureType) { |
||
653 | this.feature = feature;
|
||
654 | this.featureType = featureType;
|
||
655 | switch(nextstate) {
|
||
656 | case STATE_NEED_RELOADALL:
|
||
657 | case STATE_NEED_RELOAD_IF_FEATURE_COUNT_CHANGED:
|
||
658 | case STATE_NEED_RELOAD_IF_FEATURE_UPDATED:
|
||
659 | switch(this.state) { |
||
660 | case STATE_NEED_RELOADALL:
|
||
661 | case STATE_NEED_RELOAD_IF_FEATURE_COUNT_CHANGED:
|
||
662 | //case STATE_NEED_RELOAD_IF_FEATURE_UPDATED:
|
||
663 | this.state = STATE_NEED_RELOADALL;
|
||
664 | break;
|
||
665 | case STATE_NEED_RELOAD_IF_FEATURE_TYPE_CHANGED:
|
||
666 | case STATE_NEED_RELOAD_FEATURE_TYPE:
|
||
667 | this.state = STATE_NEED_RELOAD_FEATURE_TYPE;
|
||
668 | break;
|
||
669 | case STATE_NEED_RELOAD_IF_FEATURE_UPDATED:
|
||
670 | case STATE_NEED_RELOAD_ALL_FEATURES:
|
||
671 | this.state=STATE_NEED_RELOAD_ALL_FEATURES;
|
||
672 | break;
|
||
673 | case STATE_NEED_SELECTION_UP:
|
||
674 | this.state = nextstate;
|
||
675 | this.isSelecctionUp = true; |
||
676 | break;
|
||
677 | case STATE_NONE:
|
||
678 | default:
|
||
679 | this.state = nextstate;
|
||
680 | break;
|
||
681 | } |
||
682 | break;
|
||
683 | case STATE_NEED_RELOAD_IF_FEATURE_TYPE_CHANGED:
|
||
684 | case STATE_NEED_RELOAD_FEATURE_TYPE:
|
||
685 | switch(this.state) { |
||
686 | case STATE_NEED_RELOADALL:
|
||
687 | case STATE_NEED_RELOAD_IF_FEATURE_COUNT_CHANGED:
|
||
688 | case STATE_NEED_RELOAD_IF_FEATURE_UPDATED:
|
||
689 | case STATE_NEED_RELOAD_ALL_FEATURES:
|
||
690 | case STATE_NEED_RELOAD_IF_FEATURE_TYPE_CHANGED:
|
||
691 | case STATE_NEED_RELOAD_FEATURE_TYPE:
|
||
692 | this.state = STATE_NEED_RELOAD_FEATURE_TYPE;
|
||
693 | break;
|
||
694 | case STATE_NEED_SELECTION_UP:
|
||
695 | this.state = nextstate;
|
||
696 | this.isSelecctionUp = true; |
||
697 | break;
|
||
698 | case STATE_NONE:
|
||
699 | default:
|
||
700 | this.state = nextstate;
|
||
701 | break;
|
||
702 | } |
||
703 | break;
|
||
704 | case STATE_NEED_SELECTION_UP:
|
||
705 | switch(this.state) { |
||
706 | case STATE_NEED_RELOADALL:
|
||
707 | case STATE_NEED_RELOAD_IF_FEATURE_COUNT_CHANGED:
|
||
708 | case STATE_NEED_RELOAD_IF_FEATURE_UPDATED:
|
||
709 | case STATE_NEED_RELOAD_IF_FEATURE_TYPE_CHANGED:
|
||
710 | case STATE_NEED_RELOAD_ALL_FEATURES:
|
||
711 | case STATE_NEED_RELOAD_FEATURE_TYPE:
|
||
712 | case STATE_NEED_SELECTION_UP:
|
||
713 | this.isSelecctionUp = true; |
||
714 | break;
|
||
715 | case STATE_NONE:
|
||
716 | default:
|
||
717 | this.state = nextstate;
|
||
718 | this.isSelecctionUp = true; |
||
719 | break;
|
||
720 | } |
||
721 | break;
|
||
722 | case STATE_NONE:
|
||
723 | default:
|
||
724 | this.state = STATE_NONE;
|
||
725 | break;
|
||
726 | } |
||
727 | if( this.state != STATE_NONE ) { |
||
728 | this.start();
|
||
729 | } |
||
730 | } |
||
731 | |||
732 | } |
||
733 | |||
734 | /**
|
||
735 | * Reloads the table data if a feature has been changed, not through the
|
||
736 | * table.
|
||
737 | */
|
||
738 | private void reloadIfFeatureCountChanged(Feature feature) { |
||
739 | // Is any data is changed in the FeatureStore, notify the model
|
||
740 | // listeners. Ignore the case where the updated feature is
|
||
741 | // changed through us.
|
||
742 | if (editableFeature == null || !editableFeature.equals(feature)) { |
||
743 | reloadFeatures(); |
||
744 | //Selection must be locked to avoid losing it when the table is refreshed
|
||
745 | selectionLocked=true;
|
||
746 | //The table is refreshed
|
||
747 | try {
|
||
748 | fireTableDataChanged(); |
||
749 | } catch (Exception e) { |
||
750 | logger.warn("Couldn't reload changed table");
|
||
751 | }finally{
|
||
752 | //The locked selection is unlocked.
|
||
753 | selectionLocked=false;
|
||
754 | } |
||
755 | } |
||
756 | } |
||
757 | |||
758 | private void reloadIfFeatureUpdated(Feature feature) { |
||
759 | // Is any data is changed in the FeatureStore, notify the model
|
||
760 | // listeners. Ignore the case where the updated feature is
|
||
761 | // changed through us.
|
||
762 | if (editableFeature == null || !editableFeature.equals(feature)) { |
||
763 | reloadFeatures(); |
||
764 | fireTableChanged(new TableModelEvent(this, 0, getRowCount())); |
||
765 | } |
||
766 | } |
||
767 | |||
768 | /**
|
||
769 | * Reloads data and structure if the {@link FeatureType} of the features
|
||
770 | * being shown has changed.
|
||
771 | */
|
||
772 | private void reloadIfTypeChanged(FeatureType updatedType) { |
||
773 | // If the updated featured type is the one currently being
|
||
774 | // shown, reload the table.
|
||
775 | if (updatedType != null |
||
776 | && updatedType.getId().equals(getFeatureType().getId())) { |
||
777 | setFeatureType(updatedType); |
||
778 | } |
||
779 | } |
||
780 | |||
781 | private void reloadAll() { |
||
782 | reloadFeatureType(); |
||
783 | } |
||
784 | |||
785 | private void reloadFeatureType() { |
||
786 | try {
|
||
787 | FeatureType featureType = this.getFeaturePager().getFeatureType();
|
||
788 | FeatureStore store = this.getFeaturePager().getFeatureStore();
|
||
789 | this.setFeatureType( store.getFeatureType(featureType.getId()) );
|
||
790 | } catch (DataException e) {
|
||
791 | throw new FeaturesDataReloadException(e); |
||
792 | } |
||
793 | } |
||
794 | |||
795 | @Override
|
||
796 | public void update(final Observable observable, final Object notification) { |
||
797 | if (notification instanceof ComplexNotification) { |
||
798 | // A lot of things might have happened in the store, so don't
|
||
799 | // bother looking into each notification.
|
||
800 | this.delayAction.nextState(DelayAction.STATE_NEED_RELOADALL);
|
||
801 | // reloadAll();
|
||
802 | } else if (observable.equals(getFeatureStore()) |
||
803 | && notification instanceof FeatureStoreNotification) {
|
||
804 | FeatureStoreNotification fsNotification |
||
805 | = (FeatureStoreNotification) notification; |
||
806 | String type = fsNotification.getType();
|
||
807 | |||
808 | // If there are new, updated or deleted features
|
||
809 | // reload the table data
|
||
810 | if (FeatureStoreNotification.AFTER_DELETE.equals(type)
|
||
811 | || FeatureStoreNotification.AFTER_INSERT.equals(type)) { |
||
812 | // reloadIfFeatureCountChanged(fsNotification.getFeature());
|
||
813 | this.delayAction.nextState(DelayAction.STATE_NEED_RELOAD_IF_FEATURE_COUNT_CHANGED, fsNotification.getFeature());
|
||
814 | |||
815 | } else if (FeatureStoreNotification.AFTER_UPDATE.equals(type)) { |
||
816 | // reloadIfFeatureUpdated(fsNotification.getFeature());
|
||
817 | this.delayAction.nextState(DelayAction.STATE_NEED_RELOAD_IF_FEATURE_UPDATED, fsNotification.getFeature());
|
||
818 | |||
819 | } else if (FeatureStoreNotification.AFTER_UPDATE_TYPE.equals(type)) { |
||
820 | // reloadIfTypeChanged(fsNotification.getFeatureType());
|
||
821 | this.delayAction.nextState(DelayAction.STATE_NEED_RELOAD_IF_FEATURE_TYPE_CHANGED, fsNotification.getFeatureType());
|
||
822 | |||
823 | } else if (FeatureStoreNotification.TRANSFORM_CHANGE.equals(type) |
||
824 | || FeatureStoreNotification.AFTER_UNDO.equals(type) |
||
825 | || FeatureStoreNotification.AFTER_REDO.equals(type) |
||
826 | || FeatureStoreNotification.AFTER_REFRESH.equals(type)) { |
||
827 | // reloadAll();
|
||
828 | this.delayAction.nextState(DelayAction.STATE_NEED_RELOADALL);
|
||
829 | |||
830 | } else if (FeatureStoreNotification.AFTER_FINISHEDITING.equals(type) |
||
831 | || FeatureStoreNotification.AFTER_STARTEDITING.equals(type) |
||
832 | || FeatureStoreNotification.AFTER_CANCELEDITING.equals(type)) { |
||
833 | /*
|
||
834 | No tengo nada claro por que es necesario llamar al reloadFeatureType
|
||
835 | pero si no se incluye hay problemas si durante la edicion se a?aden
|
||
836 | campos a la tabla. Sin esto, al cerrar la edicion, los campos a?adidos
|
||
837 | desaparecen de la tabla aunque estan en el fichero.
|
||
838 | Ver ticket #2434 https://devel.gvsig.org/redmine/issues/2434
|
||
839 | */
|
||
840 | // reloadFeatureType();
|
||
841 | // updatePaginHelperWithHiddenColums();
|
||
842 | this.delayAction.nextState(DelayAction.STATE_NEED_RELOAD_FEATURE_TYPE, fsNotification.getFeatureType());
|
||
843 | } else if (FeatureStoreNotification.SELECTION_CHANGE.equals(type)) { |
||
844 | if( this.isSelectionUp() ) { |
||
845 | this.setSelectionUp(true); |
||
846 | this.delayAction.nextState(DelayAction.STATE_NEED_SELECTION_UP);
|
||
847 | } |
||
848 | } |
||
849 | } |
||
850 | } |
||
851 | |||
852 | @Override
|
||
853 | public int getSelectionCount() { |
||
854 | try {
|
||
855 | FeatureSelection selection = this.getFeatureStore().getFeatureSelection();
|
||
856 | return (int) selection.getSize(); |
||
857 | } catch (DataException ex) {
|
||
858 | throw new RuntimeException("Can't get selection of the FeatureTableModel",ex); |
||
859 | } |
||
860 | } |
||
861 | 42806 | fdiaz | |
862 | |||
863 | 40435 | jjdelcerro | } |