org.eclipse.tracecompass.extension.internal.callstack.ui.views.stacktable.CallStackTableView.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.tracecompass.extension.internal.callstack.ui.views.stacktable.CallStackTableView.java

Source

/*******************************************************************************
 * Copyright (c) 2017 cole Polytechnique de Montral
 *
 * 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
 *******************************************************************************/

package org.eclipse.tracecompass.extension.internal.callstack.ui.views.stacktable;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;

import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ITableColorProvider;
import org.eclipse.jface.viewers.ITableFontProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.tracecompass.extension.internal.callstack.core.context.ContextCallStackAnalysis;
import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule;
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
import org.eclipse.tracecompass.tmf.core.signal.TmfEventSelectedSignal;
import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
import org.eclipse.tracecompass.tmf.ui.views.TmfView;

public class CallStackTableView extends TmfView {

    private @Nullable TreeViewer fTreeViewer;

    public CallStackTableView() {
        super("Call Stack Table");
    }

    /* The elements of the tree viewer are of type ITmfTreeViewerEntry */
    private class TreeContentProvider implements ITreeContentProvider {

        @Override
        public void dispose() {
        }

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

        @Override
        public Object[] getElements(@Nullable Object inputElement) {
            if (inputElement instanceof StackTableEntry) {
                return ((StackTableEntry) inputElement).getChildren();
            }
            return new StackTableEntry[0];
        }

        @Override
        public Object[] getChildren(@Nullable Object parentElement) {
            if (parentElement == null) {
                return new StackTableEntry[0];
            }
            StackTableEntry entry = (StackTableEntry) parentElement;
            return entry.getChildren();
        }

        @Override
        public @Nullable Object getParent(@Nullable Object element) {
            if (element == null) {
                return null;
            }
            StackTableEntry entry = (StackTableEntry) element;
            return entry.getParent();
        }

        @Override
        public boolean hasChildren(@Nullable Object element) {
            if (element == null) {
                return false;
            }
            StackTableEntry entry = (StackTableEntry) element;
            return entry.hasChildren();
        }

    }

    /**
     * Base class to provide the labels for the tree viewer. Views extending
     * this class typically need to override the getColumnText method if they
     * have more than one column to display. It also allows to change the font
     * and colors of the cells.
     */
    protected static class TreeLabelProvider
            implements ITableLabelProvider, ITableFontProvider, ITableColorProvider {

        @Override
        public void addListener(@Nullable ILabelProviderListener listener) {
        }

        @Override
        public void dispose() {
        }

        @Override
        public boolean isLabelProperty(@Nullable Object element, @Nullable String property) {
            return false;
        }

        @Override
        public void removeListener(@Nullable ILabelProviderListener listener) {
        }

        @Override
        public @Nullable Image getColumnImage(@Nullable Object element, int columnIndex) {
            return null;
        }

        @Override
        public String getColumnText(@Nullable Object element, int columnIndex) {
            return String.valueOf(element);
        }

        @Override
        public Color getForeground(@Nullable Object element, int columnIndex) {
            return Display.getCurrent().getSystemColor(SWT.COLOR_LIST_FOREGROUND);
        }

        @Override
        public Color getBackground(@Nullable Object element, int columnIndex) {
            return Display.getCurrent().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
        }

        @Override
        public @Nullable Font getFont(@Nullable Object element, int columnIndex) {
            return null;
        }

    }

    // ------------------------------------------------------------------------
    // ViewPart
    // ------------------------------------------------------------------------

    @Override
    public void createPartControl(@Nullable Composite parent) {
        super.createPartControl(parent);
        SashForm sf = new SashForm(parent, SWT.NONE);
        /* Build the tree viewer part of the view */
        TreeViewer treeViewer = new TreeViewer(sf, SWT.FULL_SELECTION | SWT.H_SCROLL);
        fTreeViewer = treeViewer;
        treeViewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS);
        final Tree tree = treeViewer.getTree();
        tree.setHeaderVisible(true);
        tree.setLinesVisible(true);
        TreeViewerColumn column = new TreeViewerColumn(treeViewer, SWT.LEFT);
        column.getColumn().setText("CallSite");
        column.getColumn().setWidth(50);
        treeViewer.setContentProvider(new TreeContentProvider());
        treeViewer.setLabelProvider(new TreeLabelProvider());
    }

    @Override
    public void setFocus() {

    }

    @TmfSignalHandler
    public void eventSelected(TmfEventSelectedSignal signal) {
        ITmfEvent event = signal.getEvent();
        IAnalysisModule analysisModule = event.getTrace().getAnalysisModule(ContextCallStackAnalysis.ID);
        TreeViewer treeViewer = fTreeViewer;
        if (treeViewer == null) {
            return;
        }
        if (!(analysisModule instanceof ContextCallStackAnalysis)) {
            treeViewer.setInput(null);
        }
        Map<String, List<Long>> stack = ContextCallStackAnalysis.eventHandle(event);
        treeViewer.setInput(convertStack(stack));
    }

    private class StackTableEntry {

        private @Nullable StackTableEntry fParent;

        public StackTableEntry(@Nullable StackTableEntry parent) {
            fParent = parent;
        }

        public StackTableEntry[] getChildren() {
            return new StackTableEntry[0];
        }

        public boolean hasChildren() {
            return getChildren().length != 0;
        }

        public @Nullable Object getParent() {
            return fParent;
        }

    }

    private class StackTableRootEntry extends StackTableEntry {
        List<StackTableEntry> fEntries = new ArrayList<>();

        public StackTableRootEntry() {
            super(null);
        }

        public void addEntry(StackTableEntry entry) {
            fEntries.add(entry);
        }

        @Override
        public StackTableEntry[] getChildren() {
            return fEntries.toArray(new StackTableEntry[fEntries.size()]);
        }
    }

    private class StackTableStringEntry extends StackTableEntry {
        private String fName;
        private List<StackTableEntry> fChildren;

        StackTableStringEntry(StackTableRootEntry entry, String name, List<Long> list) {
            super(entry);
            entry.addEntry(this);
            fName = name;
            fChildren = list.stream().map(l -> new StackTableLongEntry(this, l)).collect(Collectors.toList());
        }

        @Override
        public StackTableEntry[] getChildren() {
            return fChildren.toArray(new StackTableEntry[fChildren.size()]);
        }

        @Override
        public String toString() {
            return fName;
        }
    }

    private class StackTableLongEntry extends StackTableEntry {
        private long fCallsite;

        public StackTableLongEntry(StackTableStringEntry entry, long callsite) {
            super(entry);
            fCallsite = callsite;
        }

        @Override
        public String toString() {
            return Long.toHexString(fCallsite);
        }
    }

    private Object convertStack(Map<@NonNull String, @NonNull List<@NonNull Long>> stack) {
        StackTableRootEntry rootEntry = new StackTableRootEntry();
        for (Entry<String, List<Long>> entry : stack.entrySet()) {
            new StackTableStringEntry(rootEntry, entry.getKey(), entry.getValue());
        }
        return rootEntry;
    }

}