File: EventTableModel.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 (153 lines) | stat: -rw-r--r-- 7,926 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
/* Glazed Lists                                                 (c) 2003-2006 */
/* http://publicobject.com/glazedlists/                      publicobject.com,*/
/*                                                     O'Dell Engineering Ltd.*/
package ca.odell.glazedlists.swing;

import javax.swing.SwingUtilities;
import javax.swing.table.TableModel;

import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.GlazedLists;
import ca.odell.glazedlists.TransformedList;
import ca.odell.glazedlists.gui.TableFormat;

/**
 * A {@link DefaultEventTableModel} that silently wraps it's source list in a
 * SwingThreadProxyEventList to ensure that events that arrive at the TableModel do so on
 * the EDT. A {@link TableModel} that holds an {@link EventList}. Each element of the list
 * corresponds to a row in the {@link TableModel}. The columns of the table are specified using a
 * {@link TableFormat}.
 * <p>
 * The EventTableModel class 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)}.
 *
 * @see <a href="http://publicobject.com/glazedlists/tutorial/">Glazed Lists Tutorial</a>
 * @see SwingUtilities#invokeAndWait(Runnable)
 * @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=146">Bug 146</a>
 * @see <a href="https://glazedlists.dev.java.net/issues/show_bug.cgi?id=177">Bug 177</a>
 *
 * @deprecated Use {@link DefaultEventTableModel} 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 class EventTableModel<E> extends DefaultEventTableModel<E> {

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

    /**
     * Creates a new table model that extracts column data from the given <code>source</code>
     * using the the given <code>tableFormat</code>.
     *
     * @param source the EventList that provides the row objects
     * @param tableFormat the object responsible for extracting column data from the row objects
     *
     * @deprecated Use {@link DefaultEventTableModel} and
     *             {@link GlazedListsSwing#swingThreadProxyList(EventList)} instead
     */
    public EventTableModel(EventList<E> source, TableFormat<? super E> tableFormat) {
        super(source, tableFormat);
        // lock the source list for reading since we want to prevent writes
        // from occurring until we fully initialize this EventTableModel

        // KD 20090306 - Not crazy about these locks, but it was in the original
        // EventTableModel implementation, so we need to leave it.  DefaultTableModel
        // should be considered to be non-Thread Safe, so source lists should be locked
        // before constructing a DefaultEventTableModel if there are any potential
        // race conditions
        source.getReadWriteLock().readLock().lock();
        try {
            final TransformedList<E,E> decorated = createSwingThreadProxyList(source);

            if (decorated != null && decorated != source){
                //we need to switch the configuration of the DefaultEventTableModel so it
                // uses the swingThreadProxyList instead
                this.source.removeListEventListener(this);
                this.source = swingThreadSource = decorated;
                this.source.addListEventListener(this);
            }
        } finally {
            source.getReadWriteLock().readLock().unlock();
        }

    }

    /**
     * Creates a new table 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 the classes which will be obfuscated may not work with
     * reflection. In this case, implement a {@link TableFormat} manually.
     *
     * @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.
     *
     * @deprecated Use {@link GlazedListsSwing#createEventTableModel(EventList, String[], String[], boolean[])}
     * and {@link GlazedListsSwing#swingThreadProxyList(EventList)} instead
     */
    public EventTableModel(EventList<E> source, String[] propertyNames, String[] columnLabels, boolean[] writable) {
        this(source, GlazedLists.tableFormat(propertyNames, columnLabels, writable));
    }

    /**
     * This method exists as a hook for subclasses that may have custom
     * threading needs within their EventTableModels. By default, this method
     * will wrap the given <code>source</code> in a SwingThreadProxyList if it
     * is not already a SwingThreadProxyList. Subclasses may replace this logic
     * and return either a custom ThreadProxyEventList of their choosing, or
     * return <code>null</code> or the <code>source</code> unchanged in order
     * to indicate that <strong>NO</strong> ThreadProxyEventList is desired.
     * In these cases it is expected that some external mechanism will ensure
     * that threading is handled correctly.
     *
     * @param source the EventList that provides the row objects
     * @return the source wrapped in some sort of ThreadProxyEventList if
     *      Thread-proxying is desired, or either <code>null</code> or the
     *      <code>source</code> unchanged to indicate that <strong>NO</strong>
     *      Thread-proxying is desired
     */
    protected TransformedList<E,E> createSwingThreadProxyList(EventList<E> source) {
        return GlazedListsSwing.isSwingThreadProxyList(source) ? null : GlazedListsSwing.swingThreadProxyList(source);
    }

    /**
     * Releases the resources consumed by this {@link EventTableModel} so that it
     * may eventually be garbage collected.
     *
     * <p>An {@link EventTableModel} 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 EventTableModel}
     * to be garbage collected before its source {@link EventList}. This is
     * necessary for situations where an {@link EventTableModel} 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 an {@link EventTableModel} after it has been disposed.
     * As such, this {@link EventTableModel} should be detached from its
     * corresponding Component <strong>before</strong> it is disposed.
     */
    @Override
    public void dispose() {
        // if we created the swingThreadSource then we must also dispose it
        if (swingThreadSource != null)
            swingThreadSource.dispose();

        swingThreadSource = null;
        super.dispose();
    }
}