1 /* 2 * Copyright (c) 2004, 2006, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.tools.jconsole; 27 28 import java.util.List; 29 import java.awt.*; 30 import java.awt.event.*; 31 import java.util.*; 32 33 import javax.swing.*; 34 import javax.swing.border.*; 35 import javax.swing.event.*; 36 import javax.swing.plaf.basic.BasicRadioButtonUI; 37 import javax.swing.table.*; 38 39 import sun.tools.jconsole.resources.Messages; 40 41 42 import static java.awt.BorderLayout.*; 43 import static javax.swing.ListSelectionModel.*; 44 import static sun.tools.jconsole.Utilities.*; 45 46 @SuppressWarnings("serial") 47 public class ConnectDialog extends InternalDialog 48 implements DocumentListener, FocusListener, 49 ItemListener, ListSelectionListener, KeyListener { 50 51 private static final int COL_NAME = 0; 52 private static final int COL_PID = 1; 53 54 55 JConsole jConsole; 56 JTextField userNameTF, passwordTF; 57 JRadioButton localRadioButton, remoteRadioButton; 58 JLabel localMessageLabel, remoteMessageLabel; 59 JTextField remoteTF; 60 JButton connectButton, cancelButton; 61 JPanel radioButtonPanel; 62 63 private Icon mastheadIcon = 64 new MastheadIcon(Messages.CONNECT_DIALOG_MASTHEAD_TITLE); 65 private Color hintTextColor, disabledTableCellColor; 66 67 // The table of managed VM (local process) 68 JTable vmTable; 69 ManagedVmTableModel vmModel = null; 70 71 JScrollPane localTableScrollPane = null; 72 73 private Action connectAction, cancelAction; 74 75 76 public ConnectDialog(JConsole jConsole) { 77 super(jConsole, Messages.CONNECT_DIALOG_TITLE, true); 78 79 this.jConsole = jConsole; 80 setAccessibleDescription(this, 81 Messages.CONNECT_DIALOG_ACCESSIBLE_DESCRIPTION); 82 setDefaultCloseOperation(HIDE_ON_CLOSE); 83 setResizable(false); 84 Container cp = (JComponent)getContentPane(); 85 86 radioButtonPanel = new JPanel(new BorderLayout(0, 12)); 87 radioButtonPanel.setBorder(new EmptyBorder(6, 12, 12, 12)); 88 ButtonGroup radioButtonGroup = new ButtonGroup(); 89 JPanel bottomPanel = new JPanel(new BorderLayout()); 90 91 statusBar = new JLabel(" ", JLabel.CENTER); 92 setAccessibleName(statusBar, 93 Messages.CONNECT_DIALOG_STATUS_BAR_ACCESSIBLE_NAME); 94 95 Font normalLabelFont = statusBar.getFont(); 96 Font boldLabelFont = normalLabelFont.deriveFont(Font.BOLD); 97 Font smallLabelFont = normalLabelFont.deriveFont(normalLabelFont.getSize2D() - 1); 98 99 JLabel mastheadLabel = new JLabel(mastheadIcon); 100 setAccessibleName(mastheadLabel, 101 Messages.CONNECT_DIALOG_MASTHEAD_ACCESSIBLE_NAME); 102 103 cp.add(mastheadLabel, NORTH); 104 cp.add(radioButtonPanel, CENTER); 105 cp.add(bottomPanel, SOUTH); 106 107 createActions(); 108 109 remoteTF = new JTextField(); 110 remoteTF.addActionListener(connectAction); 111 remoteTF.getDocument().addDocumentListener(this); 112 remoteTF.addFocusListener(this); 113 remoteTF.setPreferredSize(remoteTF.getPreferredSize()); 114 setAccessibleName(remoteTF, 115 Messages.REMOTE_PROCESS_TEXT_FIELD_ACCESSIBLE_NAME); 116 117 // 118 // If the VM supports the local attach mechanism (is: Sun 119 // implementation) then the Local Process panel is created. 120 // 121 if (JConsole.isLocalAttachAvailable()) { 122 vmModel = new ManagedVmTableModel(); 123 vmTable = new LocalTabJTable(vmModel); 124 vmTable.setSelectionMode(SINGLE_SELECTION); 125 vmTable.setPreferredScrollableViewportSize(new Dimension(400, 250)); 126 vmTable.setColumnSelectionAllowed(false); 127 vmTable.addFocusListener(this); 128 vmTable.getSelectionModel().addListSelectionListener(this); 129 130 TableColumnModel columnModel = vmTable.getColumnModel(); 131 132 TableColumn pidColumn = columnModel.getColumn(COL_PID); 133 pidColumn.setMaxWidth(getLabelWidth("9999999")); 134 pidColumn.setResizable(false); 135 136 TableColumn cmdLineColumn = columnModel.getColumn(COL_NAME); 137 cmdLineColumn.setResizable(false); 138 139 localRadioButton = new JRadioButton(Messages.LOCAL_PROCESS_COLON); 140 localRadioButton.setMnemonic(Resources.getMnemonicInt(Messages.LOCAL_PROCESS_COLON)); 141 localRadioButton.setFont(boldLabelFont); 142 localRadioButton.addItemListener(this); 143 radioButtonGroup.add(localRadioButton); 144 145 JPanel localPanel = new JPanel(new BorderLayout()); 146 147 JPanel localTablePanel = new JPanel(new BorderLayout()); 148 149 radioButtonPanel.add(localPanel, NORTH); 150 151 localPanel.add(localRadioButton, NORTH); 152 localPanel.add(new Padder(localRadioButton), LINE_START); 153 localPanel.add(localTablePanel, CENTER); 154 155 localTableScrollPane = new JScrollPane(vmTable); 156 157 localTablePanel.add(localTableScrollPane, NORTH); 158 159 localMessageLabel = new JLabel(" "); 160 localMessageLabel.setFont(smallLabelFont); 161 localMessageLabel.setForeground(hintTextColor); 162 localTablePanel.add(localMessageLabel, SOUTH); 163 } 164 165 remoteRadioButton = new JRadioButton(Messages.REMOTE_PROCESS_COLON); 166 remoteRadioButton.setMnemonic(Resources.getMnemonicInt(Messages.REMOTE_PROCESS_COLON)); 167 remoteRadioButton.setFont(boldLabelFont); 168 radioButtonGroup.add(remoteRadioButton); 169 170 JPanel remotePanel = new JPanel(new BorderLayout()); 171 if (localRadioButton != null) { 172 remotePanel.add(remoteRadioButton, NORTH); 173 remotePanel.add(new Padder(remoteRadioButton), LINE_START); 174 175 Action nextRadioButtonAction = 176 new AbstractAction("nextRadioButton") { 177 public void actionPerformed(ActionEvent ev) { 178 JRadioButton rb = 179 (ev.getSource() == localRadioButton) ? remoteRadioButton 180 : localRadioButton; 181 rb.doClick(); 182 rb.requestFocus(); 183 } 184 }; 185 186 localRadioButton.getActionMap().put("nextRadioButton", nextRadioButtonAction); 187 remoteRadioButton.getActionMap().put("nextRadioButton", nextRadioButtonAction); 188 189 localRadioButton.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), 190 "nextRadioButton"); 191 remoteRadioButton.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), 192 "nextRadioButton"); 193 } else { 194 JLabel remoteLabel = new JLabel(remoteRadioButton.getText()); 195 remoteLabel.setFont(boldLabelFont); 196 remotePanel.add(remoteLabel, NORTH); 197 } 198 radioButtonPanel.add(remotePanel, SOUTH); 199 200 JPanel remoteTFPanel = new JPanel(new BorderLayout()); 201 remotePanel.add(remoteTFPanel, CENTER); 202 203 remoteTFPanel.add(remoteTF, NORTH); 204 205 remoteMessageLabel = new JLabel("<html>" + Messages.REMOTE_TF_USAGE); 206 remoteMessageLabel.setFont(smallLabelFont); 207 remoteMessageLabel.setForeground(hintTextColor); 208 remoteTFPanel.add(remoteMessageLabel, CENTER); 209 210 JPanel userPwdPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0)); 211 userPwdPanel.setBorder(new EmptyBorder(12, 0, 0, 0)); // top padding 212 213 int tfWidth = JConsole.IS_WIN ? 12 : 8; 214 215 userNameTF = new JTextField(tfWidth); 216 userNameTF.addActionListener(connectAction); 217 userNameTF.getDocument().addDocumentListener(this); 218 userNameTF.addFocusListener(this); 219 setAccessibleName(userNameTF, 220 Messages.USERNAME_ACCESSIBLE_NAME); 221 String labelKey = Messages.USERNAME_COLON_; 222 LabeledComponent lc; 223 lc = new LabeledComponent(labelKey, 224 Resources.getMnemonicInt(labelKey), 225 userNameTF); 226 lc.label.setFont(boldLabelFont); 227 userPwdPanel.add(lc); 228 229 passwordTF = new JPasswordField(tfWidth); 230 // Heights differ, so fix here 231 passwordTF.setPreferredSize(userNameTF.getPreferredSize()); 232 passwordTF.addActionListener(connectAction); 233 passwordTF.getDocument().addDocumentListener(this); 234 passwordTF.addFocusListener(this); 235 setAccessibleName(passwordTF, 236 Messages.PASSWORD_ACCESSIBLE_NAME); 237 labelKey = "Password: "; 238 lc = new LabeledComponent(labelKey, 239 Resources.getMnemonicInt(labelKey), 240 passwordTF); 241 lc.setBorder(new EmptyBorder(0, 12, 0, 0)); // Left padding 242 lc.label.setFont(boldLabelFont); 243 userPwdPanel.add(lc); 244 245 remoteTFPanel.add(userPwdPanel, SOUTH); 246 247 String connectButtonToolTipText = 248 Messages.CONNECT_DIALOG_CONNECT_BUTTON_TOOLTIP; 249 connectButton = new JButton(connectAction); 250 connectButton.setToolTipText(connectButtonToolTipText); 251 252 cancelButton = new JButton(cancelAction); 253 254 JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING)); 255 buttonPanel.setBorder(new EmptyBorder(12, 12, 2, 12)); 256 if (JConsole.IS_GTK) { 257 buttonPanel.add(cancelButton); 258 buttonPanel.add(connectButton); 259 } else { 260 buttonPanel.add(connectButton); 261 buttonPanel.add(cancelButton); 262 } 263 bottomPanel.add(buttonPanel, NORTH); 264 265 bottomPanel.add(statusBar, SOUTH); 266 267 updateButtonStates(); 268 Utilities.updateTransparency(this); 269 } 270 271 public void revalidate() { 272 // Adjust some colors 273 hintTextColor = 274 ensureContrast(UIManager.getColor("Label.disabledForeground"), 275 UIManager.getColor("Panel.background")); 276 disabledTableCellColor = 277 ensureContrast(new Color(0x808080), 278 UIManager.getColor("Table.background")); 279 280 if (remoteMessageLabel != null) { 281 remoteMessageLabel.setForeground(hintTextColor); 282 // Update html color setting 283 String colorStr = 284 String.format("%06x", hintTextColor.getRGB() & 0xFFFFFF); 285 remoteMessageLabel.setText("<html><font color=#" + colorStr + ">" + 286 Messages.REMOTE_TF_USAGE); 287 } 288 if (localMessageLabel != null) { 289 localMessageLabel.setForeground(hintTextColor); 290 // Update html color setting 291 valueChanged(null); 292 } 293 294 super.revalidate(); 295 } 296 297 private void createActions() { 298 connectAction = new AbstractAction(Messages.CONNECT) { 299 /* init */ { 300 putValue(Action.MNEMONIC_KEY, Resources.getMnemonicInt(Messages.CONNECT)); 301 } 302 303 public void actionPerformed(ActionEvent ev) { 304 if (!isEnabled() || !isVisible()) { 305 return; 306 } 307 setVisible(false); 308 statusBar.setText(""); 309 310 if (remoteRadioButton.isSelected()) { 311 String txt = remoteTF.getText().trim(); 312 String userName = userNameTF.getText().trim(); 313 userName = userName.equals("") ? null : userName; 314 String password = passwordTF.getText(); 315 password = password.equals("") ? null : password; 316 try { 317 if (txt.startsWith(JConsole.ROOT_URL)) { 318 String url = txt; 319 jConsole.addUrl(url, userName, password, false); 320 remoteTF.setText(JConsole.ROOT_URL); 321 return; 322 } else { 323 String host = remoteTF.getText().trim(); 324 String port = "0"; 325 int index = host.lastIndexOf(":"); 326 if (index >= 0) { 327 port = host.substring(index + 1); 328 host = host.substring(0, index); 329 } 330 if (host.length() > 0 && port.length() > 0) { 331 int p = Integer.parseInt(port.trim()); 332 jConsole.addHost(host, p, userName, password); 333 remoteTF.setText(""); 334 userNameTF.setText(""); 335 passwordTF.setText(""); 336 return; 337 } 338 } 339 } catch (Exception ex) { 340 statusBar.setText(ex.toString()); 341 } 342 setVisible(true); 343 } else if (localRadioButton != null && localRadioButton.isSelected()) { 344 // Try to connect to selected VM. If a connection 345 // cannot be established for some reason (the process has 346 // terminated for example) then keep the dialog open showing 347 // the connect error. 348 // 349 int row = vmTable.getSelectedRow(); 350 if (row >= 0) { 351 jConsole.addVmid(vmModel.vmAt(row)); 352 } 353 refresh(); 354 } 355 } 356 }; 357 358 cancelAction = new AbstractAction(Messages.CANCEL) { 359 public void actionPerformed(ActionEvent ev) { 360 setVisible(false); 361 statusBar.setText(""); 362 } 363 }; 364 } 365 366 367 // a label used solely for calculating the width 368 private static JLabel tmpLabel = new JLabel(); 369 public static int getLabelWidth(String text) { 370 tmpLabel.setText(text); 371 return (int) tmpLabel.getPreferredSize().getWidth() + 1; 372 } 373 374 private class LocalTabJTable extends JTable { 375 ManagedVmTableModel vmModel; 376 Border rendererBorder = new EmptyBorder(0, 6, 0, 6); 377 378 public LocalTabJTable(ManagedVmTableModel model) { 379 super(model); 380 this.vmModel = model; 381 382 // Remove vertical lines, expect for GTK L&F. 383 // (because GTK doesn't show header dividers) 384 if (!JConsole.IS_GTK) { 385 setShowVerticalLines(false); 386 setIntercellSpacing(new Dimension(0, 1)); 387 } 388 389 // Double-click handler 390 addMouseListener(new MouseAdapter() { 391 public void mouseClicked(MouseEvent evt) { 392 if (evt.getClickCount() == 2) { 393 connectButton.doClick(); 394 } 395 } 396 }); 397 398 // Enter should call default action 399 getActionMap().put("connect", connectAction); 400 InputMap inputMap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 401 inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "connect"); 402 } 403 404 public String getToolTipText(MouseEvent e) { 405 String tip = null; 406 java.awt.Point p = e.getPoint(); 407 int rowIndex = rowAtPoint(p); 408 int colIndex = columnAtPoint(p); 409 int realColumnIndex = convertColumnIndexToModel(colIndex); 410 411 if (realColumnIndex == COL_NAME) { 412 LocalVirtualMachine vmd = vmModel.vmAt(rowIndex); 413 tip = vmd.toString(); 414 } 415 return tip; 416 } 417 418 public TableCellRenderer getCellRenderer(int row, int column) { 419 return new DefaultTableCellRenderer() { 420 public Component getTableCellRendererComponent(JTable table, 421 Object value, 422 boolean isSelected, 423 boolean hasFocus, 424 int row, 425 int column) { 426 Component comp = 427 super.getTableCellRendererComponent(table, value, isSelected, 428 hasFocus, row, column); 429 430 if (!isSelected) { 431 LocalVirtualMachine lvm = vmModel.vmAt(row); 432 if (!lvm.isManageable() && !lvm.isAttachable()) { 433 comp.setForeground(disabledTableCellColor); 434 } 435 } 436 437 if (comp instanceof JLabel) { 438 JLabel label = (JLabel)comp; 439 label.setBorder(rendererBorder); 440 441 if (value instanceof Integer) { 442 label.setHorizontalAlignment(JLabel.RIGHT); 443 } 444 } 445 446 return comp; 447 } 448 }; 449 } 450 } 451 452 public void setConnectionParameters(String url, 453 String host, 454 int port, 455 String userName, 456 String password, 457 String msg) { 458 if ((url != null && url.length() > 0) || 459 (host != null && host.length() > 0 && port > 0)) { 460 461 remoteRadioButton.setSelected(true); 462 if (url != null && url.length() > 0) { 463 remoteTF.setText(url); 464 } else { 465 remoteTF.setText(host+":"+port); 466 } 467 userNameTF.setText((userName != null) ? userName : ""); 468 passwordTF.setText((password != null) ? password : ""); 469 470 statusBar.setText((msg != null) ? msg : ""); 471 if (getPreferredSize().width > getWidth()) { 472 pack(); 473 } 474 remoteTF.requestFocus(); 475 remoteTF.selectAll(); 476 } 477 } 478 479 480 public void itemStateChanged(ItemEvent ev) { 481 if (!localRadioButton.isSelected()) { 482 vmTable.getSelectionModel().clearSelection(); 483 } 484 updateButtonStates(); 485 } 486 487 private void updateButtonStates() { 488 boolean connectEnabled = false; 489 490 if (remoteRadioButton.isSelected()) { 491 connectEnabled = JConsole.isValidRemoteString(remoteTF.getText()); 492 } else if (localRadioButton != null && localRadioButton.isSelected()) { 493 int row = vmTable.getSelectedRow(); 494 if (row >= 0) { 495 LocalVirtualMachine lvm = vmModel.vmAt(row); 496 connectEnabled = (lvm.isManageable() || lvm.isAttachable()); 497 } 498 } 499 500 connectAction.setEnabled(connectEnabled); 501 } 502 503 public void insertUpdate(DocumentEvent e) { 504 updateButtonStates(); 505 } 506 507 public void removeUpdate(DocumentEvent e) { 508 updateButtonStates(); 509 } 510 511 public void changedUpdate(DocumentEvent e) { 512 updateButtonStates(); 513 } 514 515 public void focusGained(FocusEvent e) { 516 Object source = e.getSource(); 517 Component opposite = e.getOppositeComponent(); 518 519 if (!e.isTemporary() && 520 source instanceof JTextField && 521 opposite instanceof JComponent && 522 SwingUtilities.getRootPane(opposite) == getRootPane()) { 523 524 ((JTextField)source).selectAll(); 525 } 526 527 if (source == remoteTF) { 528 remoteRadioButton.setSelected(true); 529 } else if (source == vmTable) { 530 localRadioButton.setSelected(true); 531 if (vmModel.getRowCount() == 1) { 532 // if there's only one process then select the row 533 vmTable.setRowSelectionInterval(0, 0); 534 } 535 } 536 updateButtonStates(); 537 } 538 539 public void focusLost(FocusEvent e) { 540 } 541 542 public void keyTyped(KeyEvent e) { 543 char c = e.getKeyChar(); 544 if (c == KeyEvent.VK_ESCAPE) { 545 setVisible(false); 546 } else if (!(Character.isDigit(c) || 547 c == KeyEvent.VK_BACK_SPACE || 548 c == KeyEvent.VK_DELETE)) { 549 getToolkit().beep(); 550 e.consume(); 551 } 552 } 553 554 public void setVisible(boolean b) { 555 boolean wasVisible = isVisible(); 556 super.setVisible(b); 557 if (b && !wasVisible) { 558 SwingUtilities.invokeLater(new Runnable() { 559 public void run() { 560 if (remoteRadioButton.isSelected()) { 561 remoteTF.requestFocus(); 562 remoteTF.selectAll(); 563 } 564 } 565 }); 566 } 567 } 568 569 public void keyPressed(KeyEvent e) { 570 } 571 572 public void keyReleased(KeyEvent e) { 573 } 574 575 576 // ListSelectionListener interface 577 public void valueChanged(ListSelectionEvent e) { 578 updateButtonStates(); 579 String labelText = " "; // Non-empty to reserve vertical space 580 int row = vmTable.getSelectedRow(); 581 if (row >= 0) { 582 LocalVirtualMachine lvm = vmModel.vmAt(row); 583 if (!lvm.isManageable()) { 584 if (lvm.isAttachable()) { 585 labelText = Messages.MANAGEMENT_WILL_BE_ENABLED; 586 } else { 587 labelText = Messages.MANAGEMENT_NOT_ENABLED; 588 } 589 } 590 } 591 String colorStr = 592 String.format("%06x", hintTextColor.getRGB() & 0xFFFFFF); 593 localMessageLabel.setText("<html><font color=#" + colorStr + ">" + labelText); 594 } 595 // ---- 596 597 598 // Refresh the list of managed VMs 599 public void refresh() { 600 if (vmModel != null) { 601 // Remember selection 602 LocalVirtualMachine selected = null; 603 int row = vmTable.getSelectedRow(); 604 if (row >= 0) { 605 selected = vmModel.vmAt(row); 606 } 607 608 vmModel.refresh(); 609 610 int selectRow = -1; 611 int n = vmModel.getRowCount(); 612 if (selected != null) { 613 for (int i = 0; i < n; i++) { 614 LocalVirtualMachine lvm = vmModel.vmAt(i); 615 if (selected.vmid() == lvm.vmid() && 616 selected.toString().equals(lvm.toString())) { 617 618 selectRow = i; 619 break; 620 } 621 } 622 } 623 if (selectRow > -1) { 624 vmTable.setRowSelectionInterval(selectRow, selectRow); 625 } else { 626 vmTable.getSelectionModel().clearSelection(); 627 } 628 629 Dimension dim = vmTable.getPreferredSize(); 630 631 // Tricky. Reduce height by one to avoid double line at bottom, 632 // but that causes a scroll bar to appear, so remove it. 633 dim.height = Math.min(dim.height-1, 100); 634 localTableScrollPane.setVerticalScrollBarPolicy((dim.height < 100) 635 ? JScrollPane.VERTICAL_SCROLLBAR_NEVER 636 : JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); 637 localTableScrollPane.getViewport().setMinimumSize(dim); 638 localTableScrollPane.getViewport().setPreferredSize(dim); 639 } 640 pack(); 641 setLocationRelativeTo(jConsole); 642 } 643 644 // Represents the list of managed VMs as a tabular data model. 645 private static class ManagedVmTableModel extends AbstractTableModel { 646 private static String[] columnNames = { 647 Messages.COLUMN_NAME, 648 Messages.COLUMN_PID, 649 }; 650 651 private List<LocalVirtualMachine> vmList; 652 653 public int getColumnCount() { 654 return columnNames.length; 655 } 656 657 public String getColumnName(int col) { 658 return columnNames[col]; 659 } 660 661 public synchronized int getRowCount() { 662 return vmList.size(); 663 } 664 665 public synchronized Object getValueAt(int row, int col) { 666 assert col >= 0 && col <= columnNames.length; 667 LocalVirtualMachine vm = vmList.get(row); 668 switch (col) { 669 case COL_NAME: return vm.displayName(); 670 case COL_PID: return vm.vmid(); 671 default: return null; 672 } 673 } 674 675 public Class<?> getColumnClass(int column) { 676 switch (column) { 677 case COL_NAME: return String.class; 678 case COL_PID: return Integer.class; 679 default: return super.getColumnClass(column); 680 } 681 } 682 683 public ManagedVmTableModel() { 684 refresh(); 685 } 686 687 688 public synchronized LocalVirtualMachine vmAt(int pos) { 689 return vmList.get(pos); 690 } 691 692 public synchronized void refresh() { 693 Map<Integer, LocalVirtualMachine> map = 694 LocalVirtualMachine.getAllVirtualMachines(); 695 vmList = new ArrayList<LocalVirtualMachine>(); 696 vmList.addAll(map.values()); 697 698 // data has changed 699 fireTableDataChanged(); 700 } 701 } 702 703 // A blank component that takes up as much space as the 704 // button part of a JRadioButton. 705 private static class Padder extends JPanel { 706 JRadioButton radioButton; 707 708 Padder(JRadioButton radioButton) { 709 this.radioButton = radioButton; 710 711 setAccessibleName(this, Messages.BLANK); 712 } 713 714 public Dimension getPreferredSize() { 715 Rectangle r = getTextRectangle(radioButton); 716 int w = (r != null && r.x > 8) ? r.x : 22; 717 718 return new Dimension(w, 0); 719 } 720 721 private static Rectangle getTextRectangle(AbstractButton button) { 722 String text = button.getText(); 723 Icon icon = (button.isEnabled()) ? button.getIcon() : button.getDisabledIcon(); 724 725 if (icon == null && button.getUI() instanceof BasicRadioButtonUI) { 726 icon = ((BasicRadioButtonUI)button.getUI()).getDefaultIcon(); 727 } 728 729 if ((icon == null) && (text == null)) { 730 return null; 731 } 732 733 Rectangle paintIconR = new Rectangle(); 734 Rectangle paintTextR = new Rectangle(); 735 Rectangle paintViewR = new Rectangle(); 736 Insets paintViewInsets = new Insets(0, 0, 0, 0); 737 738 paintViewInsets = button.getInsets(paintViewInsets); 739 paintViewR.x = paintViewInsets.left; 740 paintViewR.y = paintViewInsets.top; 741 paintViewR.width = button.getWidth() - (paintViewInsets.left + paintViewInsets.right); 742 paintViewR.height = button.getHeight() - (paintViewInsets.top + paintViewInsets.bottom); 743 744 Graphics g = button.getGraphics(); 745 if (g == null) { 746 return null; 747 } 748 SwingUtilities.layoutCompoundLabel(button, 749 g.getFontMetrics(), 750 text, 751 icon, 752 button.getVerticalAlignment(), 753 button.getHorizontalAlignment(), 754 button.getVerticalTextPosition(), 755 button.getHorizontalTextPosition(), 756 paintViewR, 757 paintIconR, 758 paintTextR, 759 button.getIconTextGap()); 760 761 return paintTextR; 762 } 763 } 764 765 }