sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/ButtonPlugin.java
author Matti Laitinen <matti.t.laitinen@nokia.com>
Thu, 11 Feb 2010 15:32:31 +0200
changeset 2 b9ab3b238396
child 5 844b047e260d
permissions -rw-r--r--
Initial version of Performance Investigator under EPL

/*
 * Copyright (c) 2009 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.button;

import java.io.File;
import java.util.ArrayList;
import java.util.Vector;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.osgi.framework.BundleContext;

import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
import com.nokia.carbide.cpp.internal.pi.analyser.ProfileVisualiser;
import com.nokia.carbide.cpp.internal.pi.button.ui.SwitchBupMapDialog;
import com.nokia.carbide.cpp.internal.pi.model.GenericTrace;
import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
import com.nokia.carbide.cpp.internal.pi.plugin.model.IClassReplacer;
import com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener;
import com.nokia.carbide.cpp.internal.pi.plugin.model.IFinalizeTrace;
import com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace;
import com.nokia.carbide.cpp.internal.pi.plugin.model.IViewMenu;
import com.nokia.carbide.cpp.internal.pi.plugin.model.IVisualizable;
import com.nokia.carbide.cpp.internal.pi.test.AnalysisInfoHandler;
import com.nokia.carbide.cpp.internal.pi.test.IProvideTraceAdditionalInfo;
import com.nokia.carbide.cpp.internal.pi.test.TraceAdditionalInfo;
import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
import com.nokia.carbide.cpp.internal.pi.visual.GraphDrawRequest;
import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
import com.nokia.carbide.cpp.pi.importer.SampleImporter;
import com.nokia.carbide.cpp.pi.util.GeneralMessages;
import com.nokia.carbide.cpp.sdk.core.ISymbianSDK;
import com.nokia.carbide.cpp.sdk.core.SDKCorePlugin;


/**
 * The main plugin class to be used in the desktop.
 */
public class ButtonPlugin extends AbstractPiPlugin
			implements ITrace, IViewMenu, IEventListener, IClassReplacer, IVisualizable, IFinalizeTrace, IProvideTraceAdditionalInfo
{
	public static final String PLUGIN_ID = PIPageEditor.PI_ID + ".button";  //$NON-NLS-1$

	// There will be three graphs - one each for editor pages 0, 1, 2
	// This code may assume that page 0 has the threads graph, 1 the binaries, and 2 the functions
	private final static int GRAPH_COUNT = 3;

	//The shared instance.
	private static ButtonPlugin plugin;
	
	private static IPreferenceStore prefsStore;
	
	private static void setPlugin(ButtonPlugin newPlugin)
	{
		plugin = newPlugin;
	}

	/**
	 * The constructor.
	 */
	public ButtonPlugin() {
		super();
		setPlugin(this);
	}

	public Class getTraceClass() {
		return BupTrace.class;
	}

	public Class getReplacedClass(String className)
	{
		if (   className.indexOf("com.nokia.carbide.cpp.pi.button.BupTrace") != -1 //$NON-NLS-1$
			|| className.indexOf("com.nokia.carbide.pi.button.BupTrace") != -1 //$NON-NLS-1$
			|| className.indexOf("fi.vtt.bappea.model.BupTrace") != -1 //$NON-NLS-1$
			|| className.indexOf("fi.vtt.bappea.bupTracePlugin.BupTrace") != -1) //$NON-NLS-1$
		{
			return BupTrace.class;
		}
		else if (   className.indexOf("com.nokia.carbide.cpp.pi.button.BupSample") != -1 //$NON-NLS-1$
				 || className.indexOf("com.nokia.carbide.pi.button.BupSample") != -1 )//$NON-NLS-1$
		{
			return BupSample.class;
		}
		else
			return null;
	}
	
	public void initialiseTrace(GenericTrace trace) 
	{
		if (!(trace instanceof BupTrace))
			return;

		BupTrace bupTrace = (BupTrace)trace;
		
		NpiInstanceRepository.getInstance().activeUidAddTrace("com.nokia.carbide.cpp.pi.button", trace); //$NON-NLS-1$
	}

	public String getTraceName() {
		return "Button"; //$NON-NLS-1$
	}

	public int getTraceId() {
		return 7;
	}

	public ParsedTraceData parseTraceFile(File file) throws Exception 
	{
		try
        {
            BupTraceParser parser;
            parser = new BupTraceParser();
            return parser.parse(file);
        } catch (Exception e)
        {
            e.printStackTrace();
            throw e;
        }
	}

	public MenuManager getViewOptionManager() {
		// current tab
		if (NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.button") == null) //$NON-NLS-1$
			return null;	// no trace, so no MenuManager

		Action action;

		Boolean showEvents = Boolean.TRUE;		// by default, show button press events

		// if there is a value associated with the current Analyser tab, then use it
		Object obj = NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.button.show"); //$NON-NLS-1$
		if ((obj != null) && (obj instanceof Boolean))
			// retrieve the current value
			showEvents = (Boolean)obj;
		else
			// set the initial value
			NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.button.show", showEvents); //$NON-NLS-1$

		action = new Action(Messages.getString("ButtonPlugin.showEventsAction"), Action.AS_CHECK_BOX) { //$NON-NLS-1$
			public void run() {
				if (this.isChecked())
					receiveSelectionEvent("button_events_on"); //$NON-NLS-1$
				else
					receiveSelectionEvent("button_events_off"); //$NON-NLS-1$
			}
		};
		action.setChecked(showEvents);
		action.setToolTipText(Messages.getString("ButtonPlugin.showEventsTooltip")); //$NON-NLS-1$
		PIPageEditor.currentMenuManager().add(action);

		action = new Action("Apply New Key Press Profile", Action.AS_PUSH_BUTTON) {	//$NON-NLS-1$
			public void run() {
				switchMap();
			}
		};
		action.setChecked(showEvents);
		action.setToolTipText(Messages.getString("ButtonPlugin.applyProfile")); //$NON-NLS-1$
		PIPageEditor.currentMenuManager().add(action);

		return PIPageEditor.currentMenuManager();
	}
	
	public void receiveEvent(String actionString, Event event) 
	{
		if (   actionString.equals("button_events_on")  //$NON-NLS-1$
			|| actionString.equals("button_events_off")	//$NON-NLS-1$
			|| actionString.equals("button_map_switch")) //$NON-NLS-1$
	  	{
			BupTrace bupTrace = (BupTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.button"); //$NON-NLS-1$
			
			if (bupTrace == null)
				return;

	  		((BupTraceGraph)bupTrace.getTraceGraph(PIPageEditor.THREADS_PAGE)).action(actionString);	
	  		((BupTraceGraph)bupTrace.getTraceGraph(PIPageEditor.BINARIES_PAGE)).action(actionString);	
	  		((BupTraceGraph)bupTrace.getTraceGraph(PIPageEditor.FUNCTIONS_PAGE)).action(actionString);	
	  	}
	}

	public void receiveSelectionEvent(String actionString) 
	{
		if (actionString == null)
			return;
		
		int currentPage = PIPageEditor.currentPageIndex();

		if (   (currentPage != PIPageEditor.THREADS_PAGE)
			&& (currentPage != PIPageEditor.BINARIES_PAGE)
			&& (currentPage != PIPageEditor.FUNCTIONS_PAGE))
			  return;

		if (actionString.equals("button_events_on")) { //$NON-NLS-1$
			NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.button.show", true); //$NON-NLS-1$
	  	} else if (actionString.equals("button_events_off")) { //$NON-NLS-1$
	  		NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.button.show", false); //$NON-NLS-1$
	  	} else {
	  		return;
	  	}

		BupTrace bupTrace = (BupTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.button"); //$NON-NLS-1$
		
		if (bupTrace == null)
			return;

  		((BupTraceGraph)bupTrace.getTraceGraph(PIPageEditor.THREADS_PAGE)).action(actionString);	
  		((BupTraceGraph)bupTrace.getTraceGraph(PIPageEditor.BINARIES_PAGE)).action(actionString);	
  		((BupTraceGraph)bupTrace.getTraceGraph(PIPageEditor.FUNCTIONS_PAGE)).action(actionString);	
	}

	public Integer getLastSample(int graphIndex) {
		return null;
	}

	public GraphDrawRequest getDrawRequest(int graphIndex) {
		GraphDrawRequest request = new GraphDrawRequest();
		request.addParentGraph(
				graphIndex,
				"com.nokia.carbide.cpp.pi.address.AddressPlugin", //$NON-NLS-1$
				GraphDrawRequest.DRAW_TO_MOST_IMPORTANT_AVAILABLE,
				1);
		return request;
	}

//	public GenericTraceGraph getTraceGraph() 
//	{
//		return this.trace.getTraceGraph();
//	}

	public GenericTraceGraph getTraceGraph(int graphIndex) 
	{
		BupTrace bupTrace = (BupTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.button"); //$NON-NLS-1$
		
		if (bupTrace == null)
			return null;

		return bupTrace.getTraceGraph(graphIndex);
	}

	/**
	 * This method is called upon plug-in activation
	 */
	public void start(BundleContext context) throws Exception {
		super.start(context);
	}

	/**
	 * This method is called when the plug-in is stopped
	 */
	public void stop(BundleContext context) throws Exception {
		super.stop(context);
		setPlugin(null);
	}

	/**
	 * Returns the shared instance.
	 */
	public static ButtonPlugin getDefault() {
		return plugin;
	}

	/**
	 * Returns an image descriptor for the image file at the given
	 * plug-in relative path.
	 *
	 * @param path the path
	 * @return the image descriptor
	 */
	public static ImageDescriptor getImageDescriptor(String path) {
		return AbstractPiPlugin.imageDescriptorFromPlugin("com.nokia.carbide.cpp.pi.button", path); //$NON-NLS-1$
	}

	public int getGraphCount() {
		return GRAPH_COUNT;
	}

	public int getPageNumber(int graphIndex) {
		// Assumes page 0 has the threads graph, 1 has the binaries, and 2 has the functions
		return graphIndex;
	}

	// return whether this plugin's editor pages have been created
	public boolean arePagesCreated() {
		return false;
	}
	
	public void setPagesCreated(boolean pagesCreated) {
		return;
	}

	public int getCreatePageCount() {
		return 0;
	}

	public int getCreatePageIndex(int index) {
		return 0;
	}

	public ProfileVisualiser createPage(int index) {
		return null;
	}

	public void setPageIndex(int index, int pageIndex) {
		return;
	}

	/* (non-Javadoc)
	 * @see com.nokia.carbide.cpp.internal.pi.plugin.model.IVisualizable#getGraphTitle(int)
	 */
	public String getGraphTitle(int graphIndex) {
		return null;
	}
	
	/**
	 * Returns the shared preference store of this plugin
	 */
	public static IPreferenceStore getBupPrefsStore(){
		if (prefsStore == null){
			prefsStore = getDefault().getPreferenceStore();
		}
		
		return prefsStore;
	}

	/* (non-Javadoc)
	 * @see com.nokia.carbide.cpp.internal.pi.plugin.model.IPIPageEditorDispose#runOnDispose()
	 */
	public void runOnDispose() {
		BupTrace bupTrace = (BupTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.button"); //$NON-NLS-1$
		if (bupTrace != null) {
			BupEventMapManager.getInstance().releaseMap(bupTrace.getCurrentBupMapInUse());
		}
	}
	
	public void switchMap() {
		BupTrace bupTrace = (BupTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.button"); //$NON-NLS-1$
		IBupEventMapProfile oldProfile = bupTrace.getCurrentBupMapInUse().getProfile();
		SwitchBupMapDialog dialog = new SwitchBupMapDialog(Display.getCurrent().getActiveShell(), oldProfile);
		if (dialog.open() == Window.OK) {
			IBupEventMap oldMap = bupTrace.getCurrentBupMapInUse();
			IBupEventMap newMap = BupEventMapManager.getInstance().captureMap(dialog.getNewProfile());
			if (bupTrace != null) {
				boolean resetAll = dialog.resetAll();
				Vector<BupSample> samples = bupTrace.samples;
				for (BupSample sample : samples) {
					if (resetAll || !sample.isLabelModified()) {
						sample.resetLabelToMapDefault(newMap);
					}
				}
				bupTrace.setCurrentBupMapInUse(newMap);
				AnalysisInfoHandler handler = NpiInstanceRepository.getInstance().activeUidGetAnalysisInfoHandler();
				// apply profile change to AnalysisInfoHandler that handling additional info in NPI file lifetime
				setBupMapProfileToInfoHandler(handler, dialog.getNewProfile());
				PIPageEditor.currentPageEditor().setDirty();
				// Use this for sending graph fresh
				receiveEvent("button_map_switch", new Event());	//$NON-NLS-1$
			}
			BupEventMapManager.getInstance().releaseMap(oldMap);
		}
	}
	
	/*
	 * (non-javadoc)
	 * Only Bup Plugin should know about it's own additional info
	 * This class keep around a profile, and handle transfer in and out fo additional info
	 * in one place for consistence.
	 */
	private class BupInfoHandlerAdditionalInfo {
		// index of additional info in NPI file
		private static final transient int BUP_MAP_PROFILE_ID = 0;
		private static final transient int BUP_MAP_SYMBIAN_SDK_ID = 1;
		private static final transient int BUP_MAP_IS_BUILTIN = 2;
		private static final transient int BUP_MAP_IS_WORSPACE = 3;
		
		IBupEventMapProfile profile;
		
		Vector<Object> toAdditionalInfo() {
			
			int maxSize = BUP_MAP_PROFILE_ID;
			maxSize = Math.max(maxSize, BUP_MAP_SYMBIAN_SDK_ID);
			maxSize = Math.max(maxSize, BUP_MAP_IS_WORSPACE);
			maxSize = Math.max(maxSize, BUP_MAP_IS_BUILTIN);
			Vector<Object> result = new Vector<Object>(maxSize + 1);
			result.setSize(maxSize + 1);
			result.setElementAt(profile.getProfileId(), BUP_MAP_PROFILE_ID);
			result.setElementAt(profile.getSDK() != null ? profile.getSDK().getUniqueId() : "", BUP_MAP_SYMBIAN_SDK_ID); //$NON-NLS-1$
			result.setElementAt(new Boolean(profile.getURI().equals(BupEventMapManager.WORKSPACE_PREF_KEY_MAP_URI)), BUP_MAP_IS_WORSPACE);
			result.setElementAt(new Boolean(profile.getURI().equals(BupEventMapManager.DEFAULT_PROFILE_URI)), BUP_MAP_IS_BUILTIN);
			
			return result;
		}
		
		void fromAddtionalInfo(Vector<Object> additional_info) {
			if (!(additional_info.get(BUP_MAP_PROFILE_ID) instanceof String) ||
					!(additional_info.get(BUP_MAP_SYMBIAN_SDK_ID) instanceof String) ||
					!(additional_info.get(BUP_MAP_IS_BUILTIN) instanceof Boolean) ||
					!(additional_info.get(BUP_MAP_IS_WORSPACE) instanceof Boolean))
			{
				// did you changed anything in analysisInfoHandlerToAdditonalInfo()?
				// did you changed the data format of addition info?
				GeneralMessages.showErrorMessage(Messages.getString("ButtonPlugin.InternalError")); //$NON-NLS-1$
			}
			ArrayList<IBupEventMapProfile> profiles = new ArrayList<IBupEventMapProfile>();
			if (!additional_info.get(BUP_MAP_SYMBIAN_SDK_ID).equals("")) { //$NON-NLS-1$
				String sdkId = (String) additional_info.get(BUP_MAP_SYMBIAN_SDK_ID);
				ISymbianSDK sdk = SDKCorePlugin.getSDKManager().getSDK(sdkId, true);
				profiles.addAll(BupEventMapManager.getInstance().getProfilesFromSDK(sdk));
			} else if ((Boolean)additional_info.get(BUP_MAP_IS_WORSPACE)) {
				profiles.addAll(BupEventMapManager.getInstance().getProfilesFromWorkspacePref());
			} else if ((Boolean)additional_info.get(BUP_MAP_IS_BUILTIN)) {
				profiles.addAll(BupEventMapManager.getInstance().getProfilesFromBuiltin());
			}
			
			profile = null;
			for (IBupEventMapProfile tempProfile : profiles) {
				if (tempProfile.getProfileId().equals(additional_info.get(BUP_MAP_PROFILE_ID))) {
					profile = tempProfile;
					break;
				}
			}
			if (profile == null) {
				if (additional_info.get(BUP_MAP_PROFILE_ID).equals("")) {	//$NON-NLS-1$
					profile = BupEventMapManager.getInstance().getLegacyProfile();
				} else {
					GeneralMessages.showWarningMessage(Messages.getString("ButtonPlugin.keyMapRemoved")); //$NON-NLS-1$
					profile = BupEventMapManager.getInstance().getPrefSelectedProfile();					
				}
			}
		}
	}

	public void setupInfoHandler(AnalysisInfoHandler handler) {
		ArrayList<IBupEventMapProfile> profiles = new ArrayList<IBupEventMapProfile>();
		if (SampleImporter.getInstance().getBupMapSymbianSDKId() != null &&
			!SampleImporter.getInstance().getBupMapSymbianSDKId().equals("")) { //$NON-NLS-1$
			ISymbianSDK sdk = SDKCorePlugin.getSDKManager().getSDK(SampleImporter.getInstance().getBupMapSymbianSDKId(), true);
			profiles.addAll(BupEventMapManager.getInstance().getProfilesFromSDK(sdk));
		} else if (SampleImporter.getInstance().isBupMapIsWorkspace()) {
			profiles.addAll(BupEventMapManager.getInstance().getProfilesFromWorkspacePref());
		} else if (SampleImporter.getInstance().isBupMapIsBuiltIn()) {
			profiles.addAll(BupEventMapManager.getInstance().getProfilesFromBuiltin());
		}

		for (IBupEventMapProfile profile : profiles) {
			if (profile.getProfileId().equals(SampleImporter.getInstance().getBupMapProfileId())) {
				BupInfoHandlerAdditionalInfo info = (BupInfoHandlerAdditionalInfo) handler.getTraceDefinedInfo(getTraceId());
				if (info == null) {
					info = new BupInfoHandlerAdditionalInfo();
				}
				info.profile = profile;
				handler.setTraceDefinedInfo(getTraceId(), info);
				break;
			}
		}
	}

	public void additionalInfoToAnalysisInfoHandler(Vector<Object> additional_info, AnalysisInfoHandler handler) { 
		BupInfoHandlerAdditionalInfo info = (BupInfoHandlerAdditionalInfo) handler.getTraceDefinedInfo(getTraceId());
		if (info == null) {
			info = new BupInfoHandlerAdditionalInfo();
		}
		info.fromAddtionalInfo(additional_info);
		handler.setTraceDefinedInfo(getTraceId(), info);
	}
	
	public void analysisInfoHandlerToAdditonalInfo(TraceAdditionalInfo info, AnalysisInfoHandler handler) {
		Vector<Object> additional_info = new Vector<Object>();
		Object handlerInfo = handler.getTraceDefinedInfo(getTraceId());
		if (handlerInfo instanceof BupInfoHandlerAdditionalInfo) {
			additional_info = ((BupInfoHandlerAdditionalInfo)handlerInfo).toAdditionalInfo();
		}
		info.addAdditionalInfo(getTraceId(), additional_info);
	}

	/* (non-Javadoc)
	 * @see com.nokia.carbide.cpp.internal.pi.test.IProvideTraceAdditionalInfo#InfoHandlerToDisplayString(java.util.Vector)
	 */
	public String InfoHandlerToDisplayString(AnalysisInfoHandler handler) {
		Object info = handler.getTraceDefinedInfo(getTraceId());
		if (info instanceof BupInfoHandlerAdditionalInfo) {
			return Messages.getString("ButtonPlugin.keyPressProfile") +((BupInfoHandlerAdditionalInfo)info).profile.toString(); //$NON-NLS-1$
		}
		return ""; //$NON-NLS-1$
	}
	
	/*
	 * (non-Javadoc)
	 * Manipulate additional info among AnalysisInfoHandler during lifetime of loaded NPI file
	 */
	public void setBupMapProfileToInfoHandler(AnalysisInfoHandler handler, IBupEventMapProfile profile) {
		BupInfoHandlerAdditionalInfo info = (BupInfoHandlerAdditionalInfo) handler.getTraceDefinedInfo(getTraceId());
		if (info == null) {
			info = new BupInfoHandlerAdditionalInfo();
		}
		info.profile = profile;
		handler.setTraceDefinedInfo(getTraceId(), info);
	}

	/*
	 * (non-Javadoc)
	 * Read additional info among AnalysisInfoHandler during lifetime of loaded NPI file
	 */
	public IBupEventMapProfile getBupMapProfileFromInfoHandler(AnalysisInfoHandler handler) {
		Object info = handler.getTraceDefinedInfo(getTraceId());
		if (info != null && info instanceof BupInfoHandlerAdditionalInfo) {
			return ((BupInfoHandlerAdditionalInfo)info).profile;
		}
		GeneralMessages.showWarningMessage(Messages.getString("ButtonPlugin.keyMapRemoved")); //$NON-NLS-1$
		return BupEventMapManager.getInstance().getPrefSelectedProfile();
	}
}