| 1 | package tmcsim.simulationmanager.model; |
|---|
| 2 | |
|---|
| 3 | import java.awt.Color; |
|---|
| 4 | import java.awt.Component; |
|---|
| 5 | import java.util.Enumeration; |
|---|
| 6 | import java.util.HashMap; |
|---|
| 7 | import java.util.Iterator; |
|---|
| 8 | import java.util.Map; |
|---|
| 9 | import javax.swing.JTable; |
|---|
| 10 | import javax.swing.JTextArea; |
|---|
| 11 | import javax.swing.table.DefaultTableCellRenderer; |
|---|
| 12 | import javax.swing.table.TableCellRenderer; |
|---|
| 13 | import javax.swing.table.TableColumn; |
|---|
| 14 | import javax.swing.table.TableColumnModel; |
|---|
| 15 | |
|---|
| 16 | /** |
|---|
| 17 | * TableCellRender to display a multi-line cell. |
|---|
| 18 | * |
|---|
| 19 | * http://www.roseindia.net/javatutorials/JTable_in_JDK.shtml |
|---|
| 20 | * |
|---|
| 21 | * @author Dr. Heinz M. Kabutz |
|---|
| 22 | */ |
|---|
| 23 | @SuppressWarnings("serial") |
|---|
| 24 | public class LogEntryCellRenderer extends JTextArea implements |
|---|
| 25 | TableCellRenderer |
|---|
| 26 | { |
|---|
| 27 | /** |
|---|
| 28 | * DefaultTableCellRenderer for displaying multi line cells |
|---|
| 29 | */ |
|---|
| 30 | private final DefaultTableCellRenderer adaptee; |
|---|
| 31 | /** |
|---|
| 32 | * map from table to map of rows to map of column heights |
|---|
| 33 | */ |
|---|
| 34 | private final Map<JTable, Map<Integer, Map<Integer, Integer>>> cellSizes; |
|---|
| 35 | |
|---|
| 36 | public LogEntryCellRenderer() |
|---|
| 37 | { |
|---|
| 38 | |
|---|
| 39 | adaptee = new DefaultTableCellRenderer(); |
|---|
| 40 | cellSizes = new HashMap<JTable, Map<Integer, Map<Integer, Integer>>>(); |
|---|
| 41 | |
|---|
| 42 | setLineWrap(true); |
|---|
| 43 | setWrapStyleWord(true); |
|---|
| 44 | } |
|---|
| 45 | |
|---|
| 46 | public Component getTableCellRendererComponent(JTable table, Object obj, |
|---|
| 47 | boolean isSelected, boolean hasFocus, int row, int column) |
|---|
| 48 | { |
|---|
| 49 | |
|---|
| 50 | // set the colours, etc. using the standard for that platform |
|---|
| 51 | adaptee.getTableCellRendererComponent(table, obj, isSelected, hasFocus, |
|---|
| 52 | row, column); |
|---|
| 53 | // FIXES defect where cell text disappears when selected |
|---|
| 54 | // TODO: Better would be to make table not selectable |
|---|
| 55 | // http://stackoverflow.com/questions/8291329/set-all-jtable-cells-unselectable |
|---|
| 56 | if (isSelected) |
|---|
| 57 | { |
|---|
| 58 | setForeground(Color.WHITE); |
|---|
| 59 | setBackground(Color.GRAY); |
|---|
| 60 | } |
|---|
| 61 | else |
|---|
| 62 | { |
|---|
| 63 | setForeground(adaptee.getForeground()); |
|---|
| 64 | setBackground(adaptee.getBackground()); |
|---|
| 65 | } |
|---|
| 66 | setBorder(adaptee.getBorder()); |
|---|
| 67 | setFont(adaptee.getFont()); |
|---|
| 68 | setText(adaptee.getText()); |
|---|
| 69 | |
|---|
| 70 | // This line was very important to get it working with JDK1.4 |
|---|
| 71 | TableColumnModel columnModel = table.getColumnModel(); |
|---|
| 72 | setSize(columnModel.getColumn(column).getWidth(), 100000); |
|---|
| 73 | int height_wanted = (int) getPreferredSize().getHeight(); |
|---|
| 74 | addSize(table, row, column, height_wanted); |
|---|
| 75 | height_wanted = findTotalMaximumRowSize(table, row); |
|---|
| 76 | if (height_wanted != table.getRowHeight(row)) |
|---|
| 77 | { |
|---|
| 78 | table.setRowHeight(row, height_wanted); |
|---|
| 79 | } |
|---|
| 80 | |
|---|
| 81 | return this; |
|---|
| 82 | } |
|---|
| 83 | |
|---|
| 84 | private void addSize(JTable table, int row, int column, int height) |
|---|
| 85 | { |
|---|
| 86 | Map<Integer, Map<Integer, Integer>> rows = cellSizes.get(table); |
|---|
| 87 | if (rows == null) |
|---|
| 88 | { |
|---|
| 89 | cellSizes.put(table, rows = new HashMap<Integer, Map<Integer, Integer>>()); |
|---|
| 90 | } |
|---|
| 91 | |
|---|
| 92 | Map<Integer, Integer> rowheights = rows.get(new Integer(row)); |
|---|
| 93 | if (rowheights == null) |
|---|
| 94 | { |
|---|
| 95 | rows.put(new Integer(row), rowheights = new HashMap<Integer, Integer>()); |
|---|
| 96 | } |
|---|
| 97 | rowheights.put(new Integer(column), new Integer(height)); |
|---|
| 98 | } |
|---|
| 99 | |
|---|
| 100 | /** |
|---|
| 101 | * Look through all columns and get the renderer. If it is also a |
|---|
| 102 | * TextAreaRenderer, we look at the maximum height in its hash table for |
|---|
| 103 | * this row. |
|---|
| 104 | */ |
|---|
| 105 | private int findTotalMaximumRowSize(JTable table, int row) |
|---|
| 106 | { |
|---|
| 107 | int maximum_height = 0; |
|---|
| 108 | Enumeration columns = table.getColumnModel().getColumns(); |
|---|
| 109 | while (columns.hasMoreElements()) |
|---|
| 110 | { |
|---|
| 111 | TableColumn tc = (TableColumn) columns.nextElement(); |
|---|
| 112 | TableCellRenderer cellRenderer = tc.getCellRenderer(); |
|---|
| 113 | if (cellRenderer instanceof LogEntryCellRenderer) |
|---|
| 114 | { |
|---|
| 115 | LogEntryCellRenderer tar = (LogEntryCellRenderer) cellRenderer; |
|---|
| 116 | maximum_height = Math.max(maximum_height, tar |
|---|
| 117 | .findMaximumRowSize(table, row)); |
|---|
| 118 | } |
|---|
| 119 | } |
|---|
| 120 | return maximum_height; |
|---|
| 121 | } |
|---|
| 122 | |
|---|
| 123 | private int findMaximumRowSize(JTable table, int row) |
|---|
| 124 | { |
|---|
| 125 | Map<Integer, Map<Integer, Integer>> rows = cellSizes.get(table); |
|---|
| 126 | if (rows == null) |
|---|
| 127 | { |
|---|
| 128 | return 0; |
|---|
| 129 | } |
|---|
| 130 | |
|---|
| 131 | Map<Integer, Integer> rowheights = rows.get(new Integer(row)); |
|---|
| 132 | if (rowheights == null) |
|---|
| 133 | { |
|---|
| 134 | return 0; |
|---|
| 135 | } |
|---|
| 136 | int maximum_height = 0; |
|---|
| 137 | |
|---|
| 138 | for (Iterator it = rowheights.entrySet().iterator(); it.hasNext();) |
|---|
| 139 | { |
|---|
| 140 | Map.Entry entry = (Map.Entry) it.next(); |
|---|
| 141 | int cellHeight = ((Integer) entry.getValue()).intValue(); |
|---|
| 142 | maximum_height = Math.max(maximum_height, cellHeight); |
|---|
| 143 | } |
|---|
| 144 | return maximum_height; |
|---|
| 145 | } |
|---|
| 146 | } |
|---|