org.eclipse.mylyn.internal.builds.ui.view.BuildsView.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.mylyn.internal.builds.ui.view.BuildsView.java

Source

/*******************************************************************************
 * Copyright (c) 2010 Tasktop Technologies and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Tasktop Technologies - initial API and implementation
 *     Itema AS - bug 325079 added support for build service messages
 *     Itema AS - bug 331008 automatic resize of view columns
 *******************************************************************************/

package org.eclipse.mylyn.internal.builds.ui.view;

import java.io.File;
import java.text.DateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.Set;

import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.DecoratingStyledCellLabelProvider;
import org.eclipse.jface.viewers.IOpenListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.mylyn.builds.core.BuildStatus;
import org.eclipse.mylyn.builds.core.IBuildElement;
import org.eclipse.mylyn.builds.core.IBuildPlan;
import org.eclipse.mylyn.builds.core.IBuildServer;
import org.eclipse.mylyn.builds.internal.core.BuildModel;
import org.eclipse.mylyn.builds.internal.core.operations.RefreshOperation;
import org.eclipse.mylyn.builds.internal.core.util.BuildsConstants;
import org.eclipse.mylyn.builds.ui.BuildsUiConstants;
import org.eclipse.mylyn.commons.core.CoreUtil;
import org.eclipse.mylyn.commons.core.operations.IOperationMonitor.OperationFlag;
import org.eclipse.mylyn.commons.ui.AbstractColumnViewerSupport;
import org.eclipse.mylyn.commons.ui.CommonImages;
import org.eclipse.mylyn.commons.ui.TreeSorter;
import org.eclipse.mylyn.commons.ui.TreeViewerSupport;
import org.eclipse.mylyn.commons.ui.actions.CollapseAllAction;
import org.eclipse.mylyn.commons.ui.actions.ExpandAllAction;
import org.eclipse.mylyn.internal.builds.ui.BuildImages;
import org.eclipse.mylyn.internal.builds.ui.BuildToolTip;
import org.eclipse.mylyn.internal.builds.ui.BuildsUiInternal;
import org.eclipse.mylyn.internal.builds.ui.BuildsUiPlugin;
import org.eclipse.mylyn.internal.builds.ui.actions.RunBuildAction;
import org.eclipse.mylyn.internal.builds.ui.actions.ShowBuildOutputAction;
import org.eclipse.mylyn.internal.builds.ui.actions.ShowTestResultsAction;
import org.eclipse.mylyn.internal.builds.ui.commands.OpenHandler;
import org.eclipse.mylyn.internal.builds.ui.notifications.BuildsServiceMessageControl;
import org.eclipse.mylyn.internal.builds.ui.view.BuildContentProvider.Presentation;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
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.Link;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.IShowInSource;
import org.eclipse.ui.part.IShowInTarget;
import org.eclipse.ui.part.IShowInTargetList;
import org.eclipse.ui.part.ShowInContext;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.progress.IWorkbenchSiteProgressService;

/**
 * @author Steffen Pingel
 * @author Torkild U. Resheim
 * @author Lucas Panjer
 */
public class BuildsView extends ViewPart implements IShowInTarget {
    public class BuildsSummary {
        int numSuccess;

        int numUnstable;

        int numFailed;

        public boolean isSuccess() {
            return numSuccess > 0 && numUnstable == 0 && numFailed == 0;
        }

        public boolean isUnstable() {
            return numUnstable > 0 && numFailed == 0;
        }

        public boolean isFailed() {
            return numFailed > 0;
        }

        public boolean isEmpty() {
            return numSuccess == 0 && numSuccess == 0 && numFailed == 0;
        }

        @Override
        public String toString() {
            return NLS.bind("{0} Succeeded, {1} Unstable, {2} Failed",
                    new Object[] { numSuccess, numUnstable, numFailed });
        }
    }

    private class BuildTreeSorter extends TreeSorter {

        @Override
        public int compare(TreeViewer viewer, Object e1, Object e2, int columnIndex) {
            if (e1 instanceof IBuildServer && e2 instanceof IBuildServer) {
                // keep server sort order stable for now
                @SuppressWarnings("unchecked")
                int res = getComparator().compare(((IBuildElement) e1).getLabel(), ((IBuildElement) e2).getLabel());
                if (getSortDirection(viewer) == SWT.UP) {
                    return -res;
                }
                return res;
            }
            if (e1 instanceof IBuildPlan && e2 instanceof IBuildPlan) {
                IBuildPlan p1 = (IBuildPlan) e1;
                IBuildPlan p2 = (IBuildPlan) e2;
                switch (columnIndex) {
                case -1: // default
                    return CoreUtil.compare(p1.getLabel(), p2.getLabel());
                case 0: // build
                    return CoreUtil.compare(p1.getStatus(), p2.getStatus());
                case 1: // summary
                    return p1.getHealth() - p2.getHealth();
                case 2: // last build
                    Long t1 = (p1.getLastBuild() != null) ? p1.getLastBuild().getTimestamp() : null;
                    Long t2 = (p2.getLastBuild() != null) ? p2.getLastBuild().getTimestamp() : null;
                    return CoreUtil.compare(t1, t2);
                }
            }
            return super.compare(viewer, e1, e2, columnIndex);
        }

        @Override
        protected int compareDefault(TreeViewer viewer, Object e1, Object e2) {
            return compare(viewer, e1, e2, -1);
        }

    }

    public static BuildsView openInActivePerspective() {
        IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
        if (window != null) {
            IWorkbenchPage page = window.getActivePage();
            if (page != null) {
                try {
                    return (BuildsView) page.showView(BuildsUiConstants.ID_VIEW_BUILDS);
                } catch (PartInitException e) {
                    // ignore
                }
            }
        }
        return null;
    }

    private BuildStatusFilter buildStatusFilter;

    private Action collapseAllAction;

    private BuildContentProvider contentProvider;

    private Action expandAllAction;

    private FilterByStatusAction filterDisabledAction;

    private Date lastRefresh;

    private Composite messageComposite;

    private BuildModel model;

    private AdapterImpl modelListener;

    private BuildElementPropertiesAction propertiesAction;

    private final IPropertyChangeListener propertyChangeListener = new IPropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent event) {
            if (org.eclipse.mylyn.internal.builds.ui.BuildsUiInternal.PREF_AUTO_REFRESH_ENABLED
                    .equals(event.getProperty())) {
                Display.getDefault().asyncExec(new Runnable() {
                    public void run() {
                        if (refreshAutomaticallyAction != null) {
                            refreshAutomaticallyAction.updateState();
                        }
                    }
                });
            }
        }
    };

    private RefreshAutomaticallyAction refreshAutomaticallyAction;

    private StackLayout stackLayout;

    private IMemento stateMemento;

    private TreeViewer viewer;

    private PresentationMenuAction presentationsMenuAction;

    private BuildToolTip toolTip;

    private BuildsServiceMessageControl serviceMessageControl;

    public BuildsView() {
        BuildsUiPlugin.getDefault().initializeRefresh();
    }

    private void contributeToActionBars() {
        IActionBars bars = getViewSite().getActionBars();
        fillLocalPullDown(bars.getMenuManager());
        fillLocalToolBar(bars.getToolBarManager());
    }

    private void createMessage(Composite parent) {
        messageComposite = new Composite(parent, SWT.NONE);
        FillLayout layout = new FillLayout();
        layout.marginHeight = 5;
        layout.marginWidth = 5;
        messageComposite.setLayout(layout);
        //GridLayoutFactory.swtDefaults().applyTo(messageComposite);
        messageComposite.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));

        Link link = new Link(messageComposite, SWT.WRAP);
        link.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
        link.setText("No build servers available. Create a <a href=\"create\">build server</a>...");
        link.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent event) {
                if ("create".equals(event.text)) {
                    new NewBuildServerAction().run();
                }
            }
        });
    }

    @Override
    public void createPartControl(Composite parent) {
        Composite body = new Composite(parent, SWT.NONE);
        GridLayout layout = new GridLayout(1, false);
        layout.marginHeight = 0;
        layout.marginWidth = 0;
        layout.horizontalSpacing = 0;
        layout.verticalSpacing = 0;
        layout.numColumns = 1;
        body.setLayout(layout);

        Composite composite = new Composite(body, SWT.NONE);
        composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        stackLayout = new StackLayout();
        composite.setLayout(stackLayout);
        composite.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));

        createMessage(composite);
        createViewer(composite);

        initActions();
        createPopupMenu(body);
        contributeToActionBars();

        toolTip = new BuildToolTip(getViewer().getControl());
        toolTip.setViewer(viewer);
        // bug#160897: set to empty string to disable native tooltips (windows only?)
        viewer.getTree().setToolTipText(""); //$NON-NLS-1$

        IWorkbenchSiteProgressService progress = (IWorkbenchSiteProgressService) getSite()
                .getAdapter(IWorkbenchSiteProgressService.class);
        if (progress != null) {
            // show indicator for all running refreshes
            progress.showBusyForFamily(BuildsConstants.JOB_FAMILY);
        }

        model = BuildsUiInternal.getModel();
        modelListener = new BuildModelContentAdapter() {
            @Override
            public void doNotifyChanged(Notification msg) {
                if (!viewer.getControl().isDisposed()) {
                    lastRefresh = new Date();
                    updateContents(Status.OK_STATUS);
                }
            }
        };
        model.eAdapters().add(modelListener);

        if (stateMemento != null) {
            restoreState(stateMemento);
            stateMemento = null;
        }
        serviceMessageControl = new BuildsServiceMessageControl(body);

        viewer.setInput(model);
        viewer.setSorter(new BuildTreeSorter());
        viewer.expandAll();

        installAutomaticResize(viewer.getTree());

        getSite().setSelectionProvider(viewer);
        getSite().getSelectionProvider().addSelectionChangedListener(propertiesAction);
        propertiesAction.selectionChanged((IStructuredSelection) getSite().getSelectionProvider().getSelection());

        updateContents(Status.OK_STATUS);

        new TreeViewerSupport(viewer, getStateFile());
        // Make sure we get notifications
        NotificationSinkProxy.setControl(serviceMessageControl);
    }

    /**
     * Initializes automatic resize of the tree control columns. The size of these will be adjusted when a node is
     * expanded or collapsed and when the tree changes size.
     * 
     * @param tree
     *            the tree to resize
     */
    private void installAutomaticResize(final Tree tree) {
        Listener listener = new Listener() {
            public void handleEvent(Event e) {
                packColumnsAsync(tree);
            }

        };
        // Automatically resize columns when we expand tree nodes.
        tree.addListener(SWT.Collapse, listener);
        tree.addListener(SWT.Expand, listener);
        tree.getParent().addListener(SWT.Resize, listener);
    }

    void packColumnsAsync(final Tree tree) {
        tree.getDisplay().asyncExec(new Runnable() {
            public void run() {
                if (!tree.isDisposed()) {
                    try {
                        tree.setRedraw(false);
                        packColumns(tree);
                    } finally {
                        tree.setRedraw(true);
                    }
                }
            }
        });
    }

    private File getStateFile() {
        IPath stateLocation = Platform.getStateLocation(BuildsUiPlugin.getDefault().getBundle());
        return stateLocation.append("BuildView.xml").toFile(); //$NON-NLS-1$
    }

    protected void createPopupMenu(Composite parent) {
        MenuManager menuManager = new MenuManager();

        menuManager.add(new GroupMarker("group.open"));
        menuManager.add(new Separator("group.edit"));
        menuManager.add(new Separator("group.file"));
        menuManager.add(new Separator("group.run"));
        menuManager.add(new Separator("group.refresh"));
        menuManager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
        menuManager.add(new Separator(BuildsUiConstants.GROUP_PROPERTIES));

        Menu contextMenu = menuManager.createContextMenu(parent);
        viewer.getTree().setMenu(contextMenu);
        getSite().registerContextMenu(menuManager, viewer);
    }

    protected void createViewer(Composite parent) {
        //      Composite composite = new Composite(parent, SWT.NONE);
        //      TreeColumnLayout treeColumnLayout = new TreeColumnLayout();
        //      composite.setLayout(treeColumnLayout);

        viewer = new TreeViewer(parent, SWT.FULL_SELECTION);
        Tree tree = viewer.getTree();
        tree.setHeaderVisible(true);

        TreeViewerColumn buildViewerColumn = new TreeViewerColumn(viewer, SWT.LEFT);
        buildViewerColumn.setLabelProvider(new DecoratingStyledCellLabelProvider(new BuildLabelProvider(true),
                PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator(), null));
        TreeColumn buildColumn = buildViewerColumn.getColumn();
        buildColumn.setText("Build");
        buildColumn.setWidth(220);
        buildColumn.setData(AbstractColumnViewerSupport.KEY_COLUMN_CAN_HIDE, false);
        //treeColumnLayout.setColumnData(buildColumn, new ColumnWeightData(20, 50));

        TreeViewerColumn summaryViewerColumn = new TreeViewerColumn(viewer, SWT.LEFT);
        summaryViewerColumn.setLabelProvider(new BuildSummaryLabelProvider());
        TreeColumn summaryColumn = summaryViewerColumn.getColumn();
        summaryColumn.setText("Summary");
        summaryColumn.setWidth(220);
        //treeColumnLayout.setColumnData(summaryColumn, new ColumnWeightData(60, 200));

        TreeViewerColumn lastBuiltViewerColumn = new TreeViewerColumn(viewer, SWT.RIGHT);
        lastBuiltViewerColumn.setLabelProvider(new RelativeBuildTimeLabelProvider());
        TreeColumn lastBuiltColumn = lastBuiltViewerColumn.getColumn();
        lastBuiltColumn.setText("Last Built");
        lastBuiltColumn.setWidth(50);
        //treeColumnLayout.setColumnData(lastBuiltColumn, new ColumnWeightData(20, 50));

        contentProvider = new BuildContentProvider();
        contentProvider.setSelectedOnly(true);
        viewer.setContentProvider(contentProvider);

        viewer.addOpenListener(new IOpenListener() {
            public void open(OpenEvent event) {
                Object element = ((IStructuredSelection) event.getSelection()).getFirstElement();
                if (element instanceof IBuildElement) {
                    OpenHandler.open(getSite().getPage(), Collections.singletonList((IBuildElement) element));
                }
            }
        });
    }

    @Override
    public void dispose() {
        super.dispose();
        getModel().eAdapters().remove(modelListener);
        BuildsUiPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(propertyChangeListener);
    }

    private void fillLocalPullDown(IMenuManager manager) {
        manager.add(presentationsMenuAction);
        manager.add(new Separator());
        manager.add(collapseAllAction);
        manager.add(expandAllAction);
        manager.add(new Separator(BuildsUiConstants.GROUP_FILTER));
        manager.add(filterDisabledAction);
        manager.add(new Separator(BuildsUiConstants.GROUP_NAVIGATE));
        manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
        manager.add(new Separator(BuildsUiConstants.GROUP_PROPERTIES));
        manager.add(refreshAutomaticallyAction);
        manager.add(new Separator(BuildsUiConstants.GROUP_PREFERENCES));
        manager.add(new OpenBuildsPreferencesAction());
    }

    private void fillLocalToolBar(IToolBarManager manager) {
        manager.add(new NewBuildServerMenuAction());

        manager.add(new Separator(BuildsUiConstants.GROUP_REFRESH));

        RefreshAction refresh = new RefreshAction();
        manager.add(refresh);

        manager.add(new Separator(BuildsUiConstants.GROUP_OPEN));

        OpenWithBrowserAction openInBrowserAction = new OpenWithBrowserAction();
        openInBrowserAction.selectionChanged(StructuredSelection.EMPTY);
        viewer.addSelectionChangedListener(openInBrowserAction);
        manager.add(openInBrowserAction);

        RunBuildAction runBuildAction = new RunBuildAction();
        runBuildAction.selectionChanged(StructuredSelection.EMPTY);
        viewer.addSelectionChangedListener(runBuildAction);
        manager.add(runBuildAction);

        manager.add(new Separator(BuildsUiConstants.GROUP_FILE));

        ShowBuildOutputAction openConsoleAction = new ShowBuildOutputAction();
        openConsoleAction.selectionChanged(StructuredSelection.EMPTY);
        viewer.addSelectionChangedListener(openConsoleAction);
        manager.add(openConsoleAction);

        ShowTestResultsAction showTestResultsAction = new ShowTestResultsAction();
        showTestResultsAction.selectionChanged(StructuredSelection.EMPTY);
        viewer.addSelectionChangedListener(showTestResultsAction);
        manager.add(showTestResultsAction);
    }

    public BuildStatusFilter getBuildStatusFilter() {
        if (buildStatusFilter == null) {
            buildStatusFilter = new BuildStatusFilter();
            getViewer().addFilter(buildStatusFilter);
        }
        return buildStatusFilter;
    }

    public BuildContentProvider getContentProvider() {
        return contentProvider;
    }

    protected BuildsSummary getBuildsSummary() {
        BuildsSummary buildsSummary = new BuildsSummary();
        if (getContentProvider() != null) {
            for (IBuildPlan plan : getModel().getPlans()) {
                if (plan.getStatus() != null) {
                    switch (plan.getStatus()) {
                    case SUCCESS:
                        buildsSummary.numSuccess++;
                        break;
                    case UNSTABLE:
                        buildsSummary.numUnstable++;
                        break;
                    case FAILED:
                        buildsSummary.numFailed++;
                        break;
                    }
                }
            }
        }
        return buildsSummary;
    }

    TreeViewer getViewer() {
        return viewer;
    }

    @Override
    public void init(IViewSite site, IMemento memento) throws PartInitException {
        super.init(site, memento);

        BuildsUiPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(propertyChangeListener);

        // defer restore until view is created
        this.stateMemento = memento;
    }

    private void initActions() {
        collapseAllAction = new CollapseAllAction(viewer);
        expandAllAction = new ExpandAllAction(viewer);
        propertiesAction = new BuildElementPropertiesAction();
        refreshAutomaticallyAction = new RefreshAutomaticallyAction();
        filterDisabledAction = new FilterByStatusAction(this, BuildStatus.DISABLED);
        presentationsMenuAction = new PresentationMenuAction(this);
    }

    private void restoreState(IMemento memento) {
        IMemento child = memento.getChild("statusFilter");
        if (child != null) {
            boolean changed = false;
            for (BuildStatus status : BuildStatus.values()) {
                Boolean value = child.getBoolean(status.name());
                if (value != null && value.booleanValue()) {
                    getBuildStatusFilter().addFiltered(status);
                    changed = true;
                }
            }
            if (changed) {
                filterDisabledAction.update();
            }
        }
        child = memento.getChild("presentation");
        if (child != null) {
            String id = child.getString("id");
            if (id != null) {
                try {
                    getContentProvider().setPresentation(Presentation.valueOf(id));
                } catch (IllegalArgumentException e) {
                    // use default
                }
            }
        }
    }

    @Override
    public void saveState(IMemento memento) {
        super.saveState(memento);

        if (buildStatusFilter != null) {
            Set<BuildStatus> statuses = buildStatusFilter.getFiltered();
            if (statuses.size() > 0) {
                IMemento child = memento.createChild("statusFilter");
                for (BuildStatus status : statuses) {
                    child.putBoolean(status.name(), true);
                }
            }
        }
        IMemento child = memento.createChild("presentation");
        child.putString("id", getContentProvider().getPresentation().name());
    }

    @Override
    public void setFocus() {
        getViewer().getControl().setFocus();
        if (BuildsUiPlugin.getDefault().getPreferenceStore().getBoolean(BuildsUiInternal.PREF_REFRESH_ON_FOCUS)) {
            RefreshOperation operation = BuildsUiInternal.getFactory().getRefreshOperation();
            operation.addFlag(OperationFlag.BACKGROUND);
            operation.execute();
        }
    }

    private void setTopControl(Control control) {
        if (stackLayout.topControl != control) {
            stackLayout.topControl = control;
            control.getParent().layout();
        }
    }

    public boolean show(ShowInContext context) {
        if (context.getSelection() != null) {
            getViewer().setSelection(context.getSelection());
            return true;
        }
        return false;
    }

    private void updateContents(IStatus status) {
        boolean isShowingViewer = (stackLayout.topControl == viewer.getControl());
        boolean hasContents = false;
        if (contentProvider != null) {
            if (getModel().getPlans().size() > 0 || getModel().getServers().size() > 0) {
                hasContents = true;
            }
        }
        if (hasContents) {
            setTopControl(viewer.getControl());
            if (!isShowingViewer) {
                // initial flip
                packColumnsAsync(viewer.getTree());
            }
        } else {
            setTopControl(messageComposite);
        }
        updateDecoration(status);
    }

    public void updateDecoration(IStatus status) {
        String statusMessage = "";
        if (status.isOK()) {
            BuildsSummary buildsSummary = getBuildsSummary();
            if (buildsSummary.isSuccess()) {
                setTitleImage(CommonImages.getImageWithOverlay(BuildImages.VIEW_BUILDS,
                        CommonImages.OVERLAY_SUCCESS, false, false));
            } else if (buildsSummary.isUnstable()) {
                setTitleImage(CommonImages.getImageWithOverlay(BuildImages.VIEW_BUILDS, CommonImages.OVERLAY_FAILED,
                        false, false));
            } else if (buildsSummary.isFailed()) {
                setTitleImage(CommonImages.getImageWithOverlay(BuildImages.VIEW_BUILDS, CommonImages.OVERLAY_ERROR,
                        false, false));
            } else {
                setTitleImage(CommonImages.getImage(BuildImages.VIEW_BUILDS));
            }
            if (!buildsSummary.isEmpty()) {
                setContentDescription(buildsSummary.toString());
            } else {
                setContentDescription(""); //$NON-NLS-1$
            }
            if (lastRefresh != null) {
                statusMessage = NLS.bind("Last update: {0}", DateFormat.getDateTimeInstance().format(lastRefresh));
            }
        } else {
            setTitleImage(CommonImages.getImageWithOverlay(BuildImages.VIEW_BUILDS, CommonImages.OVERLAY_WARNING,
                    false, false));
            statusMessage = "Last update failed";
        }

        if (statusMessage != null) {
            final IViewSite viewSite = getViewSite();
            if (viewSite != null) {
                final IStatusLineManager statusLine = viewSite.getActionBars().getStatusLineManager();
                if (statusLine != null) {
                    statusLine.setMessage(statusMessage);
                }
            }
        }
    }

    @Override
    public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
        if (adapter == IShowInTargetList.class) {
            return new IShowInTargetList() {
                public String[] getShowInTargetIds() {
                    return new String[] { "org.eclipse.team.ui.GenericHistoryView" }; //$NON-NLS-1$
                }

            };
        } else if (adapter == IShowInSource.class) {
            return new IShowInSource() {
                public ShowInContext getShowInContext() {
                    return new ShowInContext(getViewer().getInput(), getViewer().getSelection());
                }
            };
        }
        return super.getAdapter(adapter);
    }

    /**
     * Packs all columns so that they are able to display all content. If there is any space left, the second column
     * (summary) will be resized so that the entire width of the control is used.
     * 
     * @param tree
     *            the tree to resize
     */
    private void packColumns(final Tree tree) {
        int totalColumnWidth = 0;
        for (TreeColumn tc : tree.getColumns()) {
            if (tc.getResizable()) {
                tc.pack();
                totalColumnWidth += tc.getWidth() + 1;
            } else {
                totalColumnWidth += 1; // TODO: Determine the exact width of the column separator
            }
        }

        // Adjust the width of the "Summary" column unless it's not resizeable 
        // which case we adjust the width of the "Build" column instead.
        TreeColumn column = (tree.getColumn(1).getResizable()) ? tree.getColumn(1) : tree.getColumn(0);
        int nw = column.getWidth() + tree.getClientArea().width - totalColumnWidth;
        column.setWidth(nw);
    }

    protected BuildModel getModel() {
        return model;
    }

}