1402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/*******************************************************************************
2402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Copyright (c) 2000, 2009 IBM Corporation and others.
3402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * All rights reserved. This program and the accompanying materials
4402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * are made available under the terms of the Eclipse Public License v1.0
5402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * which accompanies this distribution, and is available at
6402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * http://www.eclipse.org/legal/epl-v10.html
7402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *
8402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Contributors:
9402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *     IBM Corporation - initial API and implementation
10402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *******************************************************************************/
11402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpackage org.eclipse.test.internal.performance.results.ui;
12402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
13402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport java.util.HashMap;
14402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport java.util.Iterator;
15402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport java.util.List;
16402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport java.util.Map;
17402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
18402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.core.runtime.preferences.IEclipsePreferences;
19402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.core.runtime.preferences.InstanceScope;
20402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.swt.SWT;
21402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.swt.custom.CTabFolder;
22402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.swt.events.MouseEvent;
23402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.swt.events.MouseListener;
24402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.swt.events.MouseTrackListener;
25402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.swt.graphics.Color;
26402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.swt.graphics.Font;
27402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.swt.graphics.FontData;
28402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.swt.graphics.GC;
29402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.swt.graphics.Point;
30402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.swt.graphics.Rectangle;
31402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.swt.layout.GridData;
32402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.swt.widgets.Composite;
33402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.swt.widgets.Display;
34402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.swt.widgets.Shell;
35402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.swt.widgets.Table;
36402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.swt.widgets.TableColumn;
37402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.swt.widgets.TableItem;
38402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.swt.widgets.ToolTip;
39402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.test.internal.performance.results.db.AbstractResults;
40402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.test.internal.performance.results.model.BuildResultsElement;
41402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.test.internal.performance.results.model.ComponentResultsElement;
42402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.test.internal.performance.results.model.ConfigResultsElement;
43402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.test.internal.performance.results.model.ResultsElement;
44402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.test.internal.performance.results.model.ScenarioResultsElement;
45402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.test.internal.performance.results.utils.IPerformancesConstants;
46402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollimport org.eclipse.test.internal.performance.results.utils.Util;
47402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
48402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
49402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/**
50402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Tab to display all performances results numbers for a configuration (i.e a performance machine).
51402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
52402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic class ConfigTab {
53402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
54402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Colors
55402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	static final Display DEFAULT_DISPLAY = Display.getDefault();
56402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	static final Color BLUE= DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_BLUE);
57402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	static final Color DARK_GREEN= DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_DARK_GREEN);
58402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	static final Color GRAY = DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_GRAY);
59402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	static final Color MAGENTA = DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_MAGENTA);
60402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	static final Color RED = DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_RED);
61402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
62402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// SWT resources
63402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	Shell shell;
64402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	Display display;
65402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	Table table;
66402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	private GC gc;
67402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	private Color lightred;
68402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	private Color lightyellow;
69402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	private Color darkyellow;
70402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	private Color blueref;
71402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	private Font boldFont;
72402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	private Font italicFont;
73402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	private Font boldItalicFont;
74402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	Map toolTips;
75402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
76402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Information
77402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	String configBox, configName;
78402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	ComponentResultsElement results;
79402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	double[][] allValues;
80402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	double[][] allErrors;
81402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
82402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Cells management
83402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	Point tableOrigin, tableSize;
84402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	int columnsCount, rowsCount;
85402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	List firstLine;
86402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
87402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Eclipse preferences
88402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	private IEclipsePreferences preferences;
89402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
90402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/*
91402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Default constructor.
92402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
93402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic ConfigTab(String name, String box) {
94402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    this.configName = name;
95402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll    int idx = box.indexOf(" (");
96402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.configBox = idx > 0 ? box.substring(0, idx) : box;
97402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.preferences = new InstanceScope().getNode(IPerformancesConstants.PLUGIN_ID);
98402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
99402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
100402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/**
101402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Creates the tab folder page.
102402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll *
103402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @param tabFolder org.eclipse.swt.widgets.TabFolder
104402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @param fullSelection Tells whether the table should have a full line selection or not
105402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * @return the new page for the tab folder
106402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
107402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael MollComposite createTabFolderPage (ComponentResultsElement componentResultsElement, CTabFolder tabFolder, boolean fullSelection) {
108402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Cache the shell and display.
109402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.shell = tabFolder.getShell();
110402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.display = this.shell.getDisplay();
111402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
112402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Remove old table is present
113402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	boolean initResources = this.table == null;
114402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (this.table != null) {
115402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		disposeTable();
116402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
117402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
118402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Store results
119402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.results = componentResultsElement;
120402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
121402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Create the "children" table
122402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	int style = SWT.MULTI | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL;
123402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (fullSelection) style |= SWT.FULL_SELECTION;
124402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.table = new Table(tabFolder, style);
125402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.table.setLinesVisible (true);
126402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.table.setHeaderVisible (true);
127402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1);
128402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	gridData.heightHint = 150;
129402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.table.setLayoutData (gridData);
130402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.gc = new GC(this.table);
131402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
132402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Init resources
133402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (initResources) initResources();
134402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
135402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Add columns to the table
136402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	boolean fingerprints = this.preferences.getBoolean(IPerformancesConstants.PRE_FILTER_ADVANCED_SCENARIOS, IPerformancesConstants.DEFAULT_FILTER_ADVANCED_SCENARIOS);
137402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	String [] columnHeaders = getLayoutDataFieldNames(fingerprints);
138402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	int length = columnHeaders.length;
139402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	for (int i = 0; i < length; i++) {
140402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		TableColumn column = new TableColumn(this.table, SWT.CENTER);
141402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		column.setText (columnHeaders [i]);
142402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
143402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
144402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Add lines to the table
145402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.toolTips = new HashMap();
146402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	fillTableLines(fingerprints);
147402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
148402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Updated columns
149402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	for (int i=0; i<length; i++) {
150402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		TableColumn column = this.table.getColumn(i);
151402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		column.setWidth(i==0?120:100);
152402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		if (i > 0) {
153402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			String text = (String) this.firstLine.get(i);
154402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			column.setToolTipText(text);
155402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
156402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
157402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
158402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Store table info
159402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.columnsCount = length;
160402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
161402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Listen to mouse events to select the corresponding build in the components view
162402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// when a click is done in the table cell.
163402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	final ComponentsView componentsView = (ComponentsView) PerformancesView.getWorkbenchView("org.eclipse.test.internal.performance.results.ui.ComponentsView");
164402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	MouseListener mouseListener = new MouseListener() {
165402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		public void mouseUp(MouseEvent e) {
166402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
167402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		public void mouseDown(MouseEvent e) {
168402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			Point cellPosition = currentCellPosition(e.x, e.y);
169402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			Table tabTable = ConfigTab.this.table;
170402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			componentsView.select(ConfigTab.this.results, ConfigTab.this.configName, (String) ConfigTab.this.firstLine.get(cellPosition.x), tabTable.getItem(cellPosition.y).getText());
171402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
172402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		public void mouseDoubleClick(MouseEvent e) {
173402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
174402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	};
175402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.table.addMouseListener(mouseListener);
176402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
177402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Listen to mouse track events to display the table cell corresponding tooltip.
178402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	MouseTrackListener mouseTrackListener = new MouseTrackListener() {
179402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		ToolTip currentTooltip;
180402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		public void mouseHover(MouseEvent e) {
181402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			if (this.currentTooltip != null) {
182402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				this.currentTooltip.setVisible(false);
183402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				this.currentTooltip = null;
184402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			}
185402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			Point cellPosition = currentCellPosition(e.x, e.y);
186402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			if (cellPosition != null) {
187402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				ToolTip tooltip = (ToolTip) ConfigTab.this.toolTips.get(cellPosition);
188402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				if (tooltip != null) {
189402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					Point location = ConfigTab.this.table.toDisplay(new Point(e.x, e.y));
190402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					tooltip.setLocation(location);
191402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					tooltip.setVisible(true);
192402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					this.currentTooltip = tooltip;
193402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				}
194402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			}
195402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
196402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		public void mouseEnter(MouseEvent e) {
197402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
198402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		public void mouseExit(MouseEvent e) {
199402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
200402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	};
201402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.table.addMouseTrackListener(mouseTrackListener);
202402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
203402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Select the first line by default (as this is the current build)
204402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.table.select(0);
205402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
206402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Return the built composite
207402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	return this.table;
208402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
209402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
210402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/*
211402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Create and store a tooltip with the given information and at the given position.
212402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
213402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollvoid createToolTip(String toolTipText, String toolTipMessage, int toolTipStyle, Point position) {
214402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	ToolTip toolTip = new ToolTip(this.table.getShell(), toolTipStyle);
215402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	toolTip.setAutoHide(true);
216402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	toolTip.setText(toolTipText);
217402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	toolTip.setMessage(/*"("+col+","+row+") "+*/toolTipMessage);
218402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.toolTips.put(position, toolTip);
219402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
220402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
221402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/*
222402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Get the current cell position (column, row) from a point position.
223402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
224402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael MollPoint currentCellPosition(int x, int y) {
225402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
226402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Compute the origin of the visible area
227402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (this.tableOrigin == null) {
228402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		this.tableOrigin = new Point(0, this.table.getHeaderHeight());
229402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
230402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
231402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Increment width until over current y position
232402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	int height= this.tableOrigin.y;
233402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	int row = this.table.getTopIndex();
234402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	while (row<this.rowsCount && height<y) {
235402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		height += this.table.getItemHeight();
236402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		row++;
237402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
238402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (height < y) {
239402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		// return when position is over the last line
240402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		return null;
241402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
242402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	row--;
243402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
244402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Increment width until being over current x position
245402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	int col = 0;
246402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	TableItem tableItem = this.table.getItem(row);
247402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	Rectangle bounds = tableItem.getBounds(col);
248402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	while (col<this.columnsCount) {
249402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		int max = bounds.x + bounds.width + this.table.getGridLineWidth();
250402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		if (x <= max) break;
251402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		if (col == this.columnsCount) {
252402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			// return when position is over the last column
253402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			return null;
254402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
255402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		col++;
256402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		bounds = tableItem.getBounds(col);
257402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
258402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
259402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Return the found table cell position
260402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	return new Point(col, row);
261402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
262402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
263402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/*
264402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Dispose all SWT resources.
265402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
266402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic void dispose() {
267402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (this.boldFont != null) {
268402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		this.boldFont.dispose();
269402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
270402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (this.italicFont != null) {
271402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		this.italicFont.dispose();
272402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
273402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (this.boldItalicFont != null) {
274402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		this.boldItalicFont.dispose();
275402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
276402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (this.darkyellow != null) {
277402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		this.darkyellow.dispose();
278402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
279402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (this.lightyellow != null) {
280402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		this.lightyellow.dispose();
281402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
282402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (this.lightred != null) {
283402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		this.lightred.dispose();
284402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
285402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (this.blueref != null) {
286402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		this.blueref.dispose();
287402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
288402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	disposeTable();
289402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
290402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
291402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/*
292402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Dispose all SWT controls associated with the table.
293402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
294402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollprivate void disposeTable() {
295402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (this.toolTips != null) {
296402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		Iterator cells = this.toolTips.keySet().iterator();
297402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		while (cells.hasNext()) {
298402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			ToolTip toolTip = (ToolTip) this.toolTips.get(cells.next());
299402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			toolTip.dispose();
300402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
301402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
302402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.table.dispose();
303402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.tableOrigin = null;
304402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.firstLine = null;
305402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
306402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
307402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/*
308402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Fill the lines of the tables.
309402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Get all the information from the model which are returned in a list (lines) of lists (columns).
310402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
311402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollprivate void fillTableLines(boolean fingerprints) {
312402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
313402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Get preferences information
314402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	boolean onlyMilestones = this.preferences.getBoolean(IPerformancesConstants.PRE_FILTER_OLD_BUILDS, IPerformancesConstants.DEFAULT_FILTER_OLD_BUILDS);
315402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	boolean skipNightlyBuilds = this.preferences.getBoolean(IPerformancesConstants.PRE_FILTER_NIGHTLY_BUILDS, IPerformancesConstants.DEFAULT_FILTER_NIGHTLY_BUILDS);
316402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
317402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Get model information
318402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (this.results == null) return;
319402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	List differences = this.results.getConfigNumbers(this.configName, fingerprints);
320402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (differences == null) return;
321402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
322402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Store first information line which are the scenarios full names
323402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	Iterator lines = differences.iterator();
324402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.firstLine = (List) lines.next();
325402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
326402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Read each information line (one line per build results)
327402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	Object[] scenarios = this.results.getChildren(null);
328402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	ConfigResultsElement[] configs = new ConfigResultsElement[scenarios.length];
329402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	int row = 0;
330402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	while (lines.hasNext()) {
331402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		List line = (List) lines.next();
332402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		int size = line.size();
333402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
334402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		// The first column is the build name
335402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		String buildName = (String) line.get(0);
336402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		String milestoneName = Util.getMilestoneName(buildName);
337402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		TableItem item = null;
338402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
339402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		// Set item if the line is not filtered
340402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		Font italic;
341402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		if (milestoneName != null) {
342402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			item = new TableItem (this.table, SWT.NONE);
343402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			item.setText(milestoneName + " - " + buildName);
344402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			item.setFont(0, this.boldFont);
345402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			if (!onlyMilestones) item.setBackground(this.blueref);
346402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			italic = this.boldItalicFont;
347402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		} else {
348402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			if ((onlyMilestones && Util.getNextMilestone(buildName) != null) ||
349402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				(skipNightlyBuilds && buildName.charAt(0) == 'N')) {
350402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				// skip line
351402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				continue;
352402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			}
353402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			item = new TableItem (this.table, SWT.NONE);
354402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			item.setText(0, buildName);
355402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			italic = this.italicFont;
356402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
357402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
358402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		// Read each column value
359402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		String baselineName = null;
360402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		for (int col=1; col<size; col++) {
361402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
362402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			// Reset tooltip info
363402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			String toolTipText = null;
364402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			String toolTipMessage = null;
365402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			int toolTipStyle = SWT.BALLOON;
366402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
367402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			// Otherwise get values for a scenario
368402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			Font italic2 = italic;
369402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			ScenarioResultsElement scenarioResultsElement = (ScenarioResultsElement) scenarios[col-1];
370402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			if (milestoneName != null || (!fingerprints && scenarioResultsElement.hasSummary())) {
371402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				italic2 = this.boldItalicFont;
372402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				item.setFont(col, this.boldFont);
373402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			}
374402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			// Otherwise get values for a scenario
375402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			double[] values = (double[]) line.get(col);
376402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			if (values == AbstractResults.NO_BUILD_RESULTS) {
377402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				item.setText(col, "Missing");
378402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				item.setForeground(col, GRAY);
379402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				item.setFont(col, italic2);
380402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			} else if (values == AbstractResults.INVALID_RESULTS) {
381402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				item.setText(col, "Invalid");
382402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				item.setForeground(col, RED);
383402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				item.setFont(col, italic2);
384402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			} else {
385402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				// Get values array
386402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				double buildValue = values[AbstractResults.BUILD_VALUE_INDEX];
387402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				double baselineValue = values[AbstractResults.BASELINE_VALUE_INDEX];
388402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				double delta = values[AbstractResults.DELTA_VALUE_INDEX];
389402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				double error = values[AbstractResults.DELTA_ERROR_INDEX];
390402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
391402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				// Set text with delta value
392402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				item.setText(col, Util.PERCENTAGE_FORMAT.format(delta));
393402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
394402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				// Compute the tooltip to display on the cell
395402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				if (error > 0.03) {
396402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					// error is over the 3% threshold
397402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					item.setImage(col, ResultsElement.WARN_IMAGE);
398402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					item.setForeground(col, this.darkyellow);
399402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					toolTipText = "May be not reliable";
400402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					toolTipMessage = "The error on this result is "+Util.PERCENTAGE_FORMAT.format(error)+", hence it may be not reliable";
401402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					toolTipStyle |= SWT.ICON_WARNING;
402402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				}
403402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				if (delta < -0.1) {
404402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					// delta < -10%: failure shown by an red-cross icon + text in red
405402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					item.setImage(col, ResultsElement.ERROR_IMAGE);
406402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					item.setForeground(col, RED);
407402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				} else if (delta < -0.05) {
408402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					// negative delta over 5% shown in red
409402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					item.setForeground(col, RED);
410402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				} else if (delta < 0) {
411402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					// negative delta shown in magenta
412402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					item.setForeground(col, MAGENTA);
413402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				} else if (delta > 0.2) {
414402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					// positive delta over 20% shown in green
415402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					item.setForeground(col, DARK_GREEN);
416402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				} else if (delta > 0.1) {
417402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					// positive delta between 10% and 20% shown in blue
418402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					item.setForeground(col, BLUE);
419402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				}
420402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
421402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				// Moderate the status if the build value or the difference is small
422402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				if (delta < 0) {
423402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					double diff = Math.abs(baselineValue - buildValue);
424402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					if (buildValue < 100 || diff < 100) {
425402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						if (toolTipText == null) {
426402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll							toolTipText = "";
427402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						} else {
428402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll							toolTipText += ", ";
429402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						}
430402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						toolTipText += "Small value";
431402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						if (toolTipMessage == null) {
432402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll							toolTipMessage = "";
433402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						} else {
434402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll							toolTipMessage += ".\n";
435402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						}
436402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						if (buildValue < 100) {
437402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll							toolTipMessage += "This test has a small value ("+buildValue+"ms)";
438402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						} else {
439402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll							toolTipMessage += "This test variation has a small value ("+diff+"ms)";
440402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						}
441402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						toolTipMessage +=  ", hence it may not be necessary to spend time on fixing this possible regression";
442402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						// set the text in italic
443402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						item.setFont(col, italic2);
444402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						toolTipStyle |= SWT.ICON_INFORMATION;
445402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					}
446402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				}
447402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
448402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				// Add information in tooltip when history shows big variation
449402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				ConfigResultsElement configResultsElement = configs[col-1];
450402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				if (configResultsElement == null) {
451402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					configResultsElement = (ConfigResultsElement) scenarioResultsElement.getResultsElement(this.configName);
452402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					configs[col-1] = configResultsElement;
453402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				}
454402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				double deviation = configResultsElement == null ? 0 : configResultsElement.getStatistics()[3];
455402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				if (deviation > 0.2) {
456402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					// deviation is over 20% over the entire history
457402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					if (toolTipText == null) {
458402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						toolTipText = "";
459402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					} else {
460402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						toolTipText += ", ";
461402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					}
462402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					toolTipText += "History shows erratic values";
463402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					if (toolTipMessage == null) {
464402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						toolTipMessage = "";
465402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					} else {
466402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						toolTipMessage += ".\n";
467402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					}
468402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					toolTipMessage += "The results history shows that the variation of its delta is over 20% ("+Util.PERCENTAGE_FORMAT.format(deviation)+"), hence its result is surely not reliable";
469402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					// set the text in italic
470402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					item.setFont(col, italic2);
471402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					toolTipStyle |= SWT.ICON_INFORMATION;
472402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				} else if (deviation > 0.1) { // moderate the status when the test
473402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					// deviation is between 10% and 20% over the entire history
474402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					if (toolTipText == null) {
475402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						toolTipText = "";
476402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					} else {
477402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						toolTipText += ", ";
478402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					}
479402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					toolTipText += "History shows unstable values";
480402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					if (toolTipMessage == null) {
481402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						toolTipMessage = "";
482402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					} else {
483402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						toolTipMessage += ".\n";
484402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					}
485402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					toolTipMessage += "The results history shows that the variation of its delta is between 10% and 20% ("+Util.PERCENTAGE_FORMAT.format(deviation)+"), hence its result may not be really reliable";
486402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					// set the text in italic
487402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					item.setFont(col, italic2);
488402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					if (toolTipStyle == SWT.BALLOON && delta >= -0.1) {
489402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						toolTipStyle |= SWT.ICON_INFORMATION;
490402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					} else {
491402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						// reduce icon severity from error to warning
492402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll						toolTipStyle |= SWT.ICON_WARNING;
493402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					}
494402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				}
495402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			}
496402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
497402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			// Set tooltip
498402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			if (toolTipText != null) {
499402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				createToolTip(toolTipText, toolTipMessage, toolTipStyle, new Point(col, row));
500402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			}
501402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
502402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			// Baseline name
503402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			ConfigResultsElement configResultsElement = (ConfigResultsElement) scenarioResultsElement.getResultsElement(this.configName);
504402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			if (configResultsElement != null) {
505402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				String configBaselineName = configResultsElement.getBaselineBuildName(buildName);
506402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				if (baselineName == null) {
507402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					baselineName = configBaselineName;
508402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				} else if (baselineName.indexOf(configBaselineName) < 0) {
509402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll					baselineName += ", " +configBaselineName;
510402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll				}
511402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			}
512402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
513402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
514402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		// Set the tooltip over the build name
515402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		if (baselineName != null) {
516402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			createToolTip(buildName, "Baseline: "+baselineName, SWT.BALLOON | SWT.ICON_INFORMATION, new Point(0, row));
517402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
518402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
519402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		// Increment row counter
520402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		row++;
521402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
522402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.rowsCount = row;
523402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
524402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
525402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/*
526402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Get the columns name.
527402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
528402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollprivate String[] getLayoutDataFieldNames(boolean fingerprints) {
529402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	if (this.results == null) {
530402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		return new String[0];
531402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
532402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	List labels = this.results.getScenariosLabels(fingerprints);
533402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	labels.add(0, "Build");
534402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	String[] names = new String[labels.size()];
535402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	labels.toArray(names);
536402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	return names;
537402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
538402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
539402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/*
540402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * The tab text is the full machine name.
541402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
542402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollpublic String getTabText() {
543402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	return this.configBox;
544402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
545402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
546402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/*
547402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Init the SWT resources
548402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
549402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollprivate void initResources() {
550402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Fonts
551402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	String fontDataName = this.gc.getFont().getFontData()[0].toString();
552402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	FontData fdItalic = new FontData(fontDataName);
553402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	fdItalic.setStyle(SWT.ITALIC);
554402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.italicFont = new Font(this.display, fdItalic);
555402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	FontData fdBold = new FontData(fontDataName);
556402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	fdBold.setStyle(SWT.BOLD);
557402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.boldFont = new Font(this.display, fdBold);
558402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	FontData fdBoldItalic = new FontData(fontDataName);
559402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	fdBoldItalic.setStyle(SWT.BOLD | SWT.ITALIC);
560402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.boldItalicFont = new Font(this.display, fdBoldItalic);
561402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
562402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	// Colors
563402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.lightred = new Color(DEFAULT_DISPLAY, 220, 50, 50);
564402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.lightyellow = new Color(DEFAULT_DISPLAY, 255, 255, 160);
565402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.darkyellow = new Color(DEFAULT_DISPLAY, 160, 160, 0);
566402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	this.blueref = new Color(DEFAULT_DISPLAY, 200, 200, 255);
567402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
568402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll
569402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll/*
570402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll * Select the line corresponding to the given build.
571402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll */
572402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Mollvoid select(BuildResultsElement buildResultsElement) {
573402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	int count = this.table.getItemCount();
574402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	String buildName = buildResultsElement.getName();
575402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	TableItem[] items = this.table.getItems();
576402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	for (int i=0; i<count; i++) {
577402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		if (items[i].getText().endsWith(buildName)) {
578402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			this.table.deselect(this.table.getSelectionIndex());
579402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			this.table.select(i);
580402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll			return;
581402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll		}
582402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll	}
583402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
584402794e73aed8611d62eb4b01cd155e2d76fcb87Raphael Moll}
585