1 19 20 21 package org.netbeans.modules.progress.ui; 22 import java.awt.AWTEvent ; 23 import java.awt.Component ; 24 import java.awt.Container ; 25 import java.awt.Cursor ; 26 import java.awt.Dimension ; 27 import java.awt.FlowLayout ; 28 import java.awt.Frame ; 29 import java.awt.Graphics ; 30 import java.awt.Image ; 31 import java.awt.Point ; 32 import java.awt.Rectangle ; 33 import java.awt.Toolkit ; 34 import java.awt.event.AWTEventListener ; 35 import java.awt.event.ActionEvent ; 36 import java.awt.event.ComponentAdapter ; 37 import java.awt.event.ComponentEvent ; 38 import java.awt.event.KeyEvent ; 39 import java.awt.event.MouseAdapter ; 40 import java.awt.event.MouseEvent ; 41 import java.awt.event.MouseListener ; 42 import java.awt.event.WindowEvent ; 43 import java.awt.event.WindowStateListener ; 44 import java.util.HashMap ; 45 import java.util.Map ; 46 import javax.swing.AbstractAction ; 47 import javax.swing.Action ; 48 import javax.swing.BorderFactory ; 49 import javax.swing.Icon ; 50 import javax.swing.ImageIcon ; 51 import javax.swing.JButton ; 52 import javax.swing.JComponent ; 53 import javax.swing.JLabel ; 54 import javax.swing.JPanel ; 55 import javax.swing.JPopupMenu ; 56 import javax.swing.JSeparator ; 57 import javax.swing.JWindow ; 58 import javax.swing.KeyStroke ; 59 import javax.swing.Popup ; 60 import javax.swing.SwingUtilities ; 61 import javax.swing.UIManager ; 62 import javax.swing.event.ListDataEvent ; 63 import javax.swing.event.ListDataListener ; 64 import javax.swing.event.ListSelectionEvent ; 65 import javax.swing.event.ListSelectionListener ; 66 import org.netbeans.progress.spi.InternalHandle; 67 import org.netbeans.progress.spi.ProgressEvent; 68 import org.netbeans.progress.module.ProgressListAction; 69 import org.netbeans.progress.spi.ProgressUIWorkerWithModel; 70 import org.netbeans.progress.spi.TaskModel; 71 import org.openide.DialogDisplayer; 72 import org.openide.NotifyDescriptor; 73 import org.openide.util.NbBundle; 74 import org.openide.util.Utilities; 75 import org.openide.windows.WindowManager; 76 77 78 82 public class StatusLineComponent extends JPanel implements ProgressUIWorkerWithModel { 83 private NbProgressBar bar; 84 private JLabel label; 85 private JSeparator separator; 86 private InternalHandle handle; 87 private boolean showingPopup = false; 88 private TaskModel model; 89 private MouseListener mouseListener; 90 private HideAWTListener hideListener; 91 private Popup popup; 92 private JWindow popupWindow; 93 private PopupPane pane; 94 private Map <InternalHandle, ListComponent> handleComponentMap; 95 private final int prefferedHeight; 96 private JButton closeButton; 97 98 public StatusLineComponent() { 99 handleComponentMap = new HashMap <InternalHandle, ListComponent>(); 100 FlowLayout flay = new FlowLayout (); 101 flay.setVgap(1); 102 flay.setHgap(5); 103 setLayout(flay); 104 mouseListener = new MListener(); 105 addMouseListener(mouseListener); 106 hideListener = new HideAWTListener(); 107 108 createLabel(); 109 createBar(); 110 bar.setStringPainted(true); 112 bar.setString("XXX"); 113 label.setText("XXX"); 114 prefferedHeight = Math.max(label.getPreferredSize().height, bar.getPreferredSize().height) + 2; 115 116 discardLabel(); 117 discardBar(); 118 119 pane = new PopupPane(); 120 pane.getActionMap().put("HidePopup", new AbstractAction () { 121 public void actionPerformed(ActionEvent actionEvent) { 122 hidePopup(); 124 } 125 }); 126 pane.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "HidePopup"); 127 pane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "HidePopup"); 128 129 130 } 131 132 private void createLabel() { 133 discardLabel(); 134 label = new JLabel (); 135 label.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); 136 label.addMouseListener(mouseListener); 137 } 138 139 private void discardLabel() { 140 if (label != null) { 141 label.removeMouseListener(mouseListener); 142 label = null; 143 } 144 } 145 private void createBar() { 146 discardBar(); 147 bar = new NbProgressBar(); 148 bar.setUseInStatusBar(true); 149 bar.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); 150 bar.addMouseListener(mouseListener); 156 157 } 158 159 private void discardBar() { 160 if (bar != null) { 161 bar.removeMouseListener(mouseListener); 162 bar = null; 163 } 164 } 165 166 private void createCloseButton() { 167 discardCloseButton(); 168 closeButton = new JButton (); 169 closeButton.setBorderPainted(false); 170 closeButton.setBorder(BorderFactory.createEmptyBorder()); 171 closeButton.setOpaque(false); 172 closeButton.setContentAreaFilled(false); 173 174 Image img = (Image )UIManager.get("nb.progress.cancel.icon"); 175 if( null != img ) { 176 closeButton.setIcon( new ImageIcon ( img ) ); 177 } 178 img = (Image )UIManager.get("nb.progress.cancel.icon.mouseover"); 179 if( null != img ) { 180 closeButton.setRolloverEnabled(true); 181 closeButton.setRolloverIcon( new ImageIcon ( img ) ); 182 } 183 img = (Image )UIManager.get("nb.progress.cancel.icon.pressed"); 184 if( null != img ) { 185 closeButton.setPressedIcon( new ImageIcon ( img ) ); 186 } 187 closeButton.setToolTipText(NbBundle.getMessage(ListComponent.class, "ListComponent.btnClose.tooltip")); 188 } 189 190 private void discardCloseButton() { 191 closeButton = null; 192 } 193 194 private void createSeparator() { 195 discardSeparator(); 196 separator = new JSeparator (JSeparator.VERTICAL); 197 separator.setBorder(BorderFactory.createEmptyBorder(1, 0, 2, 0)); 199 } 200 201 private void discardSeparator() { 202 separator = null; 203 } 204 205 public Dimension getPreferredSize() { 206 Dimension retValue; 207 retValue = super.getPreferredSize(); 208 retValue.height = prefferedHeight; 209 return retValue; 210 } 211 212 public Dimension getMinimumSize() { 213 Dimension retValue; 214 retValue = super.getMinimumSize(); 215 retValue.height = prefferedHeight; 216 return retValue; 217 } 218 219 public Dimension getMaximumSize() { 220 Dimension retValue; 221 retValue = super.getMaximumSize(); 222 retValue.height = prefferedHeight; 223 return retValue; 224 } 225 226 public void setModel(TaskModel mod) { 227 model = mod; 228 model.addListDataListener(new Listener ()); 229 model.addListSelectionListener(new ListSelectionListener () { 230 public void valueChanged(ListSelectionEvent e) { 231 pane.updateBoldFont(model.getSelectedHandle()); 232 } 233 }); 234 } 235 236 private void setTooltipForAll() { 237 int size = model.getSize(); 238 String key = "NbProgressBar.tooltip1"; if (size == 1) { 240 key = "NbProgressBar.tooltip2"; } 242 String text = NbBundle.getMessage(StatusLineComponent.class, key, new Integer (size)); 243 setToolTipText(text); 244 if (label != null) { 245 label.setToolTipText(text); 246 } 247 if (bar != null) { 248 bar.setToolTipText(text); 249 } 250 } 251 252 public void processProgressEvent(ProgressEvent event) { 253 if (event.getType() == ProgressEvent.TYPE_START) { 254 createListItem(event.getSource()); 255 } else if (event.getType() == ProgressEvent.TYPE_PROGRESS || 256 event.getType() == ProgressEvent.TYPE_SWITCH || 257 event.getType() == ProgressEvent.TYPE_SILENT) { 258 ListComponent comp = (ListComponent)handleComponentMap.get(event.getSource()); 259 if (comp == null) { 260 createListItem(event.getSource()); 261 comp = (ListComponent)handleComponentMap.get(event.getSource()); 262 } 263 comp.processProgressEvent(event); 264 } else if (event.getType() == ProgressEvent.TYPE_FINISH) { 265 removeListItem(event.getSource()); 266 if (model.getSelectedHandle() != null && handle != model.getSelectedHandle()) { 267 ProgressEvent snap = model.getSelectedHandle().requestStateSnapshot(); 268 initiateComponent(snap); 269 if (snap.getSource().isInSleepMode()) { 270 bar.setString(snap.getMessage()); 271 } 272 273 } 274 } 275 276 } 277 278 public void processSelectedProgressEvent(ProgressEvent event) { 279 if (event.getType() == ProgressEvent.TYPE_START) { 280 initiateComponent(event); 281 return; 282 } else if (event.getType() == ProgressEvent.TYPE_FINISH) { 283 hidePopup(); 285 removeAll(); 286 discardSeparator(); 287 discardCloseButton(); 288 discardBar(); 289 discardLabel(); 290 revalidate(); 292 repaint(); 293 return; 294 } else { 295 if (event.getSource() != handle || event.isSwitched() || 296 event.getType() == ProgressEvent.TYPE_SILENT || 297 (event.getSource().isInSleepMode() != (bar.getClientProperty(NbProgressBar.SLEEPY) != null))) { initiateComponent(event); 300 } 301 if (event.getWorkunitsDone() > 0) { 302 bar.setValue(event.getWorkunitsDone()); 303 } 304 bar.setString(getBarString(event.getPercentageDone(), event.getEstimatedCompletion())); 305 if (event.getDisplayName() != null) { 306 label.setText(event.getDisplayName()); 307 } 308 if (event.getSource().isInSleepMode()) { 309 bar.setString(event.getMessage()); 310 } 311 312 } 313 } 314 315 static String formatEstimate(long estimate) { 316 long minutes = estimate / 60; 317 long seconds = estimate - (minutes * 60); 318 return "" + minutes + (seconds < 10 ? ":0" : ":") + seconds; 319 } 320 321 static String getBarString(int percentage, long estimatedCompletion) { 322 if (estimatedCompletion != -1) { 323 return formatEstimate(estimatedCompletion); 324 } 325 if (percentage != -1) { 326 return "" + percentage + "%"; 327 } 328 return ""; 329 } 330 331 private void initiateComponent(ProgressEvent event) { 332 handle = event.getSource(); 333 boolean toShow = false; 334 if (label == null) { 335 createLabel(); 336 add(label); 337 toShow = true; 338 label.setToolTipText(getToolTipText()); 339 } 340 label.setText(handle.getDisplayName()); 341 342 if (bar == null) { 343 createBar(); 344 add(bar); 345 toShow = true; 346 bar.setToolTipText(getToolTipText()); 347 348 } 349 NbProgressBar.setupBar(event.getSource(), bar); 350 351 if (closeButton == null) { 352 createCloseButton(); 353 add(closeButton); 354 toShow = true; 355 } 356 if (separator == null) { 357 createSeparator(); 358 add(separator); 359 toShow = true; 360 } 361 if (handle.isAllowCancel()) { 362 closeButton.setAction(new CancelAction(false)); 363 } else { 364 closeButton.setAction(new EmptyCancelAction()); 365 } 366 if (toShow) { 367 revalidate(); 368 repaint(); 369 } 370 } 371 372 private class Listener implements ListDataListener { 373 public void intervalAdded(ListDataEvent e) { 374 setTooltipForAll(); 375 } 376 377 public void intervalRemoved(ListDataEvent e) { 378 setTooltipForAll(); 379 } 380 381 382 public void contentsChanged(ListDataEvent e) { 383 setTooltipForAll(); 384 } 385 } 386 387 public void hidePopup() { 388 if (popupWindow != null) { 389 popupWindow.setVisible(false); 391 } 392 Toolkit.getDefaultToolkit().removeAWTEventListener(hideListener); 393 WindowManager.getDefault().getMainWindow().removeWindowStateListener(hideListener); 394 WindowManager.getDefault().getMainWindow().removeComponentListener(hideListener); 395 showingPopup = false; 396 } 397 398 private void createListItem(InternalHandle handle) { 399 ListComponent comp; 400 if (handleComponentMap.containsKey(handle)) { 401 comp = handleComponentMap.get(handle); 404 } else { 405 comp = new ListComponent(handle); 406 handleComponentMap.put(handle, comp); 407 } 408 pane.addListComponent(comp); 409 pane.updateBoldFont(model.getSelectedHandle()); 410 if (showingPopup) { 411 resizePopup(); 412 } 413 } 414 415 private void removeListItem(InternalHandle handle) { 416 handleComponentMap.remove(handle); 417 pane.removeListComponent(handle); 418 pane.updateBoldFont(model.getSelectedHandle()); 419 if (showingPopup) { 420 resizePopup(); 421 } 422 } 423 424 425 public void showPopup() { 426 if (showingPopup) { 427 return; 428 } 429 InternalHandle[] handles = model.getHandles(); 430 if (handles.length == 0) { 431 return; 433 } 434 showingPopup = true; 435 436 if (popupWindow == null) { 441 popupWindow = new JWindow (WindowManager.getDefault().getMainWindow()); 442 popupWindow.getContentPane().add(pane); 443 } 444 Toolkit.getDefaultToolkit().addAWTEventListener(hideListener, AWTEvent.MOUSE_EVENT_MASK); 445 WindowManager.getDefault().getMainWindow().addWindowStateListener(hideListener); 446 WindowManager.getDefault().getMainWindow().addComponentListener(hideListener); 447 resizePopup(); 448 popupWindow.setVisible(true); 449 pane.requestFocus(); 450 } 452 453 private void resizePopup() { 454 popupWindow.pack(); 455 Point point = new Point (0,0); 456 SwingUtilities.convertPointToScreen(point, this); 457 Dimension dim = popupWindow.getSize(); 458 Rectangle usableRect = Utilities.getUsableScreenBounds(); 460 Point loc = new Point (point.x + this.getSize().width - dim.width - separator.getSize().width - 5 * 2 , point.y - dim.height - 5); 461 if (! usableRect.contains(loc)) { 463 loc = new Point (loc.x, point.y + 5 + this.getSize().height); 464 } 465 popupWindow.setLocation(loc); 468 } 471 472 private class HideAWTListener extends ComponentAdapter implements AWTEventListener , WindowStateListener { 473 public void eventDispatched(java.awt.AWTEvent aWTEvent) { 474 if (aWTEvent instanceof MouseEvent ) { 475 MouseEvent mv = (MouseEvent )aWTEvent; 476 if (mv.getClickCount() > 0) { 477 Component comp = (Component )aWTEvent.getSource(); 478 Container par = SwingUtilities.getAncestorNamed("progresspopup", comp); Container barpar = SwingUtilities.getAncestorOfClass(StatusLineComponent.class, comp); 480 if (par == null && barpar == null) { 481 hidePopup(); 482 } 483 } 484 } 485 } 486 487 public void windowStateChanged(WindowEvent windowEvent) { 488 if (showingPopup) { 489 int oldState = windowEvent.getOldState(); 490 int newState = windowEvent.getNewState(); 491 492 if (((oldState & Frame.ICONIFIED) == 0) && 493 ((newState & Frame.ICONIFIED) == Frame.ICONIFIED)) { 494 hidePopup(); 495 } 499 } 500 501 } 502 503 public void componentResized(ComponentEvent evt) { 504 if (showingPopup) { 505 resizePopup(); 506 } 507 } 508 509 public void componentMoved(ComponentEvent evt) { 510 if (showingPopup) { 511 resizePopup(); 512 } 513 } 514 515 } 516 517 private class MListener extends MouseAdapter { 518 public void mouseClicked(java.awt.event.MouseEvent e) { 519 if (e.getButton() != MouseEvent.BUTTON1) { 520 showMenu(e); 521 } else { 522 if (showingPopup) { 523 hidePopup(); 524 } else { 525 showPopup(); 526 } 527 } 528 } 529 530 } 531 532 private void showMenu(MouseEvent e) { 533 JPopupMenu popup = new JPopupMenu (); 534 popup.add(new ProgressListAction(NbBundle.getMessage(StatusLineComponent.class, "StatusLineComponent.ShowProcessList"))); 535 popup.add(new ViewAction()); 536 popup.add(new CancelAction(true)); 537 popup.show((Component )e.getSource(), e.getX(), e.getY()); 538 } 539 540 private class CancelAction extends AbstractAction { 541 public CancelAction(boolean text) { 542 if (text) { 543 putValue(Action.NAME, NbBundle.getMessage(StatusLineComponent.class, "StatusLineComponent.Cancel")); 544 } else { 545 Image icon = (Image )UIManager.get("nb.progress.cancel.icon"); 546 if (icon == null) { 547 icon = Utilities.loadImage("org/netbeans/progress/module/resources/buton.png"); 549 } 550 putValue(Action.SMALL_ICON, new ImageIcon (icon)); 551 } 552 setEnabled(handle == null ? false : handle.isAllowCancel()); 553 } 554 public void actionPerformed(ActionEvent actionEvent) { 555 InternalHandle hndl = handle; 556 if (hndl !=null && hndl.getState() == InternalHandle.STATE_RUNNING) { 557 String message = NbBundle.getMessage(StatusLineComponent.class, "Cancel_Question", handle.getDisplayName()); 558 String title = NbBundle.getMessage(StatusLineComponent.class, "Cancel_Question_Title"); 559 NotifyDescriptor dd = new NotifyDescriptor(message, title, 560 NotifyDescriptor.YES_NO_OPTION, 561 NotifyDescriptor.QUESTION_MESSAGE, null, null); 562 Object retType = DialogDisplayer.getDefault().notify(dd); 563 if (retType == NotifyDescriptor.YES_OPTION && hndl.getState() == InternalHandle.STATE_RUNNING) { 564 hndl.requestCancel(); 565 } 566 } 567 } 568 } 569 570 private class ViewAction extends AbstractAction { 571 public ViewAction() { 572 putValue(Action.NAME, NbBundle.getMessage(StatusLineComponent.class, "StatusLineComponent.View")); 573 setEnabled(handle == null ? false : handle.isAllowView()); 574 575 } 576 public void actionPerformed(ActionEvent actionEvent) { 577 if (handle != null) { 578 handle.requestView(); 579 } 580 } 581 } 582 583 584 private class EmptyCancelAction extends AbstractAction { 585 public EmptyCancelAction() { 586 setEnabled(false); 587 putValue(Action.SMALL_ICON, new Icon () { 588 public int getIconHeight() { 589 return 12; 590 } 591 public int getIconWidth() { 592 return 12; 593 } 594 public void paintIcon(Component c, Graphics g, int x, int y) { 595 } 596 }); 597 putValue(Action.NAME, ""); 598 } 599 600 public void actionPerformed(ActionEvent e) { 601 } 602 } 603 604 } 605 | Popular Tags |