| /******************************************************************************* |
| * Copyright (c) 2000, 2009 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 java.util.StringTokenizer; |
| |
| import org.eclipse.core.runtime.preferences.IEclipsePreferences; |
| import org.eclipse.core.runtime.preferences.InstanceScope; |
| import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener; |
| import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent; |
| 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.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.Table; |
| import org.eclipse.test.internal.performance.results.db.DB_Results; |
| 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.ResultsElement; |
| import org.eclipse.test.internal.performance.results.model.ScenarioResultsElement; |
| import org.eclipse.test.internal.performance.results.utils.IPerformancesConstants; |
| import org.eclipse.ui.IActionBars; |
| import org.eclipse.ui.IMemento; |
| import org.eclipse.ui.IViewSite; |
| import org.eclipse.ui.PartInitException; |
| 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: |
| * <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><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 { |
| |
| // Constants |
| private static final String ORG_ECLIPSE = "org.eclipse."; |
| |
| // SWT resources |
| CTabFolder tabFolder; |
| |
| // Model information |
| ConfigTab[] tabs; |
| ComponentResultsElement componentResultsElement; |
| |
| // Action |
| Action fullLineSelection; |
| Action filterNonFingerprints; |
| Action filterNonImportantBuilds; |
| 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 = new InstanceScope().getNode(IPerformancesConstants.PLUGIN_ID); |
| this.preferences.addPreferenceChangeListener(this); |
| } |
| |
| /* |
| * 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()); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) |
| */ |
| 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 |
| PerformancesView performancesView = (PerformancesView) PerformancesView.getWorkbenchView("org.eclipse.test.internal.performance.results.ui.ComponentsView"); |
| if (performancesView != null) { |
| performancesView.viewer.addSelectionChangedListener(this); |
| } |
| |
| // Set actions |
| 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() { |
| String[] configNames = DB_Results.getConfigs(); |
| String[] configDescriptions = DB_Results.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); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * @see org.eclipse.ui.part.WorkbenchPart#dispose() |
| */ |
| 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 local pull-down menu with: |
| * - filter nightly builds |
| * - filter non-milestone builds |
| * - filter non-fingerprint scenarios |
| */ |
| void fillLocalPullDown(IMenuManager manager) { |
| manager.add(this.filterNightlyBuilds); |
| manager.add(this.filterNonImportantBuilds); |
| manager.add(new Separator()); |
| manager.add(this.filterNonFingerprints); |
| } |
| |
| /* |
| * Fill the local tool bar with: |
| * - change line selection display |
| */ |
| void fillLocalToolBar(IToolBarManager manager) { |
| manager.add(this.fullLineSelection); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * @see org.eclipse.ui.part.ViewPart#init(org.eclipse.ui.IViewSite, org.eclipse.ui.IMemento) |
| */ |
| 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) { |
| 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.filterNonFingerprints = new Action("Filter non-fingerprint scenarios", IAction.AS_CHECK_BOX) { |
| public void run() { |
| ComponentResultsView.this.preferences.putBoolean(IPerformancesConstants.PRE_FILTER_NON_FINGERPRINT_SCENARIOS, isChecked()); |
| resetTabFolders(false/*refresh*/); |
| } |
| }; |
| this.filterNonFingerprints.setChecked(true); |
| this.filterNonFingerprints.setToolTipText("Show only fingerprints scenarios"); |
| |
| // Filter non-important builds action |
| this.filterNonImportantBuilds = new Action("Filter non-important builds", IAction.AS_CHECK_BOX) { |
| public void run() { |
| ComponentResultsView.this.preferences.putBoolean(IPerformancesConstants.PRE_FILTER_NON_MILESTONES_BUILDS, isChecked()); |
| resetTabFolders(false/*refresh*/); |
| } |
| }; |
| this.filterNonImportantBuilds.setChecked(false); |
| this.filterNonImportantBuilds.setToolTipText("Show only important builds (i.e. milestones and recent builds)"); |
| |
| // Filter baselines action |
| this.filterNightlyBuilds = new Action("Filter nightly builds", IAction.AS_CHECK_BOX) { |
| public void run() { |
| ComponentResultsView.this.preferences.putBoolean(IPerformancesConstants.PRE_FILTER_NIGHTLY_BUILDS, isChecked()); |
| resetTabFolders(false/*refresh*/); |
| } |
| }; |
| this.filterNightlyBuilds.setToolTipText("Do not show nightly builds in table"); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener#preferenceChange(org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent) |
| */ |
| public void preferenceChange(PreferenceChangeEvent event) { |
| String propertyName = event.getKey(); |
| Object newValue = event.getNewValue(); |
| |
| // Filter non-fingerprints change |
| if (propertyName.equals(IPerformancesConstants.PRE_FILTER_NON_FINGERPRINT_SCENARIOS)) { |
| boolean checked = newValue == null ? IPerformancesConstants.DEFAULT_FILTER_NON_FINGERPRINT_SCENARIOS : "true".equals(newValue); |
| this.filterNonFingerprints.setChecked(checked); |
| resetTabFolders(false/*refresh*/); |
| } |
| |
| // Filter non-milestone change |
| if (propertyName.equals(IPerformancesConstants.PRE_FILTER_NON_MILESTONES_BUILDS)) { |
| boolean checked = newValue == null ? IPerformancesConstants.DEFAULT_FILTER_NON_MILESTONES_BUILDS : "true".equals(newValue); |
| this.filterNonImportantBuilds.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(); |
| } |
| |
| // 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 ? false : state.booleanValue(); |
| this.fullLineSelection.setChecked(fullLine); |
| } |
| |
| // Filter non fingerprints action state |
| boolean checked = this.preferences.getBoolean(IPerformancesConstants.PRE_FILTER_NON_FINGERPRINT_SCENARIOS, IPerformancesConstants.DEFAULT_FILTER_NON_FINGERPRINT_SCENARIOS); |
| this.filterNonFingerprints.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_NON_MILESTONES_BUILDS, IPerformancesConstants.DEFAULT_FILTER_NON_MILESTONES_BUILDS); |
| this.filterNonImportantBuilds.setChecked(checked); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * @see org.eclipse.ui.part.ViewPart#saveState(org.eclipse.ui.IMemento) |
| */ |
| public void saveState(IMemento memento) { |
| super.saveState(memento); |
| memento.putBoolean(IPerformancesConstants.PRE_FULL_LINE_SELECTION, this.fullLineSelection.isChecked()); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent) |
| */ |
| 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); |
| } |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * @see org.eclipse.ui.part.WorkbenchPart#setFocus() |
| */ |
| 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()); |
| } |
| |
| } |