/*
* Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.ui;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
import sun.jvm.hotspot.oops.ObjectHistogram;
import sun.jvm.hotspot.oops.ObjectHistogramElement;
import sun.jvm.hotspot.oops.Klass;
import sun.jvm.hotspot.ui.table.LongCellRenderer;
import sun.jvm.hotspot.ui.table.SortableTableModel;
import sun.jvm.hotspot.ui.table.SortHeaderCellRenderer;
import sun.jvm.hotspot.ui.table.SortHeaderMouseAdapter;
import sun.jvm.hotspot.ui.table.TableModelComparator;
import sun.jvm.hotspot.ui.action.*;
import com.sun.java.swing.ui.StatusBar;
import com.sun.java.swing.ui.CommonToolBar;
import com.sun.java.swing.action.ActionManager;
import com.sun.java.swing.action.DelegateAction;
/**
* Displays the results of an ObjectHistogram run in a JTable, with a
* button to display all objects of that type
*/
public class ObjectHistogramPanel extends JPanel implements ActionListener {
private ObjectHistogramTableModel dataModel;
private ObjectHistogramToolBar toolbar;
private StatusBar statusBar;
private JTable table;
private java.util.List listeners;
public ObjectHistogramPanel(ObjectHistogram histo) {
dataModel = new ObjectHistogramTableModel(histo);
statusBar = new StatusBar();
table = new JTable(dataModel, new ObjectHistogramColummModel());
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent evt) {
if (evt.getClickCount() == 2) {
fireShowObjectsOfType();
}
}
});
JTableHeader header = table.getTableHeader();
header.setDefaultRenderer(new SortHeaderCellRenderer(header, dataModel));
header.addMouseListener(new SortHeaderMouseAdapter(table, dataModel));
setLayout(new BorderLayout());
toolbar = new ObjectHistogramToolBar(statusBar);
add(toolbar, BorderLayout.NORTH);
add(new JScrollPane(table), BorderLayout.CENTER);
add(statusBar, BorderLayout.SOUTH);
registerActions();
}
private class ObjectHistogramToolBar extends CommonToolBar {
private JTextField searchTF;
public ObjectHistogramToolBar(StatusBar status) {
super(HSDBActionManager.getInstance(), status);
}
protected void addComponents() {
searchTF = new JTextField();
searchTF.setToolTipText("Find in Class Description");
// Pressing Enter on the text field will search
InputMap im = searchTF.getInputMap();
im.put(KeyStroke.getKeyStroke("ENTER"), "enterPressed");
ActionMap am = searchTF.getActionMap();
am.put("enterPressed", manager.getAction(FindAction.VALUE_COMMAND));
add(searchTF);
addButton(manager.getAction(FindAction.VALUE_COMMAND));
addButton(manager.getAction(ShowAction.VALUE_COMMAND));
}
public String getFindText() {
return searchTF.getText();
}
}
private class ObjectHistogramColummModel extends DefaultTableColumnModel {
private final String LABEL_SIZE = "Size";
private final String LABEL_COUNT = "Count";
private final String LABEL_DESC = "Class Description";
public ObjectHistogramColummModel() {
// Should actually get the line metrics for
int PREF_WIDTH = 80;
int MAX_WIDTH = 100;
int HUGE_WIDTH = 140;
LongCellRenderer lcRender = new LongCellRenderer();
TableColumn column;
// Size
column = new TableColumn(0, PREF_WIDTH);
column.setHeaderValue(LABEL_SIZE);
column.setMaxWidth(MAX_WIDTH);
column.setResizable(false);
column.setCellRenderer(lcRender);
addColumn(column);
// Count
column = new TableColumn(1, PREF_WIDTH);
column.setHeaderValue(LABEL_COUNT);
column.setMaxWidth(MAX_WIDTH);
column.setResizable(false);
column.setCellRenderer(lcRender);
addColumn(column);
// Description
column = new TableColumn(2, HUGE_WIDTH);
column.setHeaderValue(LABEL_DESC);
addColumn(column);
}
}
/**
* A table model which encapsulates the ObjectHistogram
*/
private class ObjectHistogramTableModel extends SortableTableModel {
private String[] columnNames = { "Size", "Count", "Class Description" };
private Class[] columnClasses = { Long.class, Long.class, String.class };
public ObjectHistogramTableModel(ObjectHistogram histo) {
// Set the rows
elements = histo.getElements();
setComparator(new ObjectHistogramComparator(this));
}
public int getColumnCount() {
return columnNames.length;
}
public int getRowCount() {
return elements.size();
}
public String getColumnName(int col) {
return columnNames[col];
}
public Class getColumnClass(int col) {
return columnClasses[col];
}
public Object getValueAt(int row, int col) {
return getValueForColumn(getElement(row), col);
}
public Object getValueForColumn(Object obj, int col) {
ObjectHistogramElement el = (ObjectHistogramElement)obj;
switch (col) {
case 0:
return new Long(el.getSize());
case 1:
return new Long(el.getCount());
case 2:
return el.getDescription();
default:
throw new RuntimeException("Index (" + col + ") out of bounds");
}
}
public ObjectHistogramElement getElement(int index) {
return (ObjectHistogramElement) elements.get(index);
}
private class ObjectHistogramComparator extends TableModelComparator {
public ObjectHistogramComparator(ObjectHistogramTableModel model) {
super(model);
}
/**
* Returns the value for the comparing object for the
* column.
*
* @param obj Object that was passed for Comparator
* @param column the column to retrieve
*/
public Object getValueForColumn(Object obj, int column) {
ObjectHistogramTableModel omodel = (ObjectHistogramTableModel)model;
return omodel.getValueForColumn(obj, column);
}
}
}
//
// ActionListener implementation and actions support
//
public void actionPerformed(ActionEvent evt) {
String command = evt.getActionCommand();
if (command.equals(ShowAction.VALUE_COMMAND)) {
fireShowObjectsOfType();
} else if (command.equals(FindAction.VALUE_COMMAND)) {
findObject();
}
}
protected void registerActions() {
registerAction(FindAction.VALUE_COMMAND);
registerAction(ShowAction.VALUE_COMMAND);
}
private void registerAction(String actionName) {
ActionManager manager = ActionManager.getInstance();
DelegateAction action = manager.getDelegateAction(actionName);
action.addActionListener(this);
}
public interface Listener {
public void showObjectsOfType(Klass type);
}
public void addPanelListener(Listener listener) {
if (listeners == null) {
listeners = new ArrayList();
}
listeners.add(listener);
}
public void removePanelListener(Listener listener) {
if (listeners != null) {
listeners.remove(listener);
}
}
//--------------------------------------------------------------------------------
// Internals only below this point
//
/**
* Find and select the row that contains the text in the find field starting
* from the current selected row.
*
* Uses a linear search from the current row. Could be optimized withing the
* model and internal representation.
*/
private void findObject() {
String findText = toolbar.getFindText();
if (findText == null || findText.equals("")) {
return;
}
TableModel model = table.getModel();
int row = table.getSelectedRow();
if (row == model.getRowCount()) {
row = 0;
} else {
// Start at the row after the selected row.
row++;
}
String value;
for (int i = row; i < model.getRowCount(); i++) {
value = (String)model.getValueAt(i, 2);
if (value != null && value.startsWith(findText)) {
table.setRowSelectionInterval(i, i);
Rectangle cellBounds = table.getCellRect(i, 0, true);
table.scrollRectToVisible(cellBounds);
return;
}
}
// Wrap the table to search in the top rows.
for (int i = 0; i < row; i++) {
value = (String)model.getValueAt(i, 2);
if (value != null && value.startsWith(findText)) {
table.setRowSelectionInterval(i, i);
Rectangle cellBounds = table.getCellRect(i, 0, true);
table.scrollRectToVisible(cellBounds);
return;
}
}
}
private void fireShowObjectsOfType() {
int i = table.getSelectedRow();
if (i < 0) {
return;
}
ObjectHistogramElement el = dataModel.getElement(i);
for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
Listener listener = (Listener) iter.next();
listener.showObjectsOfType(el.getKlass());
}
}
public static void main(String[] args) {
}
}