blob: fe45ecc8741ef75d4ef3ef7f1f3fa9012ed541a4 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal.progress;
import java.net.URL;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.TreeListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.internal.misc.Assert;
import org.eclipse.ui.internal.util.ImageSupport;
import org.eclipse.ui.progress.IProgressConstants;
public class NewProgressViewer extends TreeViewer implements FinishedJobs.KeptJobsListener {
static final boolean DEBUG= false;
static final boolean isCarbon = "carbon".equals(SWT.getPlatform()); //$NON-NLS-1$
private static String ELLIPSIS = ProgressMessages.getString("ProgressFloatingWindow.EllipsisValue"); //$NON-NLS-1$
static final QualifiedName KEEP_PROPERTY= IProgressConstants.KEEP_PROPERTY;
static final QualifiedName KEEPONE_PROPERTY= IProgressConstants.KEEPONE_PROPERTY;
static final QualifiedName ICON_PROPERTY= IProgressConstants.ICON_PROPERTY;
private FinishedJobs finishedJobs;
private boolean dialogContext; // viewer runs in dialog: filter accordingly
private HashMap map= new HashMap();
private JobTreeItem highlightItem;
private Job highlightJob;
private Composite list;
private ScrolledComposite scroller;
private Color linkColor;
private Color linkColor2;
private Color errorColor;
private Color errorColor2;
private Color darkColor;
private Color lightColor;
private Color textColor;
private Color selectedColor;
private Color selectedTextColor;
private Color highlightColor;
private Font defaultFont= JFaceResources.getDefaultFont();
// to be disposed
private Cursor handCursor;
private Cursor normalCursor;
private Image defaultJobIcon;
private Image cancelJobIcon, cancelJobDIcon;
private Image clearJobIcon, clearJobDIcon;
private Font boldFont;
private Font smallerFont;
//
class ListLayout extends Layout {
static final int VERTICAL_SPACING = 1;
boolean refreshBackgrounds;
protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
int w= 0, h= -VERTICAL_SPACING;
Control[] cs= composite.getChildren();
for (int i= 0; i < cs.length; i++) {
Control c= cs[i];
Point e= c.computeSize(SWT.DEFAULT, SWT.DEFAULT, flushCache);
w= Math.max(w, e.x);
h+= e.y+VERTICAL_SPACING;
}
return new Point(w, h);
}
protected void layout(Composite composite, boolean flushCache) {
int x= 0, y= 0;
Point e= composite.getSize();
Control[] cs= getSortedChildren();
boolean dark= (cs.length % 2) == 1;
for (int i= 0; i < cs.length; i++) {
Control c= cs[i];
Point s= c.computeSize(e.x, SWT.DEFAULT, flushCache);
c.setBounds(x, y, s.x, s.y);
y+= s.y+VERTICAL_SPACING;
if (refreshBackgrounds && c instanceof JobItem) {
((JobItem)c).updateBackground(dark);
dark= !dark;
}
}
}
}
abstract class JobTreeItem extends Canvas implements Listener {
JobTreeElement jobTreeElement;
boolean jobTerminated;
boolean keepItem;
JobTreeItem(Composite parent, JobTreeElement info, int flags) {
super(parent, flags);
jobTreeElement= info;
map.put(jobTreeElement, this);
addListener(SWT.Dispose, this);
}
void init(JobTreeElement info) {
if (jobTreeElement != info) {
map.remove(jobTreeElement);
jobTreeElement= info;
map.put(jobTreeElement, this);
}
refresh();
}
protected void dump(String message) {
if (DEBUG) {
System.out.println(message + " (" + jobTreeElement.hashCode() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
System.out.println(" terminated: " + jobTerminated); //$NON-NLS-1$
if (jobTreeElement instanceof JobInfo)
System.out.println(" type: JobInfo"); //$NON-NLS-1$
else if (jobTreeElement instanceof SubTaskInfo)
System.out.println(" type: SubTaskInfo"); //$NON-NLS-1$
else if (jobTreeElement instanceof GroupInfo)
System.out.println(" type: GroupInfo"); //$NON-NLS-1$
Job job= getJob();
if (job != null) {
System.out.println(" name: " + job.getName()); //$NON-NLS-1$
System.out.println(" isSystem: " + job.isSystem()); //$NON-NLS-1$
}
System.out.println(" keep: " + keepItem); //$NON-NLS-1$
}
}
void setKept() {
if (!jobTerminated) {
keepItem= jobTerminated= true;
remove(); // bring to keep mode
}
}
public void handleEvent(Event e) {
switch (e.type) {
case SWT.Dispose:
map.remove(jobTreeElement);
break;
}
}
Job getJob() {
if (jobTreeElement instanceof JobInfo)
return ((JobInfo)jobTreeElement).getJob();
if (jobTreeElement instanceof SubTaskInfo)
return ((SubTaskInfo)jobTreeElement).jobInfo.getJob();
return null;
}
public boolean kill(boolean refresh, boolean broadcast) {
return true;
}
boolean checkKeep() {
if (jobTreeElement instanceof JobInfo && FinishedJobs.keep((JobInfo) jobTreeElement))
setKeep();
return keepItem;
}
void setKeep() {
keepItem= true;
Composite parent= getParent();
if (parent instanceof JobTreeItem) {
((JobTreeItem)parent).keepItem= true;
}
}
abstract boolean refresh();
public boolean remove() {
jobTerminated= true;
refresh();
if (dialogContext || !keepItem) {
dispose();
return true;
}
return false;
}
}
/*
* Label with hyperlink capability.
*/
class Hyperlink extends JobTreeItem implements Listener, IPropertyChangeListener {
final static int MARGINWIDTH = 1;
final static int MARGINHEIGHT = 1;
boolean hasFocus;
boolean mouseOver;
boolean isError;
boolean linkEnabled;
boolean foundImage;
String text= ""; //$NON-NLS-1$
IAction gotoAction;
IStatus result;
JobItem jobitem;
Hyperlink(JobItem parent, JobTreeElement info) {
super(parent, info, SWT.NO_BACKGROUND);
jobitem= parent;
setFont(smallerFont);
addListener(SWT.KeyDown, this);
addListener(SWT.Paint, this);
addListener(SWT.MouseEnter, this);
addListener(SWT.MouseExit, this);
addListener(SWT.MouseDown, this);
addListener(SWT.MouseUp, this);
addListener(SWT.FocusIn, this);
addListener(SWT.FocusOut, this);
refresh();
}
boolean isLinkEnabled() {
return !dialogContext && linkEnabled;
}
public void handleEvent(Event e) {
super.handleEvent(e);
switch (e.type) {
case SWT.Dispose:
if (gotoAction != null) {
gotoAction.removePropertyChangeListener(this);
gotoAction= null;
}
break;
case SWT.KeyDown:
if (e.character == '\r')
handleActivate();
else if (e.keyCode == SWT.DEL) {
cancelSelection();
} else {
select(null, e);
}
break;
case SWT.Paint:
paint(e.gc);
break;
case SWT.FocusIn :
hasFocus = true;
case SWT.MouseEnter :
if (isLinkEnabled()) {
mouseOver = true;
redraw();
}
break;
case SWT.FocusOut :
hasFocus = false;
case SWT.MouseExit :
if (isLinkEnabled()) {
mouseOver = false;
redraw();
}
break;
case SWT.DefaultSelection :
handleActivate();
break;
case SWT.MouseDown :
if (!isLinkEnabled())
select((JobItem) getParent(), e);
break;
case SWT.MouseUp :
if (isLinkEnabled()) {
Point size= getSize();
if (e.button != 1 || e.x < 0 || e.y < 0 || e.x >= size.x || e.y >= size.y)
return;
handleActivate();
}
break;
}
}
private void setText(String t) {
if (t == null)
t= ""; //$NON-NLS-1$
if (!t.equals(text)) {
text= t;
updateToolTip();
redraw();
}
}
private void setAction(IAction action) {
if (action == gotoAction)
return;
if (gotoAction != null)
gotoAction.removePropertyChangeListener(this);
gotoAction= action;
if (gotoAction != null) {
// temporary workaround for CVS actionWrapper problem
String actionName= gotoAction.getClass().getName();
if (actionName.indexOf("RefreshSubscriberJob$2") >= 0) //$NON-NLS-1$
gotoAction.setEnabled(false);
// end of temporary workaround
gotoAction.addPropertyChangeListener(this);
}
updateToolTip();
setLinkEnable(action != null && action.isEnabled());
}
private void setLinkEnable(boolean enable) {
if (enable != linkEnabled) {
linkEnabled= enable;
if (isLinkEnabled())
setCursor(handCursor);
updateToolTip();
redraw();
}
}
private void updateToolTip() {
String tt= text;
if (isLinkEnabled() && gotoAction != null && gotoAction.isEnabled()) {
String tooltip= gotoAction.getToolTipText();
if (tooltip != null && tooltip.trim().length() > 0)
tt= tooltip;
}
String oldtt= getToolTipText();
if (oldtt == null || !oldtt.equals(tt))
setToolTipText(tt);
}
public void propertyChange(PropertyChangeEvent event) {
if (gotoAction != null) {
getDisplay().asyncExec(new Runnable() {
public void run() {
if (!isDisposed()) {
checkKeep();
setLinkEnable(gotoAction != null && gotoAction.isEnabled());
}
}
});
}
}
public Point computeSize(int wHint, int hHint, boolean changed) {
checkWidget();
int innerWidth= wHint;
if (innerWidth != SWT.DEFAULT)
innerWidth -= MARGINWIDTH * 2;
GC gc= new GC(this);
gc.setFont(getFont());
Point extent= gc.textExtent(text);
gc.dispose();
return new Point(extent.x + 2 * MARGINWIDTH, extent.y + 2 * MARGINHEIGHT);
}
private Color getFGColor() {
if (jobitem.selected)
return selectedTextColor;
if (isLinkEnabled()) {
if (mouseOver) {
if (isError)
return errorColor2;
return linkColor2;
}
if (isError)
return errorColor;
return linkColor;
}
return textColor;
}
protected void paint(GC gc) {
Rectangle clientArea= getClientArea();
if (clientArea.isEmpty())
return;
Color fg= getFGColor(), bg= getBackground();
if (jobitem.selected)
bg= selectedColor;
Image buffer= null;
GC bufferGC= gc;
if (!isCarbon) {
buffer= new Image(getDisplay(), clientArea.width, clientArea.height);
buffer.setBackground(bg);
bufferGC= new GC(buffer, gc.getStyle());
}
bufferGC.setForeground(fg);
bufferGC.setBackground(bg);
bufferGC.fillRectangle(0, 0, clientArea.width, clientArea.height);
bufferGC.setFont(getFont());
String t= shortenText(bufferGC, clientArea.width, text);
bufferGC.drawText(t, MARGINWIDTH, MARGINHEIGHT, true);
int sw= bufferGC.stringExtent(t).x;
if (isLinkEnabled()) {
FontMetrics fm= bufferGC.getFontMetrics();
int lineY= clientArea.height - MARGINHEIGHT - fm.getDescent() + 1;
bufferGC.drawLine(MARGINWIDTH, lineY, MARGINWIDTH + sw, lineY);
if (hasFocus)
bufferGC.drawFocus(0, 0, sw, clientArea.height);
}
if (buffer != null) {
gc.drawImage(buffer, 0, 0);
bufferGC.dispose();
buffer.dispose();
}
}
protected boolean handleActivate() {
if (isLinkEnabled() && gotoAction != null && gotoAction.isEnabled()) {
jobitem.locked= true;
gotoAction.run();
if (jobitem.jobTerminated)
jobitem.kill(true, true);
return true;
}
return false;
}
public boolean refresh() {
if (jobTreeElement == null) // shouldn't happen
return false;
Job job= getJob();
if (job != null) {
// check for icon property and propagate to parent
if (jobitem.image == null)
jobitem.updateIcon(job);
// check for action property
Object property= job.getProperty(IProgressConstants.ACTION_PROPERTY);
if (property instanceof IAction)
setAction((IAction) property);
// poll for result status
IStatus status= job.getResult();
if (status != null && status != result) {
result= status;
if (result.getSeverity() == IStatus.ERROR) {
setKeep();
isError= true;
setAction(new Action() {
public void run() {
String title= ProgressMessages.getString("NewProgressView.errorDialogTitle"); //$NON-NLS-1$
String msg= ProgressMessages.getString("NewProgressView.errorDialogMessage"); //$NON-NLS-1$
ErrorDialog.openError(getShell(), title, msg, result);
}
});
}
}
}
checkKeep();
// now build the string for displaying
String name= null;
if (jobTreeElement instanceof SubTaskInfo) { // simple job case
SubTaskInfo sti= (SubTaskInfo) jobTreeElement;
String taskName= null;
if (sti.jobInfo != null) {
TaskInfo ti= sti.jobInfo.getTaskInfo();
if (ti != null)
taskName= ti.getTaskName();
}
if (jobTerminated && result != null) {
name= result.getMessage();
if (taskName != null && taskName.trim().length() > 0)
name= ProgressMessages.format("JobInfo.TaskFormat", new Object[]{ taskName, name}); //$NON-NLS-1$
} else {
name= jobTreeElement.getDisplayString();
if (taskName != null && taskName.trim().length() > 0)
name= ProgressMessages.format("JobInfo.TaskFormat2", new Object[]{ taskName, name}); //$NON-NLS-1$
}
if (name.length() == 0) {
dispose();
return true;
}
} else if (jobTreeElement instanceof JobInfo) { // group case
JobInfo ji= (JobInfo) jobTreeElement;
if (/*jobTerminated && */ result != null) {
name= result.getMessage();
if (name == null || name.trim().length() == 0 || "OK".equals(name)) { //$NON-NLS-1$
if (!keepItem) {
dispose();
return true;
}
}
} else {
// get the Job name
name= getJobNameAndStatus(ji, job, jobTerminated, false);
// get percentage and task name
String taskName= null;
TaskInfo info = ji.getTaskInfo();
if (info != null) {
taskName= info.getTaskName();
int percent = info.getPercentDone();
if (percent >= 0 && percent <= 100) {
if (taskName != null)
taskName= ProgressMessages.format("JobInfo.Percent", //$NON-NLS-1$
new Object[]{ Integer.toString(percent), taskName});
else
taskName= ProgressMessages.format("JobInfo.Percent2", //$NON-NLS-1$
new Object[]{ Integer.toString(percent) });
}
}
// get sub task name
String subTaskName= null;
Object[] subtasks= ji.getChildren();
if (subtasks != null && subtasks.length > 0) {
JobTreeElement sub= (JobTreeElement) subtasks[0];
if (sub != null)
subTaskName= sub.getDisplayString();
}
boolean hasTask= taskName != null && taskName.trim().length() > 0;
boolean hasSubTask= subTaskName != null && subTaskName.trim().length() > 0;
if (hasTask && hasSubTask) {
name= ProgressMessages.format("JobInfo.Format", new Object[]{ name, taskName, subTaskName}); //$NON-NLS-1$
} else if (hasTask) {
name= ProgressMessages.format("JobInfo.TaskFormat", new Object[]{ name, taskName}); //$NON-NLS-1$
} else if (hasSubTask) {
name= ProgressMessages.format("JobInfo.TaskFormat", new Object[]{ name, subTaskName}); //$NON-NLS-1$
}
}
if (highlightJob == job)
highlightItem= jobitem;
}
if (name == null)
name= jobTreeElement.getDisplayString();
setText(name);
return false;
}
}
/*
* An SWT widget representing a JobModel
*/
class JobItem extends JobTreeItem {
static final int MARGIN= 2;
static final int HGAP= 7;
static final int VGAP= 1;
static final int MAX_PROGRESS_HEIGHT= 12;
static final int MIN_ICON_SIZE= 16;
int cachedWidth= -1;
int cachedHeight= -1;
private Image image;
private boolean disposeImage;
private boolean locked; // don't add children
Label nameItem;
Label iconItem;
ProgressBar progressBar;
ToolBar actionBar;
ToolItem actionButton;
ToolItem gotoButton;
boolean selected;
JobItem(Composite parent, JobTreeElement info) {
super(parent, info, SWT.NONE);
Assert.isNotNull(info);
Display display= getDisplay();
iconItem= new Label(this, SWT.NONE);
iconItem.addListener(SWT.MouseDown, this);
updateIcon(getJob());
if (image == null)
iconItem.setImage(defaultJobIcon);
nameItem= new Label(this, SWT.NONE);
nameItem.setFont(boldFont);
nameItem.addListener(SWT.MouseDown, this);
actionBar= new ToolBar(this, SWT.FLAT);
actionBar.setCursor(normalCursor); // set cursor to overwrite any busy cursor we might have
actionButton= new ToolItem(actionBar, SWT.NONE);
actionButton.setImage(cancelJobIcon);
actionButton.setDisabledImage(cancelJobDIcon);
actionButton.setToolTipText(ProgressMessages.getString("NewProgressView.CancelJobToolTip")); //$NON-NLS-1$
actionButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
actionButton.setEnabled(false);
cancelOrRemove();
}
});
addListener(SWT.MouseDown, this);
addListener(SWT.KeyDown, this);
addControlListener(new ControlAdapter() {
public void controlResized(ControlEvent e) {
handleResize();
}
});
refresh();
}
void createChild(JobTreeElement jte) {
if (!locked)
new Hyperlink(this, jte);
}
void updateIcon(Job job) {
if (job != null) {
Image im= null;
boolean dispImage= false;
Display display= getDisplay();
Object property= job.getProperty(ICON_PROPERTY);
if (property instanceof ImageDescriptor) {
dispImage= true;
im= ((ImageDescriptor) property).createImage(display);
} else if (property instanceof URL) {
dispImage= true;
im= ImageDescriptor.createFromURL((URL) property).createImage(display);
} else {
dispImage= false;
im= ProgressManager.getInstance().getIconFor(job);
}
if (im != null && im != image) {
if (disposeImage && image != null) {
if (DEBUG) System.err.println("JobItem.setImage: disposed image"); //$NON-NLS-1$
image.dispose();
}
image= im;
disposeImage= dispImage;
if (iconItem != null)
iconItem.setImage(image);
}
}
}
boolean cancelOrRemove() {
if (jobTerminated)
return kill(true, true);
jobTreeElement.cancel();
return false;
}
public void handleEvent(Event event) {
switch (event.type) {
case SWT.Dispose:
super.handleEvent(event);
if (disposeImage && image != null && !image.isDisposed()) {
if (DEBUG) System.err.println("JobItem.image disposed"); //$NON-NLS-1$
image.dispose();
}
image= null;
break;
case SWT.KeyDown:
if (event.character == '\r') {
doSelection();
} else if (event.character == '\t') {
scroller.getParent().forceFocus();
} else if (event.keyCode == SWT.DEL) {
cancelSelection();
} else {
select(null, event);
}
break;
case SWT.MouseDown:
forceFocus();
select(JobItem.this, event);
break;
default:
super.handleEvent(event);
break;
}
}
public boolean remove() {
jobTerminated= true;
if (finishedJobs.isFinished(jobTreeElement)) {
keepItem= true;
}
// propagate status down
Control[] children= getChildren();
for (int i= 0; i < children.length; i++) {
if (children[i] instanceof JobTreeItem)
((JobTreeItem)children[i]).jobTerminated= true;
}
if (! dialogContext) { // we never keep jobs in dialogs
if (!keepItem)
checkKeep();
if (keepItem)
return aboutToKeep();
}
return super.remove();
}
private boolean aboutToKeep() {
boolean changed= false;
// finish progress reporting
if (progressBar != null && !progressBar.isDisposed()) {
progressBar.setSelection(100);
progressBar.dispose();
changed= true;
}
// turn cancel button in remove button
if (!actionButton.isDisposed()) {
actionButton.setImage(clearJobIcon);
actionButton.setDisabledImage(clearJobDIcon);
actionButton.setToolTipText(ProgressMessages.getString("NewProgressView.RemoveJobToolTip")); //$NON-NLS-1$
actionButton.setEnabled(true);
changed= true;
}
changed |= refresh();
Control[] c= getChildren();
for (int i= 0; i < c.length; i++) {
if (c[i] instanceof JobTreeItem)
changed |= ((JobTreeItem) c[i]).refresh();
}
return changed;
}
public boolean kill(boolean refresh, boolean broadcast) {
if (jobTerminated) {
if (broadcast)
finishedJobs.remove(jobTreeElement);
else {
dispose();
relayout(refresh, refresh);
return true;
}
}
return false;
}
void handleResize() {
Point e= getSize();
Point e1= iconItem.computeSize(SWT.DEFAULT, SWT.DEFAULT); e1.x= MIN_ICON_SIZE;
Point e2= nameItem.computeSize(SWT.DEFAULT, SWT.DEFAULT);
Point e5= actionBar.computeSize(SWT.DEFAULT, SWT.DEFAULT);
int iw= e.x-MARGIN-HGAP-e5.x-MARGIN;
int indent= 16+HGAP;
int y= MARGIN;
int h= Math.max(e1.y, e2.y);
nameItem.setBounds(MARGIN+e1.x+HGAP, y+(h-e2.y)/2, iw-e1.x-HGAP, e2.y);
y+= h;
if (progressBar != null && !progressBar.isDisposed()) {
Point e3= progressBar.computeSize(SWT.DEFAULT, SWT.DEFAULT); e3.y= MAX_PROGRESS_HEIGHT;
y+= VGAP+1;
progressBar.setBounds(MARGIN+indent, y, iw-indent, e3.y);
y+= e3.y;
}
Control[] cs= getChildren();
for (int i= 0; i < cs.length; i++) {
if (cs[i] instanceof Hyperlink) {
Point e4= cs[i].computeSize(SWT.DEFAULT, SWT.DEFAULT);
y+= VGAP;
cs[i].setBounds(MARGIN+indent, y, iw-indent, e4.y);
y+= e4.y;
}
}
int hm= (MARGIN+HGAP)/2;
int vm= (y-e1.y)/2;
if (hm < (y-e1.y)/2)
vm= hm;
iconItem.setBounds(hm, vm, e1.x, e1.y);
actionBar.setBounds(e.x-MARGIN-e5.x, (e.y-e5.y)/2, e5.x, e5.y);
}
public Point computeSize(int wHint, int hHint, boolean changed) {
if (changed || cachedHeight <= 0 || cachedWidth <= 0) {
Point e1= iconItem.computeSize(SWT.DEFAULT, SWT.DEFAULT); e1.x= MIN_ICON_SIZE;
Point e2= nameItem.computeSize(SWT.DEFAULT, SWT.DEFAULT);
cachedWidth= MARGIN + e1.x + HGAP + 100 + MARGIN;
cachedHeight= MARGIN + Math.max(e1.y, e2.y);
if (progressBar != null && !progressBar.isDisposed()) {
cachedHeight+= 1;
Point e3= progressBar.computeSize(SWT.DEFAULT, SWT.DEFAULT); e3.y= MAX_PROGRESS_HEIGHT;
cachedHeight+= VGAP + e3.y;
}
Control[] cs= getChildren();
for (int i= 0; i < cs.length; i++) {
if (cs[i] instanceof Hyperlink) {
Point e4= cs[i].computeSize(SWT.DEFAULT, SWT.DEFAULT);
cachedHeight+= VGAP + e4.y;
}
}
cachedHeight+= MARGIN;
}
int w= wHint == SWT.DEFAULT ? cachedWidth : wHint;
int h= hHint == SWT.DEFAULT ? cachedHeight : hHint;
return new Point(w, h);
}
/*
* Update the background colors.
*/
void updateBackground(boolean dark) {
Color fg, bg;
if (selected) {
fg= selectedTextColor;
bg= selectedColor;
} else {
if (highlightJob != null && (highlightJob == getJob() || highlightItem == this))
fg= highlightColor;
else
fg= textColor;
bg= dark ? darkColor : lightColor;
}
setForeground(fg);
setBackground(bg);
Control[] cs= getChildren();
for (int i= 0; i < cs.length; i++) {
if (!(cs[i] instanceof ProgressBar)) {
cs[i].setForeground(fg);
cs[i].setBackground(bg);
}
}
}
boolean setPercentDone(int percentDone) {
if (percentDone >= 0 && percentDone < 100) {
if (progressBar == null) {
progressBar= new ProgressBar(this, SWT.HORIZONTAL);
progressBar.setMaximum(100);
progressBar.setSelection(percentDone);
progressBar.addListener(SWT.MouseDown, this);
return true;
} else if (!progressBar.isDisposed())
progressBar.setSelection(percentDone);
} else {
if (progressBar == null) {
progressBar= new ProgressBar(this, SWT.HORIZONTAL | SWT.INDETERMINATE);
progressBar.addListener(SWT.MouseDown, this);
return true;
}
}
return false;
}
boolean isCanceled() {
if (jobTreeElement instanceof JobInfo)
return ((JobInfo)jobTreeElement).isCanceled();
return false;
}
IStatus getResult() {
//checkKeep();
if (jobTerminated) {
Job job= getJob();
if (job != null)
return job.getResult();
}
return null;
}
/*
* Update the widgets from the model.
*/
public boolean refresh() {
if (isDisposed())
return false;
boolean changed= false;
boolean isGroup= jobTreeElement instanceof GroupInfo;
Object[] roots= contentProviderGetChildren(jobTreeElement);
Job job= getJob();
// poll for properties
checkKeep();
if (image == null && job != null)
updateIcon(job);
// name
String name= null;
if (isGroup) {
name= getGroupHeader((GroupInfo) jobTreeElement);
} else if (jobTreeElement instanceof JobInfo)
name= getJobNameAndStatus((JobInfo) jobTreeElement, job, jobTerminated, true);
if (name == null)
name= stripPercent(jobTreeElement.getDisplayString());
if (highlightJob != null && (highlightJob == job || highlightItem == this))
name= ProgressMessages.format("JobInfo.BlocksUserOperationFormat", new Object[]{name}); //$NON-NLS-1$
nameItem.setToolTipText(name);
nameItem.setText(shortenText(nameItem, name));
// percentage
if (jobTreeElement instanceof JobInfo) {
TaskInfo ti= ((JobInfo)jobTreeElement).getTaskInfo();
if (ti != null)
changed |= setPercentDone(ti.getPercentDone());
} else if (isGroup) {
if (roots.length == 1 && roots[0] instanceof JobTreeElement) {
TaskInfo ti= ((JobInfo)roots[0]).getTaskInfo();
if (ti != null)
changed |= setPercentDone(ti.getPercentDone());
} else {
GroupInfo gi= (GroupInfo) jobTreeElement;
changed |= setPercentDone(gi.getPercentDone());
}
}
// children
if (!jobTreeElement.hasChildren())
return changed;
Control[] children= getChildren();
int n= 0;
for (int i= 0; i < children.length; i++)
if (children[i] instanceof Hyperlink)
n++;
if (!isGroup && roots.length == n) { // reuse all children
int z= 0;
for (int i= 0; i < children.length; i++) {
if (children[i] instanceof Hyperlink) {
Hyperlink l= (Hyperlink) children[i];
l.init((JobTreeElement) roots[z++]);
}
}
} else {
HashSet modelJobs= new HashSet();
for (int z= 0; z < roots.length; z++)
modelJobs.add(roots[z]);
// find all removed
HashSet shownJobs= new HashSet();
for (int i= 0; i < children.length; i++) {
if (children[i] instanceof Hyperlink) {
JobTreeItem ji= (JobTreeItem)children[i];
shownJobs.add(ji.jobTreeElement);
if (modelJobs.contains(ji.jobTreeElement)) {
ji.refresh();
} else {
changed |= ji.remove();
}
}
}
// find all added
for (int i= 0; i < roots.length; i++) {
Object element= roots[i];
if (!shownJobs.contains(element)) {
createChild((JobTreeElement)element);
changed= true;
}
}
}
return changed;
}
private String getGroupHeader(GroupInfo gi) {
String name= stripPercent(jobTreeElement.getDisplayString());
if (jobTerminated)
return getFinishedString(gi, name, true);
return name;
}
}
private String getJobNameAndStatus(JobInfo ji, Job job, boolean terminated, boolean withTime) {
String name= job.getName();
if (job.isSystem())
name= ProgressMessages.format("JobInfo.System", new Object[]{name}); //$NON-NLS-1$
if (ji.isCanceled())
return ProgressMessages.format("JobInfo.Cancelled", new Object[]{name}); //$NON-NLS-1$
if (terminated)
return getFinishedString(ji, name, withTime);
if (ji.isBlocked()) {
IStatus blockedStatus= ji.getBlockedStatus();
return ProgressMessages.format("JobInfo.Blocked", //$NON-NLS-1$
new Object[]{name, blockedStatus.getMessage()});
}
switch (job.getState()) {
case Job.RUNNING:
return name;
case Job.SLEEPING:
return ProgressMessages.format("JobInfo.Sleeping", new Object[]{name}); //$NON-NLS-1$
default:
return ProgressMessages.format("JobInfo.Waiting", new Object[]{name}); //$NON-NLS-1$
}
}
private String getFinishedString(JobTreeElement jte, String name, boolean withTime) {
String time= null;
if (withTime)
time= getTimeString(jte);
if (time != null)
return ProgressMessages.format("JobInfo.FinishedAt", new Object[]{ name, time}); //$NON-NLS-1$
return ProgressMessages.format("JobInfo.Finished", new Object[]{name}); //$NON-NLS-1$
}
private String getTimeString(JobTreeElement jte) {
Date date= finishedJobs.getFinishDate(jte);
if (date != null)
return DateFormat.getTimeInstance(DateFormat.SHORT).format(date);
return null;
}
private String stripPercent(String s) {
int l= s.length();
if (l > 0) {
if (s.charAt(0) == '(') {
int pos= s.indexOf("%) "); //$NON-NLS-1$
if (pos >= 0)
s= s.substring(pos+3);
} else if (s.charAt(l-1) == ')') {
int pos= s.lastIndexOf(": ("); //$NON-NLS-1$
if (pos >= 0)
s= s.substring(0, pos);
}
}
return s;
}
/**
* Create a new ProgressViewer
*/
public NewProgressViewer(Composite parent, int flags) {
super(parent, flags);
Tree c = getTree();
if (c instanceof Tree)
c.dispose();
dialogContext= (flags & SWT.BORDER) != 0; // hack to determine context
finishedJobs= FinishedJobs.getInstance();
finishedJobs.addListener(this);
Display display= parent.getDisplay();
handCursor= new Cursor(display, SWT.CURSOR_HAND);
normalCursor= new Cursor(display, SWT.CURSOR_ARROW);
defaultJobIcon= ImageSupport.getImageDescriptor("icons/full/progress/progress_task.gif").createImage(display); //$NON-NLS-1$
cancelJobIcon= ImageSupport.getImageDescriptor("icons/full/elcl16/progress_stop.gif").createImage(display); //$NON-NLS-1$
cancelJobDIcon= ImageSupport.getImageDescriptor("icons/full/dlcl16/progress_stop.gif").createImage(display); //$NON-NLS-1$
clearJobIcon= ImageSupport.getImageDescriptor("icons/full/elcl16/progress_rem.gif").createImage(display); //$NON-NLS-1$
clearJobDIcon= ImageSupport.getImageDescriptor("icons/full/dlcl16/progress_rem.gif").createImage(display); //$NON-NLS-1$
boldFont= defaultFont;
FontData fds[]= defaultFont.getFontData();
if (fds.length > 0) {
FontData fd= fds[0];
int h= fd.getHeight();
boldFont= new Font(display, fd.getName(), h, fd.getStyle() | SWT.BOLD);
smallerFont= new Font(display, fd.getName(), h, fd.getStyle());
}
int shift= isCarbon ? -25 : -10; // Mac has different Gamma value
lightColor= display.getSystemColor(SWT.COLOR_LIST_BACKGROUND);
darkColor= new Color(display, Math.max(0, lightColor.getRed()+shift),
Math.max(0, lightColor.getGreen()+shift),
Math.max(0, lightColor.getBlue()+shift));
textColor= display.getSystemColor(SWT.COLOR_LIST_FOREGROUND);
selectedTextColor= display.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT);
selectedColor= display.getSystemColor(SWT.COLOR_LIST_SELECTION);
linkColor= display.getSystemColor(SWT.COLOR_DARK_BLUE);
linkColor2= display.getSystemColor(SWT.COLOR_BLUE);
errorColor= display.getSystemColor(SWT.COLOR_DARK_RED);
errorColor2= display.getSystemColor(SWT.COLOR_RED);
highlightColor= display.getSystemColor(SWT.COLOR_DARK_RED);
scroller= new ScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL | flags);
int height= defaultFont.getFontData()[0].getHeight();
scroller.getVerticalBar().setIncrement(height * 2);
scroller.setExpandHorizontal(true);
scroller.setExpandVertical(true);
list= new Composite(scroller, SWT.NONE);
list.setFont(defaultFont);
list.setBackground(lightColor);
list.setLayout(new ListLayout());
list.addListener(SWT.MouseDown, new Listener() {
public void handleEvent(Event event) {
select(null, event); // clear selection
}
});
scroller.addListener(SWT.Dispose, new Listener() {
public void handleEvent(Event event) {
finishedJobs.removeListener(NewProgressViewer.this);
defaultJobIcon.dispose();
cancelJobIcon.dispose();
cancelJobDIcon.dispose();
clearJobIcon.dispose();
clearJobDIcon.dispose();
handCursor.dispose();
normalCursor.dispose();
if (boldFont != defaultFont)
boldFont.dispose();
if (smallerFont != defaultFont)
smallerFont.dispose();
darkColor.dispose();
NewProgressViewer.this.handleDispose(null);
}
});
scroller.setContent(list);
// refresh UI
refresh(true);
}
public void setFocus() {
if (list != null) {
Control[] cs= list.getChildren();
for (int i= 0; i < cs.length; i++) {
JobItem ji= (JobItem) cs[i];
if (ji.selected) {
ji.forceFocus();
return;
}
}
if (cs.length > 0)
cs[0].forceFocus();
}
}
public Control getControl() {
return scroller;
}
/**
* Returns true if given element is filtered (i.e. not shown).
*/
private boolean filtered(Object element) {
if (element == null)
return true;
if (!dialogContext && ProgressViewUpdater.getSingleton().debug) // display all in debug mode
return false;
if (element instanceof JobInfo)
return jobFiltered((JobInfo) element);
if (element instanceof GroupInfo) {
Object[] children = ((GroupInfo) element).getChildren();
for (int i= 0; i< children.length; i++)
if (jobFiltered((JobInfo) children[i]))
return true;
}
if (element instanceof TaskInfo) {
Object parent = ((TaskInfo) element).getParent();
if (parent instanceof JobInfo)
return jobFiltered((JobInfo) parent);
}
return false;
}
private boolean jobFiltered(JobInfo ji) {
Job job= ji.getJob();
if (job != null && job == highlightJob)
return false;
if (job == null || job.isSystem() || job.getState() == Job.SLEEPING)
return true;
return false;
}
public void add(Object parentElement, Object[] elements) {
if (DEBUG) System.err.println("add"); //$NON-NLS-1$
if (list.isDisposed())
return;
JobTreeItem lastAdded= null;
for (int i= 0; i < elements.length; i++)
if (!filtered(elements[i]))
lastAdded= findJobItem(elements[i], true);
relayout(true, true);
if (lastAdded != null)
reveal(lastAdded);
}
public void remove(Object[] elements) {
if (list.isDisposed())
return;
if (DEBUG) System.err.println("remove"); //$NON-NLS-1$
boolean changed= false;
for (int i= 0; i < elements.length; i++) {
JobTreeItem ji= findJobItem(elements[i], false);
if (ji != null)
changed |= ji.remove();
}
relayout(changed, changed);
}
public void refresh(Object element, boolean updateLabels) {
if (list.isDisposed())
return;
if (filtered(element))
return;
JobTreeItem ji= findJobItem(element, false);
if (ji == null) { // not found -> add it (workaround for #68151)
ji= findJobItem(element, true);
relayout(true, true);
} else { // just a refresh
if (ji.refresh())
relayout(true, true);
}
}
public void refresh(boolean updateLabels) {
if (list.isDisposed())
return;
if (DEBUG) System.err.println("refreshAll"); //$NON-NLS-1$
boolean changed= false;
boolean countChanged= false;
JobTreeItem lastAdded= null;
Object[] roots= contentProviderGetRoots(getInput());
HashSet modelJobs= new HashSet();
for (int z= 0; z < roots.length; z++)
modelJobs.add(roots[z]);
// find all removed
Control[] children= list.getChildren();
for (int i= 0; i < children.length; i++) {
JobItem ji= (JobItem)children[i];
if (modelJobs.contains(ji.jobTreeElement)) {
if (DEBUG) System.err.println(" refresh"); //$NON-NLS-1$
changed |= ji.refresh();
} else {
if (DEBUG) System.err.println(" remove: " + ji.jobTreeElement); //$NON-NLS-1$
if (ji.remove())
countChanged= changed= true;
}
}
// find all added
for (int i= 0; i < roots.length; i++) {
Object element= roots[i];
if (filtered(element))
continue;
if (findJobItem(element, false) == null) {
if (DEBUG) System.err.println(" added"); //$NON-NLS-1$
lastAdded= createItem(element);
changed= countChanged= true;
}
}
// now add kept finished jobs
if (!dialogContext) {
JobTreeElement[] infos= finishedJobs.getJobInfos();
for (int i= 0; i < infos.length; i++) {
Object element= infos[i];
if (filtered(element))
continue;
JobTreeItem jte= findJobItem(element, true);
if (jte != null) {
jte.setKept();
lastAdded= jte;
if (jte instanceof Hyperlink) {
JobItem p= (JobItem) jte.getParent();
p.setKept();
lastAdded= p;
}
changed= countChanged= true;
}
}
}
relayout(changed, countChanged);
if (lastAdded != null)
reveal(lastAdded);
}
private JobItem createItem(Object element) {
return new JobItem(list, (JobTreeElement) element);
}
private JobTreeItem findJobItem(Object element, boolean create) {
JobTreeItem ji= (JobTreeItem) map.get(element);
if (ji == null && create) {
JobTreeElement jte= (JobTreeElement) element;
Object parent= jte.getParent();
if (parent != null) {
JobTreeItem parentji= findJobItem(parent, true);
if (parentji instanceof JobItem && !(jte instanceof TaskInfo)) {
if (findJobItem(jte, false) == null) {
JobItem p= (JobItem)parentji;
p.createChild(jte);
}
}
} else {
ji= createItem(jte);
}
}
return ji;
}
public void reveal(JobTreeItem jti) {
if (jti != null && !jti.isDisposed()) {
Rectangle bounds= jti.getBounds();
int s= bounds.y;
int e= bounds.y + bounds.height;
int as= scroller.getOrigin().y;
int ae= as + scroller.getClientArea().height;
if (s < as)
scroller.setOrigin(0, s);
else if (e > ae)
scroller.setOrigin(0, as+(e-ae));
}
}
/*
* Needs to be called after items have been added or removed,
* or after the size of an item has changed.
* Optionally updates the background of all items.
* Ensures that the background following the last item is always white.
*/
private void relayout(boolean layout, boolean refreshBackgrounds) {
if (layout) {
ListLayout l= (ListLayout) list.getLayout();
l.refreshBackgrounds= refreshBackgrounds;
Point size= list.computeSize(list.getClientArea().x, SWT.DEFAULT);
list.setSize(size);
scroller.setMinSize(size);
}
}
void clearAll() {
finishedJobs.clearAll();
if (DEBUG) {
JobTreeElement[] elements = finishedJobs.getJobInfos();
System.out.println("jobs: " + elements.length); //$NON-NLS-1$
for (int i= 0; i < elements.length; i++)
System.out.println(" " + elements[i]); //$NON-NLS-1$
}
}
private Control[] getSortedChildren() {
Control[] cs= list.getChildren();
ViewerSorter vs= getSorter();
if (vs != null) {
HashMap map2= new HashMap(); // temp remember items for sorting
JobTreeElement[] elements= new JobTreeElement[cs.length];
for (int i= 0; i < cs.length; i++) {
JobItem ji= (JobItem)cs[i];
elements[i]= ji.jobTreeElement;
map2.put(elements[i], ji);
}
vs.sort(NewProgressViewer.this, elements);
for (int i= 0; i < cs.length; i++)
cs[i]= (JobItem) map2.get(elements[i]);
}
return cs;
}
private void select(JobItem newSelection, Event e) {
boolean clearAll= false;
JobItem newSel= null;
Control[] cs= getSortedChildren();
JobTreeElement element= null;
if (newSelection != null)
element= newSelection.jobTreeElement;
if (e.type == SWT.KeyDown) { // key
if (e.keyCode == SWT.ARROW_UP) {
for (int i= 0; i < cs.length; i++) {
JobItem ji= (JobItem) cs[i];
if (ji.selected) {
if (i-1 >= 0) {
newSel= (JobItem) cs[i-1];
if ((e.stateMask & SWT.MOD2) != 0) {
newSel.selected= true;
} else {
clearAll= true;
}
break;
}
return;
}
}
if (newSel == null && cs.length > 0) {
newSel= (JobItem) cs[cs.length-1];
newSel.selected= true;
}
} else if (e.keyCode == SWT.ARROW_DOWN) {
for (int i= cs.length-1; i >= 0; i--) {
JobItem ji= (JobItem) cs[i];
if (ji.selected) {
if (i+1 < cs.length) {
newSel= (JobItem) cs[i+1];
if ((e.stateMask & SWT.MOD2) != 0) {
newSel.selected= true;
} else {
clearAll= true;
}
break;
}
return;
}
}
if (newSel == null && cs.length > 0) {
newSel= (JobItem) cs[0];
newSel.selected= true;
}
}
} else if (e.type == SWT.MouseDown) { // mouse
if (newSelection == null) {
clearAll= true;
} else {
if ((e.stateMask & SWT.MOD1) != 0) {
newSelection.selected= !newSelection.selected;
} else if ((e.stateMask & SWT.MOD2) != 0) {
// not yet implemented
} else {
if (newSelection.selected)
return;
clearAll= true;
newSel= newSelection;
}
}
}
if (clearAll) {
for (int i= 0; i < cs.length; i++) {
JobItem ji= (JobItem) cs[i];
ji.selected= ji == newSel;
}
}
boolean dark= (cs.length % 2) == 1;
for (int i= 0; i < cs.length; i++) {
JobItem ji= (JobItem) cs[i];
ji.updateBackground(dark);
dark= !dark;
}
if (newSel != null)
reveal(newSel);
}
/**
* Shorten the given text <code>t</code> so that its length
* doesn't exceed the given width. This implementation
* replaces characters in the center of the original string with an
* ellipsis ("...").
*/
static String shortenText(GC gc, int maxWidth, String textValue) {
if (gc.textExtent(textValue).x < maxWidth) {
return textValue;
}
int length = textValue.length();
int ellipsisWidth = gc.textExtent(ELLIPSIS).x;
int pivot = length / 2;
int start = pivot;
int end = pivot + 1;
while (start >= 0 && end < length) {
String s1 = textValue.substring(0, start);
String s2 = textValue.substring(end, length);
int l1 = gc.textExtent(s1).x;
int l2 = gc.textExtent(s2).x;
if (l1 + ellipsisWidth + l2 < maxWidth) {
return s1 + ELLIPSIS + s2;
}
start--;
end++;
}
return textValue;
}
/**
* Shorten the given text <code>t</code> so that its length
* doesn't exceed the width of the given control. This implementation
* replaces characters in the center of the original string with an
* ellipsis ("...").
*/
static String shortenText(Control control, String textValue) {
if (textValue != null) {
Display display = control.getDisplay();
GC gc = new GC(display);
int maxWidth = control.getBounds().width;
textValue = shortenText(gc, maxWidth, textValue);
gc.dispose();
}
return textValue;
}
Object[] contentProviderGetChildren(Object parent) {
IContentProvider provider = getContentProvider();
if (provider instanceof ITreeContentProvider)
return ((ITreeContentProvider)provider).getChildren(parent);
return new Object[0];
}
Object[] contentProviderGetRoots(Object parent) {
IContentProvider provider = getContentProvider();
if (provider instanceof ITreeContentProvider)
return ((ITreeContentProvider)provider).getElements(parent);
return new Object[0];
}
private void forcedRemove(final JobTreeElement jte) {
if (list != null && !list.isDisposed()) {
list.getDisplay().asyncExec(new Runnable() {
public void run() {
if (DEBUG) System.err.println(" forced remove"); //$NON-NLS-1$
JobTreeItem ji= findJobItem(jte, false);
if (ji != null && !ji.isDisposed() && ji.remove())
relayout(true, true);
}
});
}
}
/* (non-Javadoc)
* @see org.eclipse.ui.internal.progress.NewKeptJobs.KeptJobsListener#finished(org.eclipse.ui.internal.progress.JobInfo)
*/
public void finished(JobTreeElement jte) {
}
/* (non-Javadoc)
* @see org.eclipse.ui.internal.progress.NewKeptJobs.KeptJobsListener#removed(org.eclipse.ui.internal.progress.JobInfo)
*/
public void removed(final JobTreeElement info) {
if (list != null && !list.isDisposed()) {
list.getDisplay().asyncExec(new Runnable() {
public void run() {
if (info != null) { // we got a specific item to remove
JobTreeItem ji= findJobItem(info, false);
if (ji != null && ji.jobTerminated) {
ji.dispose();
relayout(true, true);
}
} else {
// remove all terminated
Control[] children = list.getChildren();
for (int i= 0; i < children.length; i++) {
JobTreeItem ji= (JobItem)children[i];
if (ji.jobTerminated)
ji.dispose();
}
relayout(true, true);
}
}
});
}
}
////// SelectionProvider
public ISelection getSelection() {
if (list.isDisposed())
return new StructuredSelection();
ArrayList l= new ArrayList();
Control[] cs= list.getChildren();
for (int i= 0; i < cs.length; i++) {
JobItem ji= (JobItem) cs[i];
l.add(ji.jobTreeElement);
}
return new StructuredSelection(l);
}
public void setSelection(ISelection selection) {
}
public void setUseHashlookup(boolean b) {
}
public void setInput(IContentProvider provider) {
refresh(true);
}
public void cancelSelection() {
boolean changed= false;
Control[] cs= list.getChildren();
for (int i= 0; i < cs.length; i++) {
JobItem ji= (JobItem) cs[i];
if (ji.selected)
changed |= ji.cancelOrRemove();
}
relayout(changed, changed);
}
void doSelection() {
boolean changed= false;
Control[] cs= list.getChildren();
for (int i= 0; i < cs.length; i++) {
JobItem ji= (JobItem) cs[i];
if (ji.selected) {
Control[] children= ji.getChildren();
for (int j= 0; j < children.length; j++) {
if (children[j] instanceof Hyperlink) {
Hyperlink hl= (Hyperlink) children[j];
if (hl.handleActivate())
return;
}
}
}
}
}
///////////////////////////////////
protected void addTreeListener(Control c, TreeListener listener) {
}
protected void doUpdateItem(final Item item, Object element) {
}
protected Item[] getChildren(Widget o) {
return new Item[0];
}
protected boolean getExpanded(Item item) {
return true;
}
protected Item getItem(int x, int y) {
return null;
}
protected int getItemCount(Control widget) {
return 1;
}
protected int getItemCount(Item item) {
return 0;
}
protected Item[] getItems(Item item) {
return new Item[0];
}
protected Item getParentItem(Item item) {
return null;
}
protected Item[] getSelection(Control widget) {
return new Item[0];
}
public Tree getTree() {
Tree t= super.getTree();
if (t != null && !t.isDisposed())
return t;
return null;
}
protected Item newItem(Widget parent, int flags, int ix) {
return null;
}
protected void removeAll(Control widget) {
}
protected void setExpanded(Item node, boolean expand) {
}
protected void setSelection(List items) {
}
protected void showItem(Item item) {
}
protected void createChildren(Widget widget) {
refresh(true);
}
protected void internalRefresh(Object element, boolean updateLabels) {
}
public void setHighlightJob(Job job) {
highlightJob= job;
relayout(true, true);
}
}