File: GlazedListsSwing.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 (301 lines) | stat: -rw-r--r-- 14,755 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
/* 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.GlazedLists;
import ca.odell.glazedlists.ThresholdList;
import ca.odell.glazedlists.TransformedList;
import ca.odell.glazedlists.gui.TableFormat;
import ca.odell.glazedlists.impl.swing.LowerThresholdRangeModel;
import ca.odell.glazedlists.impl.swing.SwingThreadProxyEventList;
import ca.odell.glazedlists.impl.swing.UpperThresholdRangeModel;

import javax.swing.BoundedRangeModel;
import javax.swing.SwingUtilities;

/**
 * A factory for creating all sorts of objects to be used with Glazed Lists.
 *
 * @author <a href="mailto:jesse@swank.ca">Jesse Wilson</a>
 */
public final class GlazedListsSwing {

    /**
     * A dummy constructor to prevent instantiation of this class
     */
    private GlazedListsSwing() {
        throw new UnsupportedOperationException();
    }

    // EventLists // // // // // // // // // // // // // // // // // // // // //

    /**
     * Wraps the source in an {@link EventList} that fires all of its update
     * events from the Swing event dispatch thread.
     */
    public static <E> TransformedList<E, E> swingThreadProxyList(EventList<E> source) {
        return new SwingThreadProxyEventList<E>(source);
    }

    /**
     * Returns true iff <code>list</code> is an {@link EventList} that fires
     * all of its update events from the Swing event dispatch thread.
     */
    public static boolean isSwingThreadProxyList(EventList list) {
        return list instanceof SwingThreadProxyEventList;
    }

    // ThresholdRangeModels // // // // // // // // // // // // // // // // //

    /**
     * Creates a model that manipulates the lower bound of the specified
     * ThresholdList.  The ThresholdList linked to this model type will contain
     * a range of Objects between the results of getValue() and getMaximum()
     * on the BoundedRangeModel.
     */
    public static BoundedRangeModel lowerRangeModel(ThresholdList target) {
        return new LowerThresholdRangeModel(target);
    }

    /**
     * Creates a model that manipulates the upper bound of the specified
     * ThresholdList.  The ThresholdList linked to this model type will contain
     * a range of Objects between the results of getMinimum() and getValue()
     * on the BoundedRangeModel.
     */
    public static BoundedRangeModel upperRangeModel(ThresholdList target) {
        return new UpperThresholdRangeModel(target);
    }

    // TableModel convenience creators

    /**
     * Creates a new table model that extracts column data from the given
     * <code>source</code> using the the given <code>tableFormat</code>.
     *
     * <p>The returned table model is <strong>not thread-safe</strong>. Unless otherwise
     * noted, all methods are only safe to be called from the event dispatch thread.
     * To do this programmatically, use {@link SwingUtilities#invokeAndWait(Runnable)} and
     * wrap the source list (or some part of the source list's pipeline) using
     * {@link GlazedListsSwing#swingThreadProxyList(EventList)}.</p>
     *
     * @param source the EventList that provides the row objects
     * @param tableFormat the object responsible for extracting column data
     *      from the row objects
     */
    public static <E> AdvancedTableModel<E> eventTableModel(EventList<E> source, TableFormat<? super E> tableFormat) {
        return new DefaultEventTableModel<E>(source, tableFormat);
    }

    /**
     * Creates a new table model that extracts column data from the given <code>source</code>
     * using the the given <code>tableFormat</code>. While holding a read lock,
     * this method wraps the source list using
     * {@link GlazedListsSwing#swingThreadProxyList(EventList)}.
     * <p>
     * The returned table model is <strong>not thread-safe</strong>. Unless otherwise noted, all
     * methods are only safe to be called from the event dispatch thread.
     * </p>
     *
     * @param source the EventList that provides the row objects
     * @param tableFormat the object responsible for extracting column data from the row objects
     */
    public static <E> AdvancedTableModel<E> eventTableModelWithThreadProxyList(EventList<E> source, TableFormat<? super E> tableFormat) {
        final EventList<E> proxySource = createSwingThreadProxyList(source);
        return new DefaultEventTableModel<E>(proxySource, true, tableFormat);
    }

    /**
     * Creates a new table model that renders the specified list with an automatically
     * generated {@link TableFormat}. It uses JavaBeans and reflection to create
     * a {@link TableFormat} as specified.
     *
     * <p>Note that classes that will be obfuscated may not work with
     * reflection. In this case, implement a {@link TableFormat} manually.</p>
     *
     * <p>The returned table model is <strong>not thread-safe</strong>. Unless otherwise
     * noted, all methods are only safe to be called from the event dispatch thread.
     * To do this programmatically, use {@link SwingUtilities#invokeAndWait(Runnable)} and
     * wrap the source list (or some part of the source list's pipeline) using
     * {@link GlazedListsSwing#swingThreadProxyList(EventList)}.</p>
     *
     * @param source the EventList that provides the row objects
     * @param propertyNames an array of property names in the JavaBeans format.
     *      For example, if your list contains Objects with the methods getFirstName(),
     *      setFirstName(String), getAge(), setAge(Integer), then this array should
     *      contain the two strings "firstName" and "age". This format is specified
     *      by the JavaBeans {@link java.beans.PropertyDescriptor}.
     * @param columnLabels the corresponding column names for the listed property
     *      names. For example, if your columns are "firstName" and "age", then
     *      your labels might be "First Name" and "Age".
     * @param writable an array of booleans specifying which of the columns in
     *      your table are writable.
     *
     */
    public static <E> AdvancedTableModel<E> eventTableModel(EventList<E> source, String[] propertyNames, String[] columnLabels, boolean[] writable) {
        return eventTableModel(source, GlazedLists.tableFormat(propertyNames, columnLabels, writable));
    }

    /**
     * Creates a new table model that renders the specified list with an automatically
     * generated {@link TableFormat}. It uses JavaBeans and reflection to create
     * a {@link TableFormat} as specified.  While holding a read lock,
     * this method wraps the source list using
     * {@link GlazedListsSwing#swingThreadProxyList(EventList)}.
     *
     * <p>Note that classes that will be obfuscated may not work with
     * reflection. In this case, implement a {@link TableFormat} manually.</p>
     *
     * <p>The returned table model is <strong>not thread-safe</strong>. Unless otherwise
     * noted, all methods are only safe to be called from the event dispatch thread.<p>
     *
     * @param source the EventList that provides the row objects
     * @param propertyNames an array of property names in the JavaBeans format.
     *      For example, if your list contains Objects with the methods getFirstName(),
     *      setFirstName(String), getAge(), setAge(Integer), then this array should
     *      contain the two strings "firstName" and "age". This format is specified
     *      by the JavaBeans {@link java.beans.PropertyDescriptor}.
     * @param columnLabels the corresponding column names for the listed property
     *      names. For example, if your columns are "firstName" and "age", then
     *      your labels might be "First Name" and "Age".
     * @param writable an array of booleans specifying which of the columns in
     *      your table are writable.
     *
     */
    public static <E> AdvancedTableModel<E> eventTableModelWithThreadProxyList(EventList<E> source, String[] propertyNames, String[] columnLabels, boolean[] writable) {
        return eventTableModelWithThreadProxyList(source, GlazedLists.tableFormat(propertyNames, columnLabels, writable));
    }

    // ListSelectionModel convenience creators

    /**
     * Creates a new selection model that also presents a list of the selection.
     *
     * The {@link AdvancedListSelectionModel} 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.
     *
     * <p>The returned selection model is <strong>not thread-safe</strong>. Unless otherwise
     * noted, all methods are only safe to be called from the event dispatch thread.
     * To do this programmatically, use {@link SwingUtilities#invokeAndWait(Runnable)} and
     * wrap the source list (or some part of the source list's pipeline) using
     * {@link GlazedListsSwing#swingThreadProxyList(EventList)}.</p>
     *
     * @param source the {@link EventList} whose selection will be managed. This should
     *      be the same {@link EventList} passed to the constructor of your
     *      {@link AdvancedTableModel} or {@link EventListModel}.
     */
    public static <E> AdvancedListSelectionModel<E> eventSelectionModel(EventList<E> source) {
        return new DefaultEventSelectionModel<E>(source);
    }

    /**
     * Creates a new selection model that also presents a list of the selection.
     * While holding a read lock, it wraps the source list using
     * {@link GlazedListsSwing#swingThreadProxyList(EventList)}. The
     * {@link AdvancedListSelectionModel} 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.
     * <p>
     * The returned selection model is <strong>not thread-safe</strong>. Unless otherwise noted,
     * all methods are only safe to be called from the event dispatch thread.
     * </p>
     *
     * @param source the {@link EventList} whose selection will be managed. This should be the
     *            same {@link EventList} passed to the constructor of your
     *            {@link AdvancedTableModel} or {@link EventListModel}.
     */
    public static <E> AdvancedListSelectionModel<E> eventSelectionModelWithThreadProxyList(EventList<E> source) {
        final EventList<E> proxySource = createSwingThreadProxyList(source);
        return new DefaultEventSelectionModel<E>(proxySource, true);
    }

    // EventListModel convenience creators

    /**
     * Creates a new list model that contains all objects located in the given
     * <code>source</code> and reacts to any changes in the given <code>source</code>.
     *
     * <p>The returned selection model is <strong>not thread-safe</strong>. Unless otherwise
     * noted, all methods are only safe to be called from the event dispatch thread.
     * To do this programmatically, use {@link SwingUtilities#invokeAndWait(Runnable)} and
     * wrap the source list (or some part of the source list's pipeline) using
     * {@link GlazedListsSwing#swingThreadProxyList(EventList)}.
     * </p>
     *
     * @param source the EventList that provides the elements
     */
    public static <E> DefaultEventListModel<E> eventListModel(EventList<E> source) {
        return new DefaultEventListModel<E>(source);
    }

    /**
     * Creates a new list model that contains all objects located in the given
     * <code>source</code> and reacts to any changes in the given <code>source</code>.
     * While holding a read lock, it wraps the source list using
     * {@link GlazedListsSwing#swingThreadProxyList(EventList)}.
     *
     * <p>The returned selection model is <strong>not thread-safe</strong>. Unless otherwise
     * noted, all methods are only safe to be called from the event dispatch thread.
     * </p>
     *
     * @param source the EventList that provides the elements
     */
    public static <E> DefaultEventListModel<E> eventListModelWithThreadProxyList(EventList<E> source) {
        final EventList<E> proxySource = createSwingThreadProxyList(source);
        return new DefaultEventListModel<E>(proxySource, true);
    }

    // EventComboBoxModel convenience creators

    /**
     * Creates a new combobox model that contains all objects located in the given
     * <code>source</code> and reacts to any changes in the given <code>source</code>.
     *
     * <p>The returned combobox model is <strong>not thread-safe</strong>. Unless otherwise
     * noted, all methods are only safe to be called from the event dispatch thread.
     * To do this programmatically, use {@link SwingUtilities#invokeAndWait(Runnable)} and
     * wrap the source list (or some part of the source list's pipeline) using
     * {@link GlazedListsSwing#swingThreadProxyList(EventList)}.
     * </p>
     *
     * @param source the EventList that provides the elements
     */
    public static <E> DefaultEventComboBoxModel<E> eventComboBoxModel(EventList<E> source) {
        return new DefaultEventComboBoxModel<E>(source);
    }

    /**
     * Creates a new combobox model that contains all objects located in the given
     * <code>source</code> and reacts to any changes in the given <code>source</code>.
     * While holding a read lock, it wraps the source list using
     * {@link GlazedListsSwing#swingThreadProxyList(EventList)}.
     *
     * <p>The returned combobox model is <strong>not thread-safe</strong>. Unless otherwise
     * noted, all methods are only safe to be called from the event dispatch thread.
     * </p>
     *
     * @param source the EventList that provides the elements
     */
    public static <E> DefaultEventComboBoxModel<E> eventComboBoxModelWithThreadProxyList(EventList<E> source) {
        final EventList<E> proxySource = createSwingThreadProxyList(source);
        return new DefaultEventComboBoxModel<E>(proxySource, true);
    }

    /** Helper method to create a SwingThreadProxyList with read locks. */
    private static <E> EventList<E> createSwingThreadProxyList(EventList<E> source) {
        final EventList<E> result;
        source.getReadWriteLock().readLock().lock();
        try {
            result = GlazedListsSwing.swingThreadProxyList(source);
        } finally {
            source.getReadWriteLock().readLock().unlock();
        }
        return result;
    }


}