net.rim.ejde.internal.ui.views.BasicDebugView.java Source code

Java tutorial

Introduction

Here is the source code for net.rim.ejde.internal.ui.views.BasicDebugView.java

Source

/*
* Copyright (c) 2010-2012 Research In Motion Limited. All rights reserved.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License, Version 1.0,
* which accompanies this distribution and is available at
*
* http://www.eclipse.org/legal/epl-v10.html
*
*/
package net.rim.ejde.internal.ui.views;

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

import net.rim.ejde.internal.core.ContextManager;
import net.rim.ejde.internal.ui.CompositeFactory;
import net.rim.ejde.internal.util.DebugUtils;
import net.rim.ejde.internal.util.Messages;
import net.rim.ide.core.VarContentsHelper.MenuAction;

import org.apache.log4j.Logger;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IDebugEventSetListener;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchesListener2;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
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.ui.part.ViewPart;

/**
 * This class is the basic view class of the debugger views (profiler, memory states, objects etc.) All other debugger views are
 * supposed to extend from this class.
 */
abstract public class BasicDebugView extends ViewPart implements IDebugEventSetListener, ILaunchesListener2 {
    private static final Logger log = Logger.getLogger(BasicDebugView.class);

    // bit mask for tool bar buttons
    final public static int REFRESH_BUTTON = 0x0001;

    final public static int SAVE_BUTTON = 0x0002;

    final public static int CLEAR_BUTTON = 0x0004;

    final public static int OPTIONS_BUTTON = 0x0008;

    final public static int COMPARE_BUTTON = 0x0010;

    final public static int SNAPSHOT_BUTTON = 0x0020;

    final public static int GARBAGE_COLLECTION_BUTTON = 0x0040;

    final public static int FILTER_BUTTON = 0x0080;

    final public static int FORWARD_BUTTON = 0x0100;

    final public static int BACKWARD_BUTTON = 0x0200;

    final public static int RETURN_TO_START_BUTTON = 0x0400;

    final public static int RETURN_TO_END_BUTTON = 0x0800;

    final public static int SAVE_TO_XML = 0x2000;

    final public static int SAVE_RAW_TO_XML = 0x4000;

    final public static int OPEN_PROFILEVIS = 0x8000;

    final static String HPROF_EXTENSION = "hprof"; //$NON-NLS-1$

    private int _buttons;

    private boolean _isSuspended;

    protected List<Object> _toolbarActionList;

    protected List<MenuAction> _menuActionList;

    private boolean _hasData;

    private boolean _hasSnapShot;

    private Label _messageLabel;

    /**
     * Constructs an instance of this view.
     *
     * @param buttons
     *            bit mask to indicate what buttons will be created on the tool bar of this view.
     */
    public BasicDebugView(int buttons) {
        _buttons = buttons;
        _toolbarActionList = new ArrayList<Object>();
        DebugPlugin.getDefault().addDebugEventListener(this);
        DebugPlugin.getDefault().getLaunchManager().addLaunchListener(this);
    }

    /**
     * Creates the UI of this view. This method only creates tool bar buttons on the view, and is supposed to be overridden by its
     * subclasses to create other UI parts.
     *
     * Caution: super#createPartControl(Composite parent) must be called in the beginning of the overridden method in subclasses.
     */
    public void createPartControl(Composite parent) {
        createToolbarButtons();
        // debugger may be suspended before this view is created
        setSuspended(ContextManager.PLUGIN.isSuspended());
        // initialize buttons
        updateToolbar();
        parent.setLayout(new GridLayout(1, false));
        // create message labels
        createMessageComposite(parent);
        // create table
        Composite tableComposite = CompositeFactory.gridComposite(parent, 1);
        tableComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
        // create the table view part
        createTableViewPart(tableComposite);
    }

    abstract public void createTableViewPart(Composite parent);

    public void setMessage(final String errorMessage, final boolean error) {
        Display.getDefault().syncExec(new Runnable() {

            @Override
            public void run() {
                if (_messageLabel != null) {
                    if (error) {
                        _messageLabel.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_RED));
                    } else {
                        _messageLabel.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK));
                    }
                    _messageLabel.setText(errorMessage);
                }
            }

        });

    }

    public void cleanMessage() {
        Display.getDefault().syncExec(new Runnable() {

            @Override
            public void run() {
                if (_messageLabel != null) {
                    _messageLabel.setText("");
                }
            }

        });
    }

    private void createMessageComposite(Composite parent) {
        Composite composite = CompositeFactory.gridComposite(parent, 1);
        // message label
        _messageLabel = new Label(composite, SWT.NONE);
        _messageLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    }

    protected void setHasData(boolean hasData) {
        _hasData = hasData;
    }

    protected void setHasSnapshot(boolean hasSnapshot) {
        _hasSnapShot = hasSnapshot;
    }

    protected boolean hasData() {
        return _hasData;
    }

    protected boolean hasSnapshot() {
        return _hasSnapShot;
    }

    /**
     * Creates the Image instance indicated by <code>imageId</code>.
     *
     * @param imageId
     *            <code>int</code> number which indicates the image to be created.
     * @return Image instance or <code>null</code> if some exception occurs.
     */
    static protected Image createImage(int imageId) {
        Image image = null;
        ImageDescriptor descriptor = null;
        switch (imageId) {
        case REFRESH_BUTTON: {
            descriptor = ContextManager.imageDescriptorFromPlugin(ContextManager.PLUGIN_ID,
                    "icons/obj16/refresh_enabled.gif");
            break;
        }
        case SAVE_BUTTON: {
            descriptor = ContextManager.imageDescriptorFromPlugin(ContextManager.PLUGIN_ID,
                    "icons/obj16/save_edit_enabled.gif");
            break;
        }
        case CLEAR_BUTTON: {
            descriptor = ContextManager.imageDescriptorFromPlugin(ContextManager.PLUGIN_ID,
                    "icons/obj16/clear.gif");
            break;
        }
        case OPTIONS_BUTTON: {
            descriptor = ContextManager.imageDescriptorFromPlugin(ContextManager.PLUGIN_ID,
                    "icons/obj16/options.gif");
            break;
        }
        case COMPARE_BUTTON: {
            descriptor = ContextManager.imageDescriptorFromPlugin(ContextManager.PLUGIN_ID,
                    "icons/obj16/compare.gif");
            break;
        }
        case SNAPSHOT_BUTTON: {
            descriptor = ContextManager.imageDescriptorFromPlugin(ContextManager.PLUGIN_ID,
                    "icons/obj16/snapshot.gif");
            break;
        }
        case GARBAGE_COLLECTION_BUTTON: {
            descriptor = ContextManager.imageDescriptorFromPlugin(ContextManager.PLUGIN_ID,
                    "icons/obj16/recycle.gif");
            break;
        }
        case FILTER_BUTTON: {
            descriptor = ContextManager.imageDescriptorFromPlugin(ContextManager.PLUGIN_ID,
                    "icons/obj16/filter.gif");
            break;
        }
        case FORWARD_BUTTON: {
            descriptor = ContextManager.imageDescriptorFromPlugin(ContextManager.PLUGIN_ID,
                    "icons/obj16/forward_nav.gif");
            break;
        }
        case BACKWARD_BUTTON: {
            descriptor = ContextManager.imageDescriptorFromPlugin(ContextManager.PLUGIN_ID,
                    "icons/obj16/backward_nav.gif");
            break;
        }
        case RETURN_TO_START_BUTTON: {
            descriptor = ContextManager.imageDescriptorFromPlugin(ContextManager.PLUGIN_ID,
                    "icons/obj16/return_to_start.gif");
            break;
        }
        case RETURN_TO_END_BUTTON: {
            descriptor = ContextManager.imageDescriptorFromPlugin(ContextManager.PLUGIN_ID,
                    "icons/obj16/return_to_end.gif");
            break;
        }
        case SAVE_TO_XML: {
            descriptor = ContextManager.imageDescriptorFromPlugin(ContextManager.PLUGIN_ID,
                    "icons/obj16/save_edit_enabled.gif");
            break;
        }
        case SAVE_RAW_TO_XML: {
            descriptor = ContextManager.imageDescriptorFromPlugin(ContextManager.PLUGIN_ID,
                    "icons/obj16/save_edit_enabled.gif");
            break;
        }
        case OPEN_PROFILEVIS: {
            descriptor = ContextManager.imageDescriptorFromPlugin(ContextManager.PLUGIN_ID,
                    "icons/obj16/openfile.gif");
            break;
        }
        }
        if (descriptor != null) {
            image = descriptor.createImage();
        }
        return image;
    }

    /**
     * Disposes created image instances.
     */
    public void dispose() {
        super.dispose();
        log.trace("Disposing the debug view and removing the debug listener");
        // fixed IDP350529, remove this object from the listener lists
        DebugPlugin.getDefault().removeDebugEventListener(this);
        DebugPlugin.getDefault().getLaunchManager().removeLaunchListener(this);
        // dispose all created actions
        for (Iterator iterator = _toolbarActionList.iterator(); iterator.hasNext();) {
            Object obj = iterator.next();
            if (obj instanceof BasicAction) {
                BasicAction action = (BasicAction) obj;
                action.dispose();
            } else if (obj instanceof Separator) {
                Separator separator = (Separator) obj;
                separator.dispose();
            }
        }

    }

    /**
     * Creates a tool bar Action instance indicated by <code>action</code>.
     *
     * @param action
     *            the action to be created.
     */
    private void createToolbarAction(int action) {
        String text;
        String hint;
        switch (action) {
        case REFRESH_BUTTON: {
            // create fresh action
            text = Messages.BasicView_REFRESH_ACTION_TITLE;
            hint = Messages.BasicView_REFRESH_ACTION_HINT;
            break;
        }
        case SAVE_BUTTON: {
            // create save action
            text = Messages.BasicView_SAVE_ACTION_TITLE;
            hint = Messages.BasicView_SAVE_ACTION_HINT;
            break;
        }
        case CLEAR_BUTTON: {
            // create clear action
            text = Messages.BasicView_CLEAR_ACTION_TITLE;
            hint = Messages.BasicView_CLEAR_ACTION_HINT;
            break;
        }
        case OPTIONS_BUTTON: {
            // create options action
            text = Messages.BasicView_OPTIONS_ACTION_TITLE;
            hint = Messages.BasicView_OPTIONS_ACTION_HINT;
            break;
        }
        case COMPARE_BUTTON: {
            // create compare action
            text = Messages.BasicView_COMPARE_ACTION_TITLE;
            hint = Messages.BasicView_COMPARE_ACTION_HINT;
            break;
        }
        case SNAPSHOT_BUTTON: {
            // create snapshot action
            text = Messages.BasicView_SNAPSHOT_ACTION_TITLE;
            hint = Messages.BasicView_SNAPSHOT_ACTION_HINT;
            break;
        }
        case GARBAGE_COLLECTION_BUTTON: {
            // create garbage collection action
            text = Messages.BasicView_GC_ACTION_TITLE;
            hint = Messages.BasicView_GC_ACTION_HINT;
            break;
        }
        case FILTER_BUTTON: {
            // create filter action
            text = Messages.BasicView_FILTER_ACTION_TITLE;
            hint = Messages.BasicView_FILTER_ACTION_HINT;
            break;
        }
        case FORWARD_BUTTON: {
            // create forward action
            text = Messages.BasicView_FORWARD_ACTION_TITLE;
            hint = Messages.BasicView_FORWARD_ACTION_HINT;
            break;
        }
        case BACKWARD_BUTTON: {
            // create backward action
            text = Messages.BasicView_BACKWARD_ACTION_TITLE;
            hint = Messages.BasicView_BACKWARD_ACTION_HINT;
            break;
        }
        case RETURN_TO_START_BUTTON: {
            // create "return to start" action
            text = Messages.BasicView_RETURN_TO_START_ACTION_TITLE;
            hint = Messages.BasicView_RETURN_TO_START_ACTION_HINT;
            break;
        }
        case RETURN_TO_END_BUTTON: {
            // create filter action
            text = Messages.BasicView_GO_TO_END_ACTION_TITLE;
            hint = Messages.BasicView_GO_TO_END_ACTION_HINT;
            break;
        }
        case SAVE_TO_XML: {
            // dump heap
            text = Messages.BasicView_SAVE_XML_ACTION_TITLE;
            hint = Messages.BasicView_SAVE_XML_ACTION_HINT;
            break;
        }
        case SAVE_RAW_TO_XML: {
            // dump heap
            text = Messages.BasicView_SAVE_RAW_XML_ACTION_TITLE;
            hint = Messages.BasicView_SAVE_RAW_XML_ACTION_HINT;
            break;
        }
        case OPEN_PROFILEVIS: {
            // dump heap
            text = Messages.BasicView_OPEN_PROFILEVIS_ACTION_TITLE;
            hint = Messages.BasicView_OPEN_PROFILEVIS_ACTION_HINT;
            break;
        }
        default:
            return;
        }
        _toolbarActionList.add(new BasicAction(this, text, action, hint));
    }

    /**
     * Creates buttons on the tool bar of this view.
     */
    private void createToolbarButtons() {
        // create and add buttons to tool bar
        IToolBarManager toolBarMgr = getViewSite().getActionBars().getToolBarManager();
        // create actions
        if ((_buttons & RETURN_TO_START_BUTTON) != 0) {
            createToolbarAction(RETURN_TO_START_BUTTON);
        }
        if ((_buttons & BACKWARD_BUTTON) != 0) {
            createToolbarAction(BACKWARD_BUTTON);
        }
        if ((_buttons & FORWARD_BUTTON) != 0) {
            createToolbarAction(FORWARD_BUTTON);
        }
        if ((_buttons & RETURN_TO_END_BUTTON) != 0) {
            createToolbarAction(RETURN_TO_END_BUTTON);
        }

        if ((_buttons & RETURN_TO_START_BUTTON) != 0 || (_buttons & BACKWARD_BUTTON) != 0
                || (_buttons & FORWARD_BUTTON) != 0 || (_buttons & RETURN_TO_END_BUTTON) != 0)
            _toolbarActionList.add(new Separator("Navagition Group"));

        if ((_buttons & REFRESH_BUTTON) != 0) {
            createToolbarAction(REFRESH_BUTTON);
        }
        if ((_buttons & SAVE_BUTTON) != 0) {
            createToolbarAction(SAVE_BUTTON);
        }
        if ((_buttons & CLEAR_BUTTON) != 0) {
            createToolbarAction(CLEAR_BUTTON);
        }
        if ((_buttons & OPTIONS_BUTTON) != 0) {
            createToolbarAction(OPTIONS_BUTTON);
        }
        if ((_buttons & FILTER_BUTTON) != 0) {
            createToolbarAction(FILTER_BUTTON);
        }
        if ((_buttons & COMPARE_BUTTON) != 0) {
            createToolbarAction(COMPARE_BUTTON);
        }
        if ((_buttons & SNAPSHOT_BUTTON) != 0) {
            createToolbarAction(SNAPSHOT_BUTTON);
        }
        if ((_buttons & GARBAGE_COLLECTION_BUTTON) != 0) {
            createToolbarAction(GARBAGE_COLLECTION_BUTTON);
        }
        if ((_buttons & SAVE_TO_XML) != 0) {
            createToolbarAction(SAVE_TO_XML);
        }
        if ((_buttons & SAVE_RAW_TO_XML) != 0) {
            createToolbarAction(SAVE_RAW_TO_XML);
        }
        if ((_buttons & OPEN_PROFILEVIS) != 0) {
            createToolbarAction(OPEN_PROFILEVIS);
        }
        // add the buttons to the tool bar
        for (Iterator iterator = _toolbarActionList.iterator(); iterator.hasNext();) {
            Object obj = iterator.next();
            if (obj instanceof BasicAction)
                toolBarMgr.add((BasicAction) obj);
            else if (obj instanceof IContributionItem)
                toolBarMgr.add((IContributionItem) obj);
        }
    }

    public void setFocus() {
        // nothing to do
    }

    /**
     * @see IDebugEventSetListener#handleDebugEvents(DebugEvent[]).
     *
     */
    public void handleDebugEvents(DebugEvent[] events) {
        if (events == null || events.length == 0)
            return;

        for (int i = 0; i < events.length; i++) {
            if (!DebugUtils.isFromRIMLaunch(events[i])) {
                continue;
            }
            if (events[i].getKind() == DebugEvent.SUSPEND && !_isSuspended) {
                _isSuspended = true;
                updateToolbar();
            }

            else if (events[i].getKind() == DebugEvent.RESUME && _isSuspended) {
                _isSuspended = false;
                updateToolbar();
            }
            handleRIMDebugEvent(events[i]);
        }

    } // method handleDebugEvents

    protected void handleRIMDebugEvent(DebugEvent event) {
        // do nothing here
    }

    // ------ implementation of methods of ILaunchesListener2 ------

    /**
     * @see ILaunchesListener2#launchesTerminated(ILaunch[]).
     */
    public void launchesTerminated(ILaunch[] launches) {
        debugTerminated(launches);
    }

    /**
     * @see ILaunchesListener#launchesRemoved(ILaunch[]).
     */
    public void launchesRemoved(ILaunch[] launches) {
        // in hot-swap, only launch removed event is fired, there is no launch terminated event.
        debugTerminated(launches);
    }

    /**
     * @see ILaunchesListener#launchesAdded(ILaunch[]).
     */
    public void launchesAdded(ILaunch[] launches) {
    }

    /**
     * @see ILaunchesListener#launchesChanged(ILaunch[]).
     */
    public void launchesChanged(ILaunch[] launches) {
    }

    /**
     * Set actions indicated by <code>actions</code> as <code>enabled</code>.
     *
     * @param actions
     *            bit mask which indicates what actions will be enabled/disabled.
     * @param enabled
     *            <code>true</code> enable the actions indicated by <code>actions</code>, <code>false</code> otherwise.
     */
    public void enableActions(int actions, boolean enabled) {
        for (Iterator iterator = _toolbarActionList.iterator(); iterator.hasNext();) {
            Object obj = iterator.next();
            if (!(obj instanceof BasicAction))
                continue;
            BasicAction action = (BasicAction) obj;
            if ((action.getActionCode() & actions) != 0 && action.isEnabled() != enabled)
                action.setEnabled(enabled);
        }

    }

    /**
     * Checks whether the debugger is suspended.
     *
     * @return <code>true</code>if the debugger is suspended, <code>false</code> otherwise.
     */
    public boolean isSuspended() {
        return _isSuspended;
    }

    /**
     * Sets whether the debugger is suspended or not.
     *
     * @param suspeneded
     *            <code>true</code>if the debugger is suspended, <code>false</code> otherwise.
     */
    public void setSuspended(boolean suspeneded) {
        _isSuspended = suspeneded;
    }

    /**
     * Despatch task when an action is executed (a button is clicked).
     *
     * @param action
     *            the action executed.
     * @throws CoreException
     */
    protected void run(BasicAction action) throws CoreException {
        switch (action.getActionCode()) {
        case REFRESH_BUTTON: {
            refresh();
            return;
        }
        case SAVE_BUTTON: {
            save();
            return;
        }
        case CLEAR_BUTTON: {
            clear();
            return;
        }
        case OPTIONS_BUTTON: {
            setOptions();
            return;
        }
        case COMPARE_BUTTON: {
            compare();
            break;
        }
        case SNAPSHOT_BUTTON: {
            snapshot();
            return;
        }
        case GARBAGE_COLLECTION_BUTTON: {
            gc();
            return;
        }
        case FILTER_BUTTON: {
            filter();
            return;
        }
        case FORWARD_BUTTON: {
            forward();
            return;
        }
        case BACKWARD_BUTTON: {
            backward();
            return;
        }
        case RETURN_TO_START_BUTTON: {
            returnToStart();
            return;
        }
        case RETURN_TO_END_BUTTON: {
            returnToEnd();
            return;
        }
        case SAVE_TO_XML: {
            saveXML();
            return;
        }
        case SAVE_RAW_TO_XML: {
            saveRawToXML();
            return;
        }
        case OPEN_PROFILEVIS: {
            openProfileVis();
            return;
        }
        default:
            return;
        }
    }

    /**
     * Debug session is terminated.
     */
    private void debugTerminated(ILaunch[] launches) {
        List<ILaunch> rimLaunches = DebugUtils.getRIMLaunches(launches);
        if (rimLaunches.size() == 0) {
            return;
        }
        _isSuspended = false;
        Display.getDefault().asyncExec(new Runnable() {
            public void run() {
                clear();
            }
        });
        RIMDebugTerminated(rimLaunches.toArray(new ILaunch[rimLaunches.size()]));
    }

    public void RIMDebugTerminated(ILaunch[] launches) {
        // do nothing here
    }

    /**
     * Enables/Disables the buttons on the tool bar.
     */
    public void updateToolbar() {
        enableActions(OPTIONS_BUTTON, optionsEnabled());
        if (isSuspended()) {
            enableActions(REFRESH_BUTTON | GARBAGE_COLLECTION_BUTTON | FILTER_BUTTON, true);
            if (_hasSnapShot)
                enableActions(COMPARE_BUTTON, true);
            else
                enableActions(COMPARE_BUTTON, false);
        } else
            enableActions(REFRESH_BUTTON | GARBAGE_COLLECTION_BUTTON | COMPARE_BUTTON | FILTER_BUTTON
                    | BACKWARD_BUTTON | FORWARD_BUTTON | RETURN_TO_START_BUTTON | RETURN_TO_END_BUTTON, false);

        // set others
        if (_hasData)
            enableActions(
                    SNAPSHOT_BUTTON | SAVE_BUTTON | CLEAR_BUTTON | SAVE_TO_XML | SAVE_RAW_TO_XML | OPEN_PROFILEVIS,
                    true);
        else
            enableActions(
                    SNAPSHOT_BUTTON | SAVE_BUTTON | CLEAR_BUTTON | SAVE_TO_XML | SAVE_RAW_TO_XML | OPEN_PROFILEVIS,
                    false);
    }

    /**
     * Checks if the options action button on the view is enabled.<p>
     * <b> The sub classes can override this method to make the options action button to be enabled under different conditions</b>
     *
     * @return
     */
    public boolean optionsEnabled() {
        return DebugUtils.isRIMDebuggerRunning();
    }

    // subclasses of this class are supposed to override
    // these methods but can ignore the actions that are not
    // applied to them
    /**
     * Clears the current display content.
     * <p>
     * <b>subclasses need to override this method.</b>
     */
    public void clear() {
        // do nothing;
    }

    /**
     * Save the currently displayed data into a csv file.
     * <p>
     * <b>subclasses need to override this method.</b>
     */
    public void save() {
        // do nothing;
    }

    /**
     * Reloads the data and refresh the display.
     * <p>
     * <b>subclasses need to override this method.</b>
     *
     * @throws CoreException
     */
    public void refresh() throws CoreException {
        // do nothing;
    }

    /**
     * Takes a snapshot of current data
     * <p>
     * <b>subclasses need to override this method.</b>
     */
    public void snapshot() {
        // do nothing;
    }

    /**
     * Sets up options.
     * <p>
     * <b>subclasses need to override this method.</b>
     */
    public void setOptions() {
        // do nothing;
    }

    /**
     * Compares the current data with the snapshot.
     * <p>
     * <b>subclasses need to override this method.</b>
     */
    public void compare() {
        // do nothing;
    }

    /**
     * Perform garbage collection.
     * <p>
     * <b>subclasses need to override this method.</b>
     */
    public void gc() {
        // do nothing;
    }

    /**
     * Sets filters.
     * <p>
     * <b>subclasses need to override this method.</b>
     */
    public void filter() {
        // do nothing
    }

    /**
     * Forwards to the next step.
     * <p>
     * <b>subclasses need to override this method.</b>
     */
    public void forward() {
        // do nothing
    }

    /**
     * Backwards to the last step.
     * <p>
     * <b>subclasses need to override this method.</b>
     */
    public void backward() {
        // do nothing
    }

    /**
     * Returns to the start.
     * <p>
     * <b>subclasses need to override this method.</b>
     */
    public void returnToStart() {
        // do nothing
    }

    /**
     * Goes to the end
     * <p>
     * <b>subclasses need to override this method.</b>
     */
    public void returnToEnd() {
        // do nothing
    }

    /**
     * Save view content to a XML file.
     * <p>
     * <b>subclasses need to override this method.</b>
     */
    public void saveXML() {
        // do nothing
    }

    /**
     * Save raw data of the view content to a XML file.
     * <p>
     * <b>subclasses need to override this method.</b>
     */
    public void saveRawToXML() {
        // do nothing
    }

    /**
     * Open ProfileVisDesktop to display the collected profile data
     */
    public void openProfileVis() {
        // do nothing
    }
}