|
1 /* |
|
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 |
|
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 import java.net.MalformedURLException; |
|
33 import java.io.IOException; |
|
34 |
|
35 import javax.accessibility.*; |
|
36 import javax.swing.*; |
|
37 import javax.swing.Timer; |
|
38 import javax.swing.border.*; |
|
39 import javax.swing.event.*; |
|
40 import javax.swing.plaf.basic.BasicRadioButtonUI; |
|
41 import javax.swing.table.*; |
|
42 |
|
43 import javax.management.remote.JMXServiceURL; |
|
44 import javax.management.remote.JMXConnector; |
|
45 |
|
46 import static java.awt.BorderLayout.*; |
|
47 import static javax.swing.ListSelectionModel.*; |
|
48 import static sun.tools.jconsole.Resources.*; |
|
49 import static sun.tools.jconsole.Utilities.*; |
|
50 |
|
51 @SuppressWarnings("serial") |
|
52 public 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 } |