001/* A graphical component displaying matrix contents.
002
003 Copyright (c) 1997-2014 The Regents of the University of California.
004 All rights reserved.
005 Permission is hereby granted, without written agreement and without
006 license or royalty fees, to use, copy, modify, and distribute this
007 software and its documentation for any purpose, provided that the above
008 copyright notice and the following two paragraphs appear in all copies
009 of this software.
010
011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
015 SUCH DAMAGE.
016
017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
022 ENHANCEMENTS, OR MODIFICATIONS.
023
024 PT_COPYRIGHT_VERSION_2
025 COPYRIGHTENDKEY
026
027
028 */
029package ptolemy.actor.gui;
030
031import javax.swing.JScrollPane;
032import javax.swing.JTable;
033import javax.swing.SwingUtilities;
034import javax.swing.table.AbstractTableModel;
035
036import ptolemy.data.MatrixToken;
037import ptolemy.data.StringToken;
038import ptolemy.data.Token;
039
040///////////////////////////////////////////////////////////////////
041//// MatrixPane
042
043/**
044 A graphical component that displays the values in a matrix.
045 The data to display is supplied in the form of a MatrixToken.
046 The table is currently not editable, although this may be changed
047 in the future.  The table is an instance of Java's JTable class,
048 which is exposed as a public member.  The rich interface
049 of the JTable class can be used to customize the display
050 in various ways.
051
052 @author Bart Kienhuis and Edward A. Lee
053 @version $Id$
054 @since Ptolemy II 2.1
055 @Pt.ProposedRating Red (eal)
056 @Pt.AcceptedRating Red (eal)
057 */
058@SuppressWarnings("serial")
059public class MatrixPane extends JScrollPane {
060    /** Construct an empty matrix pane.
061     */
062    public MatrixPane() {
063        super();
064
065        // Create a table.
066        table = new JTable();
067
068        // No table header.
069        table.setTableHeader(null);
070
071        // Adjust column widths automatically.
072        // If the matrix is large, then elements will be
073        // elided and replaced with ...
074        table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
075
076        // Add the table to the scroll pane.
077        setViewportView(table);
078
079        // Inherit the background color from the container.
080        table.setBackground(null);
081    }
082
083    ///////////////////////////////////////////////////////////////////
084    ////                         public methods                    ////
085
086    /** Clear the display. */
087    public void clear() {
088        // When invoking methods in the table object,
089        // be sure to invoke them from the Swing Event
090        // thread.
091        // See http://bugzilla.ecoinformatics.org/show_bug.cgi?id=4826
092        SwingUtilities.invokeLater(new Runnable() {
093            @Override
094            public void run() {
095                table.setModel(_emptyTableModel);
096            }
097        });
098    }
099
100    /** Set the matrix to display in the table.
101     *  @param matrix The matrix to display in the table.
102     */
103    public void display(MatrixToken matrix) {
104        final MatrixToken myMatrix = matrix;
105        SwingUtilities.invokeLater(new Runnable() {
106            @Override
107            public void run() {
108                table.setModel(new MatrixAsTable(myMatrix));
109            }
110        });
111    }
112
113    ///////////////////////////////////////////////////////////////////
114    ////                         public variables                  ////
115
116    /** The table representing the matrix. Methods in the class
117     *  referred to by this field should only be invoked from the
118     *  Swing event thread. See SwingUtilities.invokeLater().
119     */
120    public JTable table;
121
122    ///////////////////////////////////////////////////////////////////
123    ////                         private variables                 ////
124
125    /** Empty string. */
126    private static Token _emptyStringToken = new StringToken("");
127
128    /** Empty table model. */
129    private static EmptyTableModel _emptyTableModel = new EmptyTableModel();
130
131    ///////////////////////////////////////////////////////////////////
132    ////                         inner class                       ////
133
134    /** This class provides an implementation of the
135     *  TableModel interface for viewing matrix tokens.
136     *  Each element of the matrix is represented as an instance
137     *  of Token, so all matrix types are supported.
138     */
139    private static class MatrixAsTable extends AbstractTableModel {
140        // FindBugs suggests making this class static so as to decrease
141        // the size of instances and avoid dangling references.
142
143        /** Construct a table for the specified matrix.
144         *  @param matrix The matrix.
145         */
146        MatrixAsTable(MatrixToken matrix) {
147            _matrix = matrix;
148        }
149
150        ///////////////////////////////////////////////////////////////////
151        ////                         public methods                    ////
152
153        /** Get the column count of the Matrix.
154         *  @return the column count.
155         */
156        @Override
157        public int getColumnCount() {
158            return _matrix.getColumnCount();
159        }
160
161        /** Get the name of the specified column, which is the column
162         *  index as a string.
163         *  @return The column index as a string.
164         */
165        @Override
166        public String getColumnName(int columnIndex) {
167            return Integer.toString(columnIndex);
168        }
169
170        /** Get the row count of the Matrix.
171         *  @return the row count.
172         */
173        @Override
174        public int getRowCount() {
175            return _matrix.getRowCount();
176        }
177
178        /** Get the specified entry from the matrix as a Token.
179         *  @param row The row number.
180         *  @param column The column number.
181         *  @return An instance of Token representing the matrix value
182         *   at the specified row and column.
183         */
184        @Override
185        public Object getValueAt(int row, int column) {
186            // There is a bug in JTable, where it happily tries to access
187            // rows and columns that are outside of range.
188            if (row >= _matrix.getRowCount()
189                    || column >= _matrix.getColumnCount()) {
190                return _emptyStringToken;
191            }
192
193            return _matrix.getElementAsToken(row, column).toString();
194        }
195
196        ///////////////////////////////////////////////////////////////////
197        ////                         private members                   ////
198
199        /** The Matrix for which a Table Model is created. */
200        private MatrixToken _matrix = null;
201    }
202
203    /** This class provides an implementation of the
204     *  TableModel interface representing an empty matrix.
205     *  This is used to clear the display.
206     */
207    private static class EmptyTableModel extends AbstractTableModel {
208        ///////////////////////////////////////////////////////////////////
209        ////                         public methods                    ////
210
211        /** Get the column count of the Matrix.
212         *  @return Zero.
213         */
214        @Override
215        public int getColumnCount() {
216            return 0;
217        }
218
219        /** Get the row count of the Matrix.
220         *  @return Zero.
221         */
222        @Override
223        public int getRowCount() {
224            return 0;
225        }
226
227        /** Get the specified entry from the matrix as a Token.
228         *  @param row The row number.
229         *  @param column The column number.
230         *  @return An instance of Token representing the matrix value
231         *   at the specified row and column.
232         */
233        @Override
234        public Object getValueAt(int row, int column) {
235            return _emptyStringToken;
236        }
237    }
238}