/* * Copyright (c) 2001, 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.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.table.*; import sun.jvm.hotspot.debugger.*; public class ProcessListPanel extends JPanel { private Debugger dbg; private AbstractTableModel dataModel; private java.util.List els; private boolean sortByName = true; private boolean sortReversed = false; private javax.swing.Timer timer; private JTable table; /** Takes a Debugger in constructor. Updates the list once during construction; list can be updated automatically by "starting" the panel. */ public ProcessListPanel(Debugger dbg) { super(); this.dbg = dbg; update(); dataModel = new AbstractTableModel() { public int getColumnCount() { return 2; } public int getRowCount() { return els.size(); } public String getColumnName(int col) { switch (col) { case 0: return "Process Name"; case 1: return "Process ID"; default: throw new RuntimeException("Index " + col + " out of bounds"); } } public Object getValueAt(int row, int col) { ProcessInfo info = (ProcessInfo) els.get(row); switch (col) { case 0: return info.getName(); case 1: return new Integer(info.getPid()); default: throw new RuntimeException("Index (" + col + ", " + row + ") out of bounds"); } } }; // Create user interface setLayout(new BorderLayout()); table = new JTable(dataModel); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); JTableHeader header = table.getTableHeader(); header.setReorderingAllowed(false); table.setRowSelectionAllowed(true); table.setColumnSelectionAllowed(false); // Provide sorting in similar fashion to Task Manager header.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { int viewColumn = table.getColumnModel().getColumnIndexAtX(e.getX()); int column = table.convertColumnIndexToModel(viewColumn); if (column != -1) { boolean newSortByName = (column == 0); if (newSortByName == sortByName) { // Switch sense of "reversed" instead sortReversed = !sortReversed; } else { sortByName = newSortByName; sortReversed = false; } // Keep the current selection if possible int i = table.getSelectedRow(); int pid = getPid(els, i); sort(els); i = findPid(els, pid); dataModel.fireTableDataChanged(); if ((i >= 0) || (els.size() > 0)) { if (i >= 0) { table.setRowSelectionInterval(i, i); } else { table.setRowSelectionInterval(0, 0); } } } } }); JScrollPane scrollPane = new JScrollPane(table); add(scrollPane, BorderLayout.CENTER); if (els.size() > 0) { table.setRowSelectionInterval(0, 0); } } /** Set update interval for automatic updating of the process list */ public void setAutoUpdateInterval(int millis) { getTimer().setDelay(millis); } /** Start auto updating of the panel */ public void start() { getTimer().start(); } /** Stop auto updating of the panel */ public void stop() { getTimer().stop(); } /** Call this to update the panel's notion of the process list */ public synchronized void update() { if (!dbg.hasProcessList()) { throw new RuntimeException("ProcessListPanel requires that debugger supports getProcessList()"); } java.util.List newEls = dbg.getProcessList(); sort(newEls); if (table != null) { // Keep the current selection if possible int i = table.getSelectedRow(); int pid = getPid(els, i); i = findPid(newEls, pid); els = newEls; dataModel.fireTableDataChanged(); if ((i >= 0) || (els.size() > 0)) { if (i >= 0) { table.setRowSelectionInterval(i, i); } else { table.setRowSelectionInterval(0, 0); } } } else { els = newEls; } } /** Call this to get the selected ProcessInfo, or null if none selected */ public synchronized ProcessInfo getSelectedProcess() { int i = table.getSelectedRow(); if (i < 0) { return null; } return (ProcessInfo) els.get(i); } private synchronized void sort(java.util.List els) { Comparator c; if (sortByName) { c = new Comparator() { public int compare(Object o1, Object o2) { int scale = (sortReversed ? -1 : 1); return scale * ((ProcessInfo) o1).getName().compareToIgnoreCase(((ProcessInfo) o2).getName()); } }; } else { c = new Comparator() { public int compare(Object o1, Object o2) { int scale = (sortReversed ? -1 : 1); int pid1 = ((ProcessInfo) o1).getPid(); int pid2 = ((ProcessInfo) o2).getPid(); int ret; if (pid1 < pid2) ret = -1; else if (pid1 == pid2) ret = 0; else ret = 1; return ret * scale; } }; } Collections.sort(els, c); } private javax.swing.Timer getTimer() { if (timer == null) { timer = new javax.swing.Timer(1000, new ActionListener() { public void actionPerformed(ActionEvent e) { update(); } }); } return timer; } private synchronized int getPid(java.util.List els, int index) { return ((ProcessInfo) els.get(index)).getPid(); } private synchronized int findPid(java.util.List els, int pid) { for (int i = 0; i < els.size(); i++) { ProcessInfo info = (ProcessInfo) els.get(i); if (info.getPid() == pid) { return i; } } return -1; } }