sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/BupTraceGraph.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.button;
       
    19 
       
    20 import java.util.ArrayList;
       
    21 import java.util.Enumeration;
       
    22 import java.util.Vector;
       
    23 
       
    24 import org.eclipse.draw2d.ColorConstants;
       
    25 import org.eclipse.draw2d.FigureCanvas;
       
    26 import org.eclipse.draw2d.Graphics;
       
    27 import org.eclipse.draw2d.Panel;
       
    28 import org.eclipse.swt.SWT;
       
    29 import org.eclipse.swt.events.MouseEvent;
       
    30 import org.eclipse.swt.events.MouseListener;
       
    31 import org.eclipse.swt.events.MouseMoveListener;
       
    32 import org.eclipse.swt.events.SelectionAdapter;
       
    33 import org.eclipse.swt.events.SelectionEvent;
       
    34 import org.eclipse.swt.events.SelectionListener;
       
    35 import org.eclipse.swt.graphics.GC;
       
    36 import org.eclipse.swt.graphics.Point;
       
    37 import org.eclipse.swt.layout.GridData;
       
    38 import org.eclipse.swt.layout.GridLayout;
       
    39 import org.eclipse.swt.widgets.Button;
       
    40 import org.eclipse.swt.widgets.Display;
       
    41 import org.eclipse.swt.widgets.Label;
       
    42 import org.eclipse.swt.widgets.Menu;
       
    43 import org.eclipse.swt.widgets.MenuItem;
       
    44 import org.eclipse.swt.widgets.Shell;
       
    45 
       
    46 import com.nokia.carbide.cpp.internal.pi.actions.SaveSamples;
       
    47 import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
       
    48 import com.nokia.carbide.cpp.internal.pi.interfaces.ISaveSamples;
       
    49 import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTrace;
       
    50 import com.nokia.carbide.cpp.internal.pi.plugin.model.IContextMenu;
       
    51 import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
       
    52 import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
       
    53 
       
    54 
       
    55 public class BupTraceGraph extends GenericTraceGraph implements MouseMoveListener,
       
    56 																MouseListener,
       
    57 																IContextMenu
       
    58 {
       
    59 	/*
       
    60 	 * Draw button text in existing Address plugin panel
       
    61 	 *
       
    62 	 * For each button press, draw a line from the top to below the thread/binary/function start and end
       
    63 	 * indicators, but above the x-axis label that tells seconds
       
    64 	 */
       
    65 	
       
    66 	// whether to display events
       
    67 	private boolean display_events = true;
       
    68 
       
    69 	// constants used in drawing event: line coming down with a rectangle at the end and a name underneath
       
    70 	private static final int EVENT_TOPOFLINE    = 50;
       
    71 	private static final int EVENT_BOTTOMOFLINE = 30;
       
    72 	private static final int EVENT_RECTWIDTH    = 5;
       
    73 	private static final int EVENT_RECTHEIGHT   = 5;
       
    74 
       
    75 	private ArrayList<BupSample> matchingSamples;
       
    76 	private Button eventButtons[];
       
    77 	private boolean selectedEventButtons;
       
    78 	
       
    79 	// class to pass sample data to the save wizard
       
    80     public class SaveSampleString implements ISaveSamples {
       
    81     	boolean done = false;
       
    82     	
       
    83     	public SaveSampleString() {
       
    84 		}
       
    85 
       
    86     	public String getData() {
       
    87     		if (done)
       
    88     			return null;
       
    89     		
       
    90 			String returnString = getSampleString();
       
    91 			done = true;
       
    92 			return returnString;
       
    93 		}
       
    94 
       
    95 		public String getData(int size) {
       
    96  			return getData();
       
    97 		}
       
    98 
       
    99 		public int getIndex() {
       
   100 			return done ? 1 : 0;
       
   101 		}
       
   102 
       
   103 		public void clear() {
       
   104 			done = false;
       
   105 		}
       
   106    }
       
   107 
       
   108 	/*
       
   109 	 * return the button samples selected in the interval 
       
   110 	 */
       
   111 	protected String getSampleString()
       
   112 	{
       
   113 		int startTime = (int) this.getSelectionStart();
       
   114 		int endTime   = (int) this.getSelectionEnd();
       
   115 		
       
   116 		Vector sampleVector = ((GenericSampledTrace) this.getTrace()).samples;
       
   117 		
       
   118 		int i = 0;
       
   119 		while (i < sampleVector.size() && ((BupSample) sampleVector.get(i)).sampleSynchTime < startTime)
       
   120 			i++;
       
   121 	
       
   122 		String returnString = Messages.getString("BupTraceGraph.saveSamplesHeading"); //$NON-NLS-1$
       
   123 
       
   124 		while (i < sampleVector.size() && ((BupSample) sampleVector.get(i)).sampleSynchTime <= endTime) {
       
   125 			BupSample sample = (BupSample) sampleVector.get(i);
       
   126 			returnString += sample.sampleSynchTime + "," + sample.getLabel() + ",\""; //$NON-NLS-1$ //$NON-NLS-2$
       
   127 
       
   128 			String comment = sample.getComment();
       
   129 			if (comment != null) {
       
   130 				for (int j = 0; j < comment.length(); j++) {
       
   131 					if (comment.charAt(j) == '"')
       
   132 						returnString += '"';
       
   133 					returnString += comment.charAt(j);
       
   134 				}
       
   135 			}
       
   136 			returnString += "\"\n"; //$NON-NLS-1$
       
   137 			i++;
       
   138 		}
       
   139 
       
   140 		return returnString;
       
   141 	}
       
   142 
       
   143 	protected void actionSaveSamples(ISaveSamples saveSamples)
       
   144 	{
       
   145 		new SaveSamples(saveSamples);
       
   146 	}
       
   147 
       
   148 	protected MenuItem getSaveSamplesItem(Menu menu, boolean enabled) {
       
   149 	    MenuItem saveSamplesItem = new MenuItem(menu, SWT.PUSH);
       
   150 
       
   151 		saveSamplesItem.setText(Messages.getString("BupTraceGraph.saveSamplesForInterval")); //$NON-NLS-1$
       
   152 		saveSamplesItem.setEnabled(enabled);
       
   153 		
       
   154 		if (enabled) {
       
   155 			saveSamplesItem.addSelectionListener(new SelectionAdapter() { 
       
   156 				public void widgetSelected(SelectionEvent e) {
       
   157 					saveEventSamples();
       
   158 				}
       
   159 			});
       
   160 		}
       
   161 	
       
   162 		return saveSamplesItem;
       
   163 	}
       
   164 
       
   165 	public BupTraceGraph(int graphIndex, BupTrace trace)
       
   166 	{
       
   167 		super(trace);
       
   168 		this.graphIndex = graphIndex;
       
   169 	}
       
   170 
       
   171 	public void paint(Panel panel, Graphics graphics)
       
   172 	{
       
   173 		if (!display_events)
       
   174 			return;
       
   175 
       
   176 		Enumeration samples = ((GenericSampledTrace)this.getTrace()).samples.elements();
       
   177 		graphics.setForegroundColor(ColorConstants.red);
       
   178 		double scale = this.getScale();
       
   179 		int height = this.getVisualSize().height;
       
   180 		String eventName;
       
   181 
       
   182 		while (samples.hasMoreElements())
       
   183 		{
       
   184 			BupSample sa = (BupSample)samples.nextElement();
       
   185 			int x = (int)(sa.sampleSynchTime/scale);
       
   186 
       
   187 			graphics.setForegroundColor(ColorConstants.red);
       
   188 			graphics.drawLine(x, height - EVENT_TOPOFLINE, x, height - EVENT_BOTTOMOFLINE);
       
   189 
       
   190 			// center the text under vertical line
       
   191 			eventName = sa.getLabel();
       
   192 
       
   193 			graphics.setFont(PIPageEditor.helvetica_8);
       
   194 
       
   195 			GC gc = new GC(PIPageEditor.currentPageEditor().getSite().getShell());
       
   196 			Point point = gc.stringExtent(eventName);
       
   197 			gc.dispose();
       
   198 
       
   199 			if (sa.isLabelModified()) {
       
   200 				graphics.setForegroundColor(ColorConstants.blue);
       
   201 			} else {
       
   202 				graphics.setForegroundColor(ColorConstants.red);
       
   203 			}
       
   204 			graphics.drawString(eventName, x - (point.x / 2), height - EVENT_BOTTOMOFLINE + 3 + EVENT_RECTHEIGHT);
       
   205 
       
   206 			// events with comments will have blue rectangles; otherwise, red triangles
       
   207 			if ((sa.getComment() != null) && (!sa.getComment().equals(""))) //$NON-NLS-1$
       
   208 			{
       
   209 				graphics.setForegroundColor(ColorConstants.blue);
       
   210 				graphics.setBackgroundColor(ColorConstants.blue);
       
   211 			}
       
   212 			else
       
   213 			{
       
   214 				graphics.setBackgroundColor(ColorConstants.red);
       
   215 			}
       
   216 			graphics.drawLine(x , height - EVENT_BOTTOMOFLINE + 1, x, height - EVENT_BOTTOMOFLINE + 2);
       
   217 			graphics.fillRectangle(x - (EVENT_RECTWIDTH / 2), height - EVENT_BOTTOMOFLINE + 3,
       
   218 									EVENT_RECTWIDTH, EVENT_RECTHEIGHT);
       
   219 		}
       
   220 	}
       
   221 
       
   222 	public void repaint()
       
   223 	{
       
   224 	}
       
   225 
       
   226 	public void refreshDataFromTrace()
       
   227 	{
       
   228 	}
       
   229 
       
   230 	public void action(String action)
       
   231 	{
       
   232 		// do/don't show events in graph
       
   233 		if (   action.equals("button_events_on") //$NON-NLS-1$
       
   234 			|| action.equals("button_events_off")) //$NON-NLS-1$
       
   235   		{
       
   236   			this.display_events = action.equals(Messages.getString("BupTraceGraph.button.events.on")); //$NON-NLS-1$
       
   237   			this.parentComponent.repaintComponent();
       
   238   		} else if (action.equals("button_map_switch")){ //$NON-NLS-1$
       
   239   			this.parentComponent.repaintComponent();
       
   240   		}
       
   241   	}
       
   242 
       
   243 	public void mouseMove(MouseEvent me)
       
   244 //	public void mouseHover(MouseEvent me)
       
   245 	{
       
   246 		if (!display_events)
       
   247 			return;
       
   248 
       
   249 		long x = me.x;
       
   250 		long y = me.y;
       
   251 
       
   252 		int height = this.getVisualSize().height;
       
   253 
       
   254 		// make sure we're in the right area of the graph window
       
   255 		if ((y < height - EVENT_BOTTOMOFLINE) || (y > height - EVENT_BOTTOMOFLINE + EVENT_RECTHEIGHT + 2))
       
   256 			return;
       
   257 
       
   258 		Enumeration samples = ((GenericSampledTrace) this.getTrace()).samples.elements();
       
   259 		double scale = this.getScale();
       
   260 		
       
   261 //		x += ((FigureCanvas)me.getSource()).getViewport().getViewLocation().x;
       
   262 
       
   263 		String tooltip = ""; //$NON-NLS-1$
       
   264 
       
   265 		while (samples.hasMoreElements())
       
   266 		{
       
   267 			BupSample sample = (BupSample)samples.nextElement();
       
   268 			long xSample = (long)(sample.sampleSynchTime/scale + 0.5);
       
   269 			
       
   270 			// samples are in timestamp order, so stop when xSample + EVENT_RECTWIDTH is too high
       
   271 			if (x < xSample - EVENT_RECTWIDTH)
       
   272 				break;
       
   273 
       
   274 			if ((x >= xSample - EVENT_RECTWIDTH) && (x <= xSample + EVENT_RECTWIDTH))
       
   275 			{
       
   276 				String parsedName = sample.getLabel();
       
   277 				if (!tooltip.equals("")) //$NON-NLS-1$
       
   278 					tooltip += Messages.getString("BupTraceGraph.newline"); //$NON-NLS-1$
       
   279 				tooltip += Messages.getString("BupTraceGraph.tooltip1") + parsedName + Messages.getString("BupTraceGraph.tooltip2") + sample.sampleSynchTime/1000.0 + Messages.getString("BupTraceGraph.tooltip3"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
       
   280 				if (sample.getComment() != null)
       
   281 					 tooltip += Messages.getString("BupTraceGraph.tooltip4") + sample.getComment(); //$NON-NLS-1$
       
   282 			}
       
   283 		}
       
   284 		
       
   285 		if (!tooltip.equals("")) //$NON-NLS-1$
       
   286 			((FigureCanvas)me.getSource()).setToolTipText(tooltip);
       
   287 	}
       
   288 
       
   289 	public void mouseDoubleClick(MouseEvent me)
       
   290 	{
       
   291 		if (!display_events)
       
   292 			return;
       
   293 
       
   294 		long x = me.x;
       
   295 		long y = me.y;
       
   296 
       
   297 		int height = this.getVisualSize().height;
       
   298 
       
   299 		// make sure we're in the right area of the graph window
       
   300 		if ((y < height - EVENT_BOTTOMOFLINE) || (y > height - EVENT_BOTTOMOFLINE + EVENT_RECTHEIGHT + 2))
       
   301 			return;
       
   302 
       
   303 		// repaint if the name or comment changes
       
   304 		boolean redraw = false;
       
   305 
       
   306 		Enumeration samples = ((GenericSampledTrace)this.getTrace()).samples.elements();
       
   307 		double scale = this.getScale();
       
   308 
       
   309 		// unlike mouseMove, the x coordinate is not relative to the FigureCanvas
       
   310 		x += ((FigureCanvas)me.getSource()).getViewport().getViewLocation().x;
       
   311 
       
   312 		matchingSamples = new ArrayList<BupSample>();
       
   313 		
       
   314 		while (samples.hasMoreElements())
       
   315 		{
       
   316 			BupSample sample = (BupSample)samples.nextElement();
       
   317 			long xSample = (long)(sample.sampleSynchTime/scale + 0.5);
       
   318 
       
   319 			// samples are in timestamp order, so stop when xSample + EVENT_RECTWIDTH is too high
       
   320 			if (x < xSample - EVENT_RECTWIDTH)
       
   321 				break;
       
   322 
       
   323 			if ((x >= xSample - EVENT_RECTWIDTH) && (x <= xSample + EVENT_RECTWIDTH))
       
   324 			{
       
   325 				matchingSamples.add(sample);
       
   326 			}
       
   327 		}
       
   328 
       
   329 		if (matchingSamples.size() == 0)
       
   330 			return;
       
   331 	
       
   332 		// let them change some information
       
   333 		Display display = PIPageEditor.currentPageEditor().getEditorSite().getShell().getDisplay();
       
   334 
       
   335 		GridData gridData;
       
   336 
       
   337 		if (matchingSamples.size() > 1) {
       
   338 			selectedEventButtons = false;
       
   339 
       
   340 			// query for which of several to display
       
   341 			Shell shell = new Shell(display, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
       
   342 			shell.setText(Messages.getString("BupTraceGraph.chooseEvents")); //$NON-NLS-1$
       
   343 			shell.setLayout(new GridLayout(2, true));
       
   344 			final Shell shellFinal = shell;
       
   345 
       
   346 			Label label = new Label(shell, SWT.LEFT);
       
   347 			label.setText(Messages.getString("BupTraceGraph.selectEvents")); //$NON-NLS-1$
       
   348 			label.setFont(PIPageEditor.helvetica_10);
       
   349 			gridData = new GridData(GridData.FILL_HORIZONTAL);
       
   350 			gridData.horizontalSpan = 2;
       
   351 			label.setLayoutData(gridData);
       
   352 
       
   353 			eventButtons = new Button[matchingSamples.size()];
       
   354 
       
   355 			for (int i = 0; i < matchingSamples.size(); i++) {
       
   356 				eventButtons[i] = new Button(shell, SWT.CHECK);
       
   357 				gridData = new GridData(GridData.FILL_HORIZONTAL);
       
   358 				gridData.horizontalSpan = 2;
       
   359 				eventButtons[i].setLayoutData(gridData);
       
   360 				
       
   361 				BupSample sample = matchingSamples.get(i);
       
   362 				
       
   363 				String parsedName = sample.getLabel();
       
   364 				eventButtons[i].setText(Messages.getString("BupTraceGraph.buttonString1") + parsedName + Messages.getString("BupTraceGraph.buttonString2") + sample.sampleSynchTime/1000d + Messages.getString("BupTraceGraph.buttonString3")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
       
   365 				eventButtons[i].setFont(PIPageEditor.helvetica_10);
       
   366 			}
       
   367 			
       
   368 			// create the OK button
       
   369 			Button okButton = new Button(shell, SWT.NONE);
       
   370 			okButton.setText(Messages.getString("BupTraceGraph.ok")); //$NON-NLS-1$
       
   371 			gridData = new GridData(GridData.HORIZONTAL_ALIGN_CENTER);
       
   372 			okButton.setLayoutData(gridData);
       
   373 
       
   374 			// add the listener(s)
       
   375 			okButton.addSelectionListener(new SelectionListener(){
       
   376 				public void widgetSelected(SelectionEvent e) {
       
   377 					selectedEventButtons = true;
       
   378 					for (int i = matchingSamples.size() - 1; i >= 0; i--)
       
   379 						if (eventButtons[i].getSelection() == false)
       
   380 							matchingSamples.remove(i);
       
   381 
       
   382 					shellFinal.close();
       
   383 				}
       
   384 
       
   385 				public void widgetDefaultSelected(SelectionEvent e) {
       
   386 					widgetSelected(e);
       
   387 				}
       
   388 			});
       
   389 
       
   390 			// create the Cancel button
       
   391 			Button cancelButton = new Button(shell, SWT.NONE);
       
   392 			cancelButton.setText(Messages.getString("BupTraceGraph.cancel")); //$NON-NLS-1$
       
   393 			gridData = new GridData(GridData.HORIZONTAL_ALIGN_CENTER);
       
   394 			cancelButton.setLayoutData(gridData);
       
   395 
       
   396 			// add the listener(s)
       
   397 			cancelButton.addSelectionListener(new SelectionListener(){
       
   398 				public void widgetSelected(SelectionEvent e) {
       
   399 					shellFinal.close();
       
   400 				}
       
   401 
       
   402 				public void widgetDefaultSelected(SelectionEvent e) {
       
   403 					widgetSelected(e);
       
   404 				}
       
   405 			});
       
   406 
       
   407 			shell.pack();
       
   408 			shell.open();
       
   409 
       
   410 			while (!shell.isDisposed()) {
       
   411 				if (!display.readAndDispatch()) {
       
   412 					display.sleep();
       
   413 				}
       
   414 			}
       
   415 
       
   416 			if (selectedEventButtons == false)
       
   417 				matchingSamples.clear();
       
   418 		}
       
   419 
       
   420 		IBupEventMap map = ((BupTrace)this.getTrace()).getCurrentBupMapInUse();
       
   421 		for (int i = 0; i < matchingSamples.size(); i++)
       
   422 		{
       
   423 			BupSample sample = matchingSamples.get(i);
       
   424 			
       
   425 			String enumString = map.getEnum(sample.getKeyCode());
       
   426 
       
   427 			BupEventDialog eventDialog = new BupEventDialog(PIPageEditor.currentPageEditor().getEditorSite().getShell(), Messages.getString("BupTraceGraph.buttonDialog"), //$NON-NLS-1$
       
   428 														sample.getKeyCode(), enumString, sample.getLabel(), sample.getComment(), false, sample.sampleSynchTime);
       
   429 			eventDialog.open();
       
   430 
       
   431 			if (   (eventDialog.getNewName() != null)
       
   432 				&& (!eventDialog.getNewName().equals(sample.getLabel()))) {
       
   433 				sample.setLabel(eventDialog.getNewName());
       
   434 				redraw = true;
       
   435 			}
       
   436 
       
   437 			if (   (eventDialog.getNewComment() != null)
       
   438 				&& (!eventDialog.getNewComment().equals(sample.getComment()))) {
       
   439 				sample.setComment(eventDialog.getNewComment());
       
   440 				redraw = true;
       
   441 			}
       
   442 			
       
   443 			if (eventDialog.getNewSamePropagate()) {
       
   444 				Vector<BupSample> allSamples = (Vector<BupSample>)((GenericSampledTrace)this.getTrace()).samples;
       
   445 				for (BupSample currentSample : allSamples) {
       
   446 					if (currentSample.getKeyCode() == sample.getKeyCode()) {
       
   447 						currentSample.setLabel(eventDialog.getNewName());
       
   448 					}
       
   449 				}
       
   450 				redraw = true;
       
   451 			}
       
   452 		}
       
   453 
       
   454 		if (redraw)
       
   455 			((FigureCanvas)me.getSource()).redraw();
       
   456 	}
       
   457 
       
   458 	public void mouseDragged(MouseEvent me) {}
       
   459 
       
   460 	public void mouseEntered(MouseEvent me) {}
       
   461 
       
   462 	public void mouseExited(MouseEvent me) {}
       
   463 
       
   464 	public void mouseDown(MouseEvent me) {}
       
   465 
       
   466 	public void mouseUp(MouseEvent me) {}
       
   467 
       
   468 	public static boolean openButtonDialog(int buttonIndex)
       
   469 	{
       
   470 		boolean redraw = false;
       
   471 
       
   472 		BupTrace bupTrace = (BupTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.button"); //$NON-NLS-1$
       
   473 
       
   474 		if (buttonIndex > bupTrace.samples.size() || buttonIndex < 1)
       
   475 			return false;
       
   476 
       
   477 		BupSample sample = bupTrace.getBupSample(buttonIndex - 1);
       
   478 
       
   479 		// let them change some information
       
   480 		Display display = PIPageEditor.currentPageEditor().getEditorSite().getShell().getDisplay();
       
   481 
       
   482 		GridData gridData;
       
   483 
       
   484 		IBupEventMap map = bupTrace.getCurrentBupMapInUse();
       
   485 		String enumString = map.getEnum(sample.getKeyCode());
       
   486 
       
   487 		BupEventDialog eventDialog = new BupEventDialog(PIPageEditor.currentPageEditor().getEditorSite().getShell(), Messages.getString("BupTraceGraph.buttonDialog"), //$NON-NLS-1$
       
   488 													sample.getKeyCode(), enumString, sample.getLabel(), sample.getComment(), false, sample.sampleSynchTime);
       
   489 		eventDialog.open();
       
   490 
       
   491 		if (   (eventDialog.getNewName() != null)
       
   492 			&& (!eventDialog.getNewName().equals(sample.getLabel()))) {
       
   493 			sample.setLabel(eventDialog.getNewName());
       
   494 			redraw = true;
       
   495 		}
       
   496 
       
   497 		if (   (eventDialog.getNewComment() != null)
       
   498 			&& (!eventDialog.getNewComment().equals(sample.getComment()))) {
       
   499 			sample.setComment(eventDialog.getNewComment());
       
   500 			redraw = true;
       
   501 		}
       
   502 			
       
   503 		if (eventDialog.getNewSamePropagate()) {
       
   504 			Vector<BupSample> allSamples = (Vector<BupSample>)bupTrace.samples;
       
   505 			for (BupSample currentSample : allSamples) {
       
   506 				if (currentSample.getKeyCode() == sample.getKeyCode()) {
       
   507 					currentSample.setLabel(eventDialog.getNewName());
       
   508 				}
       
   509 			}
       
   510 			redraw = true;
       
   511 		}
       
   512 		
       
   513 		return true;
       
   514 	}
       
   515 
       
   516 	public void addContextMenuItems(Menu menu, MouseEvent me)
       
   517 	{
       
   518 		if (!display_events)
       
   519 			return;
       
   520 
       
   521 		long x = me.x;
       
   522 		long y = me.y;
       
   523 
       
   524 		int height = this.getVisualSize().height;
       
   525 
       
   526 		// make sure we're in the right area of the graph window
       
   527 		if ((y < height - EVENT_BOTTOMOFLINE) || (y > height - EVENT_BOTTOMOFLINE + EVENT_RECTHEIGHT + 2))
       
   528 			return;
       
   529 
       
   530 		Enumeration samples = ((GenericSampledTrace) this.getTrace()).samples.elements();
       
   531 		double scale = this.getScale();
       
   532 
       
   533 		boolean found = false;
       
   534 
       
   535 		// unlike mouseMove, the x coordinate is not relative to the FigureCanvas
       
   536 		x += ((FigureCanvas)me.getSource()).getViewport().getViewLocation().x;
       
   537 
       
   538 		while (samples.hasMoreElements())
       
   539 		{
       
   540 			BupSample sample = (BupSample)samples.nextElement();
       
   541 			long xSample = (long)(sample.sampleSynchTime/scale + 0.5);
       
   542 
       
   543 			// samples are in timestamp order, so stop when xSample + EVENT_RECTWIDTH is too high
       
   544 			if (x < xSample - EVENT_RECTWIDTH)
       
   545 				break;
       
   546 
       
   547 			if ((x >= xSample - EVENT_RECTWIDTH) && (x <= xSample + EVENT_RECTWIDTH))
       
   548 			{
       
   549 				found = true;
       
   550 				break;
       
   551 			}
       
   552 		}
       
   553 
       
   554 		if (!found)
       
   555 			return;
       
   556 
       
   557 		new MenuItem(menu, SWT.SEPARATOR);
       
   558 
       
   559 		final MouseEvent meFinal = me;
       
   560 
       
   561 		MenuItem changeEventItem = new MenuItem(menu, SWT.PUSH);
       
   562 		changeEventItem.setText(Messages.getString("BupTraceGraph.changeEvent")); //$NON-NLS-1$
       
   563 		changeEventItem.addSelectionListener(new SelectionAdapter() {
       
   564 			public void widgetSelected(SelectionEvent e) {
       
   565 				mouseDoubleClick(meFinal);
       
   566 			}
       
   567 		});
       
   568 
       
   569 		int startTime = (int) this.getSelectionStart();
       
   570 		int endTime   = (int) this.getSelectionEnd();
       
   571 
       
   572 		// save raw samples
       
   573 		Vector sampleVector = ((GenericSampledTrace) this.getTrace()).samples;
       
   574 		
       
   575 		int i = 0;
       
   576 		while (i < sampleVector.size() && ((BupSample) sampleVector.get(i)).sampleSynchTime < startTime)
       
   577 			i++;
       
   578 		
       
   579 		// enable if we have at least one event in the interval
       
   580 		getSaveSamplesItem(menu, (i < sampleVector.size() && ((BupSample) sampleVector.get(i)).sampleSynchTime <= endTime));
       
   581 	}
       
   582 	
       
   583 	public void saveEventSamples() {
       
   584     	SaveSampleString saveSampleString = new SaveSampleString();
       
   585     	actionSaveSamples(saveSampleString); //$NON-NLS-1$
       
   586 	}
       
   587 
       
   588 	public void paintLeftLegend(FigureCanvas figureCanvas, GC gc) {
       
   589 	}
       
   590 }