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