ch.hsr.ifs.cdt.metriculator.views.MetriculatorView.java Source code

Java tutorial

Introduction

Here is the source code for ch.hsr.ifs.cdt.metriculator.views.MetriculatorView.java

Source

/******************************************************************************
* Copyright (c) 2011 Institute for Software, HSR Hochschule fuer Technik 
* Rapperswil, University of applied sciences 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:
*    Ueli Kunz <kunz@ideadapt.net>, Jules Weder <julesweder@gmail.com> - initial API and implementation
******************************************************************************/

package ch.hsr.ifs.cdt.metriculator.views;

import java.awt.Color;
import java.text.NumberFormat;
import java.util.Collection;
import java.util.HashMap;
import java.util.Observable;
import java.util.Observer;

import org.eclipse.cdt.codan.core.model.CodanSeverity;
import org.eclipse.cdt.codan.core.model.IProblem;
import org.eclipse.cdt.codan.ui.CodanEditorUtility;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionManager;
import org.eclipse.jface.action.IMenuCreator;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.IOpenListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.window.ToolTip;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.texteditor.ITextEditor;

import ch.hsr.ifs.cdt.metriculator.JobObservable.JobState;
import ch.hsr.ifs.cdt.metriculator.MetriculatorPluginActivator;
import ch.hsr.ifs.cdt.metriculator.model.AbstractMetric;
import ch.hsr.ifs.cdt.metriculator.model.AbstractTreeBuilder;
import ch.hsr.ifs.cdt.metriculator.model.NodeFilter;
import ch.hsr.ifs.cdt.metriculator.model.nodes.AbstractNode;
import ch.hsr.ifs.cdt.metriculator.model.nodes.FileNode;
import ch.hsr.ifs.cdt.metriculator.model.nodes.LogicNode;
import ch.hsr.ifs.cdt.metriculator.resources.Icon;
import ch.hsr.ifs.cdt.metriculator.views.ToggleColumnActionItem.ToggleTableColumnActionContrItem;
import ch.hsr.ifs.cdt.metriculator.views.ToggleColumnActionItem.ToggleTreeColumnActionContrItem;

/**
 * @author Jules Weder, Ueli Kunz
 * */
public class MetriculatorView extends ViewPart implements Observer, ITagCloudDataProvider {

    private static final int INITIAL_SORT_ORDER = TreeColumnViewerSorter.NONE;
    private static final int SCOPE_COLUMN_DEFAULT_WIDTH = 160;
    private static final String SCOPE_COLUMN_TITLE = "Scope";
    public static final String VIEW_ID = "ch.hsr.ifs.cdt.metriculator.views.MetriculatorView"; //$NON-NLS-1$
    public static final String TABLE_COLUMN_HEADER_MENU_ID = MetriculatorView.VIEW_ID + ".menuTableColumnHeader"; //$NON-NLS-1$

    private HashMap<AbstractMetric, ToggleColumnActionItem<TreeColumn>> metricsTreeColumnActions = new HashMap<AbstractMetric, ToggleColumnActionItem<TreeColumn>>();
    private HashMap<AbstractMetric, ToggleColumnActionItem<TableColumn>> metricsTableColumnActions = new HashMap<AbstractMetric, ToggleColumnActionItem<TableColumn>>();
    private TreeViewer treeViewer;
    private TableViewer tableViewer;
    private NodeViewerFilter viewerFilter;
    private IAction actionHybridView;
    private IAction actionExpandAll;
    private IAction actionCollapseAll;
    private IAction actionFilterComposite;
    private IAction actionLogicalView;
    private IAction actionFilterFunction;
    private IAction actionFilterNamespace;
    private IAction actionFilterFile;
    private AbstractTreeBuilder currTreeBuilder;
    private ViewMode viewMode;
    private Menu tableHeaderMenu;
    private Composite treeComposite;
    private Composite tableComposite;
    private Composite parentComposite;
    private StructuredViewer activeViewer;
    private StackLayout stackLayout;
    private Action actionExport;

    public enum ViewMode {
        Hybrid, Logical, Filtered
    }

    public MetriculatorView() {
        MetriculatorPluginActivator.getDefault().getObservable().addObserver(this);
    }

    @Override
    public void dispose() {
        MetriculatorPluginActivator.getDefault().getObservable().deleteObserver(this);
        super.dispose();
    }

    @Override
    public void createPartControl(Composite parent) {
        stackLayout = new StackLayout();
        parent.setLayout(stackLayout);
        parentComposite = parent;

        MetricColumnHeaderMenu.treeMenuManager = new MenuManager();
        MetricColumnHeaderMenu.tableMenuManager = new MenuManager();

        createTreeComponents();

        createTableComponents();

        createActions();
        addActionsToMenus();

        applyViewMode(ViewMode.Hybrid, null);

        updateViewerData();
    }

    private void createTableComponents() {
        tableComposite = new Composite(parentComposite, parentComposite.getStyle());
        tableComposite.setLayout(new FillLayout());

        Table tableObject = new Table(tableComposite,
                SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.VIRTUAL);
        tableObject.setHeaderVisible(true);
        tableObject.setLinesVisible(true);

        tableViewer = new TableViewer(tableObject);
        tableViewer.addFilter(viewerFilter);
        tableViewer.setUseHashlookup(true);
        tableViewer.setContentProvider(new TableContentProvider());
        tableViewer.setLabelProvider(new MetriculatorCellLabelProvider());

        ColumnViewerToolTipSupport.enableFor(tableViewer, ToolTip.NO_RECREATE);
        addViewerOpenListener(tableViewer);
        createTableHeaderMenu();
        createTableLabelColumn();
        createAndUpdateMetricTableColumns();
    }

    private void createTreeComponents() {
        treeComposite = new Composite(parentComposite, parentComposite.getStyle());
        treeComposite.setLayout(new FillLayout());

        Tree treeObject = new Tree(treeComposite,
                SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.VIRTUAL);
        treeObject.setHeaderVisible(true);
        treeObject.setLinesVisible(true);

        viewerFilter = new NodeViewerFilter();
        treeViewer = new TreeViewer(treeObject);
        treeViewer.addFilter(viewerFilter);
        treeViewer.setUseHashlookup(true);
        treeViewer.setContentProvider(new TreeContentProvider());
        treeViewer.setLabelProvider(new MetriculatorCellLabelProvider());

        ColumnViewerToolTipSupport.enableFor(treeViewer, ToolTip.NO_RECREATE);
        addViewerOpenListener(treeViewer);
        createTreeHeaderMenu();
        createTreeLabelColumn();
        createAndUpdateMetricTreeColumns();
    }

    private void bringToFront(Composite container, StructuredViewer viewer) {
        stackLayout.topControl = container;
        activeViewer = viewer;
        Point p = parentComposite.getSize();
        parentComposite.setSize(new Point(p.x + 1, p.y));
        parentComposite.setSize(p);
    }

    private void createTableLabelColumn() {
        TableColumn colNodes = new TableColumn(tableViewer.getTable(), SWT.LEFT);
        colNodes.setText(SCOPE_COLUMN_TITLE);
        colNodes.setWidth(SCOPE_COLUMN_DEFAULT_WIDTH);
        colNodes.setMoveable(false);
        colNodes.setResizable(true);
        // make scope column sortable and set initial sorter
        TableColumnViewerSorter scopeSorter = new TableColumnViewerSorter(tableViewer, colNodes) {
            protected int doCompare(Viewer viewer, Object e1, Object e2) {
                AbstractNode p1 = (AbstractNode) e1;
                AbstractNode p2 = (AbstractNode) e2;
                return p1.toString().compareToIgnoreCase(p2.toString());
            }
        };
        scopeSorter.setSorter(scopeSorter, INITIAL_SORT_ORDER);
    }

    private void createTreeLabelColumn() {
        TreeColumn colNodes = new TreeColumn(treeViewer.getTree(), SWT.LEFT);
        colNodes.setAlignment(SWT.LEFT);
        colNodes.setText(SCOPE_COLUMN_TITLE);
        colNodes.setWidth(SCOPE_COLUMN_DEFAULT_WIDTH);
        colNodes.setMoveable(false);
        colNodes.setResizable(true);
        // make scope column sortable and set initial sorter
        TreeColumnViewerSorter scopeSorter = new TreeColumnViewerSorter(treeViewer, colNodes) {
            protected int doCompare(Viewer viewer, Object e1, Object e2) {
                AbstractNode p1 = (AbstractNode) e1;
                AbstractNode p2 = (AbstractNode) e2;
                return p1.toString().compareToIgnoreCase(p2.toString());
            }
        };
        scopeSorter.setSorter(scopeSorter, INITIAL_SORT_ORDER);
    }

    private void createTreeHeaderMenu() {
        MetricColumnHeaderMenu.create(parentComposite.getShell(), treeViewer.getTree());
    }

    private void createTableHeaderMenu() {
        tableHeaderMenu = MetricColumnHeaderMenu.create(parentComposite.getShell(), tableViewer.getTable());
        getSite().registerContextMenu(TABLE_COLUMN_HEADER_MENU_ID, MetricColumnHeaderMenu.tableMenuManager,
                tableViewer);
    }

    private void createAndUpdateMetricTreeColumns() {
        ToggleColumnActionItem<TreeColumn> actionItem = null;

        for (AbstractMetric metric : MetriculatorPluginActivator.getDefault().getMetrics()) {

            actionItem = metricsTreeColumnActions.get(metric);

            if (actionItem == null) {

                TreeColumn col = MetricColumn.createFor(metric, treeViewer);
                actionItem = createMetricMenuItemFor(col);
                metricsTreeColumnActions.put(metric, actionItem);
            }
            actionItem.toggleVisibility();
        }

        if (actionItem != null) {
            MetricColumn.createFillerColumnOnce(treeViewer.getTree());
        }
    }

    private void createAndUpdateMetricTableColumns() {
        ToggleColumnActionItem<TableColumn> actionItem = null;

        for (AbstractMetric metric : MetriculatorPluginActivator.getDefault().getMetrics()) {

            actionItem = metricsTableColumnActions.get(metric);

            if (actionItem == null) {

                TableColumn col = MetricColumn.createFor(metric, tableViewer);
                actionItem = createMetricMenuItemFor(col);
                metricsTableColumnActions.put(metric, actionItem);
            }
            actionItem.toggleVisibility();
        }

        if (actionItem != null) {
            MetricColumn.createFillerColumnOnce(tableViewer.getTable());
        }
    }

    private ToggleColumnActionItem<TreeColumn> createMetricMenuItemFor(final TreeColumn column) {

        ToggleTreeColumnActionContrItem actionItem = new ToggleTreeColumnActionContrItem(column);
        MetricColumnHeaderMenu.treeMenuManager.add(actionItem);
        return actionItem;
    }

    private ToggleColumnActionItem<TableColumn> createMetricMenuItemFor(final TableColumn column) {

        ToggleTableColumnActionContrItem actionItem = new ToggleTableColumnActionContrItem(column);
        MetricColumnHeaderMenu.tableMenuManager.add(actionItem);
        return actionItem;
    }

    @Override
    public AbstractMetric getMenuMetric() {
        TableColumn selectedCol = (TableColumn) MetricColumnHeaderMenu.getCurrColumn(tableHeaderMenu);
        if (selectedCol != null) {
            return MetricColumn.getMetric(selectedCol);
        }
        return null;
    }

    @Override
    public Collection<AbstractNode> getNodes() {
        Collection<AbstractNode> filteredNodes = viewerFilter.getNodeFilter()
                .takeFrom(currTreeBuilder.root.getChildren());
        return filteredNodes;
    }

    private void createActions() {
        createActionHybridView();
        createActionLogicalView();
        createActionExpandAll();
        createActionCollapseAll();
        createActionFilterComposite();
        createActionFilterFunction();
        createActionFilterNamespace();
        createActionFilterFile();
        createActionExport();
    }

    private void createActionExport() {
        actionExport = new Action("Export") {

            @Override
            public void runWithEvent(Event e) {
                IMenuCreator mc = this.getMenuCreator();
                Widget item = e.widget;
                ToolItem ti = (ToolItem) item;

                if (mc != null) {
                    Menu m = mc.getMenu(ti.getParent());
                    if (m != null) {
                        // position the menu below the drop down item / next to cursor
                        Point point = item.getDisplay().getCursorLocation();
                        m.setLocation(point.x, point.y);
                        m.setVisible(true);
                        return; // we don't fire the action
                    }
                }

            }
        };
        actionExport.setImageDescriptor(
                MetriculatorPluginActivator.getDefault().getImageDescriptor(Icon.Size16.EXPORT));
        actionExport.setMenuCreator(new ExportActionMenuCreator(this));
    }

    private void applyViewMode(ViewMode view, NodeFilter filter) {

        viewMode = view;
        actionLogicalView.setChecked(false);
        actionHybridView.setChecked(false);

        switch (view) {
        case Logical:
            actionLogicalView.setChecked(true);
            currTreeBuilder = MetriculatorPluginActivator.getDefault().getLogicTreeBuilder();
            applyFilterMode(NodeFilter.none());
            bringToFront(treeComposite, treeViewer);
            break;

        case Hybrid:
            actionHybridView.setChecked(true);
            currTreeBuilder = MetriculatorPluginActivator.getDefault().getHybridTreeBuilder();
            applyFilterMode(NodeFilter.none());
            bringToFront(treeComposite, treeViewer);
            break;

        case Filtered:
            if (filter == null) {
                filter = NodeFilter.none();
            }
            applyFilterMode(filter);
            bringToFront(tableComposite, tableViewer);
            break;

        default:
            break;
        }
    }

    public ViewMode getViewMode() {
        return viewMode;
    }

    private void applyFilterMode(NodeFilter filter) {

        viewerFilter.setNodeFilter(filter);

        actionFilterComposite.setChecked(filter instanceof NodeFilter.CompositeNodeFilter);
        actionFilterFile.setChecked(filter instanceof NodeFilter.FileNodeFilter);
        actionFilterFunction.setChecked(filter instanceof NodeFilter.FunctionNodeFilter);
        actionFilterNamespace.setChecked(filter instanceof NodeFilter.NamespaceNodeFilter);

        if (!(filter instanceof NodeFilter.NoneFilter)) {
            currTreeBuilder = MetriculatorPluginActivator.getDefault().getFlatTreeBuilder();
        }
    }

    private void createActionFilterFile() {
        actionFilterFile = new Action("File Nodes Only", IAction.AS_CHECK_BOX) {
            public void run() {
                if (isChecked()) {
                    applyViewMode(ViewMode.Filtered, NodeFilter.file());
                } else {
                    applyViewMode(ViewMode.Hybrid, NodeFilter.none());
                }
                updateViewerData();
            }
        };
        actionFilterFile
                .setImageDescriptor(MetriculatorPluginActivator.getDefault().getImageDescriptor(Icon.Size16.FILE));
    }

    private void createActionFilterNamespace() {
        actionFilterNamespace = new Action("Namespace Nodes Only", IAction.AS_CHECK_BOX) {
            public void run() {
                if (isChecked()) {
                    applyViewMode(ViewMode.Filtered, NodeFilter.namespace());
                } else {
                    applyViewMode(ViewMode.Hybrid, NodeFilter.none());
                }
                updateViewerData();
            }
        };
        actionFilterNamespace.setImageDescriptor(
                MetriculatorPluginActivator.getDefault().getImageDescriptor(Icon.Size16.NAMESPACE));
    }

    private void createActionExpandAll() {
        actionExpandAll = new Action("Expand All Nodes") {
            public void run() {
                treeViewer.expandAll();
            }
        };
        actionExpandAll.setImageDescriptor(
                MetriculatorPluginActivator.getDefault().getImageDescriptor(Icon.Size16.EXPAND_ALL));
    }

    private void createActionCollapseAll() {
        actionCollapseAll = new Action("collapse All Nodes",
                MetriculatorPluginActivator.getDefault().getImageDescriptor(Icon.Size16.COLLAPSE_ALL)) {
            public void run() {
                treeViewer.collapseAll();
            }
        };
    }

    private void createActionHybridView() {
        actionHybridView = new Action("Hybrid View Mode (Files, Folders and Source Code Nodes)",
                IAction.AS_RADIO_BUTTON) {
            public void run() {
                if (isChecked()) {
                    applyViewMode(ViewMode.Hybrid, NodeFilter.none());
                    updateViewerData();
                } else {
                    setChecked(true);
                }
            }
        };
        actionHybridView.setImageDescriptor(
                MetriculatorPluginActivator.getDefault().getImageDescriptor(Icon.Size16.FILESYSTEM));
    }

    private void createActionLogicalView() {
        actionLogicalView = new Action("Logical View Mode (Source Code Nodes Only)", IAction.AS_RADIO_BUTTON) {
            public void run() {
                if (isChecked()) {
                    applyViewMode(ViewMode.Logical, NodeFilter.none());
                    updateViewerData();
                } else {
                    setChecked(true);
                }
            }
        };
        actionLogicalView.setImageDescriptor(
                MetriculatorPluginActivator.getDefault().getImageDescriptor(Icon.Size16.VIEWMODE_LOGICAL));
    }

    private void createActionFilterComposite() {
        actionFilterComposite = new Action("Composite Nodes (Class / Structs / Union)", IAction.AS_CHECK_BOX) {
            public void run() {
                if (isChecked()) {
                    applyViewMode(ViewMode.Filtered, NodeFilter.composite());
                } else {
                    applyViewMode(ViewMode.Hybrid, NodeFilter.none());
                }
                updateViewerData();
            }
        };
        actionFilterComposite
                .setImageDescriptor(MetriculatorPluginActivator.getDefault().getImageDescriptor(Icon.Size16.CLASS));
    }

    private void createActionFilterFunction() {
        actionFilterFunction = new Action("Function Nodes Only", IAction.AS_CHECK_BOX) {
            public void run() {
                if (isChecked()) {
                    applyViewMode(ViewMode.Filtered, NodeFilter.function());
                } else {
                    applyViewMode(ViewMode.Hybrid, NodeFilter.none());
                }
                updateViewerData();
            }
        };
        actionFilterFunction.setImageDescriptor(
                MetriculatorPluginActivator.getDefault().getImageDescriptor(Icon.Size16.FUNCTION));
    }

    private void addActionsToMenus() {

        IContributionManager[] managers = { getViewSite().getActionBars().getMenuManager(),
                getViewSite().getActionBars().getToolBarManager() };

        for (IContributionManager manager : managers) {

            manager.add(new Separator());
            manager.add(actionHybridView);
            manager.add(actionLogicalView);
            manager.add(new Separator());
            manager.add(actionFilterFile);
            manager.add(actionFilterNamespace);
            manager.add(actionFilterComposite);
            manager.add(actionFilterFunction);
            manager.add(new Separator());
            manager.add(actionExpandAll);
            manager.add(actionCollapseAll);
            manager.add(actionExport);
        }
    }

    private void addViewerOpenListener(StructuredViewer viewer) {
        viewer.addOpenListener(new IOpenListener() {
            @Override
            public void open(OpenEvent event) {
                openSelectedNode(event.getSelection());
            }
        });
    }

    private void openSelectedNode(ISelection selection) {
        AbstractNode node = getFirstNodeFrom(selection);
        boolean selectionSupportsOpen = node instanceof LogicNode || node instanceof FileNode;

        if (selectionSupportsOpen) {

            AbstractNode.EditorInfo info = node.getEditorInfo();
            String filepath = info.getFilePath();
            IEditorPart editor = null;

            try {
                editor = CodanEditorUtility.openInEditor(filepath, null);

                if (editor instanceof ITextEditor && !(node instanceof FileNode)) {
                    ITextEditor textEditor = (ITextEditor) editor;
                    textEditor.selectAndReveal(info.getNodeOffset(), info.getNodeLength());
                }
            } catch (PartInitException e) {
                e.printStackTrace();
            }
        }
    }

    private AbstractNode getFirstNodeFrom(ISelection selection) {
        if (selection instanceof IStructuredSelection) {
            IStructuredSelection ssel = (IStructuredSelection) selection;
            return (AbstractNode) ssel.iterator().next();
        }
        return null;
    }

    @Override
    public void setFocus() {
        if (activeViewer instanceof TreeViewer) {
            treeViewer.getControl().setFocus();
        } else if (activeViewer instanceof TableViewer) {
            tableViewer.getControl().setFocus();
        }
    }

    @Override
    public void update(Observable o, Object arg) {

        if (((JobState) arg) == JobState.JOB_DONE) {

            Display.getDefault().syncExec(new Runnable() {
                @Override
                public void run() {
                    applyCodanFinishedState();
                }
            });
        }

        if (((JobState) arg) == JobState.JOB_ABOUT_TO_RUN) {

            Display.getDefault().syncExec(new Runnable() {
                @Override
                public void run() {
                    applyCodanStartedState();
                }
            });
        }
    }

    class TableContentProvider implements IStructuredContentProvider {

        @Override
        public void dispose() {
        }

        @Override
        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
        }

        @Override
        public Object[] getElements(Object inputElement) {
            return currTreeBuilder.root.getChildren().toArray();
        }
    }

    class MetriculatorCellLabelProvider extends CellLabelProvider {

        @Override
        public void update(ViewerCell cell) {
            switch (cell.getColumnIndex()) {
            case 0:
                cell.setText(cell.getElement().toString());
                cell.setImage(MetriculatorPluginActivator.getDefault()
                        .getImageDescriptor(((AbstractNode) cell.getElement()).getIconPath()).createImage());
                break;
            default:
                AbstractMetric metric;
                if (activeViewer instanceof TreeViewer) {
                    metric = MetricColumn.getMetric(treeViewer.getTree().getColumn(cell.getColumnIndex()));
                } else {
                    metric = MetricColumn.getMetric(tableViewer.getTable().getColumn(cell.getColumnIndex()));
                }

                if (metric != null) {
                    applyProblemsOf(metric, cell);
                    int metricValue = ((AbstractNode) cell.getElement()).getAggregatedValueOf(metric);
                    cell.setText(NumberFormat.getIntegerInstance().format(metricValue));
                }
                break;
            }
        }

        private void applyProblemsOf(AbstractMetric metric, ViewerCell toCell) {
            Collection<IProblem> problems = metric.getChecker().getProblemsFor((AbstractNode) toCell.getElement());

            if (problems != null) {
                for (IProblem p : problems) {
                    if (p.getSeverity() == CodanSeverity.Warning) {
                        toCell.setBackground(AwtSwtColorConverter.LIGHT_ORANGE);
                    } else if (p.getSeverity() == CodanSeverity.Error) {
                        toCell.setBackground(AwtSwtColorConverter.LIGHT_RED);
                    } else if (p.getSeverity() == CodanSeverity.Info) {
                        toCell.setBackground(AwtSwtColorConverter.fromAwt(Color.WHITE));
                    }
                }
            } else {
                toCell.setBackground(null);
            }
        }

        @Override
        public String getToolTipText(Object element) {
            if (element instanceof AbstractNode) {
                return String.format("'%s' , children: %s", ((AbstractNode) element).getPath(),
                        ((AbstractNode) element).getChildren().size());
            }
            return null;
        }

        @Override
        public int getToolTipDisplayDelayTime(Object object) {
            return 100;
        }
    }

    private void applyCodanFinishedState() {
        createAndUpdateMetricTreeColumns();
        createAndUpdateMetricTableColumns();
        applyViewMode(ViewMode.Hybrid, null);
        updateViewerData();
        MetricColumnHeaderMenu.updateItemSelections(MetricColumnHeaderMenu.treeMenuManager);
        MetricColumnHeaderMenu.updateItemSelections(MetricColumnHeaderMenu.tableMenuManager);
    }

    private void applyCodanStartedState() {
        treeViewer.setInput(null);
        tableViewer.setInput(null);
    }

    private void updateViewerData() {
        activeViewer.setInput(currTreeBuilder.root);

        if (activeViewer instanceof TableViewer) {
            int rowCount = ((TableViewer) activeViewer).getTable().getItemCount();
            String rowCountString = NumberFormat.getIntegerInstance().format(rowCount);

            tableViewer.getTable().getColumn(0)
                    .setText(String.format("%s (%s items)", SCOPE_COLUMN_TITLE, rowCountString));
        }
    }
}