Statistics
| Revision:

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 / FeatureSelectionModel.java @ 44644

History | View | Annotate | Download (13.3 KB)

1 40559 jjdelcerro
/**
2
 * gvSIG. Desktop Geographic Information System.
3 40435 jjdelcerro
 *
4 40559 jjdelcerro
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6 40435 jjdelcerro
 * 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 40559 jjdelcerro
 *
11 40435 jjdelcerro
 * 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 40559 jjdelcerro
 *
16 40435 jjdelcerro
 * 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 40559 jjdelcerro
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 40435 jjdelcerro
 * MA  02110-1301, USA.
20 40559 jjdelcerro
 *
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 40435 jjdelcerro
 */
24
/*
25
 * AUTHORS (In addition to CIT):
26
 * 2010 {}  {{Task}}
27
 */
28 42775 jjdelcerro
package org.gvsig.fmap.dal.swing.impl.featuretable;
29 40435 jjdelcerro
30 42807 jjdelcerro
import java.awt.event.ActionEvent;
31
import java.awt.event.ActionListener;
32 43358 jjdelcerro
import java.util.logging.Level;
33 40435 jjdelcerro
import javax.swing.ListSelectionModel;
34
import javax.swing.event.EventListenerList;
35
import javax.swing.event.ListSelectionEvent;
36
import javax.swing.event.ListSelectionListener;
37
38
import org.gvsig.fmap.dal.exception.DataException;
39
import org.gvsig.fmap.dal.feature.Feature;
40 42804 jbadia
import org.gvsig.fmap.dal.feature.FeatureQuery;
41 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureSelection;
42
import org.gvsig.fmap.dal.feature.FeatureSet;
43
import org.gvsig.fmap.dal.feature.FeatureStore;
44
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
45
import org.gvsig.fmap.dal.feature.exception.ConcurrentDataModificationException;
46 42775 jjdelcerro
import org.gvsig.fmap.dal.swing.FeatureTableModel;
47 40435 jjdelcerro
import org.gvsig.tools.dispose.DisposableIterator;
48
import org.gvsig.tools.observer.Observable;
49
import org.gvsig.tools.observer.Observer;
50
import org.slf4j.Logger;
51
import org.slf4j.LoggerFactory;
52
53
/**
54
 * @author 2010- C?sar Ordi?ana - gvSIG team
55
 */
56
public class FeatureSelectionModel implements ListSelectionModel, Observer {
57 42775 jjdelcerro
    private static final Logger LOG = LoggerFactory.getLogger(FeatureSelectionModel.class);
58 42639 dmartinezizquierdo
59 40435 jjdelcerro
        protected EventListenerList listenerList = new EventListenerList();
60
61
        private final FeatureTableModel featureTableModel;
62
63
        private int selectionMode = SINGLE_INTERVAL_SELECTION;
64
65
        private boolean isAdjusting = false;
66
67
        private int anchor = -1;
68
69
        private int lead = -1;
70 42639 dmartinezizquierdo
71 40435 jjdelcerro
        private int currentFirst = -1;
72
        private int currentLast = -1;
73
74
        /**
75
         * Creates a new {@link FeatureSelectionModel} with a
76
         * {@link FeatureTableModel} used to get the {@link Feature}s by position in
77
         * the table.
78 42639 dmartinezizquierdo
         *
79 40435 jjdelcerro
         * @param featureTableModel
80
         *            to get Features from
81
         * @throws DataException
82
         *             if there is an error getting the store selection
83
         */
84 42775 jjdelcerro
        public FeatureSelectionModel(FeatureTableModel featureTableModel)  {
85 40435 jjdelcerro
                this.featureTableModel = featureTableModel;
86 42807 jjdelcerro
                this.featureTableModel.getFeatureSelection().addObserver(this);
87
                this.featureTableModel.addChangeListener(new ActionListener() {
88
89
                    @Override
90
                    public void actionPerformed(ActionEvent e) {
91
                        if( FeatureTableModel.CHANGE_SELECTION.equals(e.getActionCommand()) ) {
92
                            featureSelectionChanged();
93
                        }
94
                    }
95
                });
96 40435 jjdelcerro
        }
97 42807 jjdelcerro
98
        private void featureSelectionChanged() {
99
            this.featureTableModel.getFeatureSelection().addObserver(this);
100
        }
101
102 42775 jjdelcerro
    @Override
103 40435 jjdelcerro
        public int getAnchorSelectionIndex() {
104
                return anchor;
105
        }
106
107 42775 jjdelcerro
    @Override
108 40435 jjdelcerro
        public int getLeadSelectionIndex() {
109
                return lead;
110
        }
111
112 42775 jjdelcerro
    @Override
113 40435 jjdelcerro
        public int getMaxSelectionIndex() {
114 42639 dmartinezizquierdo
115 40435 jjdelcerro
            int resp = this.getSelectionIndex(true);
116
            return resp;
117
            /*
118 42639 dmartinezizquierdo
             *
119 40435 jjdelcerro
             * The call to "featureTableModel.getFeatureAt(i)"
120
             * causes a lot of reloadPage all over
121 42639 dmartinezizquierdo
             *
122 40435 jjdelcerro
                FeatureSelection selection = getFeatureSelection();
123
                try {
124
                        if (!selection.isEmpty()) {
125
                                for (int i = featureTableModel.getRowCount() - 1; i >= 0; i--) {
126
                                        if (selection.isSelected(featureTableModel.getFeatureAt(i))) {
127
                                                return i;
128
                                        }
129
                                }
130
                        }
131
                } catch (DataException e) {
132
                        throw new SelectionChangeException(e);
133
                }
134
                return -1;
135
                */
136
        }
137
138 42775 jjdelcerro
    @Override
139 40435 jjdelcerro
        public int getMinSelectionIndex() {
140
141
            int resp = this.getSelectionIndex(false);
142
            return resp;
143 42639 dmartinezizquierdo
144 40435 jjdelcerro
            /*
145 42639 dmartinezizquierdo
             *
146 40435 jjdelcerro
         * The call to "featureTableModel.getFeatureAt(i)"
147
         * causes a lot of reloadPage all over
148 42639 dmartinezizquierdo
             *
149 40435 jjdelcerro
                try {
150

151
                    int ii = 0;
152

153
                    FeatureSelection selection = this.getFeatureSelection();
154
            for (int i = 0; i < featureTableModel.getRowCount(); i++) {
155
                if (selection.isSelected(featureTableModel.getFeatureAt(i))) {
156
                    ii = i;
157
                }
158
            }
159
                } catch (Exception e) {
160
                        throw new SelectionChangeException(e);
161
                }
162
                */
163 42639 dmartinezizquierdo
164 40435 jjdelcerro
        }
165
166 42775 jjdelcerro
    @Override
167 40435 jjdelcerro
        public void insertIndexInterval(int index, int length, boolean before) {
168
                // Nothing to do
169
        }
170
171 42775 jjdelcerro
    @Override
172 40435 jjdelcerro
        public void removeIndexInterval(int index0, int index1) {
173
                // Nothing to do
174
        }
175
176 42775 jjdelcerro
    @Override
177 40435 jjdelcerro
        public void setAnchorSelectionIndex(int index) {
178
                this.anchor = index;
179
        }
180
181 42775 jjdelcerro
    @Override
182 40435 jjdelcerro
        public void setLeadSelectionIndex(int index) {
183
                this.lead = index;
184
        }
185
186 42775 jjdelcerro
    @Override
187 40435 jjdelcerro
        public void addSelectionInterval(int index0, int index1) {
188 42639 dmartinezizquierdo
            if (!featureTableModel.isSelectionLocked()){
189
                doWithSelection(new FeatureSelectionOperation() {
190 40435 jjdelcerro
191 42775 jjdelcerro
                    @Override
192 42639 dmartinezizquierdo
                    public void doWithSelection(FeatureSelection selection, int first,
193
                        int last) throws DataException {
194
                        for (int i = first; i <= last; i++) {
195
                            Feature feature = getFeature(i);
196
                            if (!selection.isSelected(feature)) {
197
                                selection.select(feature);
198
                            }
199
                        }
200
                    }
201 40435 jjdelcerro
202 42639 dmartinezizquierdo
                }, index0, index1, true);
203
            }
204 40435 jjdelcerro
        }
205
206 42775 jjdelcerro
    @Override
207 40435 jjdelcerro
        public void setSelectionInterval(int index0, int index1) {
208 42639 dmartinezizquierdo
            if (!featureTableModel.isSelectionLocked()){
209
                doWithSelection(new FeatureSelectionOperation() {
210 40435 jjdelcerro
211 42775 jjdelcerro
                    @Override
212 42639 dmartinezizquierdo
                    public void doWithSelection(FeatureSelection selection, int first,
213
                        int last) throws DataException {
214
                        selection.deselectAll();
215
                        for (int i = first; i <= last; i++) {
216
                            Feature feature = getFeature(i);
217
                            selection.select(feature);
218
                        }
219
                    }
220 40435 jjdelcerro
221 42639 dmartinezizquierdo
                }, index0, index1, true);
222
            }
223 40435 jjdelcerro
        }
224
225 42775 jjdelcerro
    @Override
226 40435 jjdelcerro
        public void removeSelectionInterval(int index0, int index1) {
227 42639 dmartinezizquierdo
            if (!featureTableModel.isSelectionLocked()){
228
                doWithSelection(new FeatureSelectionOperation() {
229 40435 jjdelcerro
230 42775 jjdelcerro
                    @Override
231 42639 dmartinezizquierdo
                    public void doWithSelection(FeatureSelection selection, int first,
232
                        int last) throws DataException {
233
                        for (int i = first; i <= last; i++) {
234
                            Feature feature = getFeature(i);
235
                            if (selection.isSelected(feature)) {
236
                                selection.deselect(feature);
237
                            }
238
                        }
239
                    }
240 40435 jjdelcerro
241 42639 dmartinezizquierdo
                }, index0, index1, false);
242
            }
243 40435 jjdelcerro
        }
244
245 42775 jjdelcerro
    @Override
246 40435 jjdelcerro
        public void clearSelection() {
247 42639 dmartinezizquierdo
            if (!featureTableModel.isSelectionLocked()){
248
                try {
249
                    getFeatureSelection().deselectAll();
250
                } catch (DataException e) {
251
                    throw new SelectionChangeException(e);
252
                }
253
            }
254 40435 jjdelcerro
        }
255
256 42775 jjdelcerro
    @Override
257 40435 jjdelcerro
        public boolean isSelectedIndex(int index) {
258
                if (index == -1) {
259
                        return false;
260
                }
261
                Feature feature = featureTableModel.getFeatureAt(index);
262
                return getFeatureSelection().isSelected(feature);
263
        }
264
265 42775 jjdelcerro
    @Override
266 40435 jjdelcerro
        public boolean isSelectionEmpty() {
267
                try {
268
                        return getFeatureSelection().isEmpty();
269
                } catch (DataException ex) {
270
                        throw new SelectionChangeException(ex);
271
                }
272
        }
273
274 42775 jjdelcerro
    /**
275
     *
276
     * @return
277
     */
278
    @Override
279 40435 jjdelcerro
        public boolean getValueIsAdjusting() {
280
                return isAdjusting;
281
        }
282
283 42775 jjdelcerro
    @Override
284 40435 jjdelcerro
        public void setValueIsAdjusting(boolean valueIsAdjusting) {
285
                if (this.isAdjusting != valueIsAdjusting) {
286
                        this.isAdjusting = valueIsAdjusting;
287
                        if (this.isAdjusting) {
288
                                getFeatureSelection().beginComplexNotification();
289
                        } else {
290
                                getFeatureSelection().endComplexNotification();
291
                        }
292
                }
293
        }
294
295 42775 jjdelcerro
    @Override
296 40435 jjdelcerro
        public int getSelectionMode() {
297
                return selectionMode;
298
        }
299
300 42775 jjdelcerro
    @Override
301 40435 jjdelcerro
        public void setSelectionMode(int selectionMode) {
302
                this.selectionMode = selectionMode;
303
        }
304
305 42775 jjdelcerro
    @Override
306 40435 jjdelcerro
        public void addListSelectionListener(ListSelectionListener listener) {
307
                listenerList.add(ListSelectionListener.class, listener);
308
        }
309
310 42775 jjdelcerro
    @Override
311 40435 jjdelcerro
        public void removeListSelectionListener(ListSelectionListener listener) {
312
                listenerList.remove(ListSelectionListener.class, listener);
313
        }
314
315 42775 jjdelcerro
    @Override
316 40435 jjdelcerro
        public void update(Observable observable, Object notification) {
317 42807 jjdelcerro
            if( observable instanceof FeatureSelection ) {
318
                try{
319
                    fireValueChanged(-1, -1, false);
320
                }catch(ConcurrentDataModificationException e){
321
                    LOG.warn("The store has been updated and the selection can not be refreshed", e);
322
                }
323
            }
324 40435 jjdelcerro
        }
325
326
        private FeatureSelection getFeatureSelection() {
327 42807 jjdelcerro
                return this.featureTableModel.getFeatureSelection();
328 40435 jjdelcerro
        }
329
330
        /**
331
         * @param operation
332
         * @param index0
333
         * @param index1
334
         */
335
        private void doWithSelection(FeatureSelectionOperation operation,
336
                        int index0, int index1, boolean select) {
337
                // Set the anchor and lead
338
                anchor = index0;
339
                lead = index1;
340
341
                // As index0 <= index1 is no guaranteed, calculate the first and second
342
                // values
343
                int first = (index0 <= index1) ? index0 : index1;
344
                int last = (index0 <= index1) ? index1 : index0;
345 42639 dmartinezizquierdo
346 40435 jjdelcerro
                //If the new selection is not updated don't continue
347
                if ((currentFirst == first) && (currentLast == last)){
348
                    return;
349
                }
350
                currentFirst = first;
351
                currentLast = last;
352
353
                FeatureSelection selection = getFeatureSelection();
354
355
                // Perform the selection operation into a complex notification
356
                selection.beginComplexNotification();
357
                try {
358
                        // Is a full select or deselect
359
                        if (first == 00 && last == featureTableModel.getRowCount() - 1) {
360
                                if (select) {
361
                                        selection.selectAll();
362
                                } else {
363
                                        selection.deselectAll();
364
                                }
365
                        } else {
366
                                operation.doWithSelection(selection, first, last);
367
                        }
368
                } catch (DataException e) {
369
                        throw new SelectionChangeException(e);
370
                } finally {
371
                        selection.endComplexNotification();
372
                }
373
374
                fireValueChanged(first, last, isAdjusting);
375
        }
376
377
        /**
378
         * Returns a Feature by table row position.
379
         */
380
        private Feature getFeature(int index) {
381
                return featureTableModel.getFeatureAt(index);
382
        }
383
384
        /**
385
         * Returns the FeatureStore.
386
         */
387
        private FeatureStore getFeatureStore() {
388
                return featureTableModel.getFeatureStore();
389
        }
390
391
        /**
392
         * @param firstIndex
393
         *            the first index in the interval
394
         * @param lastIndex
395
         *            the last index in the interval
396
         * @param isAdjusting
397
         *            true if this is the final change in a series of adjustments
398
         * @see EventListenerList
399
         */
400
        protected void fireValueChanged(int firstIndex, int lastIndex,
401
                        boolean isAdjusting) {
402
                Object[] listeners = listenerList.getListenerList();
403
                ListSelectionEvent e = null;
404
405
                for (int i = listeners.length - 2; i >= 0; i -= 2) {
406
                        if (listeners[i] == ListSelectionListener.class) {
407
                                if (e == null) {
408
                                        e =
409
                                                        new ListSelectionEvent(this, firstIndex, lastIndex,
410
                                                                        isAdjusting);
411
                                }
412
                                ((ListSelectionListener) listeners[i + 1]).valueChanged(e);
413
                        }
414
                }
415
        }
416
417
        private interface FeatureSelectionOperation {
418
                void doWithSelection(FeatureSelection selection, int first, int last)
419
                                throws DataException;
420
        }
421 42639 dmartinezizquierdo
422 40435 jjdelcerro
        /**
423 42639 dmartinezizquierdo
         *
424
         * Return the index of the the first (last) selected feature
425
         *
426
         * @param last whether to return the index of the last selected feature
427 40435 jjdelcerro
         * @return
428
         */
429
        private int getSelectionIndex(boolean last) {
430 42639 dmartinezizquierdo
431 40435 jjdelcerro
        int ind = -1;
432
        int resp = -1;
433
434
        FeatureSet fs = null;
435
        DisposableIterator diter = null;
436
437
        try {
438
            FeatureSelection selection = getFeatureSelection();
439
            if (!selection.isEmpty()) {
440 43358 jjdelcerro
                FeatureStore store = getFeatureStore();
441 42804 jbadia
                    FeatureQuery query = this.featureTableModel.getFeatureQuery();
442 43358 jjdelcerro
                    if(query== null){
443
                    query = store.createFeatureQuery();
444 42804 jbadia
                    }else{
445 43358 jjdelcerro
                    try {
446
                        query = (FeatureQuery) query.clone();
447
                    } catch (CloneNotSupportedException ex) {
448
                    }
449 42804 jbadia
                    }
450 43358 jjdelcerro
                query.addEssentialAttributeNames(store);
451
                fs = store.getFeatureSet(query);
452 40435 jjdelcerro
                diter = fs.fastIterator();
453 43358 jjdelcerro
                Feature feat;
454 40435 jjdelcerro
                while (diter.hasNext()) {
455
                    ind++;
456
                    feat = (Feature) diter.next();
457
                    if (selection.isSelected(feat)) {
458
                        resp = ind;
459
                        if (!last) {
460
                            break;
461
                        }
462
                    }
463
                }
464 42639 dmartinezizquierdo
465 40435 jjdelcerro
            }
466
        } catch (DataException e) {
467
            throw new SelectionChangeException(e);
468
        } finally {
469
            if (diter != null) {
470
                diter.dispose();
471
            }
472
473
            if (fs != null) {
474
                fs.dispose();
475
            }
476
        }
477 42639 dmartinezizquierdo
        return resp;
478 40435 jjdelcerro
        }
479 42639 dmartinezizquierdo
480 40435 jjdelcerro
}