|
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 } |