sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/pi/editors/PIPageEditor.java
changeset 2 b9ab3b238396
child 5 844b047e260d
equal deleted inserted replaced
1:1050670c6980 2:b9ab3b238396
       
     1 /*
       
     2  * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3  * All rights reserved.
       
     4  * This component and the accompanying materials are made available
       
     5  * under the terms of the License "Eclipse Public License v1.0"
       
     6  * which accompanies this distribution, and is available
       
     7  * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8  *
       
     9  * Initial Contributors:
       
    10  * Nokia Corporation - initial contribution.
       
    11  *
       
    12  * Contributors:
       
    13  *
       
    14  * Description: 
       
    15  *
       
    16  */
       
    17 
       
    18 package com.nokia.carbide.cpp.pi.editors;
       
    19 
       
    20 import java.io.ByteArrayInputStream;
       
    21 import java.io.IOException;
       
    22 import java.io.InputStream;
       
    23 import java.lang.reflect.InvocationTargetException;
       
    24 import java.net.MalformedURLException;
       
    25 import java.net.URL;
       
    26 import java.util.ArrayList;
       
    27 import java.util.Enumeration;
       
    28 import java.util.Iterator;
       
    29 
       
    30 import org.eclipse.core.resources.IFile;
       
    31 import org.eclipse.core.resources.IMarker;
       
    32 import org.eclipse.core.resources.IResourceChangeEvent;
       
    33 import org.eclipse.core.resources.IResourceChangeListener;
       
    34 import org.eclipse.core.resources.IResourceDelta;
       
    35 import org.eclipse.core.resources.IWorkspaceRoot;
       
    36 import org.eclipse.core.resources.ResourcesPlugin;
       
    37 import org.eclipse.core.runtime.CoreException;
       
    38 import org.eclipse.core.runtime.IPath;
       
    39 import org.eclipse.core.runtime.IProgressMonitor;
       
    40 import org.eclipse.core.runtime.Path;
       
    41 import org.eclipse.core.runtime.Platform;
       
    42 import org.eclipse.jface.action.Action;
       
    43 import org.eclipse.jface.action.IAction;
       
    44 import org.eclipse.jface.action.IMenuListener;
       
    45 import org.eclipse.jface.action.IMenuManager;
       
    46 import org.eclipse.jface.action.MenuManager;
       
    47 import org.eclipse.jface.action.Separator;
       
    48 import org.eclipse.jface.resource.ImageDescriptor;
       
    49 import org.eclipse.swt.SWT;
       
    50 import org.eclipse.swt.events.FocusAdapter;
       
    51 import org.eclipse.swt.events.FocusEvent;
       
    52 import org.eclipse.swt.graphics.Font;
       
    53 import org.eclipse.swt.layout.GridLayout;
       
    54 import org.eclipse.swt.widgets.Composite;
       
    55 import org.eclipse.swt.widgets.Display;
       
    56 import org.eclipse.swt.widgets.Event;
       
    57 import org.eclipse.swt.widgets.Label;
       
    58 import org.eclipse.swt.widgets.MessageBox;
       
    59 import org.eclipse.ui.IActionBars;
       
    60 import org.eclipse.ui.IEditorInput;
       
    61 import org.eclipse.ui.IEditorSite;
       
    62 import org.eclipse.ui.IFileEditorInput;
       
    63 import org.eclipse.ui.IPartListener;
       
    64 import org.eclipse.ui.IURIEditorInput;
       
    65 import org.eclipse.ui.IWorkbenchPart;
       
    66 import org.eclipse.ui.PartInitException;
       
    67 import org.eclipse.ui.dialogs.SaveAsDialog;
       
    68 import org.eclipse.ui.ide.IDE;
       
    69 import org.eclipse.ui.part.FileEditorInput;
       
    70 import org.eclipse.ui.part.MultiPageEditorPart;
       
    71 import org.osgi.framework.Bundle;
       
    72 
       
    73 import com.nokia.carbide.cpp.internal.featureTracker.FeatureUseTrackerConsts;
       
    74 import com.nokia.carbide.cpp.internal.pi.actions.TimeSetDialog;
       
    75 import com.nokia.carbide.cpp.internal.pi.analyser.AnalyserDataProcessor;
       
    76 import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
       
    77 import com.nokia.carbide.cpp.internal.pi.analyser.PIChangeEvent;
       
    78 import com.nokia.carbide.cpp.internal.pi.analyser.ProfileReader;
       
    79 import com.nokia.carbide.cpp.internal.pi.analyser.ProfileVisualiser;
       
    80 import com.nokia.carbide.cpp.internal.pi.interfaces.IToolBarActionListener;
       
    81 import com.nokia.carbide.cpp.internal.pi.manager.PluginInitialiser;
       
    82 import com.nokia.carbide.cpp.internal.pi.manager.PluginRegisterer;
       
    83 import com.nokia.carbide.cpp.internal.pi.model.GUITooltips;
       
    84 import com.nokia.carbide.cpp.internal.pi.model.TraceDataRepository;
       
    85 import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
       
    86 import com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener;
       
    87 import com.nokia.carbide.cpp.internal.pi.plugin.model.IFinalizeTrace;
       
    88 import com.nokia.carbide.cpp.pi.core.SessionPreferences;
       
    89 import com.nokia.carbide.cpp.pi.importer.SampleImporter;
       
    90 
       
    91 
       
    92 public class PIPageEditor extends MultiPageEditorPart implements IResourceChangeListener
       
    93 {
       
    94 	public static final String PI_ID = "com.nokia.carbide.cpp.pi"; //$NON-NLS-1$
       
    95 
       
    96 	// PI menu groups for adding plug-in specific actions/menu items
       
    97 	public static final String includeFilesGroup = "includeFile";	//$NON-NLS-1$
       
    98 	public static final String reportsGroup      = "reports";		//$NON-NLS-1$
       
    99 	public static final String viewOptionsGroup  = "viewOptions";	//$NON-NLS-1$
       
   100 	public static final String exportsGroup      = "exports";		//$NON-NLS-1$
       
   101 	public static final String additionsGroup    = "additions";		//$NON-NLS-1$
       
   102 	
       
   103 	// PI menu identifier
       
   104 	public static final String menuID = "com.nokia.carbide.cpp.pi.menuID"; //$NON-NLS-1$
       
   105 	
       
   106 	// indices of the three standard pages that have graphs
       
   107 	public static final int THREADS_PAGE   = 0;
       
   108 	public static final int BINARIES_PAGE  = 1;
       
   109 	public static final int FUNCTIONS_PAGE = 2;
       
   110 	public static final int NEXT_AVAILABLE_PAGE = -1;
       
   111 	
       
   112 	public static Font helvetica_8;
       
   113 	public static Font helvetica_9;
       
   114 	public static Font helvetica_10;
       
   115 	public static Font helvetica_12;
       
   116 	public static Font helvetica_14;
       
   117 	
       
   118 	// menu manager to which plugin's can add their actions
       
   119 	private static IMenuManager menuManager;
       
   120 	private static MenuManager currentManager;
       
   121 	private static MenuManager includeManager;
       
   122 
       
   123 	// info related to the current page editor and its pages
       
   124 	private static int          currentPageIndex;
       
   125 	private static PIPageEditor currentPageEditor;
       
   126 	private static int			currentUid;
       
   127 	
       
   128 	private static boolean openingFile = false; 
       
   129 	
       
   130 	private static boolean isCanceled = false;
       
   131 	private boolean isErrorPage = false;
       
   132 	
       
   133 	private static boolean startedPlugins = false;
       
   134 	
       
   135 	// actions available to all pages
       
   136 	
       
   137 	// toolbar actions for zooming
       
   138 	private static Action zoomInAction;
       
   139 	private static Action zoomOutAction;
       
   140 	private static Action zoomToSelectionAction;
       
   141 	private static Action zoomToTraceAction;
       
   142 	
       
   143 	// toolbar start and end times
       
   144 	private static Action selectTimeAction;
       
   145 	
       
   146 	// UID for this page
       
   147 	private int uid;
       
   148 
       
   149 	private double maxEndTime = Double.MAX_VALUE;
       
   150 	private double startTime = -1;
       
   151 	private double endTime   = -1;
       
   152 
       
   153 	private boolean tooltipsEnabled = true;
       
   154 	private int activePageIndex = -1;
       
   155 	
       
   156 	private static IActionBars actionBars;
       
   157 	
       
   158 	private boolean dirty = false;
       
   159 
       
   160 	private IPartListener partListener;
       
   161 
       
   162 	// full path name of the NPI file, so we can make all open copies of the file dirty
       
   163 	// or clean at the same time
       
   164 //	private String fullPath;
       
   165 
       
   166 	/**
       
   167 	 * Creates a multi-page editor.
       
   168 	 */
       
   169 	public PIPageEditor() {
       
   170 		super();
       
   171 		
       
   172 		// initialize the current page editor
       
   173 		setCurrentPageEditor(this);
       
   174 		ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
       
   175 	}
       
   176 	
       
   177 	protected static void createFonts(Display display) {
       
   178 		if (helvetica_8 == null) {
       
   179 			helvetica_8  = new Font(display, "Helvetica",  8, SWT.NORMAL); //$NON-NLS-1$
       
   180 			helvetica_9  = new Font(display, "Helvetica",  9, SWT.NORMAL); //$NON-NLS-1$
       
   181 			helvetica_10 = new Font(display, "Helvetica", 10, SWT.NORMAL); //$NON-NLS-1$
       
   182 			helvetica_12 = new Font(display, "Helvetica", 12, SWT.NORMAL); //$NON-NLS-1$
       
   183 			helvetica_14 = new Font(display, "Helvetica", 14, SWT.NORMAL); //$NON-NLS-1$
       
   184 		}
       
   185 	}
       
   186 	
       
   187 	protected void createBlankPage() {
       
   188 		Composite container = new Composite(getContainer(), SWT.NULL);
       
   189 		GridLayout layout = new GridLayout();
       
   190 		container.setLayout(layout);
       
   191 		layout.numColumns = 1;
       
   192 		layout.verticalSpacing = 9;
       
   193 		Label message = new Label(container, SWT.NONE);
       
   194 		//addPage(container);
       
   195 		setIsErrorPage(false);
       
   196 	}
       
   197 	
       
   198 	protected void createDummyErrorPage(String msg) {
       
   199 		Composite container = new Composite(getContainer(), SWT.NULL);
       
   200 		GridLayout layout = new GridLayout();
       
   201 		container.setLayout(layout);
       
   202 		layout.numColumns = 1;
       
   203 		layout.verticalSpacing = 9;
       
   204 		Label message = new Label(container, SWT.NONE);
       
   205 		message.setText(msg);
       
   206 		addPage(container);
       
   207 		setIsErrorPage(true);
       
   208 	}
       
   209 	
       
   210 	private void createErrorPageForException() {
       
   211 		IFileEditorInput editorInput = (IFileEditorInput)getEditorInput();
       
   212 		String message = Messages.getString("PIPageEditor.invalidPiFile") + editorInput.getName() + "\n" ; //$NON-NLS-1$ //$NON-NLS-2$
       
   213 		Throwable e = AnalyserDataProcessor.getInstance().getLastException();
       
   214 		if (e != null) {
       
   215 			if (e instanceof InvocationTargetException) {
       
   216 				if (e.getMessage() != null) {
       
   217 					message += e.getMessage() + "\n";	//$NON-NLS-1$
       
   218 				}
       
   219 				e = ((InvocationTargetException)e).getTargetException();
       
   220 			}
       
   221 			message += "\n" + Messages.getString("PIPageEditor.bugReport") + "\n\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
       
   222 			message += e.getClass().toString() + "\n"; //$NON-NLS-1$
       
   223 			if (e.getMessage() != null) {
       
   224 				message += e.getMessage() + "\n"; //$NON-NLS-1$
       
   225 			}
       
   226 			if (e.getStackTrace() != null) {
       
   227 				StackTraceElement [] wholeStack = e.getStackTrace();
       
   228 				for (StackTraceElement element: wholeStack) {
       
   229 					String className = element.getClassName();
       
   230 					if (className.toString().contains("fi.vtt.") || className.toString().contains("com.nokia.")) { //$NON-NLS-1$ //$NON-NLS-2$
       
   231 						message += Messages.getString("PIPageEditor.CarbideCPlusPlusSource") + element.getFileName() + ":" + element.getLineNumber() + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
       
   232 					}
       
   233 					else {
       
   234 						message += element.toString() + "\n"; //$NON-NLS-1$
       
   235 					}
       
   236 				}
       
   237 			}
       
   238 		}
       
   239 		createDummyErrorPage(message);
       
   240 
       
   241 	}
       
   242 
       
   243 	/**
       
   244 	 * Creates the pages of the multi-page editor.
       
   245 	 */
       
   246 	protected void createPages() {
       
   247 		IURIEditorInput editorInput = (IURIEditorInput)getEditorInput();
       
   248 		
       
   249 		// Kludge because of the way Eclipse opens files: disable ability of page.addFocusListener().focusGained() to change
       
   250 		// current editor and tab info
       
   251 		openingFile = true;
       
   252 
       
   253 		// make sure we can open an input stream to the trace file
       
   254 		
       
   255 		InputStream inputStream;
       
   256 		try {
       
   257 			inputStream = editorInput.getURI().toURL().openStream();
       
   258 			inputStream.read();
       
   259 			inputStream.close();
       
   260 		} catch (MalformedURLException e) {
       
   261 			System.out.println(Messages.getString("PIPageEditor.MalformedURL1") + editorInput.getURI().toString());  //$NON-NLS-1$
       
   262 			createDummyErrorPage(Messages.getString("PIPageEditor.MalformedURL2") + editorInput.getURI().toString());  //$NON-NLS-1$
       
   263 			openingFile = false;
       
   264 			return;
       
   265 			
       
   266 		} catch (IOException e) {
       
   267 			System.out.println(Messages.getString("PIPageEditor.cannotReadFile") + editorInput.getName()); //$NON-NLS-1$
       
   268 			// something is wrong, print a dummy page
       
   269 			createDummyErrorPage(Messages.getString("PIPageEditor.cannotReadFile") + editorInput.getName()); //$NON-NLS-1$
       
   270 			openingFile = false;
       
   271 			return;
       
   272 		}
       
   273 		
       
   274 		try {
       
   275 			if (SampleImporter.getInstance().isStrippingTimeStamp()) {	
       
   276 				uid = NpiInstanceRepository.getInstance().register(getContainer());
       
   277 				AnalyserDataProcessor.getInstance().importForStrippingTimeStamp(getContainer());
       
   278 				openingFile = false;
       
   279 				return;
       
   280 			}
       
   281 			
       
   282 			if (AnalyserDataProcessor.getInstance().getState() == AnalyserDataProcessor.STATE_IMPORTING) {
       
   283 				uid = NpiInstanceRepository.getInstance().activeUid();
       
   284 				NpiInstanceRepository.getInstance().setParentComposite(uid, getContainer());
       
   285 			} else {
       
   286 				// register this editor and ask repository to prepare per instance data
       
   287 				uid = NpiInstanceRepository.getInstance().register(getContainer());
       
   288 				NpiInstanceRepository.getInstance().switchActiveUid(uid);
       
   289 			}
       
   290 			AnalyserDataProcessor.getInstance().openNpiForPIPageEditor(editorInput.getURI(), getContainer(), uid);
       
   291 			
       
   292 			if (AnalyserDataProcessor.getInstance().getState() != AnalyserDataProcessor.STATE_OK) {
       
   293 				openingFile = false;
       
   294 				
       
   295 				// user may have canceled, print a dummy page
       
   296 				// if we deleted the importer file, then don't create a dummy page
       
   297 				if (AnalyserDataProcessor.getInstance().getState() == AnalyserDataProcessor.STATE_CANCELED) {
       
   298 					createDummyErrorPage(Messages.getString("PIPageEditor.userCancelled") + editorInput.getName()); //$NON-NLS-1$
       
   299 				} else {
       
   300 					createErrorPageForException();
       
   301 				}
       
   302 
       
   303 				return;
       
   304 			}
       
   305 		} catch (Exception ex) {
       
   306 			openingFile = false;
       
   307 					
       
   308 			// user may have canceled, print a dummy page
       
   309 			// if we deleted the importer file, then don't create a dummy page
       
   310 			if (AnalyserDataProcessor.getInstance().getState() == AnalyserDataProcessor.STATE_CANCELED) {
       
   311 				createDummyErrorPage(Messages.getString("PIPageEditor.userCancelled") + editorInput.getName()); //$NON-NLS-1$
       
   312 			} else {
       
   313 				createErrorPageForException();
       
   314 			}
       
   315 
       
   316 			return;	
       
   317 		}
       
   318 		
       
   319 		// add to the editor tab all pages create by AnalyseTab 
       
   320 	  	ArrayList<ProfileVisualiser> pages = NpiInstanceRepository.getInstance().activeUidGetProfilePages();
       
   321 	  	
       
   322 	  	int index = -1;
       
   323 	  	for (Iterator<ProfileVisualiser> i = pages.iterator();i.hasNext();) {
       
   324 	  		ProfileVisualiser myPv = i.next();
       
   325 	  		final Composite page = myPv.getContentPane();
       
   326 	  		
       
   327 	  		index = addPage(page);
       
   328 	  		setPageText(index, myPv.getPageName());
       
   329 	  		
       
   330 	  		// set the composite page's data to its page number
       
   331 	  		page.setData("pageIndex", new Integer(index)); //$NON-NLS-1$
       
   332 	  		page.setData("pageEditor", this); //$NON-NLS-1$
       
   333 	  		page.setData("pageUID", new Integer(uid)); //$NON-NLS-1$
       
   334 
       
   335 	  		page.addFocusListener(new FocusAdapter() {
       
   336 
       
   337 				public void focusGained(FocusEvent e) {
       
   338 					Object data;
       
   339 					int          nextPageIndex;
       
   340 					PIPageEditor nextPageEditor;
       
   341 					Integer			nextUIDInteger;
       
   342 					
       
   343 					data = page.getData("pageIndex"); //$NON-NLS-1$
       
   344 					if ((data != null) && (data instanceof Integer))
       
   345 						nextPageIndex = ((Integer) data).intValue();
       
   346 					else
       
   347 						nextPageIndex = -1;
       
   348 					
       
   349 					data = page.getData("pageEditor"); //$NON-NLS-1$
       
   350 					if ((data != null) && (data instanceof PIPageEditor))
       
   351 						nextPageEditor = (PIPageEditor) data;
       
   352 					else
       
   353 						nextPageEditor = null;
       
   354 					
       
   355 					data = page.getData("pageUID"); //$NON-NLS-1$
       
   356 					if ((data != null) && (data instanceof Integer))
       
   357 						nextUIDInteger = (Integer) data;
       
   358 					else
       
   359 						nextUIDInteger = null;
       
   360 					
       
   361 					// add the new tab's menu items
       
   362 					if ((nextUIDInteger != null) && (nextUIDInteger != NpiInstanceRepository.getInstance().activeUid())) {
       
   363 						/* Note: some items are tab-specific and some are page-specific
       
   364 						 *       (check for the current tab when they are called)
       
   365 						 */
       
   366 						addTabMenuItems(nextUIDInteger.intValue());
       
   367 					}
       
   368 					
       
   369 					// show the new page editor's start and end times
       
   370 					if ((nextPageEditor != null) && (nextPageEditor != currentPageEditor)) {
       
   371 						double start = nextPageEditor.getStartTime();
       
   372 						double end   = nextPageEditor.getEndTime();
       
   373 						PIPageEditor.setTime(start, end);
       
   374 					}
       
   375 
       
   376 					if (!PIPageEditor.isOpeningFile()) {
       
   377 						setCurrentPageIndex(nextPageIndex);
       
   378 						setCurrentPageEditor(nextPageEditor);
       
   379 						setCurrentUid(nextUIDInteger);
       
   380 					}
       
   381 				}
       
   382 	  		});
       
   383 	  	}
       
   384 	  	
       
   385 	  	if (!pages.isEmpty()) {
       
   386 	  		currentPageIndex = 0;
       
   387 	  		setActivePage(0);
       
   388 	  	} else {
       
   389 			new Composite(getContainer(), SWT.NONE);
       
   390 	  	}
       
   391 	  	currentPageEditor = this;
       
   392 		openingFile = false;
       
   393 	}
       
   394 
       
   395 	public static int currentPageIndex() {
       
   396 		return currentPageIndex;
       
   397 	}
       
   398 	
       
   399 	public static PIPageEditor currentPageEditor() {
       
   400 		return currentPageEditor;
       
   401 	}
       
   402 	
       
   403 	public static boolean isOpeningFile() {
       
   404 		return openingFile;
       
   405 	}
       
   406 	
       
   407 	public static MenuManager currentMenuManager() {
       
   408 		return currentManager;
       
   409 	}
       
   410 	
       
   411 	public static void startPlugins() {
       
   412 		startedPlugins = true;
       
   413 	}
       
   414 	
       
   415 	public static boolean arePluginsStarted() {
       
   416 		return startedPlugins;
       
   417 	}
       
   418 
       
   419 	// set the overall menu manager for PI
       
   420 	public static void setPIMenuManager(MenuManager piManager) {
       
   421 		if (piManager == null)
       
   422 			return;
       
   423 		
       
   424 		currentManager = piManager;
       
   425 		
       
   426 		// Force an update because Eclipse hides empty menus.
       
   427 		currentManager.addMenuListener(new IMenuListener() {
       
   428 			 public void menuAboutToShow(IMenuManager menuManager) {
       
   429 				 menuManager.updateAll(true);
       
   430 			 }
       
   431 		 });
       
   432 
       
   433 		initialiseMenuManager();
       
   434 	}
       
   435 
       
   436 	// start with a fresh overall menu manager, to which you add contribution items
       
   437 	public static void initialiseMenuManager() {
       
   438 		if (currentManager == null)
       
   439 			return;
       
   440 		
       
   441 		// This currentManager can only be modified in UI thread if the menu ever gets called by user
       
   442 		Display.getDefault().syncExec( new Runnable() {
       
   443 			public void run() {
       
   444 				currentManager.removeAll();
       
   445 				
       
   446 				/* 
       
   447 				 * A typical menu hierarchy might look like:
       
   448 				 * 
       
   449 				 * ... PI ...
       
   450 				 * 		Include Other Profile File ->
       
   451 				 * 		-----------------------------
       
   452 				 * 		Profile File Summary
       
   453 				 *		Profile File Report
       
   454 				 *		-----------------------------
       
   455 				 *		CPU Load Graph			   ->
       
   456 				 *		-----------------------------
       
   457 				 */
       
   458 				currentManager.add(new Separator(PIPageEditor.includeFilesGroup));
       
   459 				currentManager.add(new Separator(PIPageEditor.reportsGroup));
       
   460 				currentManager.add(new Separator(PIPageEditor.viewOptionsGroup));
       
   461 				currentManager.add(new Separator(PIPageEditor.exportsGroup));
       
   462 				currentManager.add(new Separator(PIPageEditor.additionsGroup));
       
   463 
       
   464 			}			
       
   465 		});
       
   466 	}
       
   467 
       
   468 	public static void addExportAction(IAction action) {
       
   469 		if (action == null)
       
   470 			return;
       
   471 		
       
   472 		currentManager.appendToGroup(PIPageEditor.exportsGroup, action);
       
   473 	}
       
   474 
       
   475 	public static void addIncludeAction(IAction action) {
       
   476 		if (action == null)
       
   477 			return;
       
   478 		
       
   479 		if (currentManager.find(menuID + Messages.getString("PIPageEditor.includeActionEnding")) == null) { //$NON-NLS-1$
       
   480 			includeManager = new MenuManager(Messages.getString("PIPageEditor.includeOtherFile"), menuID + Messages.getString("PIPageEditor.includeActionEnding")); //$NON-NLS-1$ //$NON-NLS-2$
       
   481 			currentManager.add(includeManager);
       
   482 		}
       
   483 			
       
   484 		includeManager.add(action);
       
   485 	}
       
   486 
       
   487 	public static void addReportAction(IAction action) {
       
   488 		if (action == null)
       
   489 			return;
       
   490 		
       
   491 		currentManager.appendToGroup(PIPageEditor.reportsGroup, action);
       
   492 	}
       
   493 
       
   494 	public static void addReportManager(IMenuManager menuManager) {
       
   495 		if (menuManager == null)
       
   496 			return;
       
   497 		
       
   498 		currentManager.appendToGroup(PIPageEditor.reportsGroup, menuManager);
       
   499 	}
       
   500 
       
   501 	public static void addViewOptionManager(IMenuManager menuManager) {
       
   502 		if (menuManager == null)
       
   503 			return;
       
   504 		
       
   505 		if (menuManager == currentManager)
       
   506 			return;
       
   507 		
       
   508 		currentManager.appendToGroup(PIPageEditor.viewOptionsGroup, menuManager);
       
   509 	}
       
   510 
       
   511 	/**
       
   512 	 * The <code>MultiPageEditorPart</code> implementation of this 
       
   513 	 * <code>IWorkbenchPart</code> method disposes all nested editors.
       
   514 	 * Subclasses may extend.
       
   515 	 */
       
   516 	public void dispose() {
       
   517 		getSite().getPage().removePartListener(partListener);
       
   518 		ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
       
   519 		ArrayList<AbstractPiPlugin> plugins = NpiInstanceRepository.getInstance().getPlugins(uid);
       
   520 		for (AbstractPiPlugin plugin : plugins) {
       
   521 			if (plugin instanceof IFinalizeTrace) {
       
   522 				((IFinalizeTrace)plugin).runOnDispose();
       
   523 			}
       
   524 		}
       
   525 
       
   526 		NpiInstanceRepository.getInstance().unregister(uid);
       
   527 		if (NpiInstanceRepository.getInstance().size() == 0) {
       
   528 			// free up the current file's items
       
   529 			setCurrentPageEditor(null);
       
   530 			setCurrentUid(0);
       
   531 			if (NpiInstanceRepository.getInstance().activeUid() == uid) {
       
   532 				NpiInstanceRepository.getInstance().switchActiveUid(NpiInstanceRepository.DISPOSED_UID);
       
   533 			}
       
   534 			TraceDataRepository.getInstance().removeAll();
       
   535 			PluginInitialiser.removeAllTraceInstances();
       
   536 
       
   537 			// stop using the feature
       
   538 			com.nokia.carbide.cpp.internal.featureTracker.FeatureUseTrackerPlugin.getFeatureUseProxy().stopUsingFeature(FeatureUseTrackerConsts.CARBIDE_PROFILER);
       
   539 		}
       
   540 		super.dispose();
       
   541 		System.gc();
       
   542 	}
       
   543 
       
   544 	/**
       
   545 	 * Saves the multi-page editor's document.
       
   546 	 */
       
   547 	public void doSave(IProgressMonitor monitor) {
       
   548 		final IFileEditorInput newInput= new FileEditorInput(((IFileEditorInput)getEditorInput()).getFile());
       
   549 		saveDocument(newInput);
       
   550 	}
       
   551 	
       
   552 	/**
       
   553 	 * Saves the multi-page editor's document as another file.
       
   554 	 * Also updates the text for page 0's tab, and updates this multi-page editor's input
       
   555 	 * to correspond to the nested editor's.
       
   556 	 */
       
   557 	public void doSaveAs() {
       
   558 		SaveAsDialog dialog = new SaveAsDialog(getSite().getShell());
       
   559 		
       
   560 		dialog.open();
       
   561 		IPath filePath = dialog.getResult();
       
   562 		
       
   563 		if (filePath == null)
       
   564 			return;
       
   565 		if (filePath.getFileExtension() == null || filePath.getFileExtension().equals("npi") == false) { //$NON-NLS-1$
       
   566 			MessageBox errorMessage = new MessageBox(getSite().getShell(), SWT.PRIMARY_MODAL | SWT.ICON_ERROR);
       
   567 			errorMessage.setText(Messages.getString("PIPageEditor.error")); //$NON-NLS-1$
       
   568 			errorMessage.setMessage(Messages.getString("PIPageEditor.mustBeNpi")); //$NON-NLS-1$
       
   569 			errorMessage.open();
       
   570 			return;
       
   571 		}
       
   572 		
       
   573 		IWorkspaceRoot workspaceRoot= ResourcesPlugin.getWorkspace().getRoot();
       
   574 		IFile file= workspaceRoot.getFile(filePath);
       
   575 		final IFileEditorInput newInput= new FileEditorInput(file);
       
   576 
       
   577 		saveDocument(newInput);
       
   578 		
       
   579 		dialog.close();
       
   580 	}
       
   581 	
       
   582 	public boolean isSaveAsAllowed() {
       
   583 		return true;
       
   584 	}
       
   585 	
       
   586 	public boolean isDirty() {
       
   587 		return dirty;
       
   588 	}
       
   589 	
       
   590 	public boolean isSaveOnCloseNeeded() {
       
   591 		return true;
       
   592 	}
       
   593 	
       
   594 	public void setDirty() {
       
   595 		dirty = true;
       
   596 		this.firePropertyChange(PROP_DIRTY);
       
   597 		
       
   598 //		for (int i = 0; i < pageEditorList.size(); i++) {
       
   599 //			if (   (pageEditorList.get(i) != this)
       
   600 //				&& (pageEditorList.get(i).getFullPath().equals(this.getFullPath())))
       
   601 //				pageEditorList.get(i).setDirtyOnce();
       
   602 //		}
       
   603 	}
       
   604 	
       
   605 	public void setDirtyOnce() {
       
   606 		dirty = true;
       
   607 		this.firePropertyChange(PROP_DIRTY);
       
   608 	}
       
   609 
       
   610 	public void resetDirty() {
       
   611 		dirty = false;
       
   612 		this.firePropertyChange(PROP_DIRTY);
       
   613 		
       
   614 //		for (int i = 0; i < pageEditorList.size(); i++) {
       
   615 //			if (   (pageEditorList.get(i) != this)
       
   616 //				&& (pageEditorList.get(i).getFullPath().equals(this.getFullPath())))
       
   617 //				pageEditorList.get(i).resetDirtyOnce();
       
   618 //		}
       
   619 	}
       
   620 
       
   621 	public void resetDirtyOnce() {
       
   622 		dirty = false;
       
   623 		this.firePropertyChange(PROP_DIRTY);
       
   624 	}
       
   625 	
       
   626 	// Try to get close to saveDocument in IDocumentProvider in case we do rewrite
       
   627 	// see JDT CompilationUnitEditor.java for reference
       
   628 	public void saveDocument(IFileEditorInput newInput) {
       
   629 		// this block would be getDocumentProvider().saveDocument() in rewrite
       
   630 		IFile newFile = newInput.getFile();
       
   631 //		IFile oldFile = ((IFileEditorInput)getEditorInput()).getFile();
       
   632 		
       
   633 		
       
   634 		try {
       
   635 			// the Dialog already asked the user if they want to overwrite
       
   636 			// grant them the wish and remove the file
       
   637 			if(!newFile.exists()) {
       
   638 				newFile.create(new ByteArrayInputStream("".getBytes()), false, null);	//$NON-NLS-1$
       
   639 				newFile.refreshLocal(0, null);
       
   640 			}
       
   641 			AnalyserDataProcessor.getInstance().saveAnalysis(newFile.getLocation().toString(), uid);			
       
   642 			newFile.refreshLocal(0, null);
       
   643 			setInput(newInput);
       
   644 			setPartName(newInput.getName());
       
   645 			resetDirty();
       
   646 		} catch (CoreException e) {
       
   647 			e.printStackTrace();
       
   648 		} catch (Exception e) {
       
   649 			e.printStackTrace();
       
   650 		}	
       
   651 	}
       
   652 	
       
   653 	public void gotoMarker(IMarker marker) {
       
   654 		setActivePage(0);
       
   655 		IDE.gotoMarker(getEditor(0), marker);
       
   656 	}
       
   657 	
       
   658 	/**
       
   659 	 * The <code>MultiPageEditorExample</code> implementation of this method
       
   660 	 * checks that the input is an instance of <code>IFileEditorInput</code>.
       
   661 	 */
       
   662 	public void init(IEditorSite site, IEditorInput editorInput)
       
   663 		throws PartInitException {
       
   664 		if (!(editorInput instanceof IURIEditorInput))
       
   665 			throw new PartInitException(Messages.getString("PIPageEditor.mustBeIURIEditorInput")); //$NON-NLS-1$
       
   666 
       
   667 		// store the full path
       
   668 //		this.fullPath = ((FileEditorInput)editorInput).getPath().toFile().getAbsolutePath();
       
   669 
       
   670 		super.init(site, editorInput);
       
   671 
       
   672 		// now the site is initialized, so start using the feature
       
   673 		com.nokia.carbide.cpp.internal.featureTracker.FeatureUseTrackerPlugin.getFeatureUseProxy().startUsingFeature(FeatureUseTrackerConsts.CARBIDE_PROFILER);
       
   674 
       
   675 		// allocate a few fonts
       
   676 		createFonts(getEditorSite().getShell().getDisplay());
       
   677 		site.getPage().addPartListener(partListener = new IPartListener(){
       
   678 			
       
   679 			private void setMenus(IWorkbenchPart part) {
       
   680 				if (!(part instanceof PIPageEditor) || isErrorPage)
       
   681 					return;
       
   682 				
       
   683 				PIPageEditor editor = (PIPageEditor) part;
       
   684 				currentPageEditor.setActiveActions(false);
       
   685 				currentPageEditor = editor;
       
   686 				
       
   687 				setTime(editor.getStartTime(),editor.getEndTime());
       
   688 				NpiInstanceRepository.getInstance().switchActiveUid(currentPageEditor().uid);
       
   689 				addTabMenuItems(currentPageEditor().uid);
       
   690 				currentPageEditor.setActiveActions(true);
       
   691 			}
       
   692 
       
   693 			public void partActivated(IWorkbenchPart part) {
       
   694 				setMenus(part);
       
   695 			}
       
   696 
       
   697 			public void partBroughtToTop(IWorkbenchPart part) {
       
   698 				setMenus(part);
       
   699 			}
       
   700 
       
   701 			public void partClosed(IWorkbenchPart part) {
       
   702 			}
       
   703 
       
   704 			public void partDeactivated(IWorkbenchPart part) {
       
   705 			}
       
   706 
       
   707 			public void partOpened(IWorkbenchPart part) {
       
   708 			}
       
   709 		});
       
   710 
       
   711 		setSite(site);
       
   712 		setInput(editorInput);
       
   713 		this.setPartName(editorInput.getName());
       
   714 
       
   715 		// set up registry of PI plugins
       
   716 		PluginRegisterer.registerAllPlugins();
       
   717 	}
       
   718 	
       
   719 //	public String getFullPath() {
       
   720 //		return this.fullPath;
       
   721 //	}
       
   722 
       
   723 	public static void setTime(double start, double end) {
       
   724 		// set the visible time
       
   725 //		PIPageEditorContributor.getTimeSet().setTime(start, end);
       
   726 
       
   727 		// set the local copy of the time
       
   728 		if (currentPageEditor != null)
       
   729 			currentPageEditor.setLocalTime(start, end);
       
   730 	}
       
   731 
       
   732 	public void setLocalTime(double start, double end) {
       
   733 		this.startTime = start;
       
   734 		this.endTime   = end;
       
   735 	}
       
   736 
       
   737 	protected void setLocalStartTime(double start) {
       
   738 		this.startTime = start;
       
   739 	}
       
   740 
       
   741 	protected void setLocalEndTime(double end) {
       
   742 		this.endTime   = end;
       
   743 	}
       
   744 	
       
   745 	public void setMaxEndTime(double maxEndTime) {
       
   746 		this.maxEndTime = maxEndTime;
       
   747 	}
       
   748 
       
   749 	public double getStartTime() {
       
   750 		return startTime;
       
   751 	}
       
   752 
       
   753 	public double getEndTime() {
       
   754 		return endTime;
       
   755 	}
       
   756 
       
   757 	public double getMaxEndTime() {
       
   758 		return maxEndTime;
       
   759 	}
       
   760 	
       
   761 	public static void createActions() {
       
   762 		URL url;
       
   763 		ImageDescriptor createFromURL;
       
   764 		
       
   765 		Bundle piBundle = Platform.getBundle("com.nokia.carbide.cpp.pi"); //$NON-NLS-1$
       
   766 		if (piBundle == null)
       
   767 			return;
       
   768 		
       
   769 		zoomInAction = new Action(Messages.getString("PIPageEditor.zoomIn")) { //$NON-NLS-1$
       
   770 			public void run() {
       
   771 				PIChangeEvent.action("-"); //$NON-NLS-1$
       
   772 			}
       
   773 		};
       
   774 		zoomInAction.setToolTipText(Messages.getString("PIPageEditor.zoomIn")); //$NON-NLS-1$
       
   775 		url = Platform.find(piBundle, new Path(Messages.getString("PIPageEditorContributor.zoomInIcon"))); //$NON-NLS-1$
       
   776 		if (url != null) {
       
   777 			createFromURL = ImageDescriptor.createFromURL(url);
       
   778 			zoomInAction.setImageDescriptor(createFromURL);
       
   779 		}
       
   780 
       
   781 		zoomOutAction = new Action(Messages.getString("PIPageEditor.zoomOut")) { //$NON-NLS-1$
       
   782 			public void run() {
       
   783 				PIChangeEvent.action("+"); //$NON-NLS-1$
       
   784 			}
       
   785 		};
       
   786 		zoomOutAction.setToolTipText(Messages.getString("PIPageEditor.zoomOut"));  //$NON-NLS-1$
       
   787 		url = Platform.find(piBundle, new Path(Messages.getString("PIPageEditor.PIPageEditorContributor.zoomOutIcon"))); //$NON-NLS-1$
       
   788 		if (url != null) {
       
   789 			createFromURL = ImageDescriptor.createFromURL(url);
       
   790 			zoomOutAction.setImageDescriptor(createFromURL);
       
   791 		}
       
   792 
       
   793 		zoomToTraceAction = new Action(Messages.getString("PIPageEditor.showEntireGraph")) { //$NON-NLS-1$
       
   794 			public void run() {
       
   795 				PIChangeEvent.action("++"); //$NON-NLS-1$
       
   796 			}
       
   797 		};
       
   798 		zoomToTraceAction.setToolTipText(Messages.getString("PIPageEditor.showEntireGraph"));  //$NON-NLS-1$
       
   799 		url = Platform.find(piBundle, new Path(Messages.getString("PIPageEditor.PIPageEditorContributor.showEntireGraphIcon"))); //$NON-NLS-1$
       
   800 		if (url != null) {
       
   801 			createFromURL = ImageDescriptor.createFromURL(url);
       
   802 			zoomToTraceAction.setImageDescriptor(createFromURL);
       
   803 		}
       
   804 
       
   805 		zoomToSelectionAction = new Action(Messages.getString("PIPageEditor.zoomToInterval")) { //$NON-NLS-1$
       
   806 			public void run() {
       
   807 				PIChangeEvent.action("--"); //$NON-NLS-1$
       
   808 			}
       
   809 		};
       
   810 		zoomToSelectionAction.setToolTipText(Messages.getString("PIPageEditor.zoomToInterval"));  //$NON-NLS-1$
       
   811 		url = Platform.find(piBundle, new Path(Messages.getString("PIPageEditor.PIPageEditorContributor.ZoomToIntervalIcon"))); //$NON-NLS-1$
       
   812 		if (url != null) {
       
   813 			createFromURL = ImageDescriptor.createFromURL(url);
       
   814 			zoomToSelectionAction.setImageDescriptor(createFromURL);
       
   815 		}
       
   816 
       
   817 		selectTimeAction = new Action(Messages.getString("PIPageEditor.selectInterval")) { //$NON-NLS-1$
       
   818 			public void run() {
       
   819 				// remember the old time interval
       
   820 				double startTime = PIPageEditor.currentPageEditor().getStartTime();
       
   821 				double endTime   = PIPageEditor.currentPageEditor().getEndTime();
       
   822 				
       
   823 				// get the new time interval
       
   824 				new TimeSetDialog(
       
   825 						PIPageEditor.currentPageEditor.getSite().getShell().getDisplay(),
       
   826 						startTime, endTime);
       
   827 				
       
   828 				if (   (startTime == PIPageEditor.currentPageEditor().getStartTime())
       
   829 					&& (endTime   == PIPageEditor.currentPageEditor().getEndTime()))
       
   830 					return;
       
   831 				
       
   832 				// propagate the new time interval
       
   833 				PIChangeEvent.action("changeInterval"); //$NON-NLS-1$
       
   834 				
       
   835 				// after the graphs have been updated, notify plugins that might have tables but no graphs
       
   836         		Enumeration enu = PluginInitialiser.getPluginInstances(
       
   837         									"com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener"); //$NON-NLS-1$
       
   838         		if (enu != null) {
       
   839         			Event event = new Event();
       
   840         			Double[] times = new Double[2];
       
   841            			times[0] = PIPageEditor.currentPageEditor().getStartTime();
       
   842            			times[1] = PIPageEditor.currentPageEditor().getEndTime();
       
   843            			event.data = times;
       
   844         			
       
   845             		while (enu.hasMoreElements())
       
   846             		{
       
   847             			IEventListener plugin = (IEventListener)enu.nextElement();
       
   848             			plugin.receiveEvent("changeInterval", event); //$NON-NLS-1$
       
   849             		}
       
   850         		}
       
   851 			}
       
   852 		};
       
   853 		selectTimeAction.setToolTipText(Messages.getString("PIPageEditor.selectInterval"));  //$NON-NLS-1$
       
   854 		url = Platform.find(piBundle, new Path(Messages.getString("PIPageEditor.PIPageEditorContributor.selectIntervalIcon"))); //$NON-NLS-1$
       
   855 		if (url != null) {
       
   856 			createFromURL = ImageDescriptor.createFromURL(url);
       
   857 			selectTimeAction.setImageDescriptor(createFromURL);
       
   858 		}
       
   859 	}
       
   860 
       
   861 	
       
   862 	public static Action getZoomInAction() {
       
   863 		return zoomInAction;
       
   864 	}
       
   865 	
       
   866 	public static Action getZoomOutAction() {
       
   867 		return zoomOutAction;
       
   868 	}
       
   869 	
       
   870 	public static Action getZoomToSelectionAction() {
       
   871 		return zoomToSelectionAction;
       
   872 	}
       
   873 	
       
   874 	public static Action getZoomToTraceAction() {
       
   875 		return zoomToTraceAction;
       
   876 	}
       
   877 
       
   878 	public static Action getSelectTimeAction() {
       
   879 		return selectTimeAction;
       
   880 	}
       
   881 
       
   882 	/**
       
   883 	 * Closes all project files on project close.
       
   884 	 */
       
   885 	public void resourceChanged(final IResourceChangeEvent event){
       
   886 		IResourceDelta delta = event.getDelta();
       
   887 
       
   888 		if (delta == null)
       
   889 			return;
       
   890 
       
   891 		if (delta.getKind() == IResourceDelta.CHANGED) {
       
   892 			IPath editorPath = ((IFileEditorInput)getEditorInput()).getFile().getFullPath();
       
   893 			// see if current change event is relevant to this Editor
       
   894 			delta = delta.findMember(editorPath);
       
   895 			if (delta != null) {
       
   896 				int deltaKind = delta.getKind();
       
   897 				switch(deltaKind) {
       
   898 				case IResourceDelta.REMOVED:
       
   899 				case IResourceDelta.REMOVED_PHANTOM:
       
   900 					Display.getDefault().syncExec(new Runnable() {
       
   901 						public void run() {
       
   902 								PIPageEditor.this.getSite().getPage().closeEditor(PIPageEditor.this, false);
       
   903 						}
       
   904 					});
       
   905 					break;
       
   906 				}
       
   907 			}
       
   908 		}
       
   909 	}
       
   910 	
       
   911 	protected void pageChange(int newPageIndex) {
       
   912 		// on a page change, set the current page's leaving actions and the new pages' entering action
       
   913 		if (this.activePageIndex != -1)
       
   914 			setActions(false, this.activePageIndex);
       
   915 		super.pageChange(newPageIndex);
       
   916 		setCurrentPageIndex(newPageIndex);
       
   917 		setActions(true, newPageIndex);
       
   918 		this.activePageIndex = newPageIndex;
       
   919 	}
       
   920 	
       
   921 	// set the actions on entering or leaving the current page
       
   922 	public void setActiveActions(boolean entering) {
       
   923 		if (this.activePageIndex != -1)
       
   924 			setActions(entering, this.activePageIndex);
       
   925 	}
       
   926 	
       
   927 	private void setActions(boolean entering, int pageIndex) {
       
   928 		Enumeration enu;
       
   929 		AbstractPiPlugin plugin;
       
   930 
       
   931 		enu = PluginInitialiser.getPluginInstances(uid, "com.nokia.carbide.cpp.internal.pi.interfaces.IToolBarActionListener"); //$NON-NLS-1$
       
   932 		while (enu.hasMoreElements())
       
   933 		{
       
   934 			// can only set actions if the plugin is associated with this tab
       
   935 			plugin = (AbstractPiPlugin)enu.nextElement();
       
   936 			if (   (plugin instanceof IToolBarActionListener)
       
   937 				&& (NpiInstanceRepository.getInstance().getPlugins(uid) != null)
       
   938 				&& (NpiInstanceRepository.getInstance().getPlugins(uid).indexOf(plugin) >= 0)) {
       
   939 				((IToolBarActionListener)plugin).setActions(entering, pageIndex);
       
   940 			}
       
   941 		}
       
   942 	}
       
   943 	
       
   944 	public int getCurrentPage() {
       
   945 		return getActivePage();
       
   946 	}
       
   947 	
       
   948 	// whether tooltips are enabled for this file
       
   949 	public boolean getTooltipsEnabled() {
       
   950 		return this.tooltipsEnabled;
       
   951 	}
       
   952 	
       
   953 	public void setTooltipsEnabled(boolean tooltipsEnabled) {
       
   954 		SessionPreferences.getInstance().setToolTipsEnabled(tooltipsEnabled);
       
   955     	GUITooltips.setTooltipsOn(tooltipsEnabled);
       
   956 		this.tooltipsEnabled = tooltipsEnabled;
       
   957 	}
       
   958 	
       
   959 	// menu bar changes let tables and graphs change IDE menu items when focus changes
       
   960 	public static void setMenuManager(IMenuManager menuManager) {
       
   961 		PIPageEditor.menuManager = menuManager;
       
   962 	}
       
   963 	
       
   964 	public static IMenuManager getMenuManager() {
       
   965 		return PIPageEditor.menuManager;
       
   966 	}
       
   967 	
       
   968 	// action bar changes let tables and graphs change IDE menu items when focus changes
       
   969 	public static void setActionBars(IActionBars actionBars) {
       
   970 		PIPageEditor.actionBars = actionBars;
       
   971 	}
       
   972 	
       
   973 	public static IActionBars getActionBars() {
       
   974 		return PIPageEditor.actionBars;
       
   975 	}
       
   976 
       
   977 	private static void setCurrentPageIndex(int pageIndex)
       
   978 	{
       
   979 		currentPageIndex = pageIndex;
       
   980 	}
       
   981 
       
   982 	private static void setCurrentPageEditor(PIPageEditor pageEditor)
       
   983 	{
       
   984 		currentPageEditor = pageEditor;
       
   985 	}
       
   986 	
       
   987 	private static void setCurrentUid(int uid)
       
   988 	{
       
   989 		currentUid = uid;
       
   990 	}
       
   991 
       
   992 	private void setIsErrorPage(boolean isIt)
       
   993 	{
       
   994 		isErrorPage = isIt;
       
   995 	}
       
   996 	
       
   997 	private static void addTabMenuItems(int uid) {
       
   998 		ProfileReader.getInstance().setTraceMenus(NpiInstanceRepository.getInstance().getPlugins(uid), uid);
       
   999 	}
       
  1000 }