001: package tijmp.ui;
002:
003: import java.awt.Color;
004: import java.awt.Dimension;
005: import java.awt.FlowLayout;
006: import java.awt.GridBagConstraints;
007: import java.awt.GridBagLayout;
008: import java.awt.Insets;
009: import java.awt.event.MouseAdapter;
010: import java.awt.event.MouseEvent;
011: import java.util.Arrays;
012: import javax.swing.BorderFactory;
013: import javax.swing.JFrame;
014: import javax.swing.JLabel;
015: import javax.swing.JMenuItem;
016: import javax.swing.JPanel;
017: import javax.swing.JPopupMenu;
018: import javax.swing.JScrollPane;
019: import javax.swing.JTable;
020: import javax.swing.JTextArea;
021: import javax.swing.ListSelectionModel;
022: import javax.swing.SwingUtilities;
023: import javax.swing.event.ListSelectionEvent;
024: import javax.swing.event.ListSelectionListener;
025: import javax.swing.table.AbstractTableModel;
026: import javax.swing.table.TableColumn;
027: import tijmp.ProfilerHandler;
028: import tijmp.ui.ClassRenderer;
029: import tijmp.ui.ReadableSizeRenderer;
030: import tijmp.actions.ChildObjectsSummary;
031:
032: /** A class that show a table with instances of a certain class.
033: */
034: class InstanceTable {
035: private ITM m;
036: private ProfilerHandler ph;
037:
038: public InstanceTable(ProfilerHandler ph, Class<?> clz,
039: Object[] objects, long[] sizes, int[] lengths) {
040: m = new ITM(clz, objects, sizes, lengths);
041: this .ph = ph;
042: }
043:
044: public void showFrame() {
045: JTable table = new JTable(m);
046: JScrollPane scrollPane = new JScrollPane(table);
047: table.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
048: table
049: .setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
050: table.setAutoCreateRowSorter(true);
051:
052: TableColumn column;
053: for (int i = 0; i < m.getColumnCount(); i++) {
054: column = table.getColumnModel().getColumn(i);
055: if (i == ITM.COL_CLASS)
056: column.setPreferredWidth(350);
057: else
058: column.setPreferredWidth(75);
059: if (i == ITM.COL_SIZE)
060: column.setCellRenderer(new ReadableSizeRenderer());
061: }
062: table.setDefaultRenderer(Class.class, new ClassRenderer());
063: table.getRowSorter().toggleSortOrder(ITM.COL_SIZE);
064: table.getRowSorter().toggleSortOrder(ITM.COL_SIZE);
065: table.addMouseListener(new InstanceMouseHandler(table, ph));
066:
067: if (!m.getInstanceClass().isArray())
068: table.removeColumn(table.getColumnModel().getColumn(
069: ITM.COL_LENGTH));
070: table.removeColumn(table.getColumnModel().getColumn(
071: ITM.COL_OBJECT));
072: table
073: .setPreferredScrollableViewportSize(new Dimension(500,
074: 200));
075: JFrame f = new JFrame("Instances of "
076: + m.getInstanceClass().getName());
077: f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
078:
079: JTextArea ta = new JTextArea(5, 80);
080: ta.setEnabled(false);
081: JScrollPane spTa = new JScrollPane(ta);
082:
083: JLabel equals = new JLabel("-");
084: equals.setBorder(BorderFactory.createLoweredBevelBorder());
085: JLabel hashCodeEquals = new JLabel("-");
086: hashCodeEquals.setBorder(BorderFactory
087: .createLoweredBevelBorder());
088: JPanel status = new JPanel();
089: status.add(equals);
090: status.add(hashCodeEquals);
091: status.setBorder(BorderFactory.createLineBorder(Color.BLACK));
092: status.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
093:
094: ILSM lsm = new ILSM(table, equals, hashCodeEquals, ta);
095: table.getSelectionModel().addListSelectionListener(lsm);
096:
097: GridBagLayout gb = new GridBagLayout();
098: f.setLayout(gb);
099:
100: GridBagConstraints c = new GridBagConstraints();
101: c.insets = new Insets(2, 2, 2, 2);
102: c.gridx = 0;
103: c.gridy = 0;
104: c.weightx = 1;
105: c.weighty = 9;
106: c.fill = GridBagConstraints.BOTH;
107:
108: f.add(scrollPane, c);
109: c.weighty = 1;
110: c.gridy++;
111: f.add(spTa, c);
112:
113: c.weighty = 0;
114: c.gridy++;
115: f.add(status, c);
116:
117: f.pack();
118: f.setVisible(true);
119: }
120: }
121:
122: class InstanceMouseHandler extends MouseAdapter {
123: private JTable table;
124: private ProfilerHandler ph;
125:
126: public InstanceMouseHandler(JTable table, ProfilerHandler ph) {
127: this .table = table;
128: this .ph = ph;
129: }
130:
131: public void mousePressed(MouseEvent e) {
132: if (!SwingUtilities.isRightMouseButton(e))
133: return;
134: int viewRow = table.rowAtPoint(e.getPoint());
135: int modelRow = table.convertRowIndexToModel(viewRow);
136: table.getSelectionModel()
137: .setSelectionInterval(viewRow, viewRow);
138: Object o = table.getModel()
139: .getValueAt(modelRow, ITM.COL_OBJECT);
140: Class<?> c = o.getClass();
141: if (c.isPrimitive()
142: || (c.isArray() && c.getComponentType().isPrimitive()))
143: return;
144: JPopupMenu m = new JPopupMenu();
145: m.add(new JMenuItem(new ChildObjectsSummary(ph, o)));
146: m.show(e.getComponent(), e.getX(), e.getY());
147: }
148: }
149:
150: class ILSM implements ListSelectionListener {
151: private JTable table;
152: private JLabel equals;
153: private JLabel hashCodeEquals;
154: private JTextArea ta;
155:
156: public ILSM(JTable table, JLabel equals, JLabel hashCodeEquals,
157: JTextArea ta) {
158: this .table = table;
159: this .equals = equals;
160: this .hashCodeEquals = hashCodeEquals;
161: this .ta = ta;
162: }
163:
164: public void valueChanged(ListSelectionEvent e) {
165: int[] rows = table.getSelectedRows();
166: if (rows == null || rows.length < 1)
167: ta.setText("");
168: StringBuilder sb = new StringBuilder();
169: for (int r : rows) {
170: int modelRow = table.convertRowIndexToModel(r);
171: Object o = table.getModel().getValueAt(modelRow,
172: ITM.COL_OBJECT);
173: if (o != null) {
174: Class<?> c = o.getClass();
175: if (c.isArray()) {
176: Class<?> ac = c.getComponentType();
177: if (ac.isPrimitive()) {
178: String s = Arrays
179: .deepToString(new Object[] { o });
180: s = s.substring(1, s.length() - 1);
181: sb.append(s);
182: } else {
183: sb.append(Arrays.deepToString((Object[]) o));
184: }
185: } else {
186: sb.append(o.toString());
187: }
188: } else {
189: sb.append("<null>");
190: }
191: sb.append("\n");
192: }
193: sb.setLength(sb.length() - 1);
194: ta.setText(sb.toString());
195: ta.setCaretPosition(0);
196:
197: if (rows == null || rows.length < 2) {
198: equals.setText("-");
199: hashCodeEquals.setText("-");
200: return;
201: }
202:
203: Object o1 = table.getModel()
204: .getValueAt(rows[0], ITM.COL_OBJECT);
205: if (o1 == null) {
206: equals.setText("-");
207: hashCodeEquals.setText("-");
208: return;
209: }
210:
211: int hashCode = o1.hashCode();
212: boolean be = true;
213: boolean bh = true;
214: for (int i = 1; i < rows.length; i++) {
215: Object o2 = table.getModel().getValueAt(rows[i],
216: ITM.COL_OBJECT);
217: if (o2 == null) {
218: be = false;
219: bh = false;
220: break;
221: }
222: if (!(be && o1.equals(o2)))
223: be = false;
224: if (!(bh && o2.hashCode() == hashCode))
225: bh = false;
226: }
227: equals.setText(be ? "equals" : "not equals");
228: hashCodeEquals.setText(bh ? "same hashCode"
229: : "not same hashCode");
230: }
231: }
232:
233: class ITM extends AbstractTableModel {
234: private Class<?> clz;
235: private Object[] objects;
236: private long[] sizes;
237: private int[] lengths;
238:
239: private String[] columnNames = { "OBJECT", "Class", "Size",
240: "Length" };
241:
242: public static final int COL_OBJECT = 0;
243: public static final int COL_CLASS = COL_OBJECT + 1;
244: public static final int COL_SIZE = COL_CLASS + 1;
245: public static final int COL_LENGTH = COL_SIZE + 1;
246:
247: public ITM(Class<?> clz, Object[] objects, long[] sizes,
248: int[] lengths) {
249: this .clz = clz;
250: this .objects = objects;
251: this .sizes = sizes;
252: this .lengths = lengths;
253: }
254:
255: public String getColumnName(int col) {
256: return columnNames[col];
257: }
258:
259: public int getRowCount() {
260: return sizes.length;
261: }
262:
263: public int getColumnCount() {
264: return columnNames.length;
265: }
266:
267: public Class<?> getInstanceClass() {
268: return clz;
269: }
270:
271: public Object getValueAt(int row, int col) {
272: switch (col) {
273: case COL_OBJECT:
274: return objects[row];
275: case COL_CLASS:
276: return clz;
277: case COL_SIZE:
278: return sizes[row];
279: case COL_LENGTH:
280: return lengths[row];
281: default:
282: throw new IllegalArgumentException(
283: "do not know how to handle col: " + col);
284: }
285: }
286:
287: public Class<?> getColumnClass(int col) {
288: switch (col) {
289: case COL_OBJECT:
290: return Object.class;
291: case COL_CLASS:
292: return Class.class;
293: case COL_SIZE:
294: return Long.class;
295: case COL_LENGTH:
296: return Long.class;
297: default:
298: throw new IllegalArgumentException(
299: "do not know how to handle col: " + col);
300: }
301: }
302:
303: public boolean isCellEditable(int row, int col) {
304: return false;
305: }
306:
307: public void setValueAt(Object value, int row, int col) {
308: throw new IllegalStateException("non editable table");
309: }
310: }
|