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