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