KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > progress > NewProgressViewer


1 /*******************************************************************************
2  * Copyright (c) 2003, 2005 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.ui.internal.progress;
12
13 import java.net.URL JavaDoc;
14 import java.text.DateFormat JavaDoc;
15 import java.util.ArrayList JavaDoc;
16 import java.util.Date JavaDoc;
17 import java.util.HashMap JavaDoc;
18 import java.util.HashSet JavaDoc;
19 import java.util.List JavaDoc;
20
21 import org.eclipse.core.runtime.IStatus;
22 import org.eclipse.core.runtime.QualifiedName;
23 import org.eclipse.core.runtime.jobs.Job;
24 import org.eclipse.jface.action.Action;
25 import org.eclipse.jface.action.IAction;
26 import org.eclipse.jface.dialogs.ErrorDialog;
27 import org.eclipse.jface.resource.ImageDescriptor;
28 import org.eclipse.jface.resource.JFaceColors;
29 import org.eclipse.jface.resource.JFaceResources;
30 import org.eclipse.jface.util.IPropertyChangeListener;
31 import org.eclipse.jface.util.PropertyChangeEvent;
32 import org.eclipse.jface.viewers.IContentProvider;
33 import org.eclipse.jface.viewers.ISelection;
34 import org.eclipse.jface.viewers.ITreeContentProvider;
35 import org.eclipse.jface.viewers.StructuredSelection;
36 import org.eclipse.jface.viewers.TreeViewer;
37 import org.eclipse.jface.viewers.ViewerSorter;
38 import org.eclipse.osgi.util.NLS;
39 import org.eclipse.swt.SWT;
40 import org.eclipse.swt.custom.ScrolledComposite;
41 import org.eclipse.swt.events.ControlAdapter;
42 import org.eclipse.swt.events.ControlEvent;
43 import org.eclipse.swt.events.SelectionAdapter;
44 import org.eclipse.swt.events.SelectionEvent;
45 import org.eclipse.swt.events.TreeListener;
46 import org.eclipse.swt.graphics.Color;
47 import org.eclipse.swt.graphics.Cursor;
48 import org.eclipse.swt.graphics.Font;
49 import org.eclipse.swt.graphics.FontData;
50 import org.eclipse.swt.graphics.FontMetrics;
51 import org.eclipse.swt.graphics.GC;
52 import org.eclipse.swt.graphics.Image;
53 import org.eclipse.swt.graphics.Point;
54 import org.eclipse.swt.graphics.Rectangle;
55 import org.eclipse.swt.widgets.Canvas;
56 import org.eclipse.swt.widgets.Composite;
57 import org.eclipse.swt.widgets.Control;
58 import org.eclipse.swt.widgets.Display;
59 import org.eclipse.swt.widgets.Event;
60 import org.eclipse.swt.widgets.Item;
61 import org.eclipse.swt.widgets.Label;
62 import org.eclipse.swt.widgets.Layout;
63 import org.eclipse.swt.widgets.Listener;
64 import org.eclipse.swt.widgets.ProgressBar;
65 import org.eclipse.swt.widgets.ToolBar;
66 import org.eclipse.swt.widgets.ToolItem;
67 import org.eclipse.swt.widgets.Tree;
68 import org.eclipse.swt.widgets.Widget;
69 import org.eclipse.ui.internal.WorkbenchImages;
70 import org.eclipse.ui.internal.misc.Assert;
71 import org.eclipse.ui.progress.IProgressConstants;
72
73 /**
74  * The NewProgressViewer is the viewer for progress using
75  * progress monitors.
76  */

77 public class NewProgressViewer extends TreeViewer implements
78         FinishedJobs.KeptJobsListener {
79
80     /*
81      * Label with hyperlink capability.
82      */

83     class Hyperlink extends JobTreeItem implements Listener,
84             IPropertyChangeListener {
85
86         final static int MARGINHEIGHT = 1;
87         final static int MARGINWIDTH = 1;
88
89         boolean foundImage;
90
91         IAction gotoAction;
92
93         boolean hasFocus;
94
95         boolean isError;
96
97         JobItem jobitem;
98
99         boolean linkEnabled;
100
101         boolean mouseOver;
102
103         IStatus result;
104
105         String JavaDoc text = ""; //$NON-NLS-1$
106

107         Hyperlink(JobItem parent, JobTreeElement info) {
108             super(parent, info, SWT.NO_BACKGROUND);
109
110             jobitem = parent;
111
112             setFont(smallerFont);
113
114             addListener(SWT.KeyDown, this);
115             addListener(SWT.Paint, this);
116             addListener(SWT.MouseEnter, this);
117             addListener(SWT.MouseExit, this);
118             addListener(SWT.MouseDown, this);
119             addListener(SWT.MouseUp, this);
120             addListener(SWT.FocusIn, this);
121             addListener(SWT.FocusOut, this);
122
123             refresh();
124         }
125
126         public Point computeSize(int wHint, int hHint, boolean changed) {
127             checkWidget();
128             int innerWidth = wHint;
129             if (innerWidth != SWT.DEFAULT)
130                 innerWidth -= MARGINWIDTH * 2;
131             GC gc = new GC(this);
132             gc.setFont(getFont());
133             Point extent = gc.textExtent(text);
134             gc.dispose();
135             return new Point(extent.x + 2 * MARGINWIDTH, extent.y + 2
136                     * MARGINHEIGHT);
137         }
138
139         private Color getFGColor() {
140             if (jobitem.selected)
141                 return selectedTextColor;
142
143             if (isLinkEnabled()) {
144                 
145                  if (isError)
146                     return getErrorColor();
147                  
148                 if (mouseOver)
149                     return getActiveHyperlinkColor();
150                 return getHyperlinkColor();
151             }
152             return textColor;
153         }
154
155         protected boolean handleActivate() {
156             if (isLinkEnabled() && gotoAction != null && gotoAction.isEnabled()) {
157                 jobitem.locked = true;
158                 gotoAction.run();
159                 if (jobitem.jobTerminated)
160                     jobitem.kill();
161                 return true;
162             }
163             return false;
164         }
165
166         public void handleEvent(Event e) {
167             super.handleEvent(e);
168             switch (e.type) {
169             case SWT.Dispose:
170                 if (gotoAction != null) {
171                     gotoAction.removePropertyChangeListener(this);
172                     gotoAction = null;
173                 }
174                 break;
175             case SWT.KeyDown:
176                 if (e.character == '\r')
177                     handleActivate();
178                 else if (e.keyCode == SWT.DEL) {
179                     cancelSelection();
180                 } else {
181                     select(null, e);
182                 }
183                 break;
184             case SWT.Paint:
185                 paint(e.gc);
186                 break;
187             case SWT.FocusIn:
188                 hasFocus = true;
189             case SWT.MouseEnter:
190                 if (isLinkEnabled()) {
191                     mouseOver = true;
192                     redraw();
193                 }
194                 break;
195             case SWT.FocusOut:
196                 hasFocus = false;
197             case SWT.MouseExit:
198                 if (isLinkEnabled()) {
199                     mouseOver = false;
200                     redraw();
201                 }
202                 break;
203             case SWT.DefaultSelection:
204                 handleActivate();
205                 break;
206             case SWT.MouseDown:
207                 if (!isLinkEnabled())
208                     select((JobItem) getParent(), e);
209                 break;
210             case SWT.MouseUp:
211                 if (isLinkEnabled()) {
212                     Point size = getSize();
213                     if (e.button != 1 || e.x < 0 || e.y < 0 || e.x >= size.x
214                             || e.y >= size.y)
215                         return;
216                     handleActivate();
217                 }
218                 break;
219             }
220         }
221
222         boolean isLinkEnabled() {
223             return !dialogContext && linkEnabled;
224         }
225
226         protected void paint(GC gc) {
227             Rectangle clientArea = getClientArea();
228             if (clientArea.isEmpty())
229                 return;
230             Color fg = getFGColor(), bg = getBackground();
231             if (jobitem.selected)
232                 bg = selectedColor;
233             Image buffer = null;
234             GC bufferGC = gc;
235             if (!isCarbon) {
236                 buffer = new Image(getDisplay(), clientArea.width,
237                         clientArea.height);
238                 buffer.setBackground(bg);
239                 bufferGC = new GC(buffer, gc.getStyle());
240             }
241             bufferGC.setForeground(fg);
242             bufferGC.setBackground(bg);
243             bufferGC.fillRectangle(0, 0, clientArea.width, clientArea.height);
244             bufferGC.setFont(getFont());
245             String JavaDoc t = shortenText(bufferGC, clientArea.width, text);
246             bufferGC.drawText(t, MARGINWIDTH, MARGINHEIGHT, true);
247             int sw = bufferGC.stringExtent(t).x;
248             if (isLinkEnabled()) {
249                 FontMetrics fm = bufferGC.getFontMetrics();
250                 int lineY = clientArea.height - MARGINHEIGHT - fm.getDescent()
251                         + 1;
252                 bufferGC.drawLine(MARGINWIDTH, lineY, MARGINWIDTH + sw, lineY);
253                 if (hasFocus)
254                     bufferGC.drawFocus(0, 0, sw, clientArea.height);
255             }
256             if (buffer != null) {
257                 gc.drawImage(buffer, 0, 0);
258                 bufferGC.dispose();
259                 buffer.dispose();
260             }
261         }
262
263         public void propertyChange(PropertyChangeEvent event) {
264             if (gotoAction != null) {
265                 getDisplay().asyncExec(new Runnable JavaDoc() {
266                     public void run() {
267                         if (!isDisposed()) {
268                             checkKeep();
269                             setLinkEnable(gotoAction != null
270                                     && gotoAction.isEnabled());
271                         }
272                     }
273                 });
274             }
275         }
276
277         public boolean refresh() {
278
279             if (jobTreeElement == null) // shouldn't happen
280
return false;
281
282             final Job job = getJob();
283             if (job != null) {
284                 // check for icon property and propagate to parent
285
if (jobitem.image == null)
286                     jobitem.updateIcon(job);
287
288                 // check for action property
289
Object JavaDoc property = job
290                         .getProperty(IProgressConstants.ACTION_PROPERTY);
291                 if (property instanceof IAction)
292                     setAction((IAction) property);
293
294                 // poll for result status
295
IStatus status = job.getResult();
296                 if (status != null && status != result) {
297                     result = status;
298                     if (result.getSeverity() == IStatus.ERROR) {
299                         setKeep();
300                         isError = true;
301                         setAction(new Action() {
302                             /*
303                              * Get the notificationManager that this is being created for.
304                              */

305                             private ErrorNotificationManager getManager() {
306                                 return ProgressManager.getInstance().errorManager;
307                             }
308                             public void run() {
309                                 String JavaDoc title = ProgressMessages.NewProgressView_errorDialogTitle;
310                                 String JavaDoc msg = ProgressMessages.NewProgressView_errorDialogMessage;
311                                 if (!getManager().showErrorFor(job, title, msg)) {
312                                     // The error is missing from the error manager.
313
// This should only occur if what the progress view is showing is
314
// out-of-sync with the ErrorNotificationManager and/or FinishedJobs
315
// manager. In other words, it shouldn't happen but may so it is
316
// better to show the user something than fail silently
317
ErrorDialog.openError(getShell(), title, msg,
318                                             result);
319                                 }
320                             }
321                         });
322                     }
323                 }
324             }
325             checkKeep();
326
327             // now build the string for displaying
328
String JavaDoc name = null;
329
330             if (jobTreeElement instanceof SubTaskInfo) { // simple job case
331

332                 SubTaskInfo sti = (SubTaskInfo) jobTreeElement;
333                 String JavaDoc taskName = null;
334                 if (sti.jobInfo != null) {
335                     TaskInfo ti = sti.jobInfo.getTaskInfo();
336                     if (ti != null)
337                         taskName = ti.getTaskName();
338                 }
339
340                 if (jobTerminated && result != null) {
341                     name = result.getMessage();
342                     if (taskName != null && taskName.trim().length() > 0)
343                         name = NLS.bind(ProgressMessages.JobInfo_TaskFormat, taskName, name);
344                 } else {
345                     name = jobTreeElement.getDisplayString();
346                     if (taskName != null && taskName.trim().length() > 0)
347                         name = NLS.bind(ProgressMessages.JobInfo_TaskFormat2, taskName, name);
348                 }
349
350                 if (name.length() == 0) {
351                     dispose();
352                     return true;
353                 }
354
355             } else if (jobTreeElement instanceof JobInfo) { // group case
356
JobInfo ji = (JobInfo) jobTreeElement;
357
358                 if (/*jobTerminated && */result != null) {
359                     name = result.getMessage();
360                     if (name == null || name.trim().length() == 0
361                             || "OK".equals(name)) { //$NON-NLS-1$
362
if (!keepItem) {
363                             dispose();
364                             return true;
365                         }
366                     }
367                 } else {
368                     // get the Job name
369
name = getJobNameAndStatus(ji, job, jobTerminated, false);
370
371                     // get percentage and task name
372
String JavaDoc taskName = null;
373                     TaskInfo info = ji.getTaskInfo();
374                     if (info != null) {
375                         taskName = info.getTaskName();
376                         int percent = info.getPercentDone();
377                         if (percent >= 0 && percent <= 100) {
378                             if (taskName != null)
379                                 taskName = NLS.bind(ProgressMessages.JobInfo_Percent,Integer.toString(percent),taskName );
380                             else
381                                 taskName = NLS.bind(ProgressMessages.JobInfo_Percent2, Integer.toString(percent) );
382                         }
383                     }
384
385                     // get sub task name
386
String JavaDoc subTaskName = null;
387                     Object JavaDoc[] subtasks = ji.getChildren();
388                     if (subtasks != null && subtasks.length > 0) {
389                         JobTreeElement sub = (JobTreeElement) subtasks[0];
390                         if (sub != null)
391                             subTaskName = sub.getDisplayString();
392                     }
393
394                     boolean hasTask = taskName != null
395                             && taskName.trim().length() > 0;
396                     boolean hasSubTask = subTaskName != null
397                             && subTaskName.trim().length() > 0;
398
399                     if (hasTask && hasSubTask) {
400                         name = NLS.bind(ProgressMessages.JobInfo_Format, (new Object JavaDoc[] { name, taskName, subTaskName }));
401                     } else if (hasTask) {
402                         name = NLS.bind(ProgressMessages.JobInfo_TaskFormat, name, taskName );
403                     } else if (hasSubTask) {
404                         name = NLS.bind(ProgressMessages.JobInfo_TaskFormat, name, subTaskName);
405                     }
406                 }
407
408                 if (highlightJob == job)
409                     highlightItem = jobitem;
410             }
411
412             if (name == null)
413                 name = jobTreeElement.getDisplayString();
414
415             setText(name);
416
417             return false;
418         }
419
420         private void setAction(IAction action) {
421             if (action == gotoAction)
422                 return;
423             if (gotoAction != null)
424                 gotoAction.removePropertyChangeListener(this);
425             gotoAction = action;
426             if (gotoAction != null) {
427
428                 // temporary workaround for CVS actionWrapper problem
429
String JavaDoc actionName = gotoAction.getClass().getName();
430                 if (actionName.indexOf("RefreshSubscriberJob$2") >= 0) //$NON-NLS-1$
431
gotoAction.setEnabled(false);
432                 // end of temporary workaround
433

434                 gotoAction.addPropertyChangeListener(this);
435             }
436             updateToolTip();
437             setLinkEnable(action != null && action.isEnabled());
438         }
439
440         private void setLinkEnable(boolean enable) {
441             if (enable != linkEnabled) {
442                 linkEnabled = enable;
443                 if (isLinkEnabled())
444                     setCursor(handCursor);
445                 updateToolTip();
446                 redraw();
447             }
448         }
449
450         private void setText(String JavaDoc t) {
451             if (t == null)
452                 t = ""; //$NON-NLS-1$
453
if (!t.equals(text)) {
454                 text = t;
455                 updateToolTip();
456                 redraw();
457             }
458         }
459
460         private void updateToolTip() {
461             String JavaDoc tt = text;
462             if (isLinkEnabled() && gotoAction != null && gotoAction.isEnabled()) {
463                 String JavaDoc tooltip = gotoAction.getToolTipText();
464                 if (tooltip != null && tooltip.trim().length() > 0)
465                     tt = tooltip;
466             }
467             String JavaDoc oldtt = getToolTipText();
468             if (oldtt == null || !oldtt.equals(tt))
469                 setToolTipText(tt);
470         }
471     }
472
473     /*
474      * An SWT widget representing a JobModel
475      */

476     class JobItem extends JobTreeItem {
477
478         static final int HGAP = 7;
479
480         static final int MARGIN = 2;
481
482         static final int MAX_PROGRESS_HEIGHT = 12;
483
484         static final int MIN_ICON_SIZE = 16;
485
486         static final int VGAP = 1;
487
488         ToolBar actionBar;
489
490         ToolItem actionButton;
491
492         int cachedHeight = -1;
493
494         int cachedWidth = -1;
495
496         private boolean disposeImage;
497
498         ToolItem gotoButton;
499
500         Label iconItem;
501
502         private Image image;
503
504         private boolean locked; // don't add children
505

506         Label nameItem;
507
508         ProgressBar progressBar;
509
510         boolean selected;
511
512         JobItem(Composite parent, JobTreeElement info) {
513             super(parent, info, SWT.NONE);
514
515             Assert.isNotNull(info);
516
517             Display display = getDisplay();
518
519             iconItem = new Label(this, SWT.NONE);
520             iconItem.addListener(SWT.MouseDown, this);
521             updateIcon(getJob());
522             if (image == null)
523                 iconItem.setImage(defaultJobIcon);
524
525             nameItem = new Label(this, SWT.NONE);
526             nameItem.setFont(boldFont);
527             nameItem.addListener(SWT.MouseDown, this);
528
529             actionBar = new ToolBar(this, SWT.FLAT);
530             actionBar.setCursor(normalCursor); // set cursor to overwrite any busy cursor we might have
531
actionButton = new ToolItem(actionBar, SWT.NONE);
532             actionButton.setImage(cancelJobIcon);
533             actionButton.setDisabledImage(cancelJobDIcon);
534             actionButton.setToolTipText(ProgressMessages.NewProgressView_CancelJobToolTip);
535             actionButton.addSelectionListener(new SelectionAdapter() {
536                 public void widgetSelected(SelectionEvent e) {
537                     actionButton.setEnabled(false);
538                     cancelOrRemove();
539                 }
540             });
541
542             addListener(SWT.MouseDown, this);
543             addListener(SWT.KeyDown, this);
544
545             addControlListener(new ControlAdapter() {
546                 public void controlResized(ControlEvent e) {
547                     handleResize();
548                 }
549             });
550
551             refresh();
552         }
553
554         private boolean aboutToKeep() {
555             boolean changed = false;
556
557             // finish progress reporting
558
if (progressBar != null && !progressBar.isDisposed()) {
559                 progressBar.setSelection(100);
560                 progressBar.dispose();
561                 changed = true;
562             }
563
564             // turn cancel button in remove button
565
if (!actionButton.isDisposed()) {
566                 actionButton.setImage(clearJobIcon);
567                 actionButton.setDisabledImage(clearJobDIcon);
568                 actionButton.setToolTipText(ProgressMessages.NewProgressView_RemoveJobToolTip);
569                 actionButton.setEnabled(true);
570                 changed = true;
571             }
572
573             changed |= refresh();
574
575             Control[] c = getChildren();
576             for (int i = 0; i < c.length; i++) {
577                 if (c[i] instanceof JobTreeItem)
578                     changed |= ((JobTreeItem) c[i]).refresh();
579             }
580
581             return changed;
582         }
583
584         boolean cancelOrRemove() {
585             if (jobTerminated)
586                 return kill();
587             jobTreeElement.cancel();
588             return false;
589         }
590
591         public Point computeSize(int wHint, int hHint, boolean changed) {
592
593             if (changed || cachedHeight <= 0 || cachedWidth <= 0) {
594                 Point e1 = iconItem.computeSize(SWT.DEFAULT, SWT.DEFAULT);
595                 e1.x = MIN_ICON_SIZE;
596                 Point e2 = nameItem.computeSize(SWT.DEFAULT, SWT.DEFAULT);
597
598                 cachedWidth = MARGIN + e1.x + HGAP + 100 + MARGIN;
599
600                 cachedHeight = MARGIN + Math.max(e1.y, e2.y);
601                 if (progressBar != null && !progressBar.isDisposed()) {
602                     cachedHeight += 1;
603                     Point e3 = progressBar
604                             .computeSize(SWT.DEFAULT, SWT.DEFAULT);
605                     e3.y = MAX_PROGRESS_HEIGHT;
606                     cachedHeight += VGAP + e3.y;
607                 }
608                 Control[] cs = getChildren();
609                 for (int i = 0; i < cs.length; i++) {
610                     if (cs[i] instanceof Hyperlink) {
611                         Point e4 = cs[i].computeSize(SWT.DEFAULT, SWT.DEFAULT);
612                         cachedHeight += VGAP + e4.y;
613                     }
614                 }
615                 cachedHeight += MARGIN;
616             }
617
618             int w = wHint == SWT.DEFAULT ? cachedWidth : wHint;
619             int h = hHint == SWT.DEFAULT ? cachedHeight : hHint;
620
621             return new Point(w, h);
622         }
623
624         void createChild(JobTreeElement jte) {
625             if (!locked)
626                 new Hyperlink(this, jte);
627         }
628
629         private String JavaDoc getGroupHeader(GroupInfo gi) {
630             String JavaDoc name = stripPercent(jobTreeElement.getDisplayString());
631             if (jobTerminated)
632                 return getFinishedString(gi, name, true);
633             return name;
634         }
635
636         IStatus getResult() {
637             //checkKeep();
638
if (jobTerminated) {
639                 Job job = getJob();
640                 if (job != null)
641                     return job.getResult();
642             }
643             return null;
644         }
645
646         public void handleEvent(Event event) {
647             switch (event.type) {
648             case SWT.Dispose:
649                 super.handleEvent(event);
650                 if (disposeImage && image != null && !image.isDisposed()) {
651                     if (DEBUG)
652                         System.err.println("JobItem.image disposed"); //$NON-NLS-1$
653
image.dispose();
654                 }
655                 image = null;
656                 break;
657             case SWT.KeyDown:
658                 if (event.character == '\r') {
659                     doSelection();
660                 } else if (event.character == '\t') {
661                     scroller.getParent().forceFocus();
662                 } else if (event.keyCode == SWT.DEL) {
663                     cancelSelection();
664                 } else {
665                     select(null, event);
666                 }
667                 break;
668             case SWT.MouseDown:
669                 forceFocus();
670                 select(JobItem.this, event);
671                 break;
672             default:
673                 super.handleEvent(event);
674                 break;
675             }
676         }
677
678         void handleResize() {
679             Point e = getSize();
680             Point e1 = iconItem.computeSize(SWT.DEFAULT, SWT.DEFAULT);
681             e1.x = MIN_ICON_SIZE;
682             Point e2 = nameItem.computeSize(SWT.DEFAULT, SWT.DEFAULT);
683             Point e5 = actionBar.computeSize(SWT.DEFAULT, SWT.DEFAULT);
684
685             int iw = e.x - MARGIN - HGAP - e5.x - MARGIN;
686             int indent = 16 + HGAP;
687
688             int y = MARGIN;
689             int h = Math.max(e1.y, e2.y);
690
691             nameItem.setBounds(MARGIN + e1.x + HGAP, y + (h - e2.y) / 2, iw
692                     - e1.x - HGAP, e2.y);
693             y += h;
694             if (progressBar != null && !progressBar.isDisposed()) {
695                 Point e3 = progressBar.computeSize(SWT.DEFAULT, SWT.DEFAULT);
696                 e3.y = MAX_PROGRESS_HEIGHT;
697                 y += VGAP + 1;
698                 progressBar.setBounds(MARGIN + indent, y, iw - indent, e3.y);
699                 y += e3.y;
700             }
701             Control[] cs = getChildren();
702             for (int i = 0; i < cs.length; i++) {
703                 if (cs[i] instanceof Hyperlink) {
704                     Point e4 = cs[i].computeSize(SWT.DEFAULT, SWT.DEFAULT);
705                     y += VGAP;
706                     cs[i].setBounds(MARGIN + indent, y, iw - indent, e4.y);
707                     y += e4.y;
708                 }
709             }
710
711             int hm = (MARGIN + HGAP) / 2;
712             int vm = (y - e1.y) / 2;
713             if (hm < (y - e1.y) / 2)
714                 vm = hm;
715             iconItem.setBounds(hm, vm, e1.x, e1.y);
716
717             actionBar.setBounds(e.x - MARGIN - e5.x, (e.y - e5.y) / 2, e5.x,
718                     e5.y);
719         }
720
721         boolean isCanceled() {
722             if (jobTreeElement instanceof JobInfo)
723                 return ((JobInfo) jobTreeElement).isCanceled();
724             return false;
725         }
726
727         public boolean kill() {
728             if (jobTerminated) {
729                 // Removing the job from the list of jobs will
730
// remove the job from the view using a callback
731
if (!finishedJobs.remove(jobTreeElement)) {
732                     // The terminated job has already been removed
733
// from the list of finished jobs but was somehow
734
// left in the view. Dispose of the item and refresh
735
// the view
736
dispose();
737                     relayout(true, true);
738                     return true;
739                 }
740             }
741             return false;
742         }
743
744         /*
745          * Update the widgets from the model.
746          */

747         public boolean refresh() {
748
749             if (isDisposed())
750                 return false;
751
752             boolean changed = false;
753             boolean isGroup = jobTreeElement instanceof GroupInfo;
754             Object JavaDoc[] roots = contentProviderGetChildren(jobTreeElement);
755             Job job = getJob();
756
757             // poll for properties
758
checkKeep();
759             if (image == null && job != null)
760                 updateIcon(job);
761
762             // name
763
String JavaDoc name = null;
764             if (isGroup) {
765                 name = getGroupHeader((GroupInfo) jobTreeElement);
766             } else if (jobTreeElement instanceof JobInfo)
767                 name = getJobNameAndStatus((JobInfo) jobTreeElement, job,
768                         jobTerminated, true);
769             if (name == null)
770                 name = stripPercent(jobTreeElement.getDisplayString());
771
772             if (highlightJob != null
773                     && (highlightJob == job || highlightItem == this))
774                 name = NLS.bind(ProgressMessages.JobInfo_BlocksUserOperationFormat, name);
775
776             nameItem.setToolTipText(name);
777             nameItem.setText(shortenText(nameItem, name));
778
779             // percentage
780
if (jobTreeElement instanceof JobInfo) {
781                 TaskInfo ti = ((JobInfo) jobTreeElement).getTaskInfo();
782                 if (ti != null)
783                     changed |= setPercentDone(ti.getPercentDone());
784             } else if (isGroup) {
785                 if (roots.length == 1 && roots[0] instanceof JobTreeElement) {
786                     TaskInfo ti = ((JobInfo) roots[0]).getTaskInfo();
787                     if (ti != null)
788                         changed |= setPercentDone(ti.getPercentDone());
789                 } else {
790                     GroupInfo gi = (GroupInfo) jobTreeElement;
791                     changed |= setPercentDone(gi.getPercentDone());
792                 }
793             }
794
795             // children
796
if (!jobTreeElement.hasChildren())
797                 return changed;
798
799             Control[] children = getChildren();
800             int n = 0;
801             for (int i = 0; i < children.length; i++)
802                 if (children[i] instanceof Hyperlink)
803                     n++;
804
805             if (!isGroup && roots.length == n) { // reuse all children
806
int z = 0;
807                 for (int i = 0; i < children.length; i++) {
808                     if (children[i] instanceof Hyperlink) {
809                         Hyperlink l = (Hyperlink) children[i];
810                         l.init((JobTreeElement) roots[z++]);
811                     }
812                 }
813             } else {
814                 HashSet JavaDoc modelJobs = new HashSet JavaDoc();
815                 for (int z = 0; z < roots.length; z++)
816                     modelJobs.add(roots[z]);
817
818                 // find all removed
819
HashSet JavaDoc shownJobs = new HashSet JavaDoc();
820                 for (int i = 0; i < children.length; i++) {
821                     if (children[i] instanceof Hyperlink) {
822                         JobTreeItem ji = (JobTreeItem) children[i];
823                         shownJobs.add(ji.jobTreeElement);
824                         if (modelJobs.contains(ji.jobTreeElement)) {
825                             ji.refresh();
826                         } else {
827                             changed |= ji.remove();
828                         }
829                     }
830                 }
831
832                 // find all added
833
for (int i = 0; i < roots.length; i++) {
834                     Object JavaDoc element = roots[i];
835                     if (!shownJobs.contains(element)) {
836                         createChild((JobTreeElement) element);
837                         changed = true;
838                     }
839                 }
840             }
841
842             return changed;
843         }
844
845         public boolean remove() {
846
847             jobTerminated = true;
848
849             if (finishedJobs.isFinished(jobTreeElement)) {
850                 keepItem = true;
851             }
852
853             // propagate status down
854
Control[] children = getChildren();
855             for (int i = 0; i < children.length; i++) {
856                 if (children[i] instanceof JobTreeItem)
857                     ((JobTreeItem) children[i]).jobTerminated = true;
858             }
859
860             if (!dialogContext) { // we never keep jobs in dialogs
861
if (!keepItem)
862                     checkKeep();
863
864                 if (keepItem)
865                     return aboutToKeep();
866             }
867             return super.remove();
868         }
869
870         boolean setPercentDone(int percentDone) {
871             if (percentDone >= 0 && percentDone < 100) {
872                 if (progressBar == null) {
873                     progressBar = new ProgressBar(this, SWT.HORIZONTAL);
874                     progressBar.setMaximum(100);
875                     progressBar.setSelection(percentDone);
876                     progressBar.addListener(SWT.MouseDown, this);
877                     return true;
878                 } else if (!progressBar.isDisposed())
879                     progressBar.setSelection(percentDone);
880             } else {
881                 if (progressBar == null) {
882                     progressBar = new ProgressBar(this, SWT.HORIZONTAL
883                             | SWT.INDETERMINATE);
884                     progressBar.addListener(SWT.MouseDown, this);
885                     return true;
886                 }
887             }
888             return false;
889         }
890
891         /*
892          * Update the background colors.
893          */

894         void updateBackground(boolean dark) {
895             Color fg, bg;
896
897             if (selected) {
898                 fg = selectedTextColor;
899                 bg = selectedColor;
900             } else {
901                 if (highlightJob != null
902                         && (highlightJob == getJob() || highlightItem == this))
903                     fg = getHighlightColor();
904                 else
905                     fg = textColor;
906                 bg = dark ? darkColor : lightColor;
907             }
908             setForeground(fg);
909             setBackground(bg);
910
911             Control[] cs = getChildren();
912             for (int i = 0; i < cs.length; i++) {
913                 if (!(cs[i] instanceof ProgressBar)) {
914                     cs[i].setForeground(fg);
915                     cs[i].setBackground(bg);
916                 }
917             }
918         }
919
920         void updateIcon(Job job) {
921             if (job != null) {
922                 Image im = null;
923                 boolean dispImage = false;
924                 Display display = getDisplay();
925                 Object JavaDoc property = job.getProperty(ICON_PROPERTY);
926                 if (property instanceof ImageDescriptor) {
927                     dispImage = true;
928                     im = ((ImageDescriptor) property).createImage(display);
929                 } else if (property instanceof URL JavaDoc) {
930                     dispImage = true;
931                     im = ImageDescriptor.createFromURL((URL JavaDoc) property)
932                             .createImage(display);
933                 } else {
934                     dispImage = false;
935                     im = ProgressManager.getInstance().getIconFor(job);
936                 }
937                 if (im != null && im != image) {
938                     if (disposeImage && image != null) {
939                         if (DEBUG)
940                             System.err
941                                     .println("JobItem.setImage: disposed image"); //$NON-NLS-1$
942
image.dispose();
943                     }
944                     image = im;
945                     disposeImage = dispImage;
946                     if (iconItem != null)
947                         iconItem.setImage(image);
948                 }
949             }
950         }
951     }
952
953     abstract class JobTreeItem extends Canvas implements Listener {
954
955         boolean jobTerminated;
956         JobTreeElement jobTreeElement;
957
958         boolean keepItem;
959
960         JobTreeItem(Composite parent, JobTreeElement info, int flags) {
961             super(parent, flags);
962             jobTreeElement = info;
963             map.put(jobTreeElement, this);
964             addListener(SWT.Dispose, this);
965         }
966
967         boolean checkKeep() {
968             if (jobTreeElement instanceof JobInfo
969                     && FinishedJobs.keep((JobInfo) jobTreeElement))
970                 setKeep();
971             return keepItem;
972         }
973
974         protected void dump(String JavaDoc message) {
975             if (DEBUG) {
976                 System.out.println(message
977                         + " (" + jobTreeElement.hashCode() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
978

979                 System.out.println(" terminated: " + jobTerminated); //$NON-NLS-1$
980
if (jobTreeElement instanceof JobInfo)
981                     System.out.println(" type: JobInfo"); //$NON-NLS-1$
982
else if (jobTreeElement instanceof SubTaskInfo)
983                     System.out.println(" type: SubTaskInfo"); //$NON-NLS-1$
984
else if (jobTreeElement instanceof GroupInfo)
985                     System.out.println(" type: GroupInfo"); //$NON-NLS-1$
986

987                 Job job = getJob();
988                 if (job != null) {
989                     System.out.println(" name: " + job.getName()); //$NON-NLS-1$
990
System.out.println(" isSystem: " + job.isSystem()); //$NON-NLS-1$
991
}
992                 System.out.println(" keep: " + keepItem); //$NON-NLS-1$
993
}
994         }
995
996         Job getJob() {
997             if (jobTreeElement instanceof JobInfo)
998                 return ((JobInfo) jobTreeElement).getJob();
999             if (jobTreeElement instanceof SubTaskInfo)
1000                return ((SubTaskInfo) jobTreeElement).jobInfo.getJob();
1001            return null;
1002        }
1003
1004        public void handleEvent(Event e) {
1005            switch (e.type) {
1006            case SWT.Dispose:
1007                map.remove(jobTreeElement);
1008                break;
1009            }
1010        }
1011
1012        void init(JobTreeElement info) {
1013            if (jobTreeElement != info) {
1014                map.remove(jobTreeElement);
1015                jobTreeElement = info;
1016                map.put(jobTreeElement, this);
1017            }
1018            refresh();
1019        }
1020
1021        public boolean kill() {
1022            return true;
1023        }
1024
1025        abstract boolean refresh();
1026
1027        public boolean remove() {
1028            jobTerminated = true;
1029            refresh();
1030            if (dialogContext || !keepItem) {
1031                dispose();
1032                return true;
1033            }
1034            return false;
1035        }
1036
1037        void setKeep() {
1038            keepItem = true;
1039            Composite parent = getParent();
1040            if (parent instanceof JobTreeItem) {
1041                ((JobTreeItem) parent).keepItem = true;
1042            }
1043        }
1044
1045        void setKept() {
1046            if (!jobTerminated) {
1047                keepItem = jobTerminated = true;
1048                remove(); // bring to keep mode
1049
}
1050        }
1051    }
1052
1053    //
1054

1055    class ListLayout extends Layout {
1056        static final int VERTICAL_SPACING = 1;
1057
1058        boolean refreshBackgrounds;
1059
1060        protected Point computeSize(Composite composite, int wHint, int hHint,
1061                boolean flushCache) {
1062            int w = 0, h = -VERTICAL_SPACING;
1063            Control[] cs = composite.getChildren();
1064            for (int i = 0; i < cs.length; i++) {
1065                Control c = cs[i];
1066                Point e = c.computeSize(SWT.DEFAULT, SWT.DEFAULT, flushCache);
1067                w = Math.max(w, e.x);
1068                h += e.y + VERTICAL_SPACING;
1069            }
1070            return new Point(w, h);
1071        }
1072
1073        protected void layout(Composite composite, boolean flushCache) {
1074            int x = 0, y = 0;
1075            Point e = composite.getSize();
1076            Control[] cs = getSortedChildren();
1077            boolean dark = (cs.length % 2) == 1;
1078            for (int i = 0; i < cs.length; i++) {
1079                Control c = cs[i];
1080                Point s = c.computeSize(e.x, SWT.DEFAULT, flushCache);
1081                c.setBounds(x, y, s.x, s.y);
1082                y += s.y + VERTICAL_SPACING;
1083                if (refreshBackgrounds && c instanceof JobItem) {
1084                    ((JobItem) c).updateBackground(dark);
1085                    dark = !dark;
1086                }
1087            }
1088        }
1089    }
1090
1091    static final boolean DEBUG = false;
1092
1093    private static String JavaDoc ELLIPSIS = ProgressMessages.ProgressFloatingWindow_EllipsisValue;
1094
1095    static final QualifiedName ICON_PROPERTY = IProgressConstants.ICON_PROPERTY;
1096
1097    static final boolean isCarbon = "carbon".equals(SWT.getPlatform()); //$NON-NLS-1$
1098

1099    static final QualifiedName KEEP_PROPERTY = IProgressConstants.KEEP_PROPERTY;
1100
1101    static final QualifiedName KEEPONE_PROPERTY = IProgressConstants.KEEPONE_PROPERTY;
1102
1103    /**
1104     * Shorten the given text <code>t</code> so that its length
1105     * doesn't exceed the width of the given control. This implementation
1106     * replaces characters in the center of the original string with an
1107     * ellipsis ("...").
1108     */

1109    static String JavaDoc shortenText(Control control, String JavaDoc textValue) {
1110        if (textValue != null) {
1111            Display display = control.getDisplay();
1112            GC gc = new GC(display);
1113            int maxWidth = control.getBounds().width;
1114            textValue = shortenText(gc, maxWidth, textValue);
1115            gc.dispose();
1116        }
1117        return textValue;
1118    }
1119
1120    /**
1121     * Shorten the given text <code>t</code> so that its length
1122     * doesn't exceed the given width. This implementation
1123     * replaces characters in the center of the original string with an
1124     * ellipsis ("...").
1125     */

1126    static String JavaDoc shortenText(GC gc, int maxWidth, String JavaDoc textValue) {
1127        if (gc.textExtent(textValue).x < maxWidth) {
1128            return textValue;
1129        }
1130        int length = textValue.length();
1131        int ellipsisWidth = gc.textExtent(ELLIPSIS).x;
1132        int pivot = length / 2;
1133        int start = pivot;
1134        int end = pivot + 1;
1135        while (start >= 0 && end < length) {
1136            String JavaDoc s1 = textValue.substring(0, start);
1137            String JavaDoc s2 = textValue.substring(end, length);
1138            int l1 = gc.textExtent(s1).x;
1139            int l2 = gc.textExtent(s2).x;
1140            if (l1 + ellipsisWidth + l2 < maxWidth) {
1141                return s1 + ELLIPSIS + s2;
1142            }
1143            start--;
1144            end++;
1145        }
1146        return textValue;
1147    }
1148
1149    private Font boldFont;
1150
1151    private Image cancelJobIcon, cancelJobDIcon;
1152
1153    private Image clearJobIcon, clearJobDIcon;
1154
1155    private Color darkColor;
1156
1157    private Image defaultJobIcon;
1158
1159    private boolean dialogContext; // viewer runs in dialog: filter accordingly
1160

1161    private FinishedJobs finishedJobs;
1162    
1163    // to be disposed
1164
private Cursor handCursor;
1165
1166    private JobTreeItem highlightItem;
1167
1168    private Job highlightJob;
1169
1170    private Color lightColor;
1171
1172    private Composite list;
1173
1174    private HashMap JavaDoc map = new HashMap JavaDoc();
1175
1176    private Cursor normalCursor;
1177
1178    private ScrolledComposite scroller;
1179
1180    private Color selectedColor;
1181
1182    private Color selectedTextColor;
1183
1184    private Font smallerFont;
1185
1186    private Color textColor;
1187
1188    /**
1189     * Create a new ProgressViewer
1190     */

1191    public NewProgressViewer(Composite parent, int flags) {
1192        super(parent, flags);
1193        Tree c = getTree();
1194        if (c instanceof Tree)
1195            c.dispose();
1196
1197        dialogContext = (flags & SWT.BORDER) != 0; // hack to determine context
1198

1199        finishedJobs = FinishedJobs.getInstance();
1200
1201        finishedJobs.addListener(this);
1202
1203        Display display = parent.getDisplay();
1204        handCursor = new Cursor(display, SWT.CURSOR_HAND);
1205        normalCursor = new Cursor(display, SWT.CURSOR_ARROW);
1206
1207        defaultJobIcon = WorkbenchImages.getWorkbenchImageDescriptor("progress/progress_task.gif").createImage(display); //$NON-NLS-1$
1208
cancelJobIcon = WorkbenchImages.getWorkbenchImageDescriptor("elcl16/progress_stop.gif").createImage(display); //$NON-NLS-1$
1209
cancelJobDIcon =WorkbenchImages.getWorkbenchImageDescriptor("dlcl16/progress_stop.gif").createImage(display); //$NON-NLS-1$
1210
clearJobIcon = WorkbenchImages.getWorkbenchImageDescriptor("elcl16/progress_rem.gif").createImage(display); //$NON-NLS-1$
1211
clearJobDIcon = WorkbenchImages.getWorkbenchImageDescriptor("dlcl16/progress_rem.gif").createImage(display); //$NON-NLS-1$
1212

1213        boldFont = getDefaultFont();
1214        FontData fds[] = getDefaultFontData();
1215        if (fds.length > 0) {
1216            FontData fd = fds[0];
1217            int h = fd.getHeight();
1218            boldFont = new Font(display, fd.getName(), h, fd.getStyle()
1219                    | SWT.BOLD);
1220            smallerFont = new Font(display, fd.getName(), h, fd.getStyle());
1221        }
1222
1223        int shift = isCarbon ? -25 : -10; // Mac has different Gamma value
1224
lightColor = display.getSystemColor(SWT.COLOR_LIST_BACKGROUND);
1225        darkColor = new Color(display,
1226                Math.max(0, lightColor.getRed() + shift), Math.max(0,
1227                        lightColor.getGreen() + shift), Math.max(0, lightColor
1228                        .getBlue()
1229                        + shift));
1230        textColor = display.getSystemColor(SWT.COLOR_LIST_FOREGROUND);
1231        selectedTextColor = display
1232                .getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT);
1233        selectedColor = display.getSystemColor(SWT.COLOR_LIST_SELECTION);
1234
1235        scroller = new ScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL
1236                | flags);
1237        int height = getDefaultFontData()[0].getHeight();
1238        scroller.getVerticalBar().setIncrement(height * 2);
1239        scroller.setExpandHorizontal(true);
1240        scroller.setExpandVertical(true);
1241
1242        list = new Composite(scroller, SWT.NONE);
1243        list.setFont(getDefaultFont());
1244        list.setBackground(lightColor);
1245        list.setLayout(new ListLayout());
1246
1247        list.addListener(SWT.MouseDown, new Listener() {
1248            public void handleEvent(Event event) {
1249                select(null, event); // clear selection
1250
}
1251        });
1252
1253        scroller.addListener(SWT.Dispose, new Listener() {
1254            public void handleEvent(Event event) {
1255                finishedJobs.removeListener(NewProgressViewer.this);
1256
1257                defaultJobIcon.dispose();
1258                cancelJobIcon.dispose();
1259                cancelJobDIcon.dispose();
1260                clearJobIcon.dispose();
1261                clearJobDIcon.dispose();
1262
1263                handCursor.dispose();
1264                normalCursor.dispose();
1265
1266                Font defaultFont = getDefaultFont();
1267                if (boldFont != defaultFont)
1268                    boldFont.dispose();
1269                if (smallerFont != defaultFont)
1270                    smallerFont.dispose();
1271
1272                darkColor.dispose();
1273
1274                NewProgressViewer.this.handleDispose(null);
1275            }
1276        });
1277
1278        scroller.setContent(list);
1279
1280        // refresh UI
1281
refresh(true);
1282    }
1283
1284    public void add(Object JavaDoc parentElement, Object JavaDoc[] elements) {
1285        if (DEBUG)
1286            System.err.println("add"); //$NON-NLS-1$
1287
if (list.isDisposed())
1288            return;
1289        JobTreeItem lastAdded = null;
1290        for (int i = 0; i < elements.length; i++)
1291            if (!filtered(elements[i]))
1292                lastAdded = findJobItem(elements[i], true);
1293        relayout(true, true);
1294        if (lastAdded != null)
1295            reveal(lastAdded);
1296    }
1297
1298    ///////////////////////////////////
1299

1300    protected void addTreeListener(Control c, TreeListener listener) {
1301    }
1302
1303    public void cancelSelection() {
1304        boolean changed = false;
1305        Control[] cs = list.getChildren();
1306        for (int i = 0; i < cs.length; i++) {
1307            JobItem ji = (JobItem) cs[i];
1308            if (ji.selected)
1309                changed |= ji.cancelOrRemove();
1310        }
1311        relayout(changed, changed);
1312    }
1313
1314    void clearAll() {
1315
1316        finishedJobs.clearAll();
1317
1318        if (DEBUG) {
1319            JobTreeElement[] elements = finishedJobs.getJobInfos();
1320            System.out.println("jobs: " + elements.length); //$NON-NLS-1$
1321
for (int i = 0; i < elements.length; i++)
1322                System.out.println(" " + elements[i]); //$NON-NLS-1$
1323
}
1324    }
1325
1326    Object JavaDoc[] contentProviderGetChildren(Object JavaDoc parent) {
1327        IContentProvider provider = getContentProvider();
1328        if (provider instanceof ITreeContentProvider)
1329            return ((ITreeContentProvider) provider).getChildren(parent);
1330        return new Object JavaDoc[0];
1331    }
1332
1333    Object JavaDoc[] contentProviderGetRoots(Object JavaDoc parent) {
1334        IContentProvider provider = getContentProvider();
1335        if (provider instanceof ITreeContentProvider)
1336            return ((ITreeContentProvider) provider).getElements(parent);
1337        return new Object JavaDoc[0];
1338    }
1339
1340    protected void createChildren(Widget widget) {
1341        refresh(true);
1342    }
1343
1344    private JobItem createItem(Object JavaDoc element) {
1345        return new JobItem(list, (JobTreeElement) element);
1346    }
1347
1348    void doSelection() {
1349        boolean changed = false;
1350        Control[] cs = list.getChildren();
1351        for (int i = 0; i < cs.length; i++) {
1352            JobItem ji = (JobItem) cs[i];
1353            if (ji.selected) {
1354                Control[] children = ji.getChildren();
1355                for (int j = 0; j < children.length; j++) {
1356                    if (children[j] instanceof Hyperlink) {
1357                        Hyperlink hl = (Hyperlink) children[j];
1358                        if (hl.handleActivate())
1359                            return;
1360                    }
1361                }
1362            }
1363        }
1364    }
1365
1366    protected void doUpdateItem(final Item item, Object JavaDoc element) {
1367    }
1368
1369    /**
1370     * Returns true if given element is filtered (i.e. not shown).
1371     */

1372    private boolean filtered(Object JavaDoc element) {
1373
1374        if (element == null)
1375            return true;
1376
1377        if (!dialogContext && ProgressViewUpdater.getSingleton().debug) // display all in debug mode
1378
return false;
1379
1380        if (element instanceof JobInfo)
1381            return jobFiltered((JobInfo) element);
1382
1383        if (element instanceof GroupInfo) {
1384            Object JavaDoc[] children = ((GroupInfo) element).getChildren();
1385            for (int i = 0; i < children.length; i++)
1386                if (jobFiltered((JobInfo) children[i]))
1387                    return true;
1388        }
1389
1390        if (element instanceof TaskInfo) {
1391            Object JavaDoc parent = ((TaskInfo) element).getParent();
1392            if (parent instanceof JobInfo)
1393                return jobFiltered((JobInfo) parent);
1394        }
1395
1396        return false;
1397    }
1398
1399    private JobTreeItem findJobItem(Object JavaDoc element, boolean create) {
1400        JobTreeItem ji = (JobTreeItem) map.get(element);
1401        if (ji == null && create) {
1402            JobTreeElement jte = (JobTreeElement) element;
1403            Object JavaDoc parent = jte.getParent();
1404            if (parent != null) {
1405                JobTreeItem parentji = findJobItem(parent, true);
1406                if (parentji instanceof JobItem && !(jte instanceof TaskInfo)) {
1407                    if (findJobItem(jte, false) == null) {
1408                        JobItem p = (JobItem) parentji;
1409                        p.createChild(jte);
1410                    }
1411                }
1412            } else {
1413                ji = createItem(jte);
1414            }
1415        }
1416        return ji;
1417    }
1418
1419    /* (non-Javadoc)
1420     * @see org.eclipse.ui.internal.progress.NewKeptJobs.KeptJobsListener#finished(org.eclipse.ui.internal.progress.JobInfo)
1421     */

1422    public void finished(JobTreeElement jte) {
1423    }
1424
1425    private void forcedRemove(final JobTreeElement jte) {
1426        if (list != null && !list.isDisposed()) {
1427            list.getDisplay().asyncExec(new Runnable JavaDoc() {
1428                public void run() {
1429                    if (DEBUG)
1430                        System.err.println(" forced remove"); //$NON-NLS-1$
1431
JobTreeItem ji = findJobItem(jte, false);
1432                    if (ji != null && !ji.isDisposed() && ji.remove())
1433                        relayout(true, true);
1434                }
1435            });
1436        }
1437    }
1438    
1439    /**
1440     * Get the color for active hyperlinks.
1441     * @return Color
1442     */

1443    private Color getActiveHyperlinkColor(){
1444        return JFaceColors.getActiveHyperlinkText(getControl().getDisplay());
1445    }
1446
1447    protected Item[] getChildren(Widget o) {
1448        return new Item[0];
1449    }
1450
1451    public Control getControl() {
1452        return scroller;
1453    }
1454    
1455    /**
1456     * Get the default font to use.
1457     * @return Font
1458     */

1459    private Font getDefaultFont(){
1460        return JFaceResources.getDefaultFont();
1461    }
1462    
1463    /**
1464     * Get the default font data for the workbench
1465     * @return FontData[]
1466     */

1467    private FontData[] getDefaultFontData(){
1468        return JFaceResources.getDefaultFont().getFontData();
1469    }
1470    
1471    /**
1472     * Get the color for errors.
1473     * @return Color
1474     */

1475    private Color getErrorColor(){
1476        return JFaceColors.getErrorText(getControl().getDisplay());
1477    }
1478
1479    protected boolean getExpanded(Item item) {
1480        return true;
1481    }
1482
1483    private String JavaDoc getFinishedString(JobTreeElement jte, String JavaDoc name,
1484            boolean withTime) {
1485        String JavaDoc time = null;
1486        if (withTime)
1487            time = getTimeString(jte);
1488        if (time != null)
1489            return NLS.bind(ProgressMessages.JobInfo_FinishedAt, name, time );
1490        return NLS.bind(ProgressMessages.JobInfo_Finished, name );
1491    }
1492    
1493    /**
1494     * Get the color for highlight.
1495     * @return Color
1496     */

1497    private Color getHighlightColor(){
1498        return JFaceColors.getErrorText(getControl().getDisplay());
1499    }
1500    
1501    /**
1502     * Get the color for hyperlinks.
1503     * @return Color
1504     */

1505    private Color getHyperlinkColor(){
1506        return JFaceColors.getHyperlinkText(getControl().getDisplay());
1507    }
1508
1509    protected Item getItem(int x, int y) {
1510        return null;
1511    }
1512
1513    protected int getItemCount(Control widget) {
1514        return 1;
1515    }
1516
1517    protected int getItemCount(Item item) {
1518        return 0;
1519    }
1520
1521    protected Item[] getItems(Item item) {
1522        return new Item[0];
1523    }
1524
1525    private String JavaDoc getJobNameAndStatus(JobInfo ji, Job job, boolean terminated,
1526            boolean withTime) {
1527        String JavaDoc name = job.getName();
1528
1529        if (job.isSystem())
1530            name = NLS.bind(ProgressMessages.JobInfo_System, name);
1531
1532        if (ji.isCanceled())
1533            return NLS.bind(ProgressMessages.JobInfo_Cancelled, name);
1534
1535        if (terminated)
1536            return getFinishedString(ji, name, withTime);
1537
1538        if (ji.isBlocked()) {
1539            IStatus blockedStatus = ji.getBlockedStatus();
1540            return NLS.bind(ProgressMessages.JobInfo_Blocked, name, blockedStatus.getMessage());
1541        }
1542
1543        switch (job.getState()) {
1544        case Job.RUNNING:
1545            return name;
1546        case Job.SLEEPING:
1547            return NLS.bind(ProgressMessages.JobInfo_Sleeping, name);
1548        default:
1549            return NLS.bind(ProgressMessages.JobInfo_Waiting, name);
1550        }
1551    }
1552
1553    protected Item getParentItem(Item item) {
1554        return null;
1555    }
1556
1557    ////// SelectionProvider
1558

1559    public ISelection getSelection() {
1560        if (list.isDisposed())
1561            return new StructuredSelection();
1562        ArrayList JavaDoc l = new ArrayList JavaDoc();
1563        Control[] cs = list.getChildren();
1564        for (int i = 0; i < cs.length; i++) {
1565            JobItem ji = (JobItem) cs[i];
1566            l.add(ji.jobTreeElement);
1567        }
1568        return new StructuredSelection(l);
1569    }
1570
1571    protected Item[] getSelection(Control widget) {
1572        return new Item[0];
1573    }
1574
1575    private Control[] getSortedChildren() {
1576        Control[] cs = list.getChildren();
1577        ViewerSorter vs = getSorter();
1578        if (vs != null) {
1579            HashMap JavaDoc map2 = new HashMap JavaDoc(); // temp remember items for sorting
1580
JobTreeElement[] elements = new JobTreeElement[cs.length];
1581            for (int i = 0; i < cs.length; i++) {
1582                JobItem ji = (JobItem) cs[i];
1583                elements[i] = ji.jobTreeElement;
1584                map2.put(elements[i], ji);
1585            }
1586            vs.sort(NewProgressViewer.this, elements);
1587            for (int i = 0; i < cs.length; i++)
1588                cs[i] = (JobItem) map2.get(elements[i]);
1589        }
1590        return cs;
1591    }
1592
1593    private String JavaDoc getTimeString(JobTreeElement jte) {
1594        Date JavaDoc date = finishedJobs.getFinishDate(jte);
1595        if (date != null)
1596            return DateFormat.getTimeInstance(DateFormat.SHORT).format(date);
1597        return null;
1598    }
1599
1600    public Tree getTree() {
1601        Tree t = super.getTree();
1602        if (t != null && !t.isDisposed())
1603            return t;
1604        return null;
1605    }
1606
1607    protected void internalRefresh(Object JavaDoc element, boolean updateLabels) {
1608    }
1609
1610    private boolean jobFiltered(JobInfo ji) {
1611        Job job = ji.getJob();
1612        if (job != null && job == highlightJob)
1613            return false;
1614        
1615        if (job == null || job.getState() == Job.SLEEPING)
1616            return true;
1617        
1618        if(job.isSystem()){
1619            if(getContentProvider() instanceof ProgressContentProvider)
1620                return !((ProgressContentProvider) getContentProvider()).debug();
1621            return false;
1622        }
1623        return false;
1624    }
1625
1626    protected Item newItem(Widget parent, int flags, int ix) {
1627        return null;
1628    }
1629
1630    public void refresh(boolean updateLabels) {
1631        if (list.isDisposed())
1632            return;
1633        if (DEBUG)
1634            System.err.println("refreshAll"); //$NON-NLS-1$
1635
boolean changed = false;
1636        boolean countChanged = false;
1637        JobTreeItem lastAdded = null;
1638
1639        Object JavaDoc[] roots = contentProviderGetRoots(getInput());
1640        HashSet JavaDoc modelJobs = new HashSet JavaDoc();
1641        for (int z = 0; z < roots.length; z++)
1642            modelJobs.add(roots[z]);
1643
1644        // find all removed
1645
Control[] children = list.getChildren();
1646        for (int i = 0; i < children.length; i++) {
1647            JobItem ji = (JobItem) children[i];
1648            if (modelJobs.contains(ji.jobTreeElement)) {
1649                if (DEBUG)
1650                    System.err.println(" refresh"); //$NON-NLS-1$
1651
changed |= ji.refresh();
1652            } else {
1653                if (DEBUG)
1654                    System.err.println(" remove: " + ji.jobTreeElement); //$NON-NLS-1$
1655
if (ji.remove())
1656                    countChanged = changed = true;
1657            }
1658        }
1659
1660        // find all added
1661
for (int i = 0; i < roots.length; i++) {
1662            Object JavaDoc element = roots[i];
1663            if (filtered(element))
1664                continue;
1665            if (findJobItem(element, false) == null) {
1666                if (DEBUG)
1667                    System.err.println(" added"); //$NON-NLS-1$
1668
lastAdded = createItem(element);
1669                changed = countChanged = true;
1670            }
1671        }
1672        // now add kept finished jobs
1673
if (!dialogContext) {
1674            JobTreeElement[] infos = finishedJobs.getJobInfos();
1675            for (int i = 0; i < infos.length; i++) {
1676                Object JavaDoc element = infos[i];
1677                if (filtered(element))
1678                    continue;
1679                JobTreeItem jte = findJobItem(element, true);
1680                if (jte != null) {
1681                    jte.setKept();
1682                    lastAdded = jte;
1683
1684                    if (jte instanceof Hyperlink) {
1685                        JobItem p = (JobItem) jte.getParent();
1686                        p.setKept();
1687                        lastAdded = p;
1688                    }
1689
1690                    changed = countChanged = true;
1691                }
1692            }
1693        }
1694
1695        relayout(changed, countChanged);
1696        if (lastAdded != null)
1697            reveal(lastAdded);
1698    }
1699
1700    public void refresh(Object JavaDoc element, boolean updateLabels) {
1701        if (list.isDisposed())
1702            return;
1703        if (filtered(element))
1704            return;
1705        JobTreeItem ji = findJobItem(element, false);
1706        if (ji == null) { // not found -> add it (workaround for #68151)
1707
ji = findJobItem(element, true);
1708            relayout(true, true);
1709        } else { // just a refresh
1710
if (ji.refresh())
1711                relayout(true, true);
1712        }
1713    }
1714
1715    /*
1716     * Needs to be called after items have been added or removed,
1717     * or after the size of an item has changed.
1718     * Optionally updates the background of all items.
1719     * Ensures that the background following the last item is always white.
1720     */

1721    private void relayout(boolean layout, boolean refreshBackgrounds) {
1722        if (layout) {
1723            ListLayout l = (ListLayout) list.getLayout();
1724            l.refreshBackgrounds = refreshBackgrounds;
1725            Point size = list.computeSize(list.getClientArea().x, SWT.DEFAULT);
1726            list.setSize(size);
1727            scroller.setMinSize(size);
1728        }
1729    }
1730
1731    public void remove(Object JavaDoc[] elements) {
1732        if (list.isDisposed())
1733            return;
1734        if (DEBUG)
1735            System.err.println("remove"); //$NON-NLS-1$
1736
boolean changed = false;
1737        for (int i = 0; i < elements.length; i++) {
1738            JobTreeItem ji = findJobItem(elements[i], false);
1739            if (ji != null)
1740                changed |= ji.remove();
1741        }
1742        relayout(changed, changed);
1743    }
1744
1745    protected void removeAll(Control widget) {
1746    }
1747
1748    /* (non-Javadoc)
1749     * @see org.eclipse.ui.internal.progress.NewKeptJobs.KeptJobsListener#removed(org.eclipse.ui.internal.progress.JobInfo)
1750     */

1751    public void removed(final JobTreeElement info) {
1752        if (list != null && !list.isDisposed()) {
1753            list.getDisplay().asyncExec(new Runnable JavaDoc() {
1754                public void run() {
1755                    if (info != null) { // we got a specific item to remove
1756
JobTreeItem ji = findJobItem(info, false);
1757                        if (ji != null && ji.jobTerminated) {
1758                            ji.dispose();
1759                            relayout(true, true);
1760                        }
1761                    } else {
1762                        // remove all terminated
1763
Control[] children = list.getChildren();
1764                        for (int i = 0; i < children.length; i++) {
1765                            JobTreeItem ji = (JobItem) children[i];
1766                            if (ji.jobTerminated)
1767                                ji.dispose();
1768                        }
1769                        relayout(true, true);
1770                    }
1771                }
1772            });
1773        }
1774    }
1775
1776    public void reveal(JobTreeItem jti) {
1777        if (jti != null && !jti.isDisposed()) {
1778
1779            Rectangle bounds = jti.getBounds();
1780
1781            int s = bounds.y;
1782            int e = bounds.y + bounds.height;
1783
1784            int as = scroller.getOrigin().y;
1785            int ae = as + scroller.getClientArea().height;
1786
1787            if (s < as)
1788                scroller.setOrigin(0, s);
1789            else if (e > ae)
1790                scroller.setOrigin(0, as + (e - ae));
1791        }
1792    }
1793
1794    private void select(JobItem newSelection, Event e) {
1795
1796        boolean clearAll = false;
1797        JobItem newSel = null;
1798        Control[] cs = getSortedChildren();
1799
1800        JobTreeElement element = null;
1801        if (newSelection != null)
1802            element = newSelection.jobTreeElement;
1803
1804        if (e.type == SWT.KeyDown) { // key
1805
if (e.keyCode == SWT.ARROW_UP) {
1806                for (int i = 0; i < cs.length; i++) {
1807                    JobItem ji = (JobItem) cs[i];
1808                    if (ji.selected) {
1809                        if (i - 1 >= 0) {
1810                            newSel = (JobItem) cs[i - 1];
1811                            if ((e.stateMask & SWT.MOD2) != 0) {
1812                                newSel.selected = true;
1813                            } else {
1814                                clearAll = true;
1815                            }
1816                            break;
1817                        }
1818                        return;
1819                    }
1820                }
1821                if (newSel == null && cs.length > 0) {
1822                    newSel = (JobItem) cs[cs.length - 1];
1823                    newSel.selected = true;
1824                }
1825            } else if (e.keyCode == SWT.ARROW_DOWN) {
1826                for (int i = cs.length - 1; i >= 0; i--) {
1827                    JobItem ji = (JobItem) cs[i];
1828                    if (ji.selected) {
1829                        if (i + 1 < cs.length) {
1830                            newSel = (JobItem) cs[i + 1];
1831                            if ((e.stateMask & SWT.MOD2) != 0) {
1832                                newSel.selected = true;
1833                            } else {
1834                                clearAll = true;
1835                            }
1836                            break;
1837                        }
1838                        return;
1839                    }
1840                }
1841                if (newSel == null && cs.length > 0) {
1842                    newSel = (JobItem) cs[0];
1843                    newSel.selected = true;
1844                }
1845            }
1846        } else if (e.type == SWT.MouseDown) { // mouse
1847

1848            if (newSelection == null) {
1849                clearAll = true;
1850            } else {
1851                if ((e.stateMask & SWT.MOD1) != 0) {
1852                    newSelection.selected = !newSelection.selected;
1853                } else if ((e.stateMask & SWT.MOD2) != 0) {
1854                    // not yet implemented
1855
} else {
1856                    if (newSelection.selected)
1857                        return;
1858                    clearAll = true;
1859                    newSel = newSelection;
1860                }
1861            }
1862        }
1863
1864        if (clearAll) {
1865            for (int i = 0; i < cs.length; i++) {
1866                JobItem ji = (JobItem) cs[i];
1867                ji.selected = ji == newSel;
1868            }
1869        }
1870
1871        boolean dark = (cs.length % 2) == 1;
1872        for (int i = 0; i < cs.length; i++) {
1873            JobItem ji = (JobItem) cs[i];
1874            ji.updateBackground(dark);
1875            dark = !dark;
1876        }
1877
1878        if (newSel != null)
1879            reveal(newSel);
1880    }
1881
1882    protected void setExpanded(Item node, boolean expand) {
1883    }
1884
1885    public void setFocus() {
1886        if (list != null) {
1887            Control[] cs = list.getChildren();
1888            for (int i = 0; i < cs.length; i++) {
1889                JobItem ji = (JobItem) cs[i];
1890                if (ji.selected) {
1891                    ji.forceFocus();
1892                    return;
1893                }
1894            }
1895            if (cs.length > 0)
1896                cs[0].forceFocus();
1897        }
1898    }
1899
1900    public void setHighlightJob(Job job) {
1901        highlightJob = job;
1902        relayout(true, true);
1903    }
1904
1905    public void setInput(IContentProvider provider) {
1906        refresh(true);
1907    }
1908
1909    public void setSelection(ISelection selection) {
1910    }
1911
1912    protected void setSelection(List JavaDoc items) {
1913    }
1914
1915    public void setUseHashlookup(boolean b) {
1916    }
1917
1918    protected void showItem(Item item) {
1919    }
1920
1921    private String JavaDoc stripPercent(String JavaDoc s) {
1922        int l = s.length();
1923        if (l > 0) {
1924            if (s.charAt(0) == '(') {
1925                int pos = s.indexOf("%) "); //$NON-NLS-1$
1926
if (pos >= 0)
1927                    s = s.substring(pos + 3);
1928            } else if (s.charAt(l - 1) == ')') {
1929                int pos = s.lastIndexOf(": ("); //$NON-NLS-1$
1930
if (pos >= 0)
1931                    s = s.substring(0, pos);
1932            }
1933        }
1934        return s;
1935    }
1936}
1937
Popular Tags