blob: 7f2b55cf3feceb0ac75427c129694b9950453490 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2017 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.test.internal.performance.results.ui;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Table;
import org.eclipse.test.internal.performance.results.model.BuildResultsElement;
import org.eclipse.test.internal.performance.results.model.ComponentResultsElement;
import org.eclipse.test.internal.performance.results.model.ConfigResultsElement;
import org.eclipse.test.internal.performance.results.model.DimResultsElement;
import org.eclipse.test.internal.performance.results.model.PerformanceResultsElement;
import org.eclipse.test.internal.performance.results.model.ResultsElement;
import org.eclipse.test.internal.performance.results.model.ScenarioResultsElement;
import org.eclipse.test.internal.performance.results.utils.IPerformancesConstants;
import org.eclipse.test.internal.performance.results.utils.Util;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;
/**
* This view show for each performance machine the results of all builds
* run since the beginning of the current version development.
* <p>
* Each machine results are show in a separate tab.
* </p><p>
* There's no real action available action from this view, only the possibility
* to change how is displayed the line selection (full or only first column)
* and also filter the results:
* </p><ul>
* <li>Filter for builds:
* <ul>
* <li>Filter nightly: hide the nightly builds (starting with 'N')</li>
* <li>Filter non-important builds: hide all non-important builds, which means non-milestone builds and those after the last milestone</li>
* </ul>
* </li>
* <li>Filter for scenarios:
* <ul>
* <li>Filter non-fingerprints: hide the scenarios which are not in the fingerprints</li>
* </ul>
* </li>
* </ul>
* <p>
* Note that these filters are synchronized with the ones applied in the
* {@link ComponentsView Components view}.
* </p>
*
* @see ConfigTab Folder tab containing all the results for a configuration.
*/
public class ComponentResultsView extends ViewPart implements ISelectionChangedListener, IPreferenceChangeListener {
// SWT resources
CTabFolder tabFolder;
// Model information
ConfigTab[] tabs;
ComponentResultsElement componentResultsElement;
// Action
Action fullLineSelection;
Action filterAdvancedScenarios;
Action filterOldBuilds;
Action filterNightlyBuilds;
ImageDescriptor fullSelectionImageDescriptor;
// Views
IMemento viewState;
// Eclipse preferences
IEclipsePreferences preferences;
/*
* Default constructor:
* - create the image descriptor
* - register the view as a properties listener
*/
public ComponentResultsView() {
this.fullSelectionImageDescriptor = ImageDescriptor.createFromFile(getClass(), "icallout_obj.gif");
this.preferences = InstanceScope.INSTANCE.getNode(IPerformancesConstants.PLUGIN_ID);
this.preferences.addPreferenceChangeListener(this);
Util.initMilestones(this.preferences);
}
/*
* Contribute the local tools bar and the pull-down menu to the action bars.
*/
void contributeToActionBars() {
IActionBars bars = getViewSite().getActionBars();
fillLocalPullDown(bars.getMenuManager());
fillLocalToolBar(bars.getToolBarManager());
}
@Override
public void createPartControl(Composite parent) {
// Create the tab folder
this.tabFolder = new CTabFolder(parent, SWT.BORDER);
// Add results view as listener to viewer selection changes
Display.getDefault().asyncExec(() -> {
PerformancesView performancesView = (PerformancesView) PerformancesView.getWorkbenchView("org.eclipse.test.internal.performance.results.ui.ComponentsView");
if (performancesView != null) {
performancesView.viewer.addSelectionChangedListener(ComponentResultsView.this);
}
});
// Set actions
PlatformUI.getWorkbench().getHelpSystem().setHelp(this.tabFolder, "org.eclipse.test.performance.ui.results");
makeActions();
contributeToActionBars();
// Restore state
restoreState();
// Create tabs
createTabs();
// Set selections (tab and line)
this.tabFolder.setSimple(false);
}
/*
* Create the tab folder pages. There's one tab per performance machine.
* The list of these machines is got from the DB_Results contants.
*/
void createTabs() {
if (this.componentResultsElement == null) return;
PerformanceResultsElement performanceResultsElement = (PerformanceResultsElement) this.componentResultsElement.getParent(null);
String[] configNames = performanceResultsElement.getConfigs();
String[] configDescriptions = performanceResultsElement.getConfigDescriptions();
int length = configNames.length;
this.tabs = new ConfigTab[length];
for (int i=0; i<length; i++) {
this.tabs[i] = new ConfigTab(configNames[i], configDescriptions[i]);
}
for (int i=0; i<this.tabs.length; i++) {
CTabItem item = new CTabItem (this.tabFolder, SWT.NONE);
item.setText (this.tabs[i].getTabText ());
item.setControl (this.tabs[i].createTabFolderPage(this.componentResultsElement, this.tabFolder, this.fullLineSelection.isChecked()));
item.setData (this.tabs[i]);
}
this.tabFolder.setSelection(0);
}
@Override
public void dispose() {
this.tabFolder.dispose();
int length = this.tabs==null ? 0 : this.tabs.length;
for (int i=0; i<length; i++) {
this.tabs[i].dispose();
}
JFaceResources.getResources().destroyImage(this.fullSelectionImageDescriptor);
super.dispose();
}
/*
* Fill the filters drop-down menu with:
* - filter nightly builds
* - filter non-milestone builds
* - filter non-fingerprint scenarios
*/
void fillFiltersDropDown(IMenuManager manager) {
manager.add(this.filterNightlyBuilds);
manager.add(this.filterOldBuilds);
manager.add(new Separator());
manager.add(this.filterAdvancedScenarios);
}
/*
* Fill the local pull down menu.
*/
void fillLocalPullDown(IMenuManager manager) {
MenuManager filtersManager= new MenuManager("Filters");
fillFiltersDropDown(filtersManager);
manager.add(filtersManager);
}
/*
* Fill the local tool bar with:
* - change line selection display
*/
void fillLocalToolBar(IToolBarManager manager) {
manager.add(this.fullLineSelection);
}
@Override
public void init(IViewSite site, IMemento memento) throws PartInitException {
super.init(site, memento);
this.viewState = memento;
}
/*
* Make the actions of the view:
* - change table line selection display
* - filter nightly builds
* - filter non-milestone builds
* - filter non-fingerprint scenarios
*/
void makeActions() {
// Full line selection action
this.fullLineSelection = new Action("", IAction.AS_CHECK_BOX) {
@Override
public void run() {
resetTabFolders(false/*refresh*/);
}
};
this.fullLineSelection.setImageDescriptor(this.fullSelectionImageDescriptor);
this.fullLineSelection.setToolTipText("Full line selection");
// this.fullLineSelection.setChecked(true);
// Filter non-fingerprints action
this.filterAdvancedScenarios = new Action("Advanced &Scenarios", IAction.AS_CHECK_BOX) {
@Override
public void run() {
ComponentResultsView.this.preferences.putBoolean(IPerformancesConstants.PRE_FILTER_ADVANCED_SCENARIOS, isChecked());
resetTabFolders(false/*refresh*/);
}
};
this.filterAdvancedScenarios.setChecked(true);
this.filterAdvancedScenarios.setToolTipText("Filter advanced scenarios (i.e. not fingerprint ones)");
// Filter non-important builds action
this.filterOldBuilds = new Action("&Old Builds", IAction.AS_CHECK_BOX) {
@Override
public void run() {
ComponentResultsView.this.preferences.putBoolean(IPerformancesConstants.PRE_FILTER_OLD_BUILDS, isChecked());
resetTabFolders(false/*refresh*/);
}
};
this.filterOldBuilds.setChecked(false);
this.filterOldBuilds.setToolTipText("Filter old builds (i.e. before last milestone) but keep all previous milestones)");
// Filter nightly action
this.filterNightlyBuilds = new Action("&Nightly", IAction.AS_CHECK_BOX) {
@Override
public void run() {
ComponentResultsView.this.preferences.putBoolean(IPerformancesConstants.PRE_FILTER_NIGHTLY_BUILDS, isChecked());
resetTabFolders(false/*refresh*/);
}
};
this.filterNightlyBuilds.setToolTipText("Filter nightly builds");
}
@Override
public void preferenceChange(PreferenceChangeEvent event) {
String propertyName = event.getKey();
Object newValue = event.getNewValue();
// Filter non-fingerprints change
if (propertyName.equals(IPerformancesConstants.PRE_FILTER_ADVANCED_SCENARIOS)) {
boolean checked = newValue == null ? IPerformancesConstants.DEFAULT_FILTER_ADVANCED_SCENARIOS : "true".equals(newValue);
this.filterAdvancedScenarios.setChecked(checked);
resetTabFolders(false/*refresh*/);
}
// Filter non-milestone change
if (propertyName.equals(IPerformancesConstants.PRE_FILTER_OLD_BUILDS)) {
boolean checked = newValue == null ? IPerformancesConstants.DEFAULT_FILTER_OLD_BUILDS : "true".equals(newValue);
this.filterOldBuilds.setChecked(checked);
resetTabFolders(false/*refresh*/);
}
// Filter nightly builds change
if (propertyName.equals(IPerformancesConstants.PRE_FILTER_NIGHTLY_BUILDS)) {
boolean checked = newValue == null ? IPerformancesConstants.DEFAULT_FILTER_NIGHTLY_BUILDS : "true".equals(newValue);
this.filterNightlyBuilds.setChecked(checked);
resetTabFolders(false/*refresh*/);
}
}
/*
* Reset the table tab folders by re-create all the pages.
* Selections are set onto the first found error if this is the first tab creation (typically on a component change event from the ComponentsView)
* or to the previous one if this is just a refresh.
*/
void resetTabFolders(boolean init) {
// Store current indexes
int tabIndex = this.tabFolder.getSelectionIndex();
int lineIndex = tabIndex<0 ? -1 : this.tabs[tabIndex].table.getSelectionIndex();
// Create tab folders
CTabItem[] tabItems = this.tabFolder.getItems();
int length = tabItems.length;
if (length == 0) {
createTabs();
} else {
for (int i=0; i<length; i++) {
tabItems[i].setControl(this.tabs [i].createTabFolderPage(this.componentResultsElement, this.tabFolder, this.fullLineSelection.isChecked()));
}
}
// Set the part name when possible
if (this.componentResultsElement != null) {
setPartName(Util.componentDisplayName(this.componentResultsElement.getName()));
}
// If this is the first display then look for the first error to set the selection on it
if (init) {
if (this.componentResultsElement != null) {
// If the component has
if (this.componentResultsElement.hasError()) {
ResultsElement[] children = this.componentResultsElement.getChildren(); // get scenarios
int childrenLength = children.length;
for (int s=0; s<childrenLength; s++) {
if (children[s].hasError()) {
children = children[s].getChildren(); // get configs
for (int c=0; c<childrenLength; c++) {
if (children[c].hasError()) {
tabIndex = c;
break;
}
}
break;
}
}
}
}
lineIndex = 0;
}
// Set the selection
if (tabIndex >= 0 && lineIndex >= 0) {
this.tabFolder.setSelection(tabIndex);
Table table = this.tabs[tabIndex].table;
table.setSelection(lineIndex);
}
}
/*
* Restore the view state from the memento information.
*/
void restoreState() {
// Filter baselines action state
if (this.viewState != null) {
Boolean state = this.viewState.getBoolean(IPerformancesConstants.PRE_FULL_LINE_SELECTION);
boolean fullLine = state == null ? true : state.booleanValue();
this.fullLineSelection.setChecked(fullLine);
}
// Filter non fingerprints action state
boolean checked = this.preferences.getBoolean(IPerformancesConstants.PRE_FILTER_ADVANCED_SCENARIOS, IPerformancesConstants.DEFAULT_FILTER_ADVANCED_SCENARIOS);
this.filterAdvancedScenarios.setChecked(checked);
// Filter nightly builds action
checked = this.preferences.getBoolean(IPerformancesConstants.PRE_FILTER_NIGHTLY_BUILDS, IPerformancesConstants.DEFAULT_FILTER_NIGHTLY_BUILDS);
this.filterNightlyBuilds.setChecked(checked);
// Filter non important builds action state
checked = this.preferences.getBoolean(IPerformancesConstants.PRE_FILTER_OLD_BUILDS, IPerformancesConstants.DEFAULT_FILTER_OLD_BUILDS);
this.filterOldBuilds.setChecked(checked);
}
@Override
public void saveState(IMemento memento) {
super.saveState(memento);
memento.putBoolean(IPerformancesConstants.PRE_FULL_LINE_SELECTION, this.fullLineSelection.isChecked());
}
@Override
public void selectionChanged(SelectionChangedEvent event) {
ResultsElement selectedElement = (ResultsElement) ((TreeSelection) event.getSelection()).getFirstElement();
ComponentResultsElement componentElement = null;
ScenarioResultsElement scenarioResultsElement = null;
ConfigResultsElement configResultsElement = null;
BuildResultsElement buildResultsElement = null;
if (selectedElement instanceof ComponentResultsElement) {
componentElement = (ComponentResultsElement) selectedElement;
} else if (selectedElement instanceof ScenarioResultsElement) {
scenarioResultsElement = (ScenarioResultsElement) selectedElement;
componentElement = (ComponentResultsElement) scenarioResultsElement.getParent(null);
} else if (selectedElement instanceof ConfigResultsElement) {
configResultsElement = (ConfigResultsElement) selectedElement;
scenarioResultsElement = (ScenarioResultsElement) configResultsElement.getParent(null);
componentElement = (ComponentResultsElement) scenarioResultsElement.getParent(null);
} else if (selectedElement instanceof BuildResultsElement) {
buildResultsElement = (BuildResultsElement) selectedElement;
configResultsElement = (ConfigResultsElement) buildResultsElement.getParent(null);
scenarioResultsElement = (ScenarioResultsElement) configResultsElement.getParent(null);
componentElement = (ComponentResultsElement) scenarioResultsElement.getParent(null);
} else if (selectedElement instanceof DimResultsElement) {
buildResultsElement = (BuildResultsElement) selectedElement.getParent(null);
configResultsElement = (ConfigResultsElement) buildResultsElement.getParent(null);
scenarioResultsElement = (ScenarioResultsElement) configResultsElement.getParent(null);
componentElement = (ComponentResultsElement) scenarioResultsElement.getParent(null);
}
if (componentElement != this.componentResultsElement) {
this.componentResultsElement = componentElement;
if (componentElement == null || this.componentResultsElement.getChildren(null).length > 0) {
resetTabFolders(true);
}
}
if (configResultsElement != null) {
ConfigTab configTab = this.tabs[this.tabFolder.getSelectionIndex()];
if (!configResultsElement.getName().equals(configTab.configName)) {
int length = this.tabs.length;
for (int i=0; i<length; i++) {
if (this.tabs[i].configName.equals(configResultsElement.getName())) {
this.tabFolder.setSelection(i);
}
}
}
if (buildResultsElement != null) {
configTab = this.tabs[this.tabFolder.getSelectionIndex()];
configTab.select(buildResultsElement);
}
}
}
@Override
public void setFocus() {
// do nothing
}
/*
* Set the name of the part.
* This name is built from the name of the component selected in the Components view.
* The rules to build the name are:
* 1. If the component name does not start then the part name is just "'<component name>' results"
* 2. Otherwise, remove "org.eclipse." form the component name and count the tokens separated by a dot ('.')
* a. if there's only one remaining token, then the part name is "Platform/"
* + "<token uppercased>" if token is less than 3 characters,"<token with first char uppercased>" otherwise
* b. otherwise then the part name is "<first token uppercased>"
* + for each followed additional token:
* "<token uppercased>" if token is less than 3 characters,"<token with first char uppercased>" otherwise
* + " results"
* E.g.
* - org.eclipse.ui -> "Platform/UI"
* - org.eclipse.swt -> "Platform/SWT"
* - org.eclipse.team -> "Platform/Team"
* - org.eclipse.jdt.ui -> "JDT/UI"
* - org.eclipse.jdt.core -> "JDT/Core"
* - org.eclipse.pde.api.tools -> "PDE/API Tools"
*
protected void setPartName() {
String componentName = this.componentResultsElement.getName();
String partName;
StringBuffer buffer = null;
if (componentName.startsWith(ORG_ECLIPSE)) {
partName = componentName.substring(ORG_ECLIPSE.length());
StringTokenizer tokenizer = new StringTokenizer(partName, ".");
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
if (buffer == null) {
if (tokenizer.hasMoreTokens()) {
buffer = new StringBuffer("'"+token.toUpperCase());
buffer.append('/');
} else {
buffer = new StringBuffer("'Platform/");
if (token.length() > 3) {
buffer.append(Character.toUpperCase(token.charAt(0)));
buffer.append(token.substring(1));
} else {
buffer.append(token.toUpperCase());
}
}
} else {
if (token.length() > 3) {
buffer.append(Character.toUpperCase(token.charAt(0)));
buffer.append(token.substring(1));
} else {
buffer.append(token.toUpperCase());
}
if (tokenizer.hasMoreTokens()) buffer.append(' ');
}
}
} else {
buffer = new StringBuffer("'");
buffer.append(componentName);
buffer.append("'");
}
buffer.append("' results");
setPartName(buffer.toString());
}
*/
}