KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > progress > ui > StatusLineComponent


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20
21 package org.netbeans.modules.progress.ui;
22 import java.awt.AWTEvent JavaDoc;
23 import java.awt.Component JavaDoc;
24 import java.awt.Container JavaDoc;
25 import java.awt.Cursor JavaDoc;
26 import java.awt.Dimension JavaDoc;
27 import java.awt.FlowLayout JavaDoc;
28 import java.awt.Frame JavaDoc;
29 import java.awt.Graphics JavaDoc;
30 import java.awt.Image JavaDoc;
31 import java.awt.Point JavaDoc;
32 import java.awt.Rectangle JavaDoc;
33 import java.awt.Toolkit JavaDoc;
34 import java.awt.event.AWTEventListener JavaDoc;
35 import java.awt.event.ActionEvent JavaDoc;
36 import java.awt.event.ComponentAdapter JavaDoc;
37 import java.awt.event.ComponentEvent JavaDoc;
38 import java.awt.event.KeyEvent JavaDoc;
39 import java.awt.event.MouseAdapter JavaDoc;
40 import java.awt.event.MouseEvent JavaDoc;
41 import java.awt.event.MouseListener JavaDoc;
42 import java.awt.event.WindowEvent JavaDoc;
43 import java.awt.event.WindowStateListener JavaDoc;
44 import java.util.HashMap JavaDoc;
45 import java.util.Map JavaDoc;
46 import javax.swing.AbstractAction JavaDoc;
47 import javax.swing.Action JavaDoc;
48 import javax.swing.BorderFactory JavaDoc;
49 import javax.swing.Icon JavaDoc;
50 import javax.swing.ImageIcon JavaDoc;
51 import javax.swing.JButton JavaDoc;
52 import javax.swing.JComponent JavaDoc;
53 import javax.swing.JLabel JavaDoc;
54 import javax.swing.JPanel JavaDoc;
55 import javax.swing.JPopupMenu JavaDoc;
56 import javax.swing.JSeparator JavaDoc;
57 import javax.swing.JWindow JavaDoc;
58 import javax.swing.KeyStroke JavaDoc;
59 import javax.swing.Popup JavaDoc;
60 import javax.swing.SwingUtilities JavaDoc;
61 import javax.swing.UIManager JavaDoc;
62 import javax.swing.event.ListDataEvent JavaDoc;
63 import javax.swing.event.ListDataListener JavaDoc;
64 import javax.swing.event.ListSelectionEvent JavaDoc;
65 import javax.swing.event.ListSelectionListener JavaDoc;
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 /**
79  *
80  * @author Milos Kleint (mkleint@netbeans.org)
81  */

82 public class StatusLineComponent extends JPanel JavaDoc implements ProgressUIWorkerWithModel {
83     private NbProgressBar bar;
84     private JLabel JavaDoc label;
85     private JSeparator JavaDoc separator;
86     private InternalHandle handle;
87     private boolean showingPopup = false;
88     private TaskModel model;
89     private MouseListener JavaDoc mouseListener;
90     private HideAWTListener hideListener;
91     private Popup JavaDoc popup;
92     private JWindow JavaDoc popupWindow;
93     private PopupPane pane;
94     private Map JavaDoc<InternalHandle, ListComponent> handleComponentMap;
95     private final int prefferedHeight;
96     private JButton JavaDoc closeButton;
97     /** Creates a new instance of StatusLineComponent */
98     public StatusLineComponent() {
99         handleComponentMap = new HashMap JavaDoc<InternalHandle, ListComponent>();
100         FlowLayout JavaDoc flay = new FlowLayout JavaDoc();
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         // tricks to figure out correct height.
111
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 JavaDoc() {
121             public void actionPerformed(ActionEvent JavaDoc actionEvent) {
122 // System.out.println("escape pressed - hiding");
123
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 JavaDoc();
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 // setBorder(BorderFactory.createLineBorder(Color.BLUE, 1));
151
// HACK - put smaller font inside the progress bar to keep
152
// the height of the progressbar constant for determinate and indeterminate bars
153
// Font fnt = UIManager.getFont("ProgressBar.font");
154
// bar.setFont(fnt.deriveFont(fnt.getStyle(), fnt.getSize() - 3));
155
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 JavaDoc();
169         closeButton.setBorderPainted(false);
170         closeButton.setBorder(BorderFactory.createEmptyBorder());
171         closeButton.setOpaque(false);
172         closeButton.setContentAreaFilled(false);
173         
174         Image JavaDoc img = (Image JavaDoc)UIManager.get("nb.progress.cancel.icon");
175         if( null != img ) {
176             closeButton.setIcon( new ImageIcon JavaDoc( img ) );
177         }
178         img = (Image JavaDoc)UIManager.get("nb.progress.cancel.icon.mouseover");
179         if( null != img ) {
180             closeButton.setRolloverEnabled(true);
181             closeButton.setRolloverIcon( new ImageIcon JavaDoc( img ) );
182         }
183         img = (Image JavaDoc)UIManager.get("nb.progress.cancel.icon.pressed");
184         if( null != img ) {
185             closeButton.setPressedIcon( new ImageIcon JavaDoc( 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 JavaDoc(JSeparator.VERTICAL);
197 // separator.setPreferredSize(new Dimension(5, prefferedHeight));
198
separator.setBorder(BorderFactory.createEmptyBorder(1, 0, 2, 0));
199     }
200     
201     private void discardSeparator() {
202         separator = null;
203     }
204     
205     public Dimension JavaDoc getPreferredSize() {
206         Dimension JavaDoc retValue;
207         retValue = super.getPreferredSize();
208         retValue.height = prefferedHeight;
209         return retValue;
210     }
211
212     public Dimension JavaDoc getMinimumSize() {
213         Dimension JavaDoc retValue;
214         retValue = super.getMinimumSize();
215         retValue.height = prefferedHeight;
216         return retValue;
217     }
218     
219     public Dimension JavaDoc getMaximumSize() {
220         Dimension JavaDoc 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 JavaDoc());
229         model.addListSelectionListener(new ListSelectionListener JavaDoc() {
230             public void valueChanged(ListSelectionEvent JavaDoc e) {
231                 pane.updateBoldFont(model.getSelectedHandle());
232             }
233         });
234     }
235     
236     private void setTooltipForAll() {
237         int size = model.getSize();
238         String JavaDoc key = "NbProgressBar.tooltip1"; //NOI18N
239
if (size == 1) {
240             key = "NbProgressBar.tooltip2"; //NOI18N
241
}
242         String JavaDoc text = NbBundle.getMessage(StatusLineComponent.class, key, new Integer JavaDoc(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             //happens only when there's no more handles.
284
hidePopup();
285             removeAll();
286             discardSeparator();
287             discardCloseButton();
288             discardBar();
289             discardLabel();
290             //#63393, 61940 fix - removeAll() just invalidates. seems to work without revalidate/repaint on some platforms, fail on others.
291
revalidate();
292             repaint();
293             return;
294         } else {
295             if (event.getSource() != handle || event.isSwitched() ||
296                 event.getType() == ProgressEvent.TYPE_SILENT ||
297                     // the following condition re-initiates the bar when going from/to sleep mode..
298
(event.getSource().isInSleepMode() != (bar.getClientProperty(NbProgressBar.SLEEPY) != null))) { //NIO18N
299
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 JavaDoc 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 JavaDoc 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 JavaDoc {
373         public void intervalAdded(ListDataEvent JavaDoc e) {
374             setTooltipForAll();
375         }
376         
377         public void intervalRemoved(ListDataEvent JavaDoc e) {
378             setTooltipForAll();
379         }
380         
381         
382         public void contentsChanged(ListDataEvent JavaDoc e) {
383             setTooltipForAll();
384         }
385     }
386     
387     public void hidePopup() {
388         if (popupWindow != null) {
389 // popupWindow.getContentPane().removeAll();
390
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             // happens when we click to display on popup and there is a
402
// new handle waiting in the queue.
403
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             // just in case..
432
return;
433         }
434         showingPopup = true;
435         
436         // NOT using PopupFactory
437
// 1. on linux, creates mediumweight popup taht doesn't refresh behind visible glasspane
438
// 2. on mac, needs an owner frame otherwise hiding tooltip also hides the popup. (linux requires no owner frame to force heavyweight)
439
// 3. the created window is not focusable window
440
if (popupWindow == null) {
441             popupWindow = new JWindow JavaDoc(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 // System.out.println(" window focusable=" + popupWindow.isFocusableWindow());
451
}
452     
453     private void resizePopup() {
454         popupWindow.pack();
455         Point JavaDoc point = new Point JavaDoc(0,0);
456         SwingUtilities.convertPointToScreen(point, this);
457         Dimension JavaDoc dim = popupWindow.getSize();
458         //#63265
459
Rectangle JavaDoc usableRect = Utilities.getUsableScreenBounds();
460         Point JavaDoc loc = new Point JavaDoc(point.x + this.getSize().width - dim.width - separator.getSize().width - 5 * 2 , point.y - dim.height - 5);
461         // -5 in x coordinate is becuase of the hgap between the separator and button and separator and edge
462
if (! usableRect.contains(loc)) {
463             loc = new Point JavaDoc(loc.x, point.y + 5 + this.getSize().height);
464         }
465             // +4 here because of the width of the close button in popup, we
466
// want the progress bars to align visually.. but there's separator in status now..
467
popupWindow.setLocation(loc);
468 // System.out.println("count=" + count);
469
// System.out.println("offset =" + offset);
470
}
471     
472     private class HideAWTListener extends ComponentAdapter JavaDoc implements AWTEventListener JavaDoc, WindowStateListener JavaDoc {
473         public void eventDispatched(java.awt.AWTEvent JavaDoc aWTEvent) {
474             if (aWTEvent instanceof MouseEvent JavaDoc) {
475                 MouseEvent JavaDoc mv = (MouseEvent JavaDoc)aWTEvent;
476                 if (mv.getClickCount() > 0) {
477                     Component JavaDoc comp = (Component JavaDoc)aWTEvent.getSource();
478                     Container JavaDoc par = SwingUtilities.getAncestorNamed("progresspopup", comp); //NOI18N
479
Container JavaDoc barpar = SwingUtilities.getAncestorOfClass(StatusLineComponent.class, comp);
480                     if (par == null && barpar == null) {
481                         hidePopup();
482                     }
483                 }
484             }
485         }
486
487         public void windowStateChanged(WindowEvent JavaDoc 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 // } else if (((oldState & Frame.ICONIFIED) == Frame.ICONIFIED) &&
496
// ((newState & Frame.ICONIFIED) == 0 )) {
497
// //TODO remember we showed before and show again? I guess not worth the efford, not part of spec.
498
}
499             }
500
501         }
502         
503         public void componentResized(ComponentEvent JavaDoc evt) {
504             if (showingPopup) {
505                 resizePopup();
506             }
507         }
508         
509         public void componentMoved(ComponentEvent JavaDoc evt) {
510             if (showingPopup) {
511                 resizePopup();
512             }
513         }
514         
515     }
516     
517     private class MListener extends MouseAdapter JavaDoc {
518         public void mouseClicked(java.awt.event.MouseEvent JavaDoc 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 JavaDoc e) {
533         JPopupMenu JavaDoc popup = new JPopupMenu JavaDoc();
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 JavaDoc)e.getSource(), e.getX(), e.getY());
538     }
539     
540   private class CancelAction extends AbstractAction JavaDoc {
541         public CancelAction(boolean text) {
542             if (text) {
543                 putValue(Action.NAME, NbBundle.getMessage(StatusLineComponent.class, "StatusLineComponent.Cancel"));
544             } else {
545                 Image JavaDoc icon = (Image JavaDoc)UIManager.get("nb.progress.cancel.icon");
546                 if (icon == null) {
547                        // for custom L&F?
548
icon = Utilities.loadImage("org/netbeans/progress/module/resources/buton.png");
549                 }
550                 putValue(Action.SMALL_ICON, new ImageIcon JavaDoc(icon));
551             }
552             setEnabled(handle == null ? false : handle.isAllowCancel());
553         }
554         public void actionPerformed(ActionEvent JavaDoc actionEvent) {
555             InternalHandle hndl = handle;
556             if (hndl !=null && hndl.getState() == InternalHandle.STATE_RUNNING) {
557                 String JavaDoc message = NbBundle.getMessage(StatusLineComponent.class, "Cancel_Question", handle.getDisplayName());
558                 String JavaDoc 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 JavaDoc 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 JavaDoc {
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 JavaDoc actionEvent) {
577             if (handle != null) {
578                 handle.requestView();
579             }
580         }
581     }
582     
583     
584     private class EmptyCancelAction extends AbstractAction JavaDoc {
585         public EmptyCancelAction() {
586             setEnabled(false);
587             putValue(Action.SMALL_ICON, new Icon JavaDoc() {
588                 public int getIconHeight() {
589                     return 12;
590                 }
591                 public int getIconWidth() {
592                     return 12;
593                 }
594                 public void paintIcon(Component JavaDoc c, Graphics JavaDoc g, int x, int y) {
595                 }
596             });
597             putValue(Action.NAME, "");
598         }
599
600         public void actionPerformed(ActionEvent JavaDoc e) {
601         }
602     }
603
604 }
605
Popular Tags