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

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

150
                    int ii = 0;
151

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