1/* 2 * Copyright (c) 2001, 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 25package sun.jvm.hotspot.ui; 26 27import java.awt.*; 28import java.awt.event.*; 29import java.util.*; 30import javax.swing.*; 31import javax.swing.event.*; 32import javax.swing.table.*; 33 34import sun.jvm.hotspot.debugger.*; 35 36public class ProcessListPanel extends JPanel { 37 private Debugger dbg; 38 private AbstractTableModel dataModel; 39 private java.util.List els; 40 private boolean sortByName = true; 41 private boolean sortReversed = false; 42 private javax.swing.Timer timer; 43 private JTable table; 44 45 /** Takes a Debugger in constructor. Updates the list once during 46 construction; list can be updated automatically by "starting" 47 the panel. */ 48 public ProcessListPanel(Debugger dbg) { 49 super(); 50 51 this.dbg = dbg; 52 53 update(); 54 55 dataModel = new AbstractTableModel() { 56 public int getColumnCount() { return 2; } 57 public int getRowCount() { return els.size(); } 58 public String getColumnName(int col) { 59 switch (col) { 60 case 0: 61 return "Process Name"; 62 case 1: 63 return "Process ID"; 64 default: 65 throw new RuntimeException("Index " + col + " out of bounds"); 66 } 67 } 68 69 public Object getValueAt(int row, int col) { 70 ProcessInfo info = (ProcessInfo) els.get(row); 71 72 switch (col) { 73 case 0: 74 return info.getName(); 75 case 1: 76 return new Integer(info.getPid()); 77 default: 78 throw new RuntimeException("Index (" + col + ", " + row + ") out of bounds"); 79 } 80 } 81 }; 82 83 // Create user interface 84 setLayout(new BorderLayout()); 85 table = new JTable(dataModel); 86 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 87 JTableHeader header = table.getTableHeader(); 88 header.setReorderingAllowed(false); 89 table.setRowSelectionAllowed(true); 90 table.setColumnSelectionAllowed(false); 91 // Provide sorting in similar fashion to Task Manager 92 header.addMouseListener(new MouseAdapter() { 93 public void mousePressed(MouseEvent e) { 94 int viewColumn = table.getColumnModel().getColumnIndexAtX(e.getX()); 95 int column = table.convertColumnIndexToModel(viewColumn); 96 if (column != -1) { 97 boolean newSortByName = (column == 0); 98 if (newSortByName == sortByName) { 99 // Switch sense of "reversed" instead 100 sortReversed = !sortReversed; 101 } else { 102 sortByName = newSortByName; 103 sortReversed = false; 104 } 105 106 // Keep the current selection if possible 107 int i = table.getSelectedRow(); 108 int pid = getPid(els, i); 109 sort(els); 110 i = findPid(els, pid); 111 dataModel.fireTableDataChanged(); 112 if ((i >= 0) || (els.size() > 0)) { 113 if (i >= 0) { 114 table.setRowSelectionInterval(i, i); 115 } else { 116 table.setRowSelectionInterval(0, 0); 117 } 118 } 119 } 120 } 121 }); 122 123 JScrollPane scrollPane = new JScrollPane(table); 124 add(scrollPane, BorderLayout.CENTER); 125 126 if (els.size() > 0) { 127 table.setRowSelectionInterval(0, 0); 128 } 129 } 130 131 /** Set update interval for automatic updating of the process list */ 132 133 public void setAutoUpdateInterval(int millis) { 134 getTimer().setDelay(millis); 135 } 136 137 /** Start auto updating of the panel */ 138 public void start() { 139 getTimer().start(); 140 } 141 142 /** Stop auto updating of the panel */ 143 public void stop() { 144 getTimer().stop(); 145 } 146 147 /** Call this to update the panel's notion of the process list */ 148 public synchronized void update() { 149 if (!dbg.hasProcessList()) { 150 throw new RuntimeException("ProcessListPanel requires that debugger supports getProcessList()"); 151 } 152 java.util.List newEls = dbg.getProcessList(); 153 sort(newEls); 154 if (table != null) { 155 // Keep the current selection if possible 156 int i = table.getSelectedRow(); 157 int pid = getPid(els, i); 158 i = findPid(newEls, pid); 159 els = newEls; 160 dataModel.fireTableDataChanged(); 161 if ((i >= 0) || (els.size() > 0)) { 162 if (i >= 0) { 163 table.setRowSelectionInterval(i, i); 164 } else { 165 table.setRowSelectionInterval(0, 0); 166 } 167 } 168 } else { 169 els = newEls; 170 } 171 } 172 173 /** Call this to get the selected ProcessInfo, or null if none selected */ 174 public synchronized ProcessInfo getSelectedProcess() { 175 int i = table.getSelectedRow(); 176 if (i < 0) { 177 return null; 178 } 179 return (ProcessInfo) els.get(i); 180 } 181 182 private synchronized void sort(java.util.List els) { 183 Comparator c; 184 if (sortByName) { 185 c = new Comparator() { 186 public int compare(Object o1, Object o2) { 187 int scale = (sortReversed ? -1 : 1); 188 return scale * ((ProcessInfo) o1).getName().compareToIgnoreCase(((ProcessInfo) o2).getName()); 189 } 190 }; 191 } else { 192 c = new Comparator() { 193 public int compare(Object o1, Object o2) { 194 int scale = (sortReversed ? -1 : 1); 195 int pid1 = ((ProcessInfo) o1).getPid(); 196 int pid2 = ((ProcessInfo) o2).getPid(); 197 int ret; 198 if (pid1 < pid2) ret = -1; 199 else if (pid1 == pid2) ret = 0; 200 else ret = 1; 201 return ret * scale; 202 } 203 }; 204 } 205 Collections.sort(els, c); 206 } 207 208 private javax.swing.Timer getTimer() { 209 if (timer == null) { 210 timer = new javax.swing.Timer(1000, new ActionListener() { 211 public void actionPerformed(ActionEvent e) { 212 update(); 213 } 214 }); 215 } 216 return timer; 217 } 218 219 private synchronized int getPid(java.util.List els, int index) { 220 return ((ProcessInfo) els.get(index)).getPid(); 221 } 222 223 private synchronized int findPid(java.util.List els, int pid) { 224 for (int i = 0; i < els.size(); i++) { 225 ProcessInfo info = (ProcessInfo) els.get(i); 226 if (info.getPid() == pid) { 227 return i; 228 } 229 } 230 return -1; 231 } 232} 233