File: EventSelectionModel.java

package info (click to toggle)
libglazedlists-java 1.9.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 3,024 kB
  • ctags: 4,252
  • sloc: java: 22,561; xml: 818; sh: 51; makefile: 5
file content (382 lines) | stat: -rw-r--r-- 14,350 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
/* Glazed Lists                                                 (c) 2003-2006 */
/* http://publicobject.com/glazedlists/                      publicobject.com,*/
/*                                                     O'Dell Engineering Ltd.*/
package ca.odell.glazedlists.swing;

import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.TransformedList;
import ca.odell.glazedlists.matchers.Matcher;

import java.util.List;

import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionListener;

/**
 * An {@link EventSelectionModel} is a class that performs two simulaneous
 * services. It is a {@link ListSelectionModel} to provide selection tracking for a
 * {@link JTable}. It is also a {@link EventList} that contains the table's selection.
 *
 * <p>As elements are selected or deselected, the {@link EventList} aspect of this
 * {@link EventSelectionModel} changes. Changes to that {@link List} will change the
 * source {@link EventList}. To modify only the selection, use the
 * {@link ListSelectionModel}'s methods.
 *
 * <p>Alongside <code>MULTIPLE_INTERVAL_SELECTION</code>, this {@link ListSelectionModel}
 * supports an additional selection mode.
 * <code>MULTIPLE_INTERVAL_SELECTION_DEFENSIVE</code> is a new selection mode.
 * It is identical to <code>MULTIPLE_INTERVAL_SELECTION</code> in every way but
 * one. When a row is inserted immediately before a selected row in the
 * <code>MULTIPLE_INTERVAL_SELECTION</code> mode, it becomes selected. But in
 * the <code>MULTIPLE_INTERVAL_SELECTION_DEFENSIVE</code> mode, it does not
 * become selected. To set this mode, use
 * {@link #setSelectionMode(int) setSelectionMode(ListSelection.MULTIPLE_INTERVAL_SELECTION_DEFENSIVE)}.
 *
 * @see <a href="https://glazedlists.dev.java.net/issues/show_bug.cgi?id=39">Bug 39</a>
 * @see <a href="https://glazedlists.dev.java.net/issues/show_bug.cgi?id=61">Bug 61</a>
 * @see <a href="https://glazedlists.dev.java.net/issues/show_bug.cgi?id=76">Bug 76</a>
 * @see <a href="https://glazedlists.dev.java.net/issues/show_bug.cgi?id=108">Bug 108</a>
 * @see <a href="https://glazedlists.dev.java.net/issues/show_bug.cgi?id=110">Bug 110</a>
 * @see <a href="https://glazedlists.dev.java.net/issues/show_bug.cgi?id=112">Bug 112</a>
 * @see <a href="https://glazedlists.dev.java.net/issues/show_bug.cgi?id=222">Bug 222</a>
 *
 * @deprecated Use {@link DefaultEventSelectionModel} instead. This class will be removed in the GL
 *             2.0 release. The wrapping of the source list with an EDT safe list has been
 *             determined to be undesirable (it is better for the user to provide their own EDT
 *             safe list).
 *
 *
 * @author <a href="mailto:jesse@swank.ca">Jesse Wilson</a>
 */
public final class EventSelectionModel<E> implements AdvancedListSelectionModel<E> {

	/** The DefaultEventSelectionModel this delegates to. */
	private DefaultEventSelectionModel<E> delegateSelectionModel;

    /** the proxy moves events to the Swing Event Dispatch thread */
    protected TransformedList<E,E> swingThreadSource;

    /**
     * Creates a new selection model that also presents a list of the selection.
     *
     * The {@link EventSelectionModel} listens to this {@link EventList} in order
     * to adjust selection when the {@link EventList} is modified. For example,
     * when an element is added to the {@link EventList}, this may offset the
     * selection of the following elements.
     *
     * @param source the {@link EventList} whose selection will be managed. This should
     *      be the same {@link EventList} passed to the constructor of your
     *      {@link EventTableModel} or {@link EventListModel}.
     */
    public EventSelectionModel(EventList<E> source) {
        // lock the source list for reading since we want to prevent writes
        // from occurring until we fully initialize this EventSelectionModel
        source.getReadWriteLock().readLock().lock();
        try {
            swingThreadSource = GlazedListsSwing.swingThreadProxyList(source);
            delegateSelectionModel = new DefaultEventSelectionModel<E>(swingThreadSource);
        } finally {
            source.getReadWriteLock().readLock().unlock();
        }
    }

    /**
     * Add a listener to the list that's notified each time a change to
     * the selection occurs.
     *
     * Note that the change events fired by this class may include rows
     * that have been removed from the table. For this reason it is
     * advised not to <code>for()</code> through the changed range without
     * also verifying that each row is still in the table.
     */
	public void addListSelectionListener(ListSelectionListener listener) {
		delegateSelectionModel.addListSelectionListener(listener);
	}

    /**
     * Change the selection to be the set union of the current selection  and the indices between index0 and index1 inclusive
     */
	public void addSelectionInterval(int index0, int index1) {
		delegateSelectionModel.addSelectionInterval(index0, index1);
	}

    /**
     * Add a matcher which decides when source elements are valid for selection.
     *
     * @param validSelectionMatcher returns <tt>true</tt> if a source element
     *      can be selected; <tt>false</tt> otherwise
     */
	public void addValidSelectionMatcher(Matcher<E> validSelectionMatcher) {
		delegateSelectionModel.addValidSelectionMatcher(validSelectionMatcher);
	}

    /**
     * Change the selection to the empty set.
     */
	public void clearSelection() {
		delegateSelectionModel.clearSelection();
	}

    /**
     * Releases the resources consumed by this {@link EventSelectionModel} so that it
     * may eventually be garbage collected.
     *
     * <p>An {@link EventSelectionModel} will be garbage collected without a call to
     * {@link #dispose()}, but not before its source {@link EventList} is garbage
     * collected. By calling {@link #dispose()}, you allow the {@link EventSelectionModel}
     * to be garbage collected before its source {@link EventList}. This is
     * necessary for situations where an {@link EventSelectionModel} is short-lived but
     * its source {@link EventList} is long-lived.
     *
     * <p><strong><font color="#FF0000">Warning:</font></strong> It is an error
     * to call any method on a {@link EventSelectionModel} after it has been disposed.
     */
	public void dispose() {
		delegateSelectionModel.dispose();
		swingThreadSource.dispose();
	}

    /**
     * Return the first index argument from the most recent call to setSelectionInterval(), addSelectionInterval() or removeSelectionInterval().
     */
	public int getAnchorSelectionIndex() {
		return delegateSelectionModel.getAnchorSelectionIndex();
	}

    /**
     * Gets an {@link EventList} that contains only deselected values and
     * modifies the source list on mutation.
     *
     * Adding and removing items from this list performs the same operation on
     * the source list.
     */
	public EventList<E> getDeselected() {
		return delegateSelectionModel.getDeselected();
	}

    /**
     * Returns whether the EventSelectionModel is editable or not.
     */
	public boolean getEnabled() {
		return delegateSelectionModel.getEnabled();
	}

    /**
     * Gets the event list that always contains the current selection.
     *
     * @deprecated As of 2005/02/18, the naming of this method became
     *             ambiguous.  Please use {@link #getSelected()}.
     */
	public EventList<E> getEventList() {
		return delegateSelectionModel.getSelected();
	}

    /**
     * Return the second index argument from the most recent call to setSelectionInterval(), addSelectionInterval() or removeSelectionInterval().
     */
	public int getLeadSelectionIndex() {
		return delegateSelectionModel.getLeadSelectionIndex();
	}

    /**
     * Gets the selection model that provides selection management for a table.
     *
     * @deprecated As of 2004/11/26, the {@link EventSelectionModel} implements
     *      {@link ListSelectionModel} directly.
     */
	public ListSelectionModel getListSelectionModel() {
		return delegateSelectionModel;
	}

    /**
     * Gets the index of the last selected element.
     */
	public int getMaxSelectionIndex() {
		return delegateSelectionModel.getMaxSelectionIndex();
	}

    /**
     * Gets the index of the first selected element.
     */
	public int getMinSelectionIndex() {
		return delegateSelectionModel.getMinSelectionIndex();
	}

    /**
     * Gets an {@link EventList} that contains only selected
     * values and modifies the source list on mutation.
     *
     * Adding and removing items from this list performs the same operation on
     * the source list.
     */
	public EventList<E> getSelected() {
		return delegateSelectionModel.getSelected();
	}

    /**
     * Returns the current selection mode.
     */
	public int getSelectionMode() {
		return delegateSelectionModel.getSelectionMode();
	}

    /**
     * Gets an {@link EventList} that contains only deselected values and
     * modifies the selection state on mutation.
     *
     * Adding an item to this list deselects it and removing an item selects it.
     * If an item not in the source list is added an
     * {@link IllegalArgumentException} is thrown
     */
	public EventList<E> getTogglingDeselected() {
		return delegateSelectionModel.getTogglingDeselected();
	}

    /**
     * Gets an {@link EventList} that contains only selected
     * values and modifies the selection state on mutation.
     *
     * Adding an item to this list selects it and removing an item deselects it.
     * If an item not in the source list is added an
     * {@link IllegalArgumentException} is thrown.
     */
	public EventList<E> getTogglingSelected() {
		return delegateSelectionModel.getTogglingSelected();
	}

    /**
     * Returns true if the value is undergoing a series of changes.
     */
	public boolean getValueIsAdjusting() {
		return delegateSelectionModel.getValueIsAdjusting();
	}

    /**
     * Insert length indices beginning before/after index.
     */
	public void insertIndexInterval(int index, int length, boolean before) {
		delegateSelectionModel.insertIndexInterval(index, length, before);
	}

    /**
     * Inverts the current selection.
     */
	public void invertSelection() {
		delegateSelectionModel.invertSelection();
	}

    /**
     * Returns true if the specified index is selected. If the specified
     * index has not been seen before, this will return false. This is
     * in the case where the table painting and selection have fallen
     * out of sync. Usually in this case there is an update event waiting
     * in the event queue that notifies this model of the change
     * in table size.
     */
	public boolean isSelectedIndex(int index) {
		return delegateSelectionModel.isSelectedIndex(index);
	}

    /**
     * Returns true if no indices are selected.
     */
	public boolean isSelectionEmpty() {
		return delegateSelectionModel.isSelectionEmpty();
	}

    /**
     * Remove the indices in the interval index0,index1 (inclusive) from  the selection model.
     */
	public void removeIndexInterval(int index0, int index1) {
		delegateSelectionModel.removeIndexInterval(index0, index1);
	}

    /**
     * Remove a listener from the list that's notified each time a change to the selection occurs.
     */
	public void removeListSelectionListener(ListSelectionListener listener) {
		delegateSelectionModel.removeListSelectionListener(listener);
	}

    /**
     * Change the selection to be the set difference of the current selection  and the indices between index0 and index1 inclusive.
     */
	public void removeSelectionInterval(int index0, int index1) {
		delegateSelectionModel.removeSelectionInterval(index0, index1);
	}

    /**
     * Remove a matcher which decides when source elements are valid for selection.
     *
     * @param validSelectionMatcher returns <tt>true</tt> if a source element
     *      can be selected; <tt>false</tt> otherwise
     */
	public void removeValidSelectionMatcher(Matcher<E> validSelectionMatcher) {
		delegateSelectionModel
				.removeValidSelectionMatcher(validSelectionMatcher);
	}

    /**
     * Set the anchor selection index.
     */
	public void setAnchorSelectionIndex(int anchorSelectionIndex) {
		delegateSelectionModel.setAnchorSelectionIndex(anchorSelectionIndex);
	}

    /**
     * Set the EventSelectionModel as editable or not. This means that the user cannot
     * manipulate the selection by clicking. The selection can still be changed as
     * the source list changes.
     *
     * <p>Note that this will also disable the selection from being modified
     * <strong>programatically</strong>. Therefore you must use setEnabled(true) to
     * modify the selection in code.
     */
	public void setEnabled(boolean enabled) {
		delegateSelectionModel.setEnabled(enabled);
	}

    /**
     * Set the lead selection index.
     */
	public void setLeadSelectionIndex(int leadSelectionIndex) {
		delegateSelectionModel.setLeadSelectionIndex(leadSelectionIndex);
	}

    /**
     * Change the selection to be between index0 and index1 inclusive.
     *
     * <p>First this calculates the smallest range where changes occur. This
     * includes the union of the selection range before and the selection
     * range specified. It then walks through the change and sets each
     * index as selected or not based on whether the index is in the
     * new range. Finally it fires events to both the listening lists and
     * selection listeners about what changes happened.
     *
     * <p>If the selection does not change, this will not fire any events.
     */
	public void setSelectionInterval(int index0, int index1) {
		delegateSelectionModel.setSelectionInterval(index0, index1);
	}

    /**
     * Set the selection mode.
     */
	public void setSelectionMode(int selectionMode) {
		delegateSelectionModel.setSelectionMode(selectionMode);
	}

    /**
     * This property is true if upcoming changes to the value  of the model should be considered a single event.
     */
	public void setValueIsAdjusting(boolean valueIsAdjusting) {
		delegateSelectionModel.setValueIsAdjusting(valueIsAdjusting);
	}

	/** {@inheritDoc} */
	@Override
	public String toString() {
		return delegateSelectionModel.toString();
	}
}