View Javadoc
1   /*
2    * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.
8    *
9    * This code is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12   * version 2 for more details (a copy is included in the LICENSE file that
13   * accompanied this code).
14   *
15   * You should have received a copy of the GNU General Public License version
16   * 2 along with this work; if not, write to the Free Software Foundation,
17   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18   *
19   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20   * or visit www.oracle.com if you need additional information or have any
21   * questions.
22   *
23   */
24  
25  package sun.jvm.hotspot.ui;
26  
27  import java.util.*;
28  
29  import java.awt.*;
30  import java.awt.event.*;
31  
32  import javax.swing.*;
33  import javax.swing.table.*;
34  
35  import sun.jvm.hotspot.oops.ObjectHistogram;
36  import sun.jvm.hotspot.oops.ObjectHistogramElement;
37  import sun.jvm.hotspot.oops.Klass;
38  
39  import sun.jvm.hotspot.ui.table.LongCellRenderer;
40  import sun.jvm.hotspot.ui.table.SortableTableModel;
41  import sun.jvm.hotspot.ui.table.SortHeaderCellRenderer;
42  import sun.jvm.hotspot.ui.table.SortHeaderMouseAdapter;
43  import sun.jvm.hotspot.ui.table.TableModelComparator;
44  
45  import sun.jvm.hotspot.ui.action.*;
46  
47  import com.sun.java.swing.ui.StatusBar;
48  import com.sun.java.swing.ui.CommonToolBar;
49  
50  import com.sun.java.swing.action.ActionManager;
51  import com.sun.java.swing.action.DelegateAction;
52  
53  /**
54   * Displays the results of an ObjectHistogram run in a JTable, with a
55   * button to display all objects of that type
56   */
57  public class ObjectHistogramPanel extends JPanel implements ActionListener {
58      private ObjectHistogramTableModel dataModel;
59      private ObjectHistogramToolBar toolbar;
60      private StatusBar statusBar;
61      private JTable     table;
62      private java.util.List listeners;
63  
64      public ObjectHistogramPanel(ObjectHistogram histo) {
65          dataModel = new ObjectHistogramTableModel(histo);
66          statusBar = new StatusBar();
67  
68          table = new JTable(dataModel, new ObjectHistogramColummModel());
69          table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
70          table.addMouseListener(new MouseAdapter() {
71                  public void mouseClicked(MouseEvent evt) {
72                      if (evt.getClickCount() == 2) {
73                          fireShowObjectsOfType();
74                      }
75                  }
76              });
77  
78          JTableHeader header = table.getTableHeader();
79          header.setDefaultRenderer(new SortHeaderCellRenderer(header, dataModel));
80          header.addMouseListener(new SortHeaderMouseAdapter(table, dataModel));
81  
82          setLayout(new BorderLayout());
83  
84          toolbar = new ObjectHistogramToolBar(statusBar);
85          add(toolbar, BorderLayout.NORTH);
86          add(new JScrollPane(table), BorderLayout.CENTER);
87          add(statusBar, BorderLayout.SOUTH);
88  
89          registerActions();
90      }
91  
92      private class ObjectHistogramToolBar extends CommonToolBar {
93  
94          private JTextField searchTF;
95  
96          public ObjectHistogramToolBar(StatusBar status) {
97              super(HSDBActionManager.getInstance(), status);
98          }
99  
100         protected void addComponents() {
101             searchTF = new JTextField();
102             searchTF.setToolTipText("Find in Class Description");
103 
104             // Pressing Enter on the text field will search
105             InputMap im = searchTF.getInputMap();
106             im.put(KeyStroke.getKeyStroke("ENTER"), "enterPressed");
107             ActionMap am = searchTF.getActionMap();
108             am.put("enterPressed", manager.getAction(FindAction.VALUE_COMMAND));
109 
110             add(searchTF);
111             addButton(manager.getAction(FindAction.VALUE_COMMAND));
112             addButton(manager.getAction(ShowAction.VALUE_COMMAND));
113         }
114 
115         public String getFindText() {
116             return searchTF.getText();
117         }
118     }
119 
120     private class ObjectHistogramColummModel extends DefaultTableColumnModel {
121         private final String LABEL_SIZE = "Size";
122         private final String LABEL_COUNT = "Count";
123         private final String LABEL_DESC = "Class Description";
124 
125 
126         public ObjectHistogramColummModel() {
127             // Should actually get the line metrics for
128             int PREF_WIDTH = 80;
129             int MAX_WIDTH = 100;
130             int HUGE_WIDTH = 140;
131 
132             LongCellRenderer lcRender = new LongCellRenderer();
133 
134             TableColumn column;
135 
136             // Size
137             column = new TableColumn(0, PREF_WIDTH);
138             column.setHeaderValue(LABEL_SIZE);
139             column.setMaxWidth(MAX_WIDTH);
140             column.setResizable(false);
141             column.setCellRenderer(lcRender);
142             addColumn(column);
143 
144             // Count
145             column = new TableColumn(1, PREF_WIDTH);
146             column.setHeaderValue(LABEL_COUNT);
147             column.setMaxWidth(MAX_WIDTH);
148             column.setResizable(false);
149             column.setCellRenderer(lcRender);
150             addColumn(column);
151 
152             // Description
153             column = new TableColumn(2, HUGE_WIDTH);
154             column.setHeaderValue(LABEL_DESC);
155             addColumn(column);
156         }
157     }
158 
159 
160     /**
161      * A table model which encapsulates the ObjectHistogram
162      */
163     private class ObjectHistogramTableModel extends SortableTableModel {
164         private String[] columnNames = { "Size", "Count", "Class Description" };
165         private Class[] columnClasses = { Long.class, Long.class, String.class };
166 
167         public ObjectHistogramTableModel(ObjectHistogram histo) {
168             // Set the rows
169             elements = histo.getElements();
170             setComparator(new ObjectHistogramComparator(this));
171 
172         }
173 
174         public int getColumnCount() {
175             return columnNames.length;
176         }
177 
178         public int getRowCount() {
179             return elements.size();
180         }
181 
182         public String getColumnName(int col) {
183             return columnNames[col];
184         }
185 
186         public Class getColumnClass(int col) {
187             return columnClasses[col];
188         }
189 
190         public Object getValueAt(int row, int col) {
191             return getValueForColumn(getElement(row), col);
192         }
193 
194         public Object getValueForColumn(Object obj, int col) {
195             ObjectHistogramElement el = (ObjectHistogramElement)obj;
196             switch (col) {
197             case 0:
198                 return new Long(el.getSize());
199             case 1:
200                 return new Long(el.getCount());
201             case 2:
202                 return el.getDescription();
203             default:
204                 throw new RuntimeException("Index (" + col + ") out of bounds");
205             }
206         }
207 
208         public ObjectHistogramElement getElement(int index) {
209             return (ObjectHistogramElement) elements.get(index);
210         }
211 
212         private class ObjectHistogramComparator extends TableModelComparator {
213 
214             public ObjectHistogramComparator(ObjectHistogramTableModel model) {
215                 super(model);
216             }
217 
218             /**
219              * Returns the value for the comparing object for the
220              * column.
221              *
222              * @param obj Object that was passed for Comparator
223              * @param column the column to retrieve
224              */
225             public Object getValueForColumn(Object obj, int column) {
226                 ObjectHistogramTableModel omodel = (ObjectHistogramTableModel)model;
227                 return omodel.getValueForColumn(obj, column);
228             }
229         }
230 
231     }
232 
233 
234     //
235     // ActionListener implementation and actions support
236     //
237 
238     public void actionPerformed(ActionEvent evt) {
239         String command = evt.getActionCommand();
240 
241         if (command.equals(ShowAction.VALUE_COMMAND)) {
242             fireShowObjectsOfType();
243         } else if (command.equals(FindAction.VALUE_COMMAND)) {
244             findObject();
245         }
246 
247     }
248 
249     protected void registerActions() {
250         registerAction(FindAction.VALUE_COMMAND);
251         registerAction(ShowAction.VALUE_COMMAND);
252     }
253 
254     private void registerAction(String actionName) {
255         ActionManager manager = ActionManager.getInstance();
256         DelegateAction action = manager.getDelegateAction(actionName);
257         action.addActionListener(this);
258     }
259 
260     public interface Listener {
261         public void showObjectsOfType(Klass type);
262     }
263 
264     public void addPanelListener(Listener listener) {
265         if (listeners == null) {
266             listeners = new ArrayList();
267         }
268         listeners.add(listener);
269     }
270 
271     public void removePanelListener(Listener listener) {
272         if (listeners != null) {
273             listeners.remove(listener);
274         }
275     }
276 
277     //--------------------------------------------------------------------------------
278     // Internals only below this point
279     //
280 
281     /**
282      * Find and select the row that contains the text in the find field starting
283      * from the current selected row.
284      *
285      * Uses a linear search from the current row. Could be optimized withing the
286      * model and internal representation.
287      */
288     private void findObject() {
289         String findText = toolbar.getFindText();
290 
291         if (findText == null || findText.equals("")) {
292             return;
293         }
294 
295         TableModel model = table.getModel();
296 
297         int row = table.getSelectedRow();
298         if (row == model.getRowCount()) {
299             row = 0;
300         } else {
301             // Start at the row after the selected row.
302             row++;
303         }
304 
305         String value;
306         for (int i = row; i < model.getRowCount(); i++) {
307             value = (String)model.getValueAt(i, 2);
308             if (value != null && value.startsWith(findText)) {
309                 table.setRowSelectionInterval(i, i);
310                 Rectangle cellBounds = table.getCellRect(i, 0, true);
311                 table.scrollRectToVisible(cellBounds);
312                 return;
313             }
314         }
315 
316         // Wrap the table to search in the top rows.
317         for (int i = 0; i < row; i++) {
318             value = (String)model.getValueAt(i, 2);
319             if (value != null && value.startsWith(findText)) {
320                 table.setRowSelectionInterval(i, i);
321                 Rectangle cellBounds = table.getCellRect(i, 0, true);
322                 table.scrollRectToVisible(cellBounds);
323                 return;
324             }
325         }
326     }
327 
328     private void fireShowObjectsOfType() {
329         int i = table.getSelectedRow();
330         if (i < 0) {
331             return;
332         }
333 
334         ObjectHistogramElement el = dataModel.getElement(i);
335 
336         for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
337             Listener listener = (Listener) iter.next();
338             listener.showObjectsOfType(el.getKlass());
339         }
340     }
341 
342     public static void main(String[] args) {
343 
344     }
345 }