com.nokia.traceviewer.view.TraceViewerView.java Source code

Java tutorial

Introduction

Here is the source code for com.nokia.traceviewer.view.TraceViewerView.java

Source

/*
 * Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies). 
 * All rights reserved.
 * This component and the accompanying materials are made available
 * under the terms of "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:
 *
 * Trace Viewer view implementation
 *
 */
package com.nokia.traceviewer.view;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceNode;
import org.eclipse.jface.preference.IPreferencePage;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.jface.preference.PreferenceManager;
import org.eclipse.jface.preference.PreferenceNode;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.TextViewer;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
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.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Slider;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;

import com.nokia.traceviewer.TraceViewerHelpContextIDs;
import com.nokia.traceviewer.TraceViewerPlugin;
import com.nokia.traceviewer.action.ActionFactory;
import com.nokia.traceviewer.action.AddCommentToTraceAction;
import com.nokia.traceviewer.action.EditTraceCommentAction;
import com.nokia.traceviewer.action.OpenTraceLocationAction;
import com.nokia.traceviewer.action.RemoveTraceCommentAction;
import com.nokia.traceviewer.action.ShowTraceInfoAction;
import com.nokia.traceviewer.action.TraceViewerActionUtils;
import com.nokia.traceviewer.dialog.ProgressBarDialog;
import com.nokia.traceviewer.dialog.SearchDialog;
import com.nokia.traceviewer.engine.StateHolder;
import com.nokia.traceviewer.engine.TraceMetaData;
import com.nokia.traceviewer.engine.TraceProperties;
import com.nokia.traceviewer.engine.TraceViewerDialog;
import com.nokia.traceviewer.engine.TraceViewerDialogInterface;
import com.nokia.traceviewer.engine.TraceViewerGlobals;
import com.nokia.traceviewer.engine.TraceViewerTraceViewInterface;
import com.nokia.traceviewer.engine.TraceViewerUtils;
import com.nokia.traceviewer.engine.dataprocessor.DataProcessor;
import com.nokia.traceviewer.engine.preferences.PreferenceConstants;
import com.nokia.traceviewer.engine.preferences.TraceViewerAdvancedPreferencesPage;
import com.nokia.traceviewer.engine.preferences.TraceViewerConnectionPreferencesPage;
import com.nokia.traceviewer.engine.preferences.TraceViewerPreferencesPage;
import com.nokia.traceviewer.view.listener.ScrollerSelectionListener;
import com.nokia.traceviewer.view.listener.SelectionProperties;
import com.nokia.traceviewer.view.listener.ViewerClickListener;
import com.nokia.traceviewer.view.listener.ViewerKeyListener;
import com.nokia.traceviewer.view.listener.ViewerMouseWheelListener;
import com.nokia.traceviewer.view.listener.ViewerSelectionChangedListener;
import com.nokia.traceviewer.view.listener.WindowResizeListener;

/**
 * Trace Viewer view implementation
 */
public final class TraceViewerView extends ViewPart
        implements TraceViewerTraceViewInterface, TraceViewerDialogInterface, DataProcessor, Runnable {

    /**
     * Title of the view
     */
    private static final String TRACE_VIEWER_TITLE = Messages.getString("TraceViewerView.ViewTitle"); //$NON-NLS-1$

    /**
     * Hex prefix
     */
    private static final String HEX_PREFIX = "0x"; //$NON-NLS-1$

    /**
     * Max lines in the view
     */
    private static final int MAX_LINES = TraceViewerGlobals.blockSize * 2;

    /**
     * Update interval in milliseconds
     */
    private static final int UPDATE_INTERVAL = 100;

    /**
     * Normal view name
     */
    private static final String VIEWNAME_NORMAL = TRACE_VIEWER_TITLE;

    /**
     * Filtered view name
     */
    private static final String VIEWNAME_FILTERED = Messages.getString("TraceViewerView.FilteredText"); //$NON-NLS-1$

    /**
     * Paused view name
     */
    private static final String VIEWNAME_PAUSED = Messages.getString("TraceViewerView.PausedText"); //$NON-NLS-1$

    /**
     * View name when storing data while triggering
     */
    private static final String VIEWNAME_STORING = Messages.getString("TraceViewerView.StoringText"); //$NON-NLS-1$

    /**
     * View name when trigger is armed
     */
    private static final String VIEWNAME_ARMED = Messages.getString("TraceViewerView.ArmedText"); //$NON-NLS-1$

    /**
     * Opened Log file name separator shown before the log file name
     */
    private static final String LOG_FILE_NAME_SEPARATOR = " - "; //$NON-NLS-1$

    /**
     * Action factory
     */
    private ActionFactory actionFactory;

    /**
     * Text viewer
     */
    private TextViewer viewer;

    /**
     * StyledText widget
     */
    private StyledText widget;

    /**
     * String array to append to widget in next update
     */
    private final StringBuffer newData;

    /**
     * String array to append to widget in next update
     */
    private final StringBuffer scrolledData;

    /**
     * Timestamp of next update
     */
    private long updateNextTime;

    /**
     * Slider object
     */
    private Slider slider;

    /**
     * Tells from which count Viewer is showing traces from
     */
    private int showingTracesFrom;

    /**
     * Start line to highlight
     */
    private int startHighlightLine;

    /**
     * End line to highlight
     */
    private int endHighlightLine;

    /**
     * Indicates that view name should be updated
     */
    private boolean updateViewName;

    /**
     * Contains number of new traces in String buffer
     */
    private int numberOfNewTraces;

    /**
     * Contains offsets of new traces in newTraces String buffer
     */
    private final List<Integer> offsetsOfNewTraces;

    /**
     * Dialog factory
     */
    private final DialogFactory dialogFactory;

    /**
     * Indicates that view update is on
     */
    private boolean viewUpdateOn = true;

    /**
     * Inserting last block when scrolling the view
     */
    private boolean insertingLastBlock;

    /**
     * The constructor.
     */
    public TraceViewerView() {
        dialogFactory = new DialogFactory();

        // Create StringBuffers
        newData = new StringBuffer();
        scrolledData = new StringBuffer();

        // Offsets of new traces are also saved
        offsetsOfNewTraces = new ArrayList<Integer>();
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets
     * .Composite)
     */
    @Override
    public void createPartControl(Composite parent) {
        actionFactory = new ActionFactory();
        // Create layout for the shell
        createLayout(parent);

        // Creates the text viewer and set a document to it
        viewer = new TextViewer(parent, SWT.V_SCROLL | SWT.H_SCROLL);
        Document document = new Document();
        viewer.setDocument(document);
        viewer.setEditable(false);

        // Get styled text widget and configure it
        widget = viewer.getTextWidget();
        setFontSize(FONT_SIZE);
        widget.getVerticalBar().setVisible(false);
        widget.getHorizontalBar().setVisible(true);
        widget.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));

        // Create a slider
        slider = new Slider(parent, SWT.VERTICAL);
        slider.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, false, true, 1, 1));
        slider.setEnabled(false);

        fillMenuAndToolBar();
        createContextMenu();

        // Create listeners
        createListeners();

        // Sets this view to be the dialog provider
        TraceViewerGlobals.getTraceViewer().setDialogs(this);

        // Sets the view reference to trace viewer engine
        TraceViewerGlobals.getTraceViewer().setTraceView(this);

        // Set help
        PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, TraceViewerHelpContextIDs.MAIN_VIEW);

        // Set global action handler to own copy selection action
        getViewSite().getActionBars().setGlobalActionHandler(org.eclipse.ui.actions.ActionFactory.COPY.getId(),
                actionFactory.getCopySelectionAction());

        // Set global action handler to own seach action
        getViewSite().getActionBars().setGlobalActionHandler(org.eclipse.ui.actions.ActionFactory.FIND.getId(),
                actionFactory.getSearchAction());

        // Set global action handler to own select all action
        getViewSite().getActionBars().setGlobalActionHandler(
                org.eclipse.ui.actions.ActionFactory.SELECT_ALL.getId(), actionFactory.getSelectAllAction());

    }

    /**
     * Adds action items to menu and toolbar
     */
    private void fillMenuAndToolBar() {
        IActionBars bars = getViewSite().getActionBars();
        actionFactory.fillMenu(bars.getMenuManager());
        actionFactory.fillToolBar(bars.getToolBarManager());
    }

    /**
     * Returns action factory
     * 
     * @return action factory
     */
    public ActionFactory getActionFactory() {
        return actionFactory;
    }

    /**
     * Create layout for the view
     * 
     * @param parent
     *            parent shell
     */
    private void createLayout(Composite parent) {
        GridLayout layout = new GridLayout(2, false);
        layout.marginTop = 0;
        layout.marginBottom = 0;
        layout.marginHeight = 0;
        layout.marginWidth = 0;
        layout.horizontalSpacing = 0;
        parent.setLayout(layout);
    }

    /**
     * Create all listeners
     */
    private void createListeners() {
        // Create scroller selection listener
        ScrollerSelectionListener slistener = new ScrollerSelectionListener(viewer);
        slider.addSelectionListener(slistener);

        // Viewer selection changed listener
        ViewerSelectionChangedListener vlistener = new ViewerSelectionChangedListener(slider);
        viewer.addSelectionChangedListener(vlistener);

        // Create viewer mouse wheel listener
        Listener mlistener = new ViewerMouseWheelListener(slider, viewer);
        widget.addListener(SWT.MouseWheel, mlistener);

        // Create viewer key listener
        ViewerKeyListener klistener = new ViewerKeyListener(slider, viewer, this);
        widget.addKeyListener(klistener);

        // Create window resize listener
        WindowResizeListener rlistener = new WindowResizeListener(slider, viewer);
        widget.addControlListener(rlistener);

        // Create viewer click listener
        ViewerClickListener clistener = new ViewerClickListener(viewer);
        widget.addMouseListener(clistener);
    }

    /**
     * Creates context menu
     */
    private void createContextMenu() {
        // Create menu manager.
        final MenuManager menuMgr = new MenuManager();
        menuMgr.setRemoveAllWhenShown(true);
        menuMgr.addMenuListener(new IMenuListener() {
            public void menuAboutToShow(IMenuManager mgr) {
                fillContextMenu(menuMgr);
            }
        });

        // Create menu.
        Menu menu = menuMgr.createContextMenu(viewer.getControl());
        viewer.getControl().setMenu(menu);

        // Register menu for extension.
        getSite().registerContextMenu(menuMgr, viewer);
    }

    /**
     * Fills context menu
     * 
     * @param menuMgr
     *            menu manager
     */
    public void fillContextMenu(MenuManager menuMgr) {
        menuMgr.add(actionFactory.getShowTraceInfoAction());
        menuMgr.add(actionFactory.getOpenTraceLocationAction());
        menuMgr.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));

        // Nothing is selected
        if (widget.getSelectionCount() == 0) {
            actionFactory.getShowTraceInfoAction().setEnabled(false);
            actionFactory.getOpenTraceLocationAction().setEnabled(false);

            // More than one trace selected
        } else if (widget.getSelectionText().contains("\n")) { //$NON-NLS-1$
            actionFactory.getShowTraceInfoAction().setEnabled(false);
            actionFactory.getOpenTraceLocationAction().setEnabled(false);

            // One trace is selected
        } else {
            int lineNumber = showingTracesFrom + widget.getLineAtOffset(widget.getCaretOffset());

            // Get the trace from the file
            List<TraceProperties> traceList = TraceViewerGlobals.getTraceViewer().getTraces(lineNumber, lineNumber);

            TraceProperties trace = null;
            if (traceList != null && !traceList.isEmpty()) {
                trace = traceList.get(0);
            }

            ShowTraceInfoAction infoAction = (ShowTraceInfoAction) actionFactory.getShowTraceInfoAction();
            infoAction.setEnabled(true);
            infoAction.setTrace(trace);

            OpenTraceLocationAction openLocationAction = (OpenTraceLocationAction) actionFactory
                    .getOpenTraceLocationAction();

            // If traceInformation is found, enable open trace location action
            if (trace != null && trace.information != null) {
                TraceMetaData metaData = TraceViewerGlobals.getDecodeProvider().getTraceMetaData(trace.information);
                if (metaData != null && metaData.getPath() != null) {
                    openLocationAction.setEnabled(true);
                    openLocationAction.setMetaData(metaData, true);
                } else {
                    openLocationAction.setEnabled(false);
                }
            } else {
                openLocationAction.setEnabled(false);
            }

            menuMgr.add(new Separator());

            // Add / Edit / Remove trace comment actions
            if (trace != null) {
                TraceViewerGlobals.getTraceViewer().getDataProcessorAccess().getTraceCommentHandler()
                        .processData(trace);
                if (trace.traceComment == null) {
                    menuMgr.add(new AddCommentToTraceAction(trace.traceNumber));
                } else {
                    menuMgr.add(new EditTraceCommentAction(trace.traceNumber));
                    menuMgr.add(new RemoveTraceCommentAction(trace.traceNumber));
                }
            }

        }
        // Separator
        menuMgr.add(new Separator());

        // Copy action
        Action copyAction = actionFactory.getCopySelectionAction();
        menuMgr.add(copyAction);
        if (widget.getSelectionCount() > 0) {
            copyAction.setEnabled(true);
        } else {
            copyAction.setEnabled(false);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Runnable#run()
     */
    public void run() {
        if (!widget.isDisposed()) {

            // Set redraw off
            widget.setRedraw(false);

            if (TraceViewerGlobals.getTraceViewer().getStateHolder().getState() == StateHolder.State.SEARCHED) {
                slider.setSelection(startHighlightLine);
                scrollViewToLine(slider.getSelection());
            } else if (newData.length() > 0) {
                runNormalUpdate();
            }

            colorTraces();

            // If view name should be updated
            if (updateViewName) {
                generateAndSetViewName();
            }
            // Redraw
            widget.setRedraw(true);
            widget.update();
        }
    }

    /**
     * Normal update sequence
     */
    private void runNormalUpdate() {
        // Max offset is number of traces minus 1
        int max = TraceViewerGlobals.getTraceViewer().getDataReaderAccess().getCurrentDataReader().getTraceCount()
                - 1;

        // If previous data is not from the end, get latest blocks from file
        if (showingTracesFrom + widget.getLineCount() + numberOfNewTraces < max + 1) {
            slider.setMaximum(max);
            slider.setSelection(max);
            scrollViewToLine(max);
            setSliderProperties(max);
        } else {

            // If there is lot of new traces, cut down the StringBuffer already
            // in here to avoid massive insertion to text widget
            if (numberOfNewTraces > MAX_LINES + TraceViewerGlobals.blockSize) {
                int offsetOfDeletion = offsetsOfNewTraces.size() - 1 - (MAX_LINES / TraceViewerGlobals.blockSize);

                if (offsetOfDeletion >= 0 && offsetOfDeletion < offsetsOfNewTraces.size()) {
                    newData.replace(0, offsetsOfNewTraces.get(offsetOfDeletion).intValue(), ""); //$NON-NLS-1$
                }
            }

            // Append the new data to current
            widget.append(newData.toString());

            // Set slider properties
            setSliderProperties(max);

            // If there is over MAX_LINES lines, remove extra data blocks
            if (widget.getLineCount() > MAX_LINES) {
                removeDataBlocks(max);
            } // no else
        }

        // Clear variables and selection
        newData.setLength(0);
        numberOfNewTraces = 0;
        offsetsOfNewTraces.clear();
        SelectionProperties.clear();

        // Set the top index and caret to the end of the document
        viewer.setTopIndex(max - slider.getThumb());
        widget.setCaretOffset(widget.getCharCount());
    }

    /**
     * Removes extra data blocks
     * 
     * @param max
     *            number of lines alltogether
     */
    private void removeDataBlocks(int max) {
        // Get amount of full blocks
        int fullBlocks = widget.getLineCount() / TraceViewerGlobals.blockSize;

        // Showing traces is starting point of total number of blocks -
        // 1
        showingTracesFrom = (((max + 1) / TraceViewerGlobals.blockSize) - 1) * TraceViewerGlobals.blockSize;

        // Delete data from beginning of the widget
        int line = ((fullBlocks - 1) * TraceViewerGlobals.blockSize);
        int replaceTo = widget.getOffsetAtLine(line);
        widget.replaceTextRange(0, replaceTo, ""); //$NON-NLS-1$
    }

    /**
     * Sets slider properties
     * 
     * @param max
     *            max value
     */
    private void setSliderProperties(int max) {
        // Set Slider properties
        slider.setEnabled(max > 0);
        slider.setMaximum(max);
        slider.setSelection(max);
        slider.setThumb(getNumberOfLinesInView());
    }

    /**
     * Color traces
     */
    private void colorTraces() {
        // If coloring, color lines
        if (TraceViewerGlobals.getTraceViewer().getDataProcessorAccess().getColorer().isColoring()) {
            TraceViewerGlobals.getTraceViewer().getDataProcessorAccess().getColorer().createColorRules();
        }
    }

    /**
     * Adds traces before current data
     * 
     * @param traceToBeShown
     *            trace to be shown
     * @param numberOfBlocks
     *            number of block
     */
    private void insertBeforeCurrentView(int numberOfBlocks, int traceToBeShown) {

        widget.setRedraw(false);
        // Save the caret position
        int caretPos = widget.getLineAtOffset(widget.getCaretOffset());

        // Save the old data
        String oldData = getOldData(true, numberOfBlocks);

        // Append the old data after the new data
        if (!oldData.equals("")) { //$NON-NLS-1$
            scrolledData.append(oldData);
        }

        // Set the new data to widget
        widget.setText(scrolledData.toString());

        // Update showing traces variable
        showingTracesFrom = (traceToBeShown / TraceViewerGlobals.blockSize) * TraceViewerGlobals.blockSize;

        // Set view properties
        updateViewPropertiesWhenInsertingBeforeCurrentData(caretPos, traceToBeShown);

        // Empty buffer
        scrolledData.setLength(0);
        colorTraces();
        widget.setRedraw(true);
        widget.update();
    }

    /**
     * Add traces after current data
     * 
     * @param traceToBeShown
     *            trace to be shown
     * @param numberOfBlocks
     *            number of block
     */
    private void insertAfterCurrentView(int numberOfBlocks, int traceToBeShown) {

        widget.setRedraw(false);
        // Save the old data
        String oldData = getOldData(false, numberOfBlocks);

        // Create new StringBuffer with old and new data in it
        StringBuffer data = new StringBuffer(oldData.length() + scrolledData.length());
        data.append(oldData);
        data.append(scrolledData);

        // Set the new data
        widget.setText(data.toString());

        // Update showingTracesFrom variable
        int fullBlocksInView = (traceToBeShown + getNumberOfLinesInView() + 1) / TraceViewerGlobals.blockSize;
        showingTracesFrom = (fullBlocksInView * TraceViewerGlobals.blockSize) - TraceViewerGlobals.blockSize;
        if (showingTracesFrom < 0) {
            showingTracesFrom = 0;
        } // no else

        // Set view properties
        updateViewPropertiesWhenInsertingAfterCurrentData(traceToBeShown);

        // Empty buffer
        scrolledData.setLength(0);
        colorTraces();
        widget.setRedraw(true);
        widget.update();
    }

    /**
     * Gets old data
     * 
     * @param beforeCurrentData
     *            getting data to before current view
     * @param numberOfBlocks
     *            number of blocks to get
     * @return old data
     */
    private String getOldData(boolean beforeCurrentData, int numberOfBlocks) {
        String oldData = ""; //$NON-NLS-1$
        if (numberOfBlocks == 1) {
            // More thatn 1 block of data, needs to be cut
            if (widget.getLineCount() > TraceViewerGlobals.blockSize) {

                // Inserting before current view
                if (beforeCurrentData) {
                    oldData = widget.getText(0, widget.getOffsetAtLine(TraceViewerGlobals.blockSize) - 1);

                    // Inserting after current view
                } else if (!beforeCurrentData) {
                    int offsetAtBlockStart = widget.getOffsetAtLine(TraceViewerGlobals.blockSize);
                    oldData = widget.getTextRange(offsetAtBlockStart,
                            widget.getOffsetAtLine(widget.getLineCount() - 1) - offsetAtBlockStart);
                }
            } else {
                oldData = widget.getText();
            }
        }

        return oldData;
    }

    /**
     * Sets view properties when inserting before current data
     * 
     * @param caretPos
     *            old caret position
     * @param traceToBeShown
     *            trace to be shown
     */
    private void updateViewPropertiesWhenInsertingBeforeCurrentData(int caretPos, int traceToBeShown) {
        StateHolder.State state = TraceViewerGlobals.getTraceViewer().getStateHolder().getState();
        // Null check
        if (state == null) {
            TraceViewerGlobals.getTraceViewer().getStateHolder()
                    .setState(StateHolder.State.SCROLLING_WITH_SCROLLBAR);
            state = StateHolder.State.SCROLLING_WITH_SCROLLBAR;
        }
        switch (state) {
        // Set top index when scrolling with scrollbar
        case SCROLLING_WITH_SCROLLBAR:

            viewer.setTopIndex((traceToBeShown % TraceViewerGlobals.blockSize));
            break;
        // Set top index and caret offset when scrolling with arrow keys
        case SCROLLING_WITH_ARROWS:
            viewer.setTopIndex((traceToBeShown % TraceViewerGlobals.blockSize));
            if (caretPos + TraceViewerGlobals.blockSize - 1 < widget.getLineCount()) {
                widget.setCaretOffset(widget.getOffsetAtLine(caretPos + TraceViewerGlobals.blockSize - 1));
            }
            break;
        // Set top index and selection when searching
        case SEARCHED:
            updateViewerPropertiesAfterSearch();
            break;

        // Set top index and caret offset when scrolling with page up/down
        case SCROLLING_WITH_PAGEUPDOWN:
            int topIndex = traceToBeShown % TraceViewerGlobals.blockSize - 2;
            viewer.setTopIndex(topIndex);
            int caretLine = caretPos + TraceViewerGlobals.blockSize - 1;
            if (caretLine > 0 && widget.getLineCount() > 0) {
                if (caretLine > widget.getLineCount()) {
                    caretLine = widget.getLineCount() - 1;
                }
                widget.setCaretOffset(widget.getOffsetAtLine(caretLine));
            }

            break;
        default:
            break;
        }
        TraceViewerGlobals.getTraceViewer().getStateHolder().setState(StateHolder.State.NORMAL);
        setSelection();
    }

    /**
     * Sets view properties when inserting after current data
     * 
     * @param traceToBeShown
     *            trace to be shown
     */
    private void updateViewPropertiesWhenInsertingAfterCurrentData(int traceToBeShown) {
        StateHolder.State state = TraceViewerGlobals.getTraceViewer().getStateHolder().getState();

        // Null check
        if (state == null) {
            TraceViewerGlobals.getTraceViewer().getStateHolder()
                    .setState(StateHolder.State.SCROLLING_WITH_SCROLLBAR);
            state = StateHolder.State.SCROLLING_WITH_SCROLLBAR;
        }

        switch (state) {
        // Set top index when scrolling with scrollbar
        case SCROLLING_WITH_SCROLLBAR:
            viewer.setTopIndex(traceToBeShown - showingTracesFrom + 1);
            break;

        // Set top index and caret offset when scrolling with arrow keys
        case SCROLLING_WITH_ARROWS:
            viewer.setTopIndex(traceToBeShown - showingTracesFrom - 1);
            int line = traceToBeShown - showingTracesFrom + getNumberOfLinesInView();
            if (line <= widget.getLineCount() && line >= 0) {
                widget.setCaretOffset(widget.getOffsetAtLine(line));
            }
            break;
        // Set top index and selection when searching
        case SEARCHED:
            updateViewerPropertiesAfterSearch();
            break;

        // Set top index and caret offset when scrolling with page up/down
        case SCROLLING_WITH_PAGEUPDOWN:
            viewer.setTopIndex(traceToBeShown - showingTracesFrom + 1);
            int topLine = traceToBeShown - showingTracesFrom + getNumberOfLinesInView() - 1;
            if (topLine < widget.getLineCount()) {
                int caretOffset = widget
                        .getOffsetAtLine(traceToBeShown - showingTracesFrom + getNumberOfLinesInView() - 1);
                if (caretOffset >= 0 && caretOffset < widget.getCharCount()) {
                    widget.setCaretOffset(caretOffset);
                }
            } else {
                widget.setCaretOffset(widget.getCharCount() - 1);
            }
            break;
        // Unknown case, set basic top index
        case NORMAL:
            viewer.setTopIndex(
                    traceToBeShown - TraceViewerGlobals.getTraceViewer().getView().getShowingTracesFrom());
            break;
        default:
            break;
        }

        TraceViewerGlobals.getTraceViewer().getStateHolder().setState(StateHolder.State.NORMAL);
        setSelection();
    }

    /**
     * Sets selection to viewer
     */
    public void setSelection() {
        if (SelectionProperties.lastClickedLine != -1) {

            // Calculate start offset
            int startOffset = 0;

            // If clicked from the totally first line
            if (SelectionProperties.firstClickedLine < showingTracesFrom) {
                startOffset = 0;

                // If clicked in the totally last line
            } else if (SelectionProperties.firstClickedLine > showingTracesFrom + widget.getLineCount()) {
                startOffset = widget.getCharCount() - 1;

                // Clicked between the first and last line in the viewer
            } else {
                int lineNumber = SelectionProperties.firstClickedLine - showingTracesFrom;
                if (lineNumber < widget.getLineCount()) {
                    startOffset = widget.getOffsetAtLine(lineNumber)
                            + SelectionProperties.firstClickedLineCaretOffset;
                }
            }

            // Calculate end offset
            int endOffset = 0;

            // If clicked from the totally first line
            if (SelectionProperties.lastClickedLine < showingTracesFrom) {
                endOffset = 0;

                // If clicked in the totally last line
            } else if (SelectionProperties.lastClickedLine >= showingTracesFrom + widget.getLineCount()) {
                endOffset = widget.getCharCount() - 1;

                // Clicked between the first and last line in the viewer
            } else {
                int lineNumber = SelectionProperties.lastClickedLine - showingTracesFrom;
                if (lineNumber < widget.getLineCount()) {
                    endOffset = widget.getOffsetAtLine(lineNumber) + SelectionProperties.lastClickedLineCaretOffset;
                }
            }

            // Save current top index
            int topIndex = viewer.getTopIndex();

            // Set the selection to the viewer
            widget.setSelection(startOffset, endOffset);

            // Return old top index
            viewer.setTopIndex(topIndex);

            // Put caret to the end
        } else if (SelectionProperties.putCaretToTheEnd) {
            SelectionProperties.putCaretToTheEnd = false;
            widget.setCaretOffset(widget.getCharCount());
        }

        // Update trim
        ViewerSelectionChangedListener.handleTrimInformationUpdate();
    }

    /**
     * Updates top index and selection after searching
     */
    private void updateViewerPropertiesAfterSearch() {
        int selIndex = startHighlightLine - showingTracesFrom;
        int topIndex = selIndex - LINES_TO_LEAVE_BEFORE_FOUND_LINE;

        if (topIndex < 0) {
            topIndex = 0;
        }
        viewer.setTopIndex(topIndex);

        // Remove possible old selection values from the Selection Properties
        SelectionProperties.clear();

        // Select range of traces
        if (endHighlightLine != 0) {
            SelectionProperties.firstClickedLine = startHighlightLine;
            SelectionProperties.lastClickedLine = endHighlightLine + 1;

        } else {

            // Select one line
            if (topIndex < widget.getLineCount() && (selIndex + 1 < widget.getLineCount())) {
                widget.setSelection(widget.getOffsetAtLine(selIndex), widget.getOffsetAtLine(selIndex + 1) - 1);
            }
        }

        // Enable search button from search dialog
        SearchDialog searchDialog = TraceViewerGlobals.getTraceViewer().getDataProcessorAccess()
                .getSearchProcessor().getSearchDialog();
        if (searchDialog != null && searchDialog.isOpen()) {
            searchDialog.enableSearchButton();
        }
        TraceViewerGlobals.getTraceViewer().getStateHolder().setState(StateHolder.State.NORMAL);

    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.IWorkbenchPart#setFocus()
     */
    @Override
    public void setFocus() {
        viewer.getControl().setFocus();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.part.WorkbenchPart#dispose()
     */
    @Override
    public void dispose() {
        super.dispose();
        TraceViewerGlobals.getTraceViewer().shutdown();
    }

    /**
     * Gets shell
     * 
     * @return shell from the text viewer
     */
    private Shell getShell() {
        Shell shell = null;
        if (viewer != null && viewer.getControl() != null && viewer.getControl().getShell() != null
                && !viewer.getControl().getShell().isDisposed()) {
            shell = viewer.getControl().getShell();
        }
        return shell;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.nokia.traceviewer.engine.TraceViewerTraceViewInterface#getViewer()
     */
    public TextViewer getViewer() {
        return viewer;
    }

    /*
     * (non-Javadoc)
     * 
     * @seecom.nokia.traceviewer.engine.TraceViewerTraceViewInterface#
     * getShowingTracesFrom()
     */
    public int getShowingTracesFrom() {
        return showingTracesFrom;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.nokia.traceviewer.engine.DataProcessor#
     * processData(com.nokia.traceviewer.engine.TraceProperties)
     */
    public void processData(TraceProperties properties) {
        TraceViewerGlobals.debug("processData in View", //$NON-NLS-1$
                TraceViewerGlobals.DebugLevel.TEST);
        // Main if to check if trace is ok to show
        if (!properties.traceConfiguration.isFilteredOut() && properties.traceConfiguration.isShowInView()
                && !properties.traceConfiguration.isTriggeredOut()) {
            if (properties.traceConfiguration.isScrolledTrace()) {
                processScrolledTrace(properties);

                // Empty new data if we are reading last block
                if (insertingLastBlock && properties.lastTrace) {
                    newData.setLength(0);
                    insertingLastBlock = false;
                }
            } else if (viewUpdateOn) {
                processNormalTrace(properties);
            }
        }
    }

    /**
     * Process normal trace
     * 
     * @param properties
     *            trace properties
     */
    private void processNormalTrace(TraceProperties properties) {
        numberOfNewTraces++;
        // Traces missing
        if (properties.bTraceInformation.isTraceMissing()) {
            newData.append(TraceViewerActionUtils.TRACES_DROPPED_MSG);
        }

        // Append timestamp to StringBuffer
        if (properties.timestampString != null) {
            newData.append(properties.timestampString);
            newData.append(TraceViewerGlobals.getTraceViewer().getDataProcessorAccess().getTimestampParser()
                    .getTimeFromPreviousString(properties.timeFromPreviousTrace));
            newData.append('\t');
        }
        if (!properties.binaryTrace) {
            newData.append(properties.traceString);
            if (properties.traceComment != null) {
                newData.append(TraceViewerActionUtils.COMMENT_PREFIX);
                newData.append(properties.traceComment);
            }

            // Binary trace
        } else {
            addBinaryTraceToBuffer(properties, newData);
        }

        newData.append('\n');
        // Add offset of every new block to array so we know where to
        // cut the StringBuffer
        if (numberOfNewTraces % TraceViewerGlobals.blockSize == 1 && numberOfNewTraces != 1) {
            offsetsOfNewTraces.add(Integer.valueOf(newData.length()));
        }
        long time = System.currentTimeMillis();
        // If update interval has passed, call the view update
        if (time > updateNextTime) {
            updateNextTime = time + UPDATE_INTERVAL;
            update();
        }
    }

    /**
     * Process scrolled trace
     * 
     * @param properties
     *            trace properties
     */
    private void processScrolledTrace(TraceProperties properties) {
        // Traces missing
        if (properties.bTraceInformation.isTraceMissing()) {
            scrolledData.append(TraceViewerActionUtils.TRACES_DROPPED_MSG);
        }

        // Append timestamp to StringBuffer
        if (properties.timestampString != null) {
            scrolledData.append(properties.timestampString);
            scrolledData.append(TraceViewerGlobals.getTraceViewer().getDataProcessorAccess().getTimestampParser()
                    .getTimeFromPreviousString(properties.timeFromPreviousTrace));
            scrolledData.append('\t');
        }
        if (!properties.binaryTrace) {
            scrolledData.append(properties.traceString);

            if (properties.traceComment != null) {
                scrolledData.append(TraceViewerActionUtils.COMMENT_PREFIX);
                scrolledData.append(properties.traceComment);
            }

            // Binary trace
        } else {
            addBinaryTraceToBuffer(properties, scrolledData);
        }
        scrolledData.append('\n');
    }

    /**
     * Adds binary traces to buffer
     * 
     * @param properties
     *            trace properties
     * @param dataBuf
     *            data buffer to add the trace to
     */
    private void addBinaryTraceToBuffer(TraceProperties properties, StringBuffer dataBuf) {

        // Get the selected value
        String type = TraceViewerPlugin.getDefault().getPreferenceStore()
                .getString(PreferenceConstants.SHOW_UNDECODED_TRACES_TYPE);

        // Show binary trace info message
        if (type.equals(PreferenceConstants.UNDECODED_INFO_TEXT)) {
            String binMsg = Messages.getString("TraceViewerView.BinaryTraceInformationMessage"); //$NON-NLS-1$);
            dataBuf.append(binMsg);

            // Show binary traces as hex
        } else if (type.equals(PreferenceConstants.UNDECODED_HEX)) {

            // Read the message to a byte array
            String hexTrace = TraceViewerUtils.getTraceAsHexString(properties.byteBuffer, properties.messageStart,
                    properties.messageLength, true);
            dataBuf.append(hexTrace);

            // Show binary trace as ID and data
        } else if (type.equals(PreferenceConstants.UNDECODED_ID_AND_DATA)) {
            dataBuf.append(Messages.getString("TraceViewerView.BinaryTraceText")); //$NON-NLS-1$
            dataBuf.append(Messages.getString("TraceViewerView.ComponentID")); //$NON-NLS-1$
            dataBuf.append(HEX_PREFIX);
            dataBuf.append(Integer.toHexString(properties.information.getComponentId()));
            dataBuf.append(Messages.getString("TraceViewerView.GroupID")); //$NON-NLS-1$
            dataBuf.append(HEX_PREFIX);
            dataBuf.append(Integer.toHexString(properties.information.getGroupId()));
            dataBuf.append(Messages.getString("TraceViewerView.TraceID")); //$NON-NLS-1$
            dataBuf.append(properties.information.getTraceId());
            dataBuf.append(Messages.getString("TraceViewerView.DataString")); //$NON-NLS-1$

            // Read the message to a byte array
            String hexTrace = TraceViewerUtils.getTraceAsHexString(properties.byteBuffer, properties.dataStart,
                    properties.dataLength, true);
            dataBuf.append(hexTrace);

            if (properties.traceComment != null) {
                dataBuf.append(TraceViewerActionUtils.COMMENT_PREFIX);
                dataBuf.append(properties.traceComment);
            }
        }
    }

    /**
     * Returns number of lines in view
     * 
     * @return number of lines in view
     */
    public int getNumberOfLinesInView() {
        return viewer.getBottomIndex() - viewer.getTopIndex();
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.nokia.traceviewer.engine.TraceViewerViewInterface#clearAll()
     */
    public void clearAll() {
        // Sync with UI thread
        if (viewer != null && viewer.getControl() != null && viewer.getControl().getDisplay() != null) {

            viewer.getControl().getDisplay().syncExec(new Runnable() {

                public void run() {
                    // Remove text from textviewer and disable slider
                    if (!widget.isDisposed()) {
                        widget.setText(""); //$NON-NLS-1$
                    }
                    if (!slider.isDisposed()) {
                        slider.setEnabled(false);
                    }

                    // Clear all arrays
                    newData.setLength(0);
                    scrolledData.setLength(0);
                    showingTracesFrom = 0;
                    offsetsOfNewTraces.clear();

                    // Empty the trim text
                    TraceViewerGlobals.getTrimProvider().updateText(""); //$NON-NLS-1$
                }
            });
        }

    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.nokia.traceviewer.engine.TraceViewerViewInterface#hasUnshownData()
     */
    public boolean hasUnshownData() {
        return (newData.length() > 0);
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.nokia.traceviewer.engine.TraceViewerViewInterface#update()
     */
    public void update() {
        update(this);
    }

    /**
     * Calls syncExec with some Runnable
     * 
     * @param r
     *            runnable object
     */
    public void update(Runnable r) {
        Control control = viewer.getControl();
        if ((control != null) && !(control.isDisposed())) {
            control.getDisplay().syncExec(r);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.nokia.traceviewer.engine.TraceViewerTraceViewInterface#highlightLines
     * (int, int, boolean)
     */
    public void highlightLines(int startLine, int endLine, boolean syncToSource) {
        this.startHighlightLine = startLine;
        this.endHighlightLine = endLine;
        TraceViewerGlobals.getTraceViewer().getStateHolder().setState(StateHolder.State.SEARCHED);
        update();

        // Sync to source
        if (syncToSource) {
            viewer.getControl().getDisplay().asyncExec(new Runnable() {
                public void run() {

                    // Jump to selected trace source
                    jumpToSelectedTraceSource();
                }
            });
        }
    }

    /**
     * Jumps to selected traces source if needed metadata exists
     */
    private void jumpToSelectedTraceSource() {
        // Get clicked line number
        int clickedLine = widget.getLineAtOffset(widget.getSelectionRange().x)
                + TraceViewerGlobals.getTraceViewer().getView().getShowingTracesFrom();

        // Get the trace from the file
        List<TraceProperties> traceList = TraceViewerGlobals.getTraceViewer().getTraces(clickedLine, clickedLine);

        TraceProperties trace = null;
        if (traceList != null && !traceList.isEmpty()) {
            trace = traceList.get(0);
        }

        OpenTraceLocationAction openLocationAction = (OpenTraceLocationAction) actionFactory
                .getOpenTraceLocationAction();

        // If traceInformation is found, run open location action
        if (trace != null && trace.information != null) {
            TraceMetaData metaData = TraceViewerGlobals.getDecodeProvider().getTraceMetaData(trace.information);
            if (metaData != null && metaData.getPath() != null) {
                openLocationAction.setMetaData(metaData, false);
                openLocationAction.run();
            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.nokia.traceviewer.engine.TraceViewerTraceViewInterface#scrollViewToLine
     * (int)
     */
    public void scrollViewToLine(int lineNumber) {
        if (!TraceViewerGlobals.getTraceViewer().getDataProcessorAccess().getTriggerProcessor()
                .isStartTriggering()) {

            // Save trace to be shown
            int traceToBeShown = lineNumber;

            int topIndex = viewer.getTopIndex();
            int bottomIndex = viewer.getBottomIndex();

            // If we need more traces to start of the view
            if (traceToBeShown < showingTracesFrom) {
                getMoreTracesBeforeCurrentData(traceToBeShown);

                // More trace to end of the view
            } else if (traceToBeShown + getNumberOfLinesInView() + 2 > showingTracesFrom + widget.getLineCount()
                    && TraceViewerGlobals.getTraceViewer().getDataReaderAccess().getCurrentDataReader() != null
                    && (showingTracesFrom + TraceViewerGlobals.blockSize * 2 < TraceViewerGlobals.getTraceViewer()
                            .getDataReaderAccess().getCurrentDataReader().getTraceCount())) {

                getMoreTracesAfterCurrentData(traceToBeShown, bottomIndex);

                // If the trace to be shown value is different to real value
                // shown in screen or we need to highlight search result
            } else if ((slider.getSelection() < topIndex + showingTracesFrom - 1
                    || slider.getSelection() > bottomIndex + showingTracesFrom)
                    || TraceViewerGlobals.getTraceViewer().getStateHolder()
                            .getState() == StateHolder.State.SEARCHED) {
                moveViewAccordingToSlider();
            } else {
                TraceViewerGlobals.getTraceViewer().getStateHolder().setState(StateHolder.State.NORMAL);
            }
        }
    }

    /**
     * Moves view according to slider position and highlight found text if
     * searching
     */
    private void moveViewAccordingToSlider() {
        // If this is because of searching
        if (TraceViewerGlobals.getTraceViewer().getStateHolder().getState() == StateHolder.State.SEARCHED) {
            updateViewerPropertiesAfterSearch();
            setSelection();
        } else {
            viewer.setTopIndex(slider.getSelection() - showingTracesFrom);
        }
    }

    /**
     * Get more traces after the current data
     * 
     * @param traceToBeShown
     *            trace to be shown
     * @param bottomIndex
     *            bottom index value
     */
    private void getMoreTracesAfterCurrentData(int traceToBeShown, int bottomIndex) {

        int numberOfBlocks;
        int offset;

        TraceViewerGlobals.getTraceViewer().getDataProcessorAccess().getTimestampParser().nullPreviousTimestamp();

        // If we need only one block
        if (traceToBeShown < showingTracesFrom + bottomIndex + TraceViewerGlobals.blockSize) {
            numberOfBlocks = 1;
            offset = traceToBeShown + getNumberOfLinesInView() + 2;
        } else {
            numberOfBlocks = 2;
            offset = traceToBeShown + getNumberOfLinesInView() - TraceViewerGlobals.blockSize + 1;
        }

        // Check if we are getting the last block from the file
        if (offset + (TraceViewerGlobals.blockSize * numberOfBlocks) > TraceViewerGlobals.getTraceViewer()
                .getDataReaderAccess().getCurrentDataReader().getTraceCount()) {
            insertingLastBlock = true;
        } else {
            insertingLastBlock = false;
        }

        // Start scroll reader
        TraceViewerGlobals.getTraceViewer().getDataReaderAccess().startScrollReader(offset, numberOfBlocks);

        // Insert after current view
        insertAfterCurrentView(numberOfBlocks, traceToBeShown);
    }

    /**
     * Get more traces before the current data
     * 
     * @param traceToBeShown
     *            trace to be shown
     */
    private void getMoreTracesBeforeCurrentData(int traceToBeShown) {
        int numberOfBlocks;
        TraceViewerGlobals.getTraceViewer().getDataProcessorAccess().getTimestampParser().nullPreviousTimestamp();
        // If we need only one block
        if (traceToBeShown + TraceViewerGlobals.blockSize > showingTracesFrom) {
            numberOfBlocks = 1;
        } else {
            numberOfBlocks = 2;
        }

        TraceViewerGlobals.getTraceViewer().getDataReaderAccess().startScrollReader(traceToBeShown, numberOfBlocks);

        // Insert before current view
        insertBeforeCurrentView(numberOfBlocks, traceToBeShown);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.nokia.traceviewer.engine.TraceViewerTraceViewInterface#closeProgressBar
     * (com.nokia.traceviewer.dialog.ProgressBarDialog)
     */
    public void closeProgressBar(ProgressBarDialog dialog) {
        update(new ProcessProgressBarUpdater(dialog));
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.nokia.traceviewer.engine.TraceViewerTraceViewInterface#applyColorRules
     * (org.eclipse.swt.custom.StyleRange[])
     */
    public void applyColorRules(StyleRange[] ranges) {
        update(new ColorRuleUpdater(ranges));

    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.nokia.traceviewer.engine.TraceViewerTraceViewInterface#updateViewName
     * ()
     */
    public void updateViewName() {
        updateViewName = true;
        update();
    }

    /**
     * Update the name of the view
     */
    private void generateAndSetViewName() {
        StringBuilder viewName = new StringBuilder(VIEWNAME_NORMAL);

        // Triggering
        if (TraceViewerGlobals.getTraceViewer().getDataProcessorAccess().getTriggerProcessor().isTriggering()) {

            // Trigger is armed
            if (TraceViewerGlobals.getTraceViewer().getDataProcessorAccess().getTriggerProcessor()
                    .isStartTriggering()) {
                viewName.append(VIEWNAME_ARMED);
            } else if (TraceViewerGlobals.getTraceViewer().getDataProcessorAccess().getTriggerProcessor()
                    .isStopTriggering()) {
                viewName.append(VIEWNAME_STORING);
            }

        }
        // Paused
        if (TraceViewerGlobals.getTraceViewer().getDataReaderAccess().getMainDataReader().isPaused()) {
            viewName.append(VIEWNAME_PAUSED);
        }
        // Filtered
        if (TraceViewerGlobals.getTraceViewer().getDataProcessorAccess().getFilterProcessor().isFiltering()) {
            viewName.append(VIEWNAME_FILTERED);
        }

        // Log file opened
        if (TraceViewerGlobals.getTraceViewer().getDataProcessorAccess().getLogger().isLogFileOpened()) {
            String logFilePath = TraceViewerGlobals.getTraceViewer().getDataProcessorAccess().getLogger()
                    .getOpenedLogFileName();
            viewName.append(LOG_FILE_NAME_SEPARATOR);
            viewName.append(logFilePath);
        }

        this.setPartName(viewName.toString());
        updateViewName = false;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.nokia.traceviewer.engine.TraceViewerViewInterface#isDisposed()
     */
    public boolean isDisposed() {
        boolean disposed = false;
        Shell shell = getShell();
        if (shell == null || shell.isDisposed()) {
            disposed = true;
        }
        return disposed;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.nokia.traceviewer.engine.TraceViewerTraceViewInterface#stopViewUpdate
     * (boolean)
     */
    public void stopViewUpdate(boolean stop) {
        viewUpdateOn = !stop;

        // If view should be refreshed
        if (!stop) {

            // Sync with UI thread
            viewer.getControl().getDisplay().asyncExec(new Runnable() {

                public void run() {
                    refreshTraceBlock(TraceViewerGlobals.getTraceViewer().getDataReaderAccess()
                            .getCurrentDataReader().getTraceCount());
                }
            });
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.nokia.traceviewer.engine.TraceViewerTraceViewInterface#refreshCurrentView
     * ()
     */
    public void refreshCurrentView() {
        // Sync with UI thread
        viewer.getControl().getDisplay().asyncExec(new Runnable() {

            public void run() {
                refreshTraceBlock(slider.getSelection());
            }
        });
    }

    /**
     * Find the trace block containing given trace and refreshes it. When coming
     * here, we should be in UI thread
     * 
     * @param traceNumber
     *            the trace number
     */
    private void refreshTraceBlock(final int traceNumber) {
        // Set "showing traces from" variable to totally wrong and
        // then generate a request to get last block of traces
        showingTracesFrom = 0 - TraceViewerGlobals.blockSize * 5;
        scrollViewToLine(traceNumber);

    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.nokia.traceviewer.engine.TraceViewerTraceViewInterface#setFontSize
     * (int)
     */
    public void setFontSize(final int size) {
        if (widget != null && !widget.isDisposed()) {
            // Sync with UI thread
            viewer.getControl().getDisplay().syncExec(new Runnable() {

                public void run() {
                    // Set the font
                    Font font = new Font(viewer.getControl().getDisplay(), new FontData(FONT, size, SWT.NORMAL));
                    widget.setFont(font);
                }
            });
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.nokia.traceviewer.engine.TraceViewerDialogInterface#showErrorMessage
     * (java.lang.String)
     */
    public void showErrorMessage(String error) {
        MessageDialog.openError(getShell(), TRACE_VIEWER_TITLE, error);
    }

    /*
     * (non-Javadoc)
     * 
     * @seecom.nokia.traceviewer.engine.TraceViewerDialogInterface#
     * showConfirmationDialog(java.lang.String)
     */
    public boolean showConfirmationDialog(String message) {
        boolean ok = MessageDialog.openConfirm(getShell(), TRACE_VIEWER_TITLE, message);
        return ok;
    }

    /*
     * (non-Javadoc)
     * 
     * @seecom.nokia.traceviewer.engine.TraceViewerDialogInterface#
     * showInformationMessage(java.lang.String)
     */
    public void showInformationMessage(String message) {
        MessageDialog.openInformation(getShell(), TRACE_VIEWER_TITLE, message);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.nokia.traceviewer.engine.TraceViewerDialogInterface#openPreferencePage
     * (
     * com.nokia.traceviewer.engine.TraceViewerDialogInterface.TVPreferencePage)
     */
    public boolean openPreferencePage(TVPreferencePage TVpage) {
        boolean ret = false;
        PreferenceManager mgr = new PreferenceManager();

        // Create general preference page
        IPreferencePage generalPage = new TraceViewerPreferencesPage();
        generalPage.setTitle(TRACE_VIEWER_TITLE);
        IPreferenceNode generalNode = new PreferenceNode("1", generalPage); //$NON-NLS-1$
        mgr.addToRoot(generalNode);

        // Create advanced preference page
        IPreferencePage advancedPage = new TraceViewerAdvancedPreferencesPage();
        advancedPage.setTitle(Messages.getString("TraceViewerView.AdvancedPageTitle")); //$NON-NLS-1$
        IPreferenceNode advancedNode = new PreferenceNode("2", advancedPage); //$NON-NLS-1$
        mgr.addTo("1", advancedNode); //$NON-NLS-1$

        // Create connection preference page
        IPreferencePage connectionPage = new TraceViewerConnectionPreferencesPage();
        connectionPage.setTitle(Messages.getString("TraceViewerView.ConnectionPageTitle")); //$NON-NLS-1$
        IPreferenceNode connectionNode = new PreferenceNode("3", connectionPage); //$NON-NLS-1$
        mgr.addTo("1", connectionNode); //$NON-NLS-1$

        PreferenceDialog dialog = new PreferenceDialog(getShell(), mgr);
        dialog.create();
        dialog.getTreeViewer().expandAll();

        // Switch the page
        switch (TVpage) {
        case GENERAL:
            dialog.getTreeViewer().setSelection(new StructuredSelection(generalNode));
            break;
        case ADVANCED:
            dialog.getTreeViewer().setSelection(new StructuredSelection(advancedNode));
            break;
        case CONNECTION:
            dialog.getTreeViewer().setSelection(new StructuredSelection(connectionNode));
            break;
        default:
            break;
        }

        // Open dialog and get return value
        int ok = dialog.open();
        if (ok == Window.OK) {
            ret = true;
        }

        return ret;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.nokia.traceviewer.engine.TraceViewerDialogInterface
     * #createDialog
     * (com.nokia.traceviewer.engine.TraceViewerDialogInterface.Dialog)
     */
    public TraceViewerDialog createDialog(Dialog name) {
        TraceViewerDialog dialog = dialogFactory.construct(name, getShell());
        return dialog;
    }
}