com.nokia.carbide.cpp.pi.irq.IrqTraceGraph.java Source code

Java tutorial

Introduction

Here is the source code for com.nokia.carbide.cpp.pi.irq.IrqTraceGraph.java

Source

/*
 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). 
 * All rights reserved.
 * This component and the accompanying materials are made available
 * under the terms of the License "Eclipse Public License v1.0"
 * which accompanies this distribution, and is available
 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
 *
 * Initial Contributors:
 * Nokia Corporation - initial contribution.
 *
 * Contributors:
 *
 * Description: 
 *
 */

package com.nokia.carbide.cpp.pi.irq;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.Vector;

import org.eclipse.draw2d.FigureCanvas;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.MouseEvent;
import org.eclipse.draw2d.MouseMotionListener;
import org.eclipse.draw2d.Panel;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Sash;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.PlatformUI;

import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTrace;
import com.nokia.carbide.cpp.internal.pi.plugin.model.ITitleBarMenu;
import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
import com.nokia.carbide.cpp.internal.pi.visual.GraphComposite;
import com.nokia.carbide.cpp.internal.pi.visual.PIEvent;
import com.nokia.carbide.cpp.internal.pi.visual.PIEventListener;
import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
import com.nokia.carbide.cpp.pi.visual.IGenericTraceGraph;

/**
 * class for irq trace graph
 */
public class IrqTraceGraph extends GenericTraceGraph
        implements ITitleBarMenu, PIEventListener, MouseMotionListener {

    public static final char TYPE_IRQ = 1;
    public static final char TYPE_SWI = 2;
    public static final char TYPE_BOTH = 3;

    /* composite where tables are placed */
    private Composite holder;

    /* Irq trace */
    private IrqTrace irqTrace;
    private boolean readyToDraw = false;

    /* margin in the bottom of the graph */
    private static final int BOTTOM_MARGIN = 20;

    /* tables containing threads, functions and irq lines */
    private SwiThreadTable tableThreadIRQ;
    private SwiFunctionTable tableSWIFunction;
    private IrqLineTable tableIrqLine;

    /* composites for tables */
    private Composite compositeSWI;
    private Composite compositeIRQ;

    /* height of the the graph */
    private int panelHeight;

    /* hashtables that are used for drawing graphs */
    private Hashtable<String, Hashtable<RGB, TreeMap<Long, Integer>>> swiDrawList;
    private Hashtable<Long, Hashtable<RGB, TreeMap<Long, Integer>>> irqDrawList;

    /* is swi table shown */
    private boolean swiTableVisible = true;

    /* places of vectical dash lines */
    private ArrayList<Integer> interruptLines;

    /**
     * Constructor
     * 
     * @param graphIndex
     *            Index of the graph
     * @param irqTrace
     *            trace that is analysed
     * @param uid
     *            uid number of the trace
     */
    public IrqTraceGraph(int graphIndex, IrqTrace irqTrace, int uid) {
        super((GenericSampledTrace) irqTrace);

        swiDrawList = new Hashtable<String, Hashtable<RGB, TreeMap<Long, Integer>>>();
        irqDrawList = new Hashtable<Long, Hashtable<RGB, TreeMap<Long, Integer>>>();

        this.irqTrace = irqTrace;

        // create the label and a tableviewer
        holder = new Composite(
                NpiInstanceRepository.getInstance().getProfilePage(uid, graphIndex).getBottomComposite(), SWT.NONE);
        PlatformUI.getWorkbench().getHelpSystem().setHelp(holder, IrqPlugin.HELP_CONTEXT_ID_MAIN_PAGE);

        GridLayout gl = new GridLayout();
        gl.marginHeight = 0;
        gl.marginWidth = 0;
        gl.marginLeft = 0;
        gl.marginRight = 0;
        holder.setLayout(gl);

        // titlebar
        Label label = new Label(holder, SWT.CENTER);
        label.setBackground(holder.getDisplay().getSystemColor(SWT.COLOR_WHITE));
        label.setFont(PIPageEditor.helvetica_8);
        label.setText(Messages.IrqTraceGraph_0);
        label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

        // Create composite for SWI tables
        compositeSWI = new Composite(holder, SWT.NONE);
        compositeSWI.setLayout(new FormLayout());
        compositeSWI.setLayoutData(new GridData(GridData.FILL_BOTH));

        // Create composite for irq table
        compositeIRQ = new Composite(holder, SWT.NONE);
        compositeIRQ.setLayout(new FormLayout());
        compositeIRQ.setLayoutData(new GridData(GridData.FILL_BOTH));

        // Create Thread table
        tableThreadIRQ = new SwiThreadTable(this, compositeSWI);

        // vertical sash
        Sash acrossSash = new Sash(compositeSWI, SWT.VERTICAL);

        // Create SWI function table
        tableSWIFunction = new SwiFunctionTable(this, compositeSWI);

        // Create Thread table
        tableIrqLine = new IrqLineTable(this, compositeIRQ);

        // Set layout data for tables and sash

        // FormData for IRQ/Threads
        FormData formData = new FormData();
        formData.top = new FormAttachment(0);
        formData.bottom = new FormAttachment(100);
        formData.left = new FormAttachment(0);
        formData.right = new FormAttachment(acrossSash);
        tableThreadIRQ.getTable().setLayoutData(formData);

        // FormData for SWT functions
        formData = new FormData();
        formData.top = new FormAttachment(0);
        formData.bottom = new FormAttachment(100);
        formData.left = new FormAttachment(acrossSash);
        formData.right = new FormAttachment(100);
        tableSWIFunction.getTable().setLayoutData(formData);

        // FormData for irq table
        formData = new FormData();
        formData.left = new FormAttachment(0);
        formData.right = new FormAttachment(100);
        formData.top = new FormAttachment(0);
        formData.bottom = new FormAttachment(100);
        tableIrqLine.getTable().setLayoutData(formData);

        // FormData for acrossSash
        // Put it initially in the middle
        formData = new FormData();
        formData.left = new FormAttachment(50);
        formData.top = new FormAttachment(0);
        formData.bottom = new FormAttachment(100);
        acrossSash.setLayoutData(formData);

        // add selection listener to sash so that user can change sash's place
        final FormData acrossSashData = formData;
        final Composite parentFinal = acrossSash.getParent();
        acrossSash.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent event) {
                if (event.detail != SWT.DRAG) {
                    acrossSashData.left = new FormAttachment(0, event.x);
                    parentFinal.layout();
                }
            }
        });

        // initially set swi table visible
        this.setSwiTableVisible();
        this.readyToDraw = true;

    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph#action(java
     * .lang.String)
     */
    public void action(String action) {

    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph#paint(org.
     * eclipse.draw2d.Panel, org.eclipse.draw2d.Graphics)
     */
    public void paint(Panel panel, Graphics graphics) {

        // save height for tooltip
        this.panelHeight = panel.getSize().height;

        if (!this.readyToDraw) {
            return;
        }

        this.drawDottedLineBackground(graphics, BOTTOM_MARGIN, false);

        if (this.swiTableVisible) {
            // draw selected swi threads
            if (irqTrace.isFunctionNamesFound() == false) {
                this.drawText(graphics, Messages.IrqTraceGraph_1);
                return;

            }
            if (swiDrawList.size() == 0) {
                this.drawText(graphics, Messages.IrqTraceGraph_2);
                return;
            } else {
                int[] linePlaces = this.drawHorizontalLines(panel, graphics, swiDrawList.size());
                this.drawLineNames(panel, graphics, linePlaces);
                this.drawSoftwareInterrupts(panel, graphics, linePlaces);
            }

        } else {
            // draw selected irq lines
            if (irqDrawList.size() == 0) {
                this.drawText(graphics, Messages.IrqTraceGraph_3);
                return;
            } else {
                int[] linePlaces = this.drawHorizontalLines(panel, graphics, irqDrawList.size());
                this.drawLineNames(panel, graphics, linePlaces);
                this.drawHardwareInterrupts(panel, graphics, linePlaces);
            }
        }

        // draw dashed lines in the graph
        this.drawInterruptLines(graphics, panel.getSize().width);

        // draw the same selection as the Address/Thread trace
        this.drawSelectionSection(graphics, BOTTOM_MARGIN);
    }

    /**
     * Draws interrupt count lines
     * 
     * @param graphics
     *            graphics context
     * @param width
     *            width of the panel
     */
    private void drawInterruptLines(Graphics graphics, int width) {

        // get color for line
        Color previousColor = graphics.getForegroundColor();
        graphics.setForegroundColor(holder.getDisplay().getSystemColor(SWT.COLOR_GRAY));

        if (interruptLines != null) {
            // draw lines only if space between them is less than 7
            if (interruptLines.get(0) > 7) {
                for (Integer item : interruptLines) {
                    graphics.setLineStyle(Graphics.LINE_DASH);
                    graphics.drawLine(0, item - 1, width, item - 1);
                }
            }
        }
        graphics.setForegroundColor(previousColor);
    }

    /**
     * Draws text into graph
     * 
     * @param graphics
     *            graphics where text is drawn
     * @param text
     *            text that is drawn
     */
    private void drawText(Graphics graphics, String text) {
        // get current font and color
        Font previousFont = graphics.getFont();
        Color previousColor = graphics.getForegroundColor();

        // Set font size
        FontData[] fontData = previousFont.getFontData();
        fontData[0].height = 10;
        Font newFont = new Font(previousFont.getDevice(), fontData);

        // set text color as black
        Color newColor = holder.getDisplay().getSystemColor(SWT.COLOR_BLACK);
        graphics.setForegroundColor(newColor);

        graphics.setFont(newFont);
        graphics.drawText(text, new Point(5, 5));

        // restore previous values to color and font
        graphics.setForegroundColor(previousColor);
        graphics.setFont(previousFont);
    }

    /**
     * Gets places of horizontal lines between threads/irq lines
     * 
     * @param panelHeight
     *            Height of the panel
     * @param tableSize
     *            amount of threads/irq lines
     * @return array containing places of each line
     */

    public int[] getHorizontalLinePlaces(double panelHeight, int tableSize) {

        // count height of one thread/irq line in graph
        int[] array = new int[tableSize];
        double spaceForOneThread = ((panelHeight - BOTTOM_MARGIN) / (double) tableSize);

        // draw lines
        int i = 0;
        while (i < array.length) {
            array[i] = (int) ((i + 1) * spaceForOneThread);
            i++;
        }
        return array;
    }

    /**
     * Draws horizontal lines between threads/irq lines
     * 
     * @param panel
     *            panel where lines are drawn
     * @param graphics
     *            graphics that is used for drawing
     * @param tablesize
     *            table's size which details are used for drawing
     * @return array containing places of lines
     */
    public int[] drawHorizontalLines(Panel panel, Graphics graphics, int tableSize) {

        // count height of one thread/irq line in graph
        int[] array = new int[tableSize];
        double height = (double) panel.getSize().height;
        double spaceForOneThread = ((height - BOTTOM_MARGIN) / (double) tableSize);

        // draw lines
        int i = 0;
        while (i < array.length) {
            array[i] = (int) ((i + 1) * spaceForOneThread);
            graphics.drawLine(new Point(0, array[i]), new Point(panel.getSize().width, array[i]));
            i++;
        }
        return array;
    }

    /**
     * Draws thread names/irq lines into graph
     * 
     * @param panel
     *            panel where names are drawn
     * @param graphics
     *            graphics that is used for drawing
     * @param linePlaces
     *            places of lines that are separating each line in the graph
     */
    public void drawLineNames(Panel panel, Graphics graphics, int[] linePlaces) {

        if (linePlaces.length != 0) {

            // calculate font size
            int fontSize = (int) (linePlaces[0] * 0.7);

            if (fontSize > 10) {
                fontSize = 10;
            }

            if (fontSize == 0) {
                return;
            }

            Font previousFont = graphics.getFont();
            FontData[] fontData = previousFont.getFontData();
            fontData[0].height = fontSize;

            Font newFont = new Font(previousFont.getDevice(), fontData);

            graphics.setFont(newFont);

            int i = 0;

            if (swiTableVisible) {

                Enumeration<String> eventIterator = swiDrawList.keys();

                // go thru threads and draw its name into graph
                while (eventIterator.hasMoreElements()) {
                    String threadName = eventIterator.nextElement();
                    graphics.drawString(threadName, new Point(5, linePlaces[i] - linePlaces[0]));
                    i++;

                }

            } else {
                Enumeration<Long> eventIterator = irqDrawList.keys();

                // go thru irq lines and draw its name into graph
                while (eventIterator.hasMoreElements()) {
                    Long id = eventIterator.nextElement();
                    String printText = IrqSampleTypeWrapper.getLineText(id);
                    graphics.drawString(printText, new Point(5, linePlaces[i] - linePlaces[0]));
                    i++;

                }
            }

            // restore previous font
            graphics.setFont(previousFont);

        }
    }

    /**
     * Draws hardware interrupts
     * 
     * @param panel
     *            panel where names are drawn
     * @param graphics
     *            graphics that is used for drawing
     * @param linePlaces
     *            places of lines that are separating each irq line in the graph
     */
    public void drawHardwareInterrupts(Panel panel, Graphics graphics, int[] linePlaces) {

        Enumeration<Long> irqLineIterator = irqDrawList.keys();
        int tableItemIndex = 0;

        // go thru all irq lines
        while (irqLineIterator.hasMoreElements()) {

            Hashtable<RGB, TreeMap<Long, Integer>> irqLines = irqDrawList.get(irqLineIterator.nextElement());

            // draw this irq lines interrupts into graph
            this.drawInterrupts(graphics, tableItemIndex, linePlaces, irqLines,
                    irqTrace.getMaxAmountOfIRQSamples());
            tableItemIndex++;

        }

    }

    /**
     * Draws software interrupts
     * 
     * @param panel
     *            panel where names are drawn
     * @param graphics
     *            graphics that is used for drawing
     * @param table
     *            table which details are used for drawing
     * @param linePlaces
     *            places of lines that are separating each irq line in the graph
     */
    public void drawSoftwareInterrupts(Panel panel, Graphics graphics, int[] linePlaces) {

        Enumeration<String> threadIterator = swiDrawList.keys();
        int tableItemIndex = 0;

        // go thru all threads
        while (threadIterator.hasMoreElements()) {
            Hashtable<RGB, TreeMap<Long, Integer>> allThreadsFunctions = swiDrawList
                    .get(threadIterator.nextElement());
            Hashtable<RGB, TreeMap<Long, Integer>> checkedFunctions = new Hashtable<RGB, TreeMap<Long, Integer>>();

            Enumeration<RGB> functionIterator = allThreadsFunctions.keys();

            // go thru each function from thread and gather draw data into
            // hashtable
            while (functionIterator.hasMoreElements()) {
                RGB thisColor = functionIterator.nextElement();
                TreeMap<Long, Integer> events = allThreadsFunctions.get(thisColor);
                checkedFunctions.put(thisColor, events);
            }
            // draw threads interrupts into graph
            this.drawInterrupts(graphics, tableItemIndex, linePlaces, checkedFunctions,
                    irqTrace.getMaxAmountOfSWISamples());
            tableItemIndex++;

        }
    }

    /**
     * draws one thread/irq lines interrupts into graph
     * 
     * @param graphics
     *            graphics that is used for drawing
     * @param tableItemIndex
     *            index of the table item
     * @param linePlaces
     *            places of lines that are separating each thread/irq line in
     *            the graph
     * @param events
     *            events of the thread/irq line
     * @param maxAmountOfSamples
     *            maximum amount of events in one time frame
     */
    private void drawInterrupts(Graphics graphics, int tableItemIndex, int[] linePlaces,
            Hashtable<RGB, TreeMap<Long, Integer>> events, int maxAmountOfSamples) {

        // get scale for x axis.
        double scale = this.getScale();

        // get top and bottom of the irq line that is drawn into screen
        int top = 0;
        if (tableItemIndex != 0) {
            top = linePlaces[tableItemIndex - 1];
        }
        int bottom = linePlaces[tableItemIndex] - 1;

        // count one interrupts weight
        double weightOfOneInterrupt = (double) (bottom - top) / (double) maxAmountOfSamples;

        Hashtable<Long, Integer> drawnInterrupts = new Hashtable<Long, Integer>();
        Enumeration<RGB> functionIterator = events.keys();

        Color previousColor = graphics.getForegroundColor();

        // go thru each color
        while (functionIterator.hasMoreElements()) {
            RGB thisRGB = functionIterator.nextElement();
            Color thisColor = new Color(holder.getDisplay(), thisRGB);
            TreeMap<Long, Integer> eventsFromOneColor = events.get(thisRGB);

            graphics.setForegroundColor(thisColor);

            Set<Long> eventSet = eventsFromOneColor.keySet();
            Iterator<Long> eventIterator = eventSet.iterator();

            // go thru each interrupt from table and draw them into graph
            while (eventIterator.hasNext()) {

                // check if this time frame already has events and calculate
                // place of line if needed
                Long thisTime = eventIterator.next();
                int amountOfEvents = eventsFromOneColor.get(thisTime);

                if (!drawnInterrupts.containsKey(thisTime)) {

                    graphics.drawLine(new Point(thisTime / scale, bottom - weightOfOneInterrupt * amountOfEvents),
                            new Point(thisTime / scale, bottom));
                    drawnInterrupts.put(thisTime, amountOfEvents);
                } else {
                    int previousValue = drawnInterrupts.get(thisTime);
                    int newBottom = bottom - (int) (previousValue * weightOfOneInterrupt);
                    graphics.drawLine(
                            new Point(thisTime / scale, newBottom - weightOfOneInterrupt * amountOfEvents),
                            new Point(thisTime / scale, newBottom));
                    drawnInterrupts.put(thisTime, previousValue + amountOfEvents);

                }

            }
        }
        graphics.setForegroundColor(previousColor);

    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph#paintLeftLegend
     * (org.eclipse.draw2d.FigureCanvas, org.eclipse.swt.graphics.GC)
     */
    public void paintLeftLegend(FigureCanvas figureCanvas, GC gc) {
        int lineItemCount = 0;
        int maxItemsPerMS = 0;

        if (gc == null) {
            return;
        }

        // Left legend not in use
        if (swiTableVisible) {
            lineItemCount = swiDrawList.size();
            maxItemsPerMS = irqTrace.getMaxAmountOfSWISamples();
        } else {
            lineItemCount = irqDrawList.size();
            maxItemsPerMS = irqTrace.getMaxAmountOfIRQSamples();

        }

        if (lineItemCount == 0) {
            return;
        }

        Rectangle rect = ((GraphComposite) figureCanvas.getParent()).figureCanvas.getClientArea();
        double heightOfCanvas = rect.height;
        int[] linePlaces = getHorizontalLinePlaces(heightOfCanvas, lineItemCount);
        double heightOfOneLine = (heightOfCanvas - BOTTOM_MARGIN) / lineItemCount;

        interruptLines = new ArrayList<Integer>();

        this.drawLegendOfOneLine(gc, 0, (int) heightOfOneLine, maxItemsPerMS);
        for (int index = 1; index < linePlaces.length; index++) {
            this.drawLegendOfOneLine(gc, linePlaces[index - 1], (int) heightOfOneLine, maxItemsPerMS);
        }

    }

    /**
     * Draws legend of one thread or irq line
     * 
     * @param graphics
     *            graphics context
     * @param top
     *            place of the top of the line
     * @param size
     *            size of line
     * @param maxValue
     *            maximum value of interrupts at one ms
     */
    private void drawLegendOfOneLine(GC graphics, int top, int size, int maxValue) {

        double quarterOfMaxValue = (double) maxValue / 4.0;
        int drawTop = top;
        int drawValue = maxValue;

        for (int index = 1; index < 5; index++) {

            String legend = Integer.toString(drawValue) + Messages.IrqTraceGraph_4;
            org.eclipse.swt.graphics.Point extent = graphics.stringExtent(legend);

            // texts are drawn only if size of line is greater than 50 pixels
            if (size > 50) {
                graphics.drawString(legend, IGenericTraceGraph.Y_LEGEND_WIDTH - extent.x - 4, (int) drawTop - 2);
            }

            // get next draw value
            drawValue = (int) (maxValue - (double) index * quarterOfMaxValue);
            double doublevalue = size - ((double) drawValue / (double) maxValue) * size;
            // get place of the line
            drawTop = (int) (top + doublevalue);

            // add line place into interruptLines
            if (index < 4) {
                interruptLines.add(drawTop);
            }

        }

    }

    /*
     * (non-Javadoc)
     * 
     * @see com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph#repaint()
     */
    public void repaint() {
        if (parentComponent != null) {
            this.parentComponent.repaintComponent();
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @seecom.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph#
     * setLegendTableVisible(boolean)
     */
    public void graphVisibilityChanged(boolean value) {
        if (holder != null) {
            holder.setVisible(value);
            holder.getParent().layout();
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @seecom.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph#
     * setLegendTableMaximized(boolean)
     */
    public void graphMaximized(boolean value) {
        if (holder != null) {
            if (holder.getParent().getClass() == SashForm.class) {
                SashForm sashForm = (SashForm) holder.getParent();
                if (value) {
                    sashForm.setMaximizedControl(holder);
                } else {
                    sashForm.setMaximizedControl(null);

                }
            }

        }
    }

    /**
     * @return irq trace
     */
    public IrqTrace getIrqTrace() {
        return irqTrace;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.nokia.carbide.cpp.pi.visual.IGenericTraceGraph#getTitle()
     */
    public String getTitle() {
        return Messages.IrqTraceGraph_5;
    }

    /**
     * sets Irq table visible
     */
    public void setIrqTableVisible() {
        this.setSwiTableVisible(false);
    }

    /**
     * sets Swi table visible
     */
    public void setSwiTableVisible() {
        this.setSwiTableVisible(true);

    }

    /**
     * changes swi tables visibility according to parameter
     * 
     * @param value
     */
    private void setSwiTableVisible(boolean value) {

        this.swiTableVisible = value;

        compositeIRQ.setVisible(!value);
        compositeSWI.setVisible(value);

        if (compositeIRQ.getLayoutData().getClass() == GridData.class) {
            ((GridData) compositeIRQ.getLayoutData()).exclude = value;
        }
        if (compositeSWI.getLayoutData().getClass() == GridData.class) {
            ((GridData) compositeSWI.getLayoutData()).exclude = !value;
        }
        holder.layout();
        this.repaint();
    }

    /*
     * (non-Javadoc)
     * 
     * @seecom.nokia.carbide.cpp.internal.pi.plugin.model.ITitleBarMenu#
     * addTitleBarMenuItems()
     */
    public Action[] addTitleBarMenuItems() {
        // Create actions for Title Bar's drop-down list

        ArrayList<Action> actionArrayList = new ArrayList<Action>();

        // Action for showing swi interrupts
        Action showSwiTable = new Action() {
            public void run() {
                setSwiTableVisible();
            }

        };
        showSwiTable.setText(Messages.IrqTraceGraph_6);
        actionArrayList.add(showSwiTable);

        // Action for showing irq interrupts
        Action showIrqTable = new Action() {
            public void run() {
                setIrqTableVisible();
            }

        };
        showIrqTable.setText(Messages.IrqTraceGraph_7);
        actionArrayList.add(showIrqTable);

        return actionArrayList.toArray(new Action[actionArrayList.size()]);

    }

    /* (non-Javadoc)
     * @see com.nokia.carbide.cpp.internal.pi.plugin.model.ITitleBarMenu#getContextHelpId()
     */
    public String getContextHelpId() {
        return IrqPlugin.HELP_CONTEXT_ID_MAIN_PAGE;
    }

    /**
     * Function that is called when thread is checked from the thread table
     * 
     * @param threadName
     */
    public void threadChecked(String threadName) {

        Hashtable<RGB, TreeMap<Long, Integer>> hashAllFunctions = new Hashtable<RGB, TreeMap<Long, Integer>>();
        Hashtable<String, ArrayList<Long>> hash = irqTrace.getThreadsToFunctions().get(threadName);

        if (hash == null) {
            return;
        }
        Enumeration<String> it = hash.keys();

        // go thru function hashtable
        while (it.hasMoreElements()) {
            String threadname = it.nextElement();

            IrqSampleTypeWrapper wrapper = tableSWIFunction.getFunctionColors().get(threadname);
            if (!wrapper.isSelected()) {
                continue;
            }

            // get add events from one function into hashOneFunction map
            TreeMap<Long, Integer> hashOneFunction = new TreeMap<Long, Integer>();
            ArrayList<Long> eventList = hash.get(threadname);
            for (Long item : eventList) {
                // if interrupt at this time does not yet exist create new map
                // item
                if (!hashOneFunction.containsKey(item)) {
                    hashOneFunction.put(item, 1);
                }
                // if interrupt exists increase its values
                else {
                    int previousvalue = hashOneFunction.get(item);
                    hashOneFunction.put(item, previousvalue + 1);
                }
            }
            RGB rgp = wrapper.rgb;
            // save event into hash
            hashAllFunctions.put(rgp, hashOneFunction);
        }
        // add hashtable into draw list
        swiDrawList.put(threadName, hashAllFunctions);

    }

    /**
     * function that is called when thread is unchecked
     * 
     * @param threadName
     *            name of the thread
     */
    public void threadUnchecked(String threadName) {

        // remove thread from draw list
        if (swiDrawList.containsKey(threadName)) {
            swiDrawList.remove(threadName);
        }

    }

    /**
     * function that is called then irq line is checked
     * 
     * @param irqLine
     *            irq line number
     */
    public void irqLineChecked(IrqSampleTypeWrapper irqLine) {

        // get add events from one line into oneLinesInterrupts map
        TreeMap<Long, Integer> oneLinesInterrupts = new TreeMap<Long, Integer>();

        Vector<IrqSample> samples = irqLine.samples;
        for (IrqSample item : samples) {
            // if interrupt at this time does not yet exist create new map item
            if (!oneLinesInterrupts.containsKey(item.sampleSynchTime)) {
                oneLinesInterrupts.put(item.sampleSynchTime, 1);
            }
            // if interrupt exists increase its values

            else {
                int previousvalue = oneLinesInterrupts.get(item.sampleSynchTime);
                oneLinesInterrupts.put(item.sampleSynchTime, previousvalue + 1);
            }
        }

        // add hashtable into draw list
        RGB rgpColor = irqLine.rgb;
        Hashtable<RGB, TreeMap<Long, Integer>> drawTable = new Hashtable<RGB, TreeMap<Long, Integer>>();
        drawTable.put(rgpColor, oneLinesInterrupts);
        irqDrawList.put((long) irqLine.getPrototypeSample().getIrqL1Value(), drawTable);

    }

    /**
     * function that is called when irq line is unchecked
     * 
     * @param irqLine
     *            irq line number
     */
    public void irqLineUnchecked(IrqSampleTypeWrapper irqLine) {

        // remove line from the draw list
        if (irqDrawList.containsKey((long) irqLine.getPrototypeSample().getIrqL1Value())) {
            irqDrawList.remove((long) irqLine.getPrototypeSample().getIrqL1Value());
        }
    }

    /**
     * recalculated swi draw values for whole graph. This needs be done when
     * functions are checked or unchecked
     */
    public void recalculateWholeGraph() {

        // reset draw list
        swiDrawList = new Hashtable<String, Hashtable<RGB, TreeMap<Long, Integer>>>();
        Object[] wrappers = tableThreadIRQ.getTableViewer().getCheckedElements();

        // go thru each checked thread and add them again into draw list
        for (Object item : wrappers) {
            if (item.getClass() == SwiThreadWrapper.class) {
                SwiThreadWrapper wrapper = (SwiThreadWrapper) item;
                this.threadChecked(wrapper.threadName);
            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.nokia.carbide.cpp.internal.pi.visual.PIEventListener#piEventReceived
     * (com.nokia.carbide.cpp.internal.pi.visual.PIEvent)
     */
    public void piEventReceived(PIEvent be) {

        switch (be.getType()) {
        case PIEvent.SELECTION_AREA_CHANGED:

            // send this message to the 2 other graphs
            PIEvent be2 = new PIEvent(be.getValueObject(), PIEvent.SELECTION_AREA_CHANGED2);

            for (IrqTraceGraph item : irqTrace.getGraphs()) {
                if (item != this) {
                    item.piEventReceived(be2);
                }
            }

            be = be2;

            // FALL THROUGH
        case PIEvent.SELECTION_AREA_CHANGED2:
            double[] values = (double[]) be.getValueObject();
            this.setSelectionStart(values[0]);
            this.setSelectionEnd(values[1]);
            this.updateIrqCountsInLegendsAsynch(TYPE_BOTH);
            this.repaint();
            break;
        default:
            break;
        }

    }

    /**
     * updates count columns values based on the selected graph area
     * asynchronously
     * 
     * @param updateType
     *            value stating which legends need to be updated
     */
    public void updateIrqCountsInLegendsAsynch(final int updateType) {

        Runnable refreshRunnable = new Runnable() {
            public void run() {
                updateIrqCountsInLegends(updateType);
            }
        };

        Display.getDefault().asyncExec(refreshRunnable);

    }

    /**
     * updates count columns values based on the selected graph area
     * 
     * @param updateType
     *            value stating which legends need to be updated
     */
    public void updateIrqCountsInLegends(int updateType) {
        // get selection area
        double startTime = PIPageEditor.currentPageEditor().getStartTime();
        double endTime = PIPageEditor.currentPageEditor().getEndTime();
        long longStartTime = (long) (startTime * 1000);
        long longEndTime = (long) (endTime * 1000);

        Hashtable<RGB, Integer> counts = new Hashtable<RGB, Integer>();

        if (updateType == TYPE_BOTH || updateType == TYPE_SWI) {
            getColorCountsForSWILegend(counts, swiDrawList, longStartTime, longEndTime);
            setCountsForIrqLegendTable(tableSWIFunction.getTableViewer(), counts);
            tableSWIFunction.refreshTableViewer();
        }
        if (updateType == TYPE_BOTH || updateType == TYPE_IRQ) {
            getColorCountsForIRQLegend(counts, irqDrawList, longStartTime, longEndTime);
            setCountsForIrqLegendTable(tableIrqLine.getTableViewer(), counts);
            tableIrqLine.refreshTableViewer();
        }
    }

    /**
     * Gets amount of interrupts for each color in the area between starttime
     * and endtime
     * 
     * @param counts
     *            amount of interrupts
     * @param drawList
     *            drawlist in use
     * @param startTime
     *            start time
     * @param endTime
     *            end time
     */
    private void getColorCountsForSWILegend(Hashtable<RGB, Integer> counts,
            Hashtable<String, Hashtable<RGB, TreeMap<Long, Integer>>> drawList, long startTime, long endTime) {

        Enumeration<String> it = drawList.keys();
        // go thru drawlist and collect amounts for each color
        while (it.hasMoreElements()) {
            String threadName = it.nextElement();
            Hashtable<RGB, TreeMap<Long, Integer>> functionsFromThread = drawList.get(threadName);
            Enumeration<RGB> colorEnum = functionsFromThread.keys();

            // Go thru each color
            while (colorEnum.hasMoreElements()) {
                RGB color = colorEnum.nextElement();

                // get first event after start time
                TreeMap<Long, Integer> allEvents = functionsFromThread.get(color);

                // get tailmap for it
                SortedMap<Long, Integer> tailMap = allEvents.tailMap(startTime);
                Set<Long> set = tailMap.keySet();
                Iterator<Long> eventIterator = set.iterator();

                // save events into count array until entry is higher that end
                // time
                while (eventIterator.hasNext()) {
                    long time = eventIterator.next();
                    if (time > endTime) {
                        break;
                    }

                    if (!counts.containsKey(color)) {
                        counts.put(color, tailMap.get(time));
                    } else {
                        int previousValue = counts.get(color);
                        counts.put(color, previousValue + tailMap.get(time));
                    }
                }
            }
        }
    }

    /**
     * Sets amount of interrupts into count column of legend table
     * 
     * @param tableViewer
     *            viewer of the table in use
     * @param counts
     *            hashtable containing counts for each color
     */
    private void setCountsForIrqLegendTable(TableViewer tableViewer, Hashtable<RGB, Integer> counts) {
        TableItem[] swItems = tableViewer.getTable().getItems();
        for (TableItem item : swItems) {
            if (item.getData().getClass().equals(IrqSampleTypeWrapper.class)) {
                IrqSampleTypeWrapper wrapper = (IrqSampleTypeWrapper) item.getData();

                RGB rgb = wrapper.rgb;

                if (counts.containsKey(rgb)) {
                    wrapper.count = counts.get(rgb);
                } else {
                    wrapper.count = 0;

                }

            }
        }
    }

    /**
     * Gets amount of interrupts for each color in the area between starttime
     * and endtime
     * 
     * @param counts
     *            amount of interrupts
     * @param drawList
     *            drawlist in use
     * @param startTime
     *            start time
     * @param endTime
     *            end time
     */
    private void getColorCountsForIRQLegend(Hashtable<RGB, Integer> counts,
            Hashtable<Long, Hashtable<RGB, TreeMap<Long, Integer>>> drawList, long startTime, long endTime) {
        Enumeration<Long> it = drawList.keys();

        // go thru drawlist and collect amounts for each color
        while (it.hasMoreElements()) {
            Long lineNumber = it.nextElement();
            Hashtable<RGB, TreeMap<Long, Integer>> colorsFromLine = drawList.get(lineNumber);
            Enumeration<RGB> colorEnum = colorsFromLine.keys();
            while (colorEnum.hasMoreElements()) {
                RGB color = colorEnum.nextElement();

                // get first event after start time
                TreeMap<Long, Integer> allEvents = colorsFromLine.get(color);

                // get tailmap for it
                SortedMap<Long, Integer> tailMap = allEvents.tailMap(startTime);
                Set<Long> set = tailMap.keySet();
                Iterator<Long> eventIterator = set.iterator();

                // save events into count array until entry is higher that end
                // time
                while (eventIterator.hasNext()) {
                    long time = eventIterator.next();
                    if (time > endTime) {
                        break;
                    }

                    if (!counts.containsKey(color)) {
                        counts.put(color, tailMap.get(time));
                    } else {
                        int previousValue = counts.get(color);
                        counts.put(color, previousValue + tailMap.get(time));
                    }
                }
            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.eclipse.draw2d.MouseMotionListener#mouseDragged(org.eclipse.draw2d
     * .MouseEvent)
     */
    public void mouseDragged(MouseEvent arg0) {
        // nothing to be done
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.eclipse.draw2d.MouseMotionListener#mouseEntered(org.eclipse.draw2d
     * .MouseEvent)
     */
    public void mouseEntered(MouseEvent arg0) {
        // nothing to be done
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.eclipse.draw2d.MouseMotionListener#mouseExited(org.eclipse.draw2d
     * .MouseEvent)
     */
    public void mouseExited(MouseEvent arg0) {
        // nothing to be done
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.eclipse.draw2d.MouseMotionListener#mouseHover(org.eclipse.draw2d.
     * MouseEvent)
     */
    public void mouseHover(MouseEvent arg0) {
        // nothing to be done
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.eclipse.draw2d.MouseMotionListener#mouseMoved(org.eclipse.draw2d.
     * MouseEvent)
     */
    public void mouseMoved(MouseEvent event) {

        // get list sie that is shown
        double listSize = 0;
        if (swiTableVisible) {
            listSize = swiDrawList.size();
        } else {
            listSize = irqDrawList.size();

        }

        int graphHeight = panelHeight - BOTTOM_MARGIN;

        if (listSize == 0) {
            this.setToolTipText(null);
            return;
        }

        // get size of one item in the graph are
        double sizeOfOneItem = (double) graphHeight / listSize;

        // get index of item on top of which mouse is on
        int index = (int) (event.y / sizeOfOneItem);

        String tooltip = null;

        // go thru needed drawlist and set thread/irq line name as tooltip
        if (swiTableVisible) {
            Enumeration<String> enumeration = swiDrawList.keys();
            int ii = 0;
            while (enumeration.hasMoreElements()) {
                if (ii == index) {
                    tooltip = enumeration.nextElement();
                    break;
                }
                ii++;
                enumeration.nextElement();
            }
        } else {
            Enumeration<Long> enumeration = irqDrawList.keys();
            int ii = 0;
            while (enumeration.hasMoreElements()) {
                if (ii == index) {
                    tooltip = IrqSampleTypeWrapper.getLineText(enumeration.nextElement());
                    break;
                }
                ii++;
                enumeration.nextElement();
            }
        }

        this.setToolTipText(tooltip);

    }

    /**
     * updates all table viewers of the graph
     */
    public void updateTableViewers() {
        tableIrqLine.refreshTableViewer();
        tableSWIFunction.refreshTableViewer();
    }

    /**
     * @return swi thread table
     */
    public SwiThreadTable getTableThreadIRQ() {
        return tableThreadIRQ;
    }

    /**
     * @return swi function table
     */
    public SwiFunctionTable getTableSWIFunction() {
        return tableSWIFunction;
    }

    /**
     * @return irq line table
     */
    public IrqLineTable getTableIrqLine() {
        return tableIrqLine;
    }

}