1 11 package org.eclipse.ui.internal.progress; 12 13 import java.net.URL ; 14 import java.text.DateFormat ; 15 import java.util.ArrayList ; 16 import java.util.Date ; 17 import java.util.HashMap ; 18 import java.util.HashSet ; 19 import java.util.List ; 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 77 public class NewProgressViewer extends TreeViewer implements 78 FinishedJobs.KeptJobsListener { 79 80 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 text = ""; 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 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 () { 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) return false; 281 282 final Job job = getJob(); 283 if (job != null) { 284 if (jobitem.image == null) 286 jobitem.updateIcon(job); 287 288 Object property = job 290 .getProperty(IProgressConstants.ACTION_PROPERTY); 291 if (property instanceof IAction) 292 setAction((IAction) property); 293 294 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 305 private ErrorNotificationManager getManager() { 306 return ProgressManager.getInstance().errorManager; 307 } 308 public void run() { 309 String title = ProgressMessages.NewProgressView_errorDialogTitle; 310 String msg = ProgressMessages.NewProgressView_errorDialogMessage; 311 if (!getManager().showErrorFor(job, title, msg)) { 312 ErrorDialog.openError(getShell(), title, msg, 318 result); 319 } 320 } 321 }); 322 } 323 } 324 } 325 checkKeep(); 326 327 String name = null; 329 330 if (jobTreeElement instanceof SubTaskInfo) { 332 SubTaskInfo sti = (SubTaskInfo) jobTreeElement; 333 String 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) { JobInfo ji = (JobInfo) jobTreeElement; 357 358 if (result != null) { 359 name = result.getMessage(); 360 if (name == null || name.trim().length() == 0 361 || "OK".equals(name)) { if (!keepItem) { 363 dispose(); 364 return true; 365 } 366 } 367 } else { 368 name = getJobNameAndStatus(ji, job, jobTerminated, false); 370 371 String 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 String subTaskName = null; 387 Object [] 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 [] { 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 String actionName = gotoAction.getClass().getName(); 430 if (actionName.indexOf("RefreshSubscriberJob$2") >= 0) gotoAction.setEnabled(false); 432 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 t) { 451 if (t == null) 452 t = ""; if (!t.equals(text)) { 454 text = t; 455 updateToolTip(); 456 redraw(); 457 } 458 } 459 460 private void updateToolTip() { 461 String tt = text; 462 if (isLinkEnabled() && gotoAction != null && gotoAction.isEnabled()) { 463 String tooltip = gotoAction.getToolTipText(); 464 if (tooltip != null && tooltip.trim().length() > 0) 465 tt = tooltip; 466 } 467 String oldtt = getToolTipText(); 468 if (oldtt == null || !oldtt.equals(tt)) 469 setToolTipText(tt); 470 } 471 } 472 473 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; 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); 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 if (progressBar != null && !progressBar.isDisposed()) { 559 progressBar.setSelection(100); 560 progressBar.dispose(); 561 changed = true; 562 } 563 564 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 getGroupHeader(GroupInfo gi) { 630 String name = stripPercent(jobTreeElement.getDisplayString()); 631 if (jobTerminated) 632 return getFinishedString(gi, name, true); 633 return name; 634 } 635 636 IStatus getResult() { 637 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"); 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 if (!finishedJobs.remove(jobTreeElement)) { 732 dispose(); 737 relayout(true, true); 738 return true; 739 } 740 } 741 return false; 742 } 743 744 747 public boolean refresh() { 748 749 if (isDisposed()) 750 return false; 751 752 boolean changed = false; 753 boolean isGroup = jobTreeElement instanceof GroupInfo; 754 Object [] roots = contentProviderGetChildren(jobTreeElement); 755 Job job = getJob(); 756 757 checkKeep(); 759 if (image == null && job != null) 760 updateIcon(job); 761 762 String 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 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 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) { 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 modelJobs = new HashSet (); 815 for (int z = 0; z < roots.length; z++) 816 modelJobs.add(roots[z]); 817 818 HashSet shownJobs = new HashSet (); 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 for (int i = 0; i < roots.length; i++) { 834 Object 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 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) { 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 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 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 ) { 930 dispImage = true; 931 im = ImageDescriptor.createFromURL((URL ) 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"); 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 message) { 975 if (DEBUG) { 976 System.out.println(message 977 + " (" + jobTreeElement.hashCode() + ")"); 979 System.out.println(" terminated: " + jobTerminated); if (jobTreeElement instanceof JobInfo) 981 System.out.println(" type: JobInfo"); else if (jobTreeElement instanceof SubTaskInfo) 983 System.out.println(" type: SubTaskInfo"); else if (jobTreeElement instanceof GroupInfo) 985 System.out.println(" type: GroupInfo"); 987 Job job = getJob(); 988 if (job != null) { 989 System.out.println(" name: " + job.getName()); System.out.println(" isSystem: " + job.isSystem()); } 992 System.out.println(" keep: " + keepItem); } 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(); } 1050 } 1051 } 1052 1053 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 ELLIPSIS = ProgressMessages.ProgressFloatingWindow_EllipsisValue; 1094 1095 static final QualifiedName ICON_PROPERTY = IProgressConstants.ICON_PROPERTY; 1096 1097 static final boolean isCarbon = "carbon".equals(SWT.getPlatform()); 1099 static final QualifiedName KEEP_PROPERTY = IProgressConstants.KEEP_PROPERTY; 1100 1101 static final QualifiedName KEEPONE_PROPERTY = IProgressConstants.KEEPONE_PROPERTY; 1102 1103 1109 static String shortenText(Control control, String 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 1126 static String shortenText(GC gc, int maxWidth, String 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 s1 = textValue.substring(0, start); 1137 String 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; 1161 private FinishedJobs finishedJobs; 1162 1163 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 map = new HashMap (); 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 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; 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); cancelJobIcon = WorkbenchImages.getWorkbenchImageDescriptor("elcl16/progress_stop.gif").createImage(display); cancelJobDIcon =WorkbenchImages.getWorkbenchImageDescriptor("dlcl16/progress_stop.gif").createImage(display); clearJobIcon = WorkbenchImages.getWorkbenchImageDescriptor("elcl16/progress_rem.gif").createImage(display); clearJobDIcon = WorkbenchImages.getWorkbenchImageDescriptor("dlcl16/progress_rem.gif").createImage(display); 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; 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); } 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(true); 1282 } 1283 1284 public void add(Object parentElement, Object [] elements) { 1285 if (DEBUG) 1286 System.err.println("add"); 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 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); for (int i = 0; i < elements.length; i++) 1322 System.out.println(" " + elements[i]); } 1324 } 1325 1326 Object [] contentProviderGetChildren(Object parent) { 1327 IContentProvider provider = getContentProvider(); 1328 if (provider instanceof ITreeContentProvider) 1329 return ((ITreeContentProvider) provider).getChildren(parent); 1330 return new Object [0]; 1331 } 1332 1333 Object [] contentProviderGetRoots(Object parent) { 1334 IContentProvider provider = getContentProvider(); 1335 if (provider instanceof ITreeContentProvider) 1336 return ((ITreeContentProvider) provider).getElements(parent); 1337 return new Object [0]; 1338 } 1339 1340 protected void createChildren(Widget widget) { 1341 refresh(true); 1342 } 1343 1344 private JobItem createItem(Object 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 element) { 1367 } 1368 1369 1372 private boolean filtered(Object element) { 1373 1374 if (element == null) 1375 return true; 1376 1377 if (!dialogContext && ProgressViewUpdater.getSingleton().debug) return false; 1379 1380 if (element instanceof JobInfo) 1381 return jobFiltered((JobInfo) element); 1382 1383 if (element instanceof GroupInfo) { 1384 Object [] 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 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 element, boolean create) { 1400 JobTreeItem ji = (JobTreeItem) map.get(element); 1401 if (ji == null && create) { 1402 JobTreeElement jte = (JobTreeElement) element; 1403 Object 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 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 () { 1428 public void run() { 1429 if (DEBUG) 1430 System.err.println(" forced remove"); JobTreeItem ji = findJobItem(jte, false); 1432 if (ji != null && !ji.isDisposed() && ji.remove()) 1433 relayout(true, true); 1434 } 1435 }); 1436 } 1437 } 1438 1439 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 1459 private Font getDefaultFont(){ 1460 return JFaceResources.getDefaultFont(); 1461 } 1462 1463 1467 private FontData[] getDefaultFontData(){ 1468 return JFaceResources.getDefaultFont().getFontData(); 1469 } 1470 1471 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 getFinishedString(JobTreeElement jte, String name, 1484 boolean withTime) { 1485 String 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 1497 private Color getHighlightColor(){ 1498 return JFaceColors.getErrorText(getControl().getDisplay()); 1499 } 1500 1501 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 getJobNameAndStatus(JobInfo ji, Job job, boolean terminated, 1526 boolean withTime) { 1527 String 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 1559 public ISelection getSelection() { 1560 if (list.isDisposed()) 1561 return new StructuredSelection(); 1562 ArrayList l = new ArrayList (); 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 map2 = new HashMap (); 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 getTimeString(JobTreeElement jte) { 1594 Date 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 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"); boolean changed = false; 1636 boolean countChanged = false; 1637 JobTreeItem lastAdded = null; 1638 1639 Object [] roots = contentProviderGetRoots(getInput()); 1640 HashSet modelJobs = new HashSet (); 1641 for (int z = 0; z < roots.length; z++) 1642 modelJobs.add(roots[z]); 1643 1644 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"); changed |= ji.refresh(); 1652 } else { 1653 if (DEBUG) 1654 System.err.println(" remove: " + ji.jobTreeElement); if (ji.remove()) 1656 countChanged = changed = true; 1657 } 1658 } 1659 1660 for (int i = 0; i < roots.length; i++) { 1662 Object element = roots[i]; 1663 if (filtered(element)) 1664 continue; 1665 if (findJobItem(element, false) == null) { 1666 if (DEBUG) 1667 System.err.println(" added"); lastAdded = createItem(element); 1669 changed = countChanged = true; 1670 } 1671 } 1672 if (!dialogContext) { 1674 JobTreeElement[] infos = finishedJobs.getJobInfos(); 1675 for (int i = 0; i < infos.length; i++) { 1676 Object 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 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) { ji = findJobItem(element, true); 1708 relayout(true, true); 1709 } else { if (ji.refresh()) 1711 relayout(true, true); 1712 } 1713 } 1714 1715 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 [] elements) { 1732 if (list.isDisposed()) 1733 return; 1734 if (DEBUG) 1735 System.err.println("remove"); 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 1751 public void removed(final JobTreeElement info) { 1752 if (list != null && !list.isDisposed()) { 1753 list.getDisplay().asyncExec(new Runnable () { 1754 public void run() { 1755 if (info != null) { JobTreeItem ji = findJobItem(info, false); 1757 if (ji != null && ji.jobTerminated) { 1758 ji.dispose(); 1759 relayout(true, true); 1760 } 1761 } else { 1762 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) { 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) { 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 } 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 items) { 1913 } 1914 1915 public void setUseHashlookup(boolean b) { 1916 } 1917 1918 protected void showItem(Item item) { 1919 } 1920 1921 private String stripPercent(String s) { 1922 int l = s.length(); 1923 if (l > 0) { 1924 if (s.charAt(0) == '(') { 1925 int pos = s.indexOf("%) "); if (pos >= 0) 1927 s = s.substring(pos + 3); 1928 } else if (s.charAt(l - 1) == ')') { 1929 int pos = s.lastIndexOf(": ("); if (pos >= 0) 1931 s = s.substring(0, pos); 1932 } 1933 } 1934 return s; 1935 } 1936} 1937 | Popular Tags |