001    /*
002     * Copyright (C) 2008-2010 by Holger Arndt
003     *
004     * This file is part of the Universal Java Matrix Package (UJMP).
005     * See the NOTICE file distributed with this work for additional
006     * information regarding copyright ownership and licensing.
007     *
008     * UJMP is free software; you can redistribute it and/or modify
009     * it under the terms of the GNU Lesser General Public License as
010     * published by the Free Software Foundation; either version 2
011     * of the License, or (at your option) any later version.
012     *
013     * UJMP is distributed in the hope that it will be useful,
014     * but WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016     * GNU Lesser General Public License for more details.
017     *
018     * You should have received a copy of the GNU Lesser General Public
019     * License along with UJMP; if not, write to the
020     * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
021     * Boston, MA  02110-1301  USA
022     */
023    
024    package org.ujmp.gui;
025    
026    import java.awt.Component;
027    import java.awt.image.BufferedImage;
028    
029    import javax.swing.Icon;
030    import javax.swing.ImageIcon;
031    import javax.swing.JFrame;
032    import javax.swing.JPanel;
033    import javax.swing.JTable;
034    import javax.swing.ListSelectionModel;
035    import javax.swing.event.EventListenerList;
036    import javax.swing.event.TableModelEvent;
037    import javax.swing.event.TableModelListener;
038    import javax.swing.table.AbstractTableModel;
039    import javax.swing.table.DefaultTableCellRenderer;
040    import javax.swing.table.TableModel;
041    
042    import org.ujmp.core.Coordinates;
043    import org.ujmp.core.Matrix;
044    import org.ujmp.core.exceptions.MatrixException;
045    import org.ujmp.core.util.UJMPFormat;
046    import org.ujmp.core.util.UJMPSettings;
047    import org.ujmp.gui.frame.MatrixFrame;
048    import org.ujmp.gui.panels.MatrixPanel;
049    import org.ujmp.gui.util.FastListSelectionModel;
050    
051    public class MatrixGUIObject extends AbstractGUIObject implements TableModel {
052            private static final long serialVersionUID = -5777110889052748093L;
053    
054            private Matrix matrix = null;
055    
056            private int modCount = 0;
057    
058            private transient String tooltipText = null;
059    
060            private transient ListSelectionModel rowSelectionModel = null;
061    
062            private transient ListSelectionModel columnSelectionModel = null;
063    
064            private transient EventListenerList listenerList = null;
065    
066            private transient JFrame frame = null;
067    
068            private transient JPanel panel = null;
069    
070            public MatrixGUIObject(Matrix m) {
071                    this.matrix = m;
072            }
073    
074            public Matrix getMatrix() {
075                    return matrix;
076            }
077    
078            public void clear() {
079                    matrix.clear();
080                    fireValueChanged();
081            }
082    
083            public double getEstimatedMaxValue(long timeOut) throws MatrixException {
084                    double max = -Double.MAX_VALUE;
085                    long t0 = System.currentTimeMillis();
086                    long t1;
087                    double v = 0.0;
088                    for (long[] c : matrix.availableCoordinates()) {
089                            max = (v = matrix.getAsDouble(c)) > max ? v : max;
090                            t1 = System.currentTimeMillis();
091                            if (t1 - t0 > timeOut) {
092                                    return max;
093                            }
094                    }
095                    return max;
096            }
097    
098            public double getEstimatedMinValue(long timeOut) throws MatrixException {
099                    double min = Double.MAX_VALUE;
100                    long t0 = System.currentTimeMillis();
101                    long t1;
102                    double v = 0.0;
103                    for (long[] c : matrix.availableCoordinates()) {
104                            min = (v = matrix.getAsDouble(c)) < min ? v : min;
105                            t1 = System.currentTimeMillis();
106                            if (t1 - t0 > timeOut) {
107                                    return min;
108                            }
109                    }
110                    return min;
111            }
112    
113            public long getValueCount() {
114                    return matrix.getValueCount();
115            }
116    
117            public final EventListenerList getListenerList() {
118                    if (listenerList == null) {
119                            listenerList = new EventListenerList();
120                    }
121                    return listenerList;
122            }
123    
124            public String getLabel() {
125                    return matrix.getLabel();
126            }
127    
128            public void setLabel(String label) {
129                    matrix.setLabel(label);
130            }
131    
132            public final void addTableModelListener(TableModelListener l) {
133                    getListenerList().add(TableModelListener.class, l);
134            }
135    
136            public final void removeTableModelListener(TableModelListener l) {
137                    getListenerList().add(TableModelListener.class, l);
138            }
139    
140            public final String getToolTipText() {
141                    try {
142                            if (tooltipText == null) {
143                                    StringBuilder s = new StringBuilder();
144                                    s.append("<html>");
145                                    s.append("<table>");
146                                    s.append("<tr>");
147                                    s.append("<td colspan=2><h3>Matrix</h3></td>");
148                                    s.append("</tr>");
149                                    s.append("<tr>");
150                                    s.append("<td><b>Label:</b></td>");
151                                    s.append("<td>" + getLabel() + "</td>");
152                                    s.append("</tr>");
153                                    s.append("<tr>");
154                                    s.append("<td><b>Size:</b></td>");
155                                    s.append("<td>" + getRowCount() + "x" + getColumnCount()
156                                                    + "</td>");
157                                    s.append("</tr>");
158                                    s.append("<tr>");
159                                    s.append("<td><b>Values:</b></td>");
160                                    s.append("<td>");
161                                    s.append("<table border=1>");
162                                    int rowCount = getRowCount();
163                                    int columnCount = getColumnCount();
164    
165                                    // header
166                                    s.append("<tr>");
167                                    s.append("<th></th>");
168                                    for (int col = 0; col < columnCount
169                                                    && col < UJMPSettings.getMaxToolTipCols(); col++) {
170                                            s.append("<th>" + matrix.getColumnLabel(col) + "</th>");
171                                    }
172                                    if (getColumnCount() > UJMPSettings.getMaxToolTipCols()) {
173                                            s.append("<th>...</th>");
174                                    }
175                                    s.append("</tr>");
176    
177                                    for (int row = 0; row < rowCount
178                                                    && row < UJMPSettings.getMaxToolTipRows(); row++) {
179                                            s.append("<tr>");
180                                            s.append("<th>" + matrix.getRowLabel(row) + "</th>");
181                                            for (int col = 0; col < columnCount
182                                                            && col < UJMPSettings.getMaxToolTipCols(); col++) {
183                                                    s
184                                                                    .append("<td align=right>"
185                                                                                    + UJMPFormat.getSingleLineInstance()
186                                                                                                    .format(
187                                                                                                                    matrix.getAsObject(row,
188                                                                                                                                    col)) + "</td>");
189                                            }
190                                            if (getColumnCount() > UJMPSettings.getMaxToolTipCols()) {
191                                                    s.append("<td align=right>...</td>");
192                                            }
193                                            s.append("</tr>");
194                                    }
195                                    if (getRowCount() > UJMPSettings.getMaxToolTipRows()) {
196                                            s.append("<tr>");
197                                            s.append("<td></td>");
198                                            for (int col = 0; col < getColumnCount()
199                                                            && col < UJMPSettings.getMaxToolTipCols(); col++) {
200                                                    s.append("<td align=right>...</td>");
201                                            }
202                                            if (getColumnCount() > UJMPSettings.getMaxToolTipCols()) {
203                                                    s.append("<td align=right>...</td>");
204                                            }
205                                            s.append("</tr>");
206                                    }
207                                    s.append("</table>");
208                                    s.append("</td>");
209                                    s.append("</tr>");
210                                    s.append("</table>");
211                                    s.append("</html>");
212                                    tooltipText = s.toString();
213                            }
214                            return tooltipText;
215                    } catch (Exception e) {
216                            // TODO
217                            e.printStackTrace();
218                            return "error getting tooltip text";
219                    }
220            }
221    
222            public final void fireValueChanged() {
223                    for (Object o : getListenerList().getListenerList()) {
224                            if (o instanceof TableModelListener)
225                                    ((TableModelListener) o)
226                                                    .tableChanged(new TableModelEvent(this));
227                    }
228                    modCount++;
229            }
230    
231            public final void fireValueChanged(int row, int column, Object value) {
232                    for (Object o : getListenerList().getListenerList()) {
233                            if (o instanceof TableModelListener)
234                                    ((TableModelListener) o).tableChanged(new TableModelEvent(this,
235                                                    row, row, column, TableModelEvent.UPDATE));
236                    }
237                    modCount++;
238            }
239    
240            public final Class<?> getColumnClass(int columnIndex) {
241                    return Object.class;
242            }
243    
244            public int getColumnCount() {
245                    return (int) matrix.getColumnCount();
246            }
247    
248            // works only for 2D
249            public String getColumnName(int columnIndex) {
250                    if (matrix.getDimensionCount() == 2) {
251                            String label = matrix.getColumnLabel(columnIndex);
252                            return label == null || "".equals(label) ? "" + columnIndex : label;
253                    } else {
254                            return "";
255                    }
256            }
257    
258            public int getRowCount() {
259                    return (int) matrix.getRowCount();
260            }
261    
262            public Object getValueAt(long[] c) {
263                    return getValueAt((int) c[Matrix.ROW], (int) c[Matrix.COLUMN]);
264            }
265    
266            public Object getValueAt(int rowIndex, int columnIndex) {
267                    try {
268                            return matrix.getAsObject(rowIndex, columnIndex);
269                    } catch (MatrixException e) {
270                            // TODO Auto-generated catch block
271                            e.printStackTrace();
272                            return null;
273                    }
274            }
275    
276            public boolean isCellEditable(int rowIndex, int columnIndex) {
277                    return !matrix.isReadOnly();
278            }
279    
280            public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
281                    try {
282                            matrix.setAsObject(aValue, rowIndex, columnIndex);
283                    } catch (MatrixException e) {
284                            // TODO Auto-generated catch block
285                            e.printStackTrace();
286                    }
287                    fireValueChanged(rowIndex, columnIndex, aValue);
288                    tooltipText = null;
289            }
290    
291            public Iterable<long[]> coordinates() {
292                    return matrix.allCoordinates();
293            }
294    
295            // works only for 2D
296            public final String getRowName(int row) {
297                    if (matrix.getDimensionCount() == 2) {
298                            String label = matrix.getRowLabel(row);
299                            return label == null || "".equals(label) ? "" + row : label;
300                    } else {
301                            return "";
302                    }
303            }
304    
305            public int getZCount() {
306                    return (int) matrix.getZCount();
307            }
308    
309            public boolean isSquare() {
310                    return matrix.isSquare();
311            }
312    
313            public Double getDoubleValueAt(long... coordinates) throws MatrixException {
314                    return matrix.getAsDouble(coordinates);
315            }
316    
317            public boolean isSparse() {
318                    return matrix.isSparse();
319            }
320    
321            public boolean isScalar() {
322                    return matrix.isScalar();
323            }
324    
325            public ListSelectionModel getColumnSelectionModel() {
326                    if (columnSelectionModel == null) {
327                            columnSelectionModel = new FastListSelectionModel();
328                    }
329                    return columnSelectionModel;
330            }
331    
332            public void setColumnSelectionModel(ListSelectionModel columnSelectionModel) {
333                    this.columnSelectionModel = columnSelectionModel;
334            }
335    
336            public ListSelectionModel getRowSelectionModel() {
337                    if (rowSelectionModel == null) {
338                            rowSelectionModel = new FastListSelectionModel();
339                    }
340                    return rowSelectionModel;
341            }
342    
343            public void setRowSelectionModel(ListSelectionModel rowSelectionModel) {
344                    this.rowSelectionModel = rowSelectionModel;
345            }
346    
347            public long[] getSize() {
348                    return matrix.getSize();
349            }
350    
351            public final Icon getIcon() {
352                    try {
353                            TableModel dataModel = new AbstractTableModel() {
354                                    private static final long serialVersionUID = 5562866897873790623L;
355    
356                                    public int getColumnCount() {
357                                            return 1;
358                                    }
359    
360                                    public int getRowCount() {
361                                            return 1;
362                                    }
363    
364                                    public Object getValueAt(int row, int col) {
365                                            return this;
366                                    }
367                            };
368                            JTable table = new JTable(dataModel);
369                            table.getColumnModel().getColumn(0).setWidth(32);
370                            table.setRowHeight(32);
371    
372                            int WIDTH = table.getColumnModel().getColumn(0).getWidth() - 1;
373                            int HEIGHT = table.getRowHeight(0) - 1;
374    
375                            Class<?> cl = Class.forName("org.ujmp.gui.matrix.MatrixRenderer");
376                            DefaultTableCellRenderer mr = (DefaultTableCellRenderer) cl
377                                            .newInstance();
378                            Component c = mr.getTableCellRendererComponent(table, this, false,
379                                            false, 0, 0);
380                            BufferedImage bi = new BufferedImage(WIDTH, HEIGHT,
381                                            BufferedImage.TYPE_INT_RGB);
382                            c.paint(bi.getGraphics());
383                            return new ImageIcon(bi);
384    
385                    } catch (Exception e) {
386                            return new ImageIcon("resources/icons/rebuild.png");
387                    }
388            }
389    
390            // Description not supported for Matrix
391            public String getDescription() {
392                    return null;
393            }
394    
395            // Description not supported for Matrix
396            public void setDescription(String description) {
397            }
398    
399            public String toString() {
400                    if (matrix.getLabel() != null) {
401                            return "[" + Coordinates.toString(matrix.getSize()) + "] "
402                                            + matrix.getClass().getSimpleName() + " ["
403                                            + matrix.getLabel() + "]";
404                    } else {
405                            return "[" + Coordinates.toString(matrix.getSize()) + "] "
406                                            + matrix.getClass().getSimpleName();
407                    }
408            }
409    
410            public Matrix getCoreObject() {
411                    return matrix;
412            }
413    
414            public JFrame getFrame() {
415                    if (frame == null) {
416                            frame = new MatrixFrame(this);
417                    }
418                    return frame;
419            }
420    
421            public JPanel getPanel() {
422                    if (panel == null) {
423                            panel = new MatrixPanel(this);
424                    }
425                    return panel;
426            }
427    
428    }