Package org.eclipse.test.internal.performance.results.ui

Source Code of org.eclipse.test.internal.performance.results.ui.ConfigTab

/*******************************************************************************
* 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.text.NumberFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseTrackListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.ToolTip;
import org.eclipse.test.internal.performance.results.db.ComponentResults;
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.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;


/**
* Tab to display all performances results numbers for a configuration (i.e a performance machine).
*/
public class ConfigTab {

  // Formats
  static final NumberFormat PERCENTAGE_FORMAT = NumberFormat.getPercentInstance(Locale.US);
  static {
    PERCENTAGE_FORMAT.setMaximumFractionDigits(2);
  }

  // Colors
  static final Display DEFAULT_DISPLAY = Display.getDefault();
  static final Color BLUE= DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_BLUE);
  static final Color DARK_GREEN= DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_DARK_GREEN);
  static final Color GRAY = DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_GRAY);
  static final Color MAGENTA = DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_MAGENTA);
  static final Color RED = DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_RED);

  // SWT resources
  Shell shell;
  Display display;
  Table table;
  private GC gc;
  private Color lightred;
  private Color lightyellow;
  private Color darkyellow;
  private Color blueref;
  private Font boldFont;
  private Font italicFont;
  private Font boldItalicFont;
  Map toolTips;

  // Information
  String configBox, configName;
  ComponentResultsElement results;
  double[][] allValues;
  double[][] allErrors;

  // Cells management
  Point tableOrigin, tableSize;
  int columnsCount, rowsCount;
  List firstLine;

  // Eclipse preferences
  private IEclipsePreferences preferences;

/*
* Default constructor.
*/
public ConfigTab(String name, String box) {
    this.configName = name;
    int idx = box.indexOf(" (");
  this.configBox = idx > 0 ? box.substring(0, idx) : box;
  this.preferences = InstanceScope.INSTANCE.getNode(IPerformancesConstants.PLUGIN_ID);
}

/**
* Creates the tab folder page.
*
* @param tabFolder org.eclipse.swt.widgets.TabFolder
* @param fullSelection Tells whether the table should have a full line selection or not
* @return the new page for the tab folder
*/
Composite createTabFolderPage (ComponentResultsElement componentResultsElement, CTabFolder tabFolder, boolean fullSelection) {
  // Cache the shell and display.
  this.shell = tabFolder.getShell();
  this.display = this.shell.getDisplay();

  // Remove old table is present
  boolean initResources = this.table == null;
  if (this.table != null) {
    disposeTable();
  }

  // Store results
  this.results = componentResultsElement;

  // Create the "children" table
  int style = SWT.MULTI | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL;
  if (fullSelection) style |= SWT.FULL_SELECTION;
  this.table = new Table(tabFolder, style);
  this.table.setLinesVisible (true);
  this.table.setHeaderVisible (true);
  GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1);
  gridData.heightHint = 150;
  this.table.setLayoutData (gridData);
  this.gc = new GC(this.table);

  // Init resources
  if (initResources) initResources();

  // Add columns to the table
  boolean fingerprints = this.preferences.getBoolean(IPerformancesConstants.PRE_FILTER_ADVANCED_SCENARIOS, IPerformancesConstants.DEFAULT_FILTER_ADVANCED_SCENARIOS);
  String [] columnHeaders = getLayoutDataFieldNames(fingerprints);
  int length = columnHeaders.length;
  for (int i = 0; i < length; i++) {
    TableColumn column = new TableColumn(this.table, SWT.CENTER);
    column.setText (columnHeaders [i]);
  }

  // Add lines to the table
  this.toolTips = new HashMap();
  fillTableLines(fingerprints);

  // Updated columns
  for (int i=0; i<length; i++) {
    TableColumn column = this.table.getColumn(i);
    column.setWidth(i==0?120:100);
    if (i > 0) {
      String text = (String) this.firstLine.get(i);
      column.setToolTipText(text);
    }
  }

  // Store table info
  this.columnsCount = length;

  // Listen to mouse events to select the corresponding build in the components view
  // when a click is done in the table cell.
  final ComponentsView componentsView = (ComponentsView) PerformancesView.getWorkbenchView("org.eclipse.test.internal.performance.results.ui.ComponentsView");
  MouseListener mouseListener = new MouseListener() {
    public void mouseUp(MouseEvent e) {
    }
    public void mouseDown(MouseEvent e) {
      Point cellPosition = currentCellPosition(e.x, e.y);
      Table tabTable = ConfigTab.this.table;
      componentsView.select(ConfigTab.this.results, ConfigTab.this.configName, (String) ConfigTab.this.firstLine.get(cellPosition.x), tabTable.getItem(cellPosition.y).getText());
    }
    public void mouseDoubleClick(MouseEvent e) {
    }
  };
  this.table.addMouseListener(mouseListener);

  // Listen to mouse track events to display the table cell corresponding tooltip.
  MouseTrackListener mouseTrackListener = new MouseTrackListener() {
    ToolTip currentTooltip;
    public void mouseHover(MouseEvent e) {
      if (this.currentTooltip != null) {
        this.currentTooltip.setVisible(false);
        this.currentTooltip = null;
      }
      Point cellPosition = currentCellPosition(e.x, e.y);
      if (cellPosition != null) {
        ToolTip tooltip = (ToolTip) ConfigTab.this.toolTips.get(cellPosition);
        if (tooltip != null) {
          Point location = ConfigTab.this.table.toDisplay(new Point(e.x, e.y));
          tooltip.setLocation(location);
          tooltip.setVisible(true);
          this.currentTooltip = tooltip;
        }
      }
    }
    public void mouseEnter(MouseEvent e) {
    }
    public void mouseExit(MouseEvent e) {
    }
  };
  this.table.addMouseTrackListener(mouseTrackListener);

  // Select the first line by default (as this is the current build)
  this.table.select(0);

  // Return the built composite
  return this.table;
}

/*
* Create and store a tooltip with the given information and at the given position.
*/
void createToolTip(String toolTipText, String toolTipMessage, int toolTipStyle, Point position) {
  ToolTip toolTip = new ToolTip(this.table.getShell(), toolTipStyle);
  toolTip.setAutoHide(true);
  toolTip.setText(toolTipText);
  toolTip.setMessage(/*"("+col+","+row+") "+*/toolTipMessage);
  this.toolTips.put(position, toolTip);
}

/*
* Get the current cell position (column, row) from a point position.
*/
Point currentCellPosition(int x, int y) {

  // Compute the origin of the visible area
  if (this.tableOrigin == null) {
    this.tableOrigin = new Point(0, this.table.getHeaderHeight());
  }

  // Increment width until over current y position
  int height= this.tableOrigin.y;
  int row = this.table.getTopIndex();
  while (row<this.rowsCount && height<y) {
    height += this.table.getItemHeight();
    row++;
  }
  if (height < y) {
    // return when position is over the last line
    return null;
  }
  row--;

  // Increment width until being over current x position
  int col = 0;
  TableItem tableItem = this.table.getItem(row);
  Rectangle bounds = tableItem.getBounds(col);
  while (col<this.columnsCount) {
    int max = bounds.x + bounds.width + this.table.getGridLineWidth();
    if (x <= max) break;
    if (col == this.columnsCount) {
      // return when position is over the last column
      return null;
    }
    col++;
    bounds = tableItem.getBounds(col);
  }

  // Return the found table cell position
  return new Point(col, row);
}

/*
* Dispose all SWT resources.
*/
public void dispose() {
  if (this.boldFont != null) {
    this.boldFont.dispose();
  }
  if (this.italicFont != null) {
    this.italicFont.dispose();
  }
  if (this.boldItalicFont != null) {
    this.boldItalicFont.dispose();
  }
  if (this.darkyellow != null) {
    this.darkyellow.dispose();
  }
  if (this.lightyellow != null) {
    this.lightyellow.dispose();
  }
  if (this.lightred != null) {
    this.lightred.dispose();
  }
  if (this.blueref != null) {
    this.blueref.dispose();
  }
  disposeTable();
}

/*
* Dispose all SWT controls associated with the table.
*/
private void disposeTable() {
  if (this.toolTips != null) {
    Iterator cells = this.toolTips.keySet().iterator();
    while (cells.hasNext()) {
      ToolTip toolTip = (ToolTip) this.toolTips.get(cells.next());
      toolTip.dispose();
    }
  }
  this.table.dispose();
  this.tableOrigin = null;
  this.firstLine = null;
}

/*
* Fill the lines of the tables.
* Get all the information from the model which are returned in a list (lines) of lists (columns).
*/
private void fillTableLines(boolean fingerprints) {

  // Get preferences information
  boolean onlyMilestones = this.preferences.getBoolean(IPerformancesConstants.PRE_FILTER_OLD_BUILDS, IPerformancesConstants.DEFAULT_FILTER_OLD_BUILDS);
  boolean skipNightlyBuilds = this.preferences.getBoolean(IPerformancesConstants.PRE_FILTER_NIGHTLY_BUILDS, IPerformancesConstants.DEFAULT_FILTER_NIGHTLY_BUILDS);

  // Get model information
  if (this.results == null) return;
  List differences = this.results.getConfigNumbers(this.configName, fingerprints);
  if (differences == null) return;

  // Store first information line which are the scenarios full names
  Iterator lines = differences.iterator();
  this.firstLine = (List) lines.next();

  // Read each information line (one line per build results)
  Object[] scenarios = this.results.getChildren(null);
  double[] deviations = new double[scenarios.length];
  int row = 0;
  while (lines.hasNext()) {
    List line = (List) lines.next();
    int size = line.size();

    // The first column is the build name
    String buildName = (String) line.get(0);
    String milestoneName = Util.getMilestoneName(buildName);
    TableItem item = null;

    // Set item if the line is not filtered
    Font italic;
    if (milestoneName != null) {
      item = new TableItem (this.table, SWT.NONE);
      item.setText(milestoneName + " - " + buildName);
      item.setFont(0, this.boldFont);
      if (!onlyMilestones) item.setBackground(this.blueref);
      italic = this.boldItalicFont;
    } else {
      if ((onlyMilestones && Util.getNextMilestone(buildName) != null) ||
        (skipNightlyBuilds && buildName.charAt(0) == 'N')) {
        // skip line
        continue;
      }
      item = new TableItem (this.table, SWT.NONE);
      item.setText(0, buildName);
      italic = this.italicFont;
    }

    // Read each column value
    String baselineName = null;
    for (int col=1; col<size; col++) {

      // Reset tooltip info
      String toolTipText = null;
      String toolTipMessage = null;
      int toolTipStyle = SWT.BALLOON;

      // Otherwise get values for a scenario
      Font italic2 = italic;
      ScenarioResultsElement scenarioResultsElement = (ScenarioResultsElement) scenarios[col-1];
      if (milestoneName != null || (!fingerprints && scenarioResultsElement.hasSummary())) {
        italic2 = this.boldItalicFont;
        item.setFont(col, this.boldFont);
      }
      // Otherwise get values for a scenario
      double[] values = (double[]) line.get(col);
      if (values == ComponentResults.NO_BUILD_RESULTS) {
        item.setText(col, "Missing");
        item.setForeground(col, GRAY);
        item.setFont(col, italic2);
      } else if (values == ComponentResults.INVALID_RESULTS) {
        item.setText(col, "Invalid");
        item.setForeground(col, RED);
        item.setFont(col, italic2);
      } else {
        // Get values array
        double buildValue = values[ComponentResults.BUILD_VALUE_INDEX];
        double baselineValue = values[ComponentResults.BASELINE_VALUE_INDEX];
        double delta = values[ComponentResults.DELTA_VALUE_INDEX];
        double error = values[ComponentResults.DELTA_ERROR_INDEX];

        // Set text with delta value
        item.setText(col, PERCENTAGE_FORMAT.format(delta));

        // Compute the tooltip to display on the cell
        if (error > 0.03) {
          // error is over the 3% threshold
          item.setImage(col, ResultsElement.WARN_IMAGE);
          item.setForeground(col, this.darkyellow);
          if (toolTipText == null) {
            toolTipText = "";
          } else {
            toolTipText += ", ";
          }
          toolTipText += "May be not reliable";
          if (toolTipMessage == null) {
            toolTipMessage = "";
          } else {
            toolTipMessage += ".\n";
          }
          toolTipMessage += "The error on this result is "+PERCENTAGE_FORMAT.format(error)+", hence it may be not reliable";
          toolTipStyle |= SWT.ICON_WARNING;
        }
        if (delta < -0.1) {
          // delta < -10%: failure shown by an red-cross icon + text in red
          item.setImage(col, ResultsElement.ERROR_IMAGE);
          item.setForeground(col, RED);
        } else if (delta < -0.05) {
          // negative delta over 5% shown in red
          item.setForeground(col, RED);
        } else if (delta < 0) {
          // negative delta shown in magenta
          item.setForeground(col, MAGENTA);
        } else if (delta > 0.2) {
          // positive delta over 20% shown in green
          item.setForeground(col, DARK_GREEN);
        } else if (delta > 0.1) {
          // positive delta between 10% and 20% shown in blue
          item.setForeground(col, BLUE);
        }

        // Moderate the status if the build value or the difference is small
        if (delta < 0) {
          double diff = Math.abs(baselineValue - buildValue);
          if (buildValue < 100 || diff < 100) {
            if (toolTipText == null) {
              toolTipText = "";
            } else {
              toolTipText += ", ";
            }
            toolTipText += "Small value";
            if (toolTipMessage == null) {
              toolTipMessage = "";
            } else {
              toolTipMessage += ".\n";
            }
            if (buildValue < 100) {
              toolTipMessage += "This test has a small value ("+buildValue+"ms)";
            } else {
              toolTipMessage += "This test variation has a small value ("+diff+"ms)";
            }
            toolTipMessage +=  ", hence it may not be necessary to spend time on fixing this possible regression";
            // set the text in italic
            item.setFont(col, italic2);
            toolTipStyle |= SWT.ICON_INFORMATION;
          }
        }

        // Add information in tooltip when history shows big variation
        if (deviations[col-1] < 0) {
          ConfigResultsElement configResultsElement = (ConfigResultsElement) scenarioResultsElement.getResultsElement(this.configName);
          double[] stats = configResultsElement.getStatistics();
          deviations[col-1] = stats[3];
        }
        if (deviations[col-1] > 20) {
          // deviation is over 20% over the entire history
          if (toolTipText == null) {
            toolTipText = "";
          } else {
            toolTipText += ", ";
          }
          toolTipText += "History shows erratic values";
          if (toolTipMessage == null) {
            toolTipMessage = "";
          } else {
            toolTipMessage += ".\n";
          }
          toolTipMessage += "The results history shows that the variation of its delta is over 20% ("+PERCENTAGE_FORMAT.format(deviations[col-1])+"), hence its result is surely not reliable";
          // set the text in italic
          item.setFont(col, italic2);
          toolTipStyle |= SWT.ICON_INFORMATION;
        } else if (deviations[col-1] > 10) { // moderate the status when the test
          // deviation is between 10% and 20% over the entire history
          if (toolTipText == null) {
            toolTipText = "";
          } else {
            toolTipText += ", ";
          }
          toolTipText += "History shows unstable values";
          if (toolTipMessage == null) {
            toolTipMessage = "";
          } else {
            toolTipMessage += ".\n";
          }
          toolTipMessage += "The results history shows that the variation of its delta is between 10% and 20% ("+PERCENTAGE_FORMAT.format(deviations[col-1])+"), hence its result may not be really reliable";
          // set the text in italic
          item.setFont(col, italic2);
          if (toolTipStyle == SWT.BALLOON && delta >= -0.1) {
            toolTipStyle |= SWT.ICON_INFORMATION;
          } else {
            // reduce icon severity from error to warning
            toolTipStyle |= SWT.ICON_WARNING;
          }
        }
      }

      // Set tooltip
      if (toolTipText != null) {
        createToolTip(toolTipText, toolTipMessage, toolTipStyle, new Point(col, row));
      }

      // Baseline name
      ConfigResultsElement configResultsElement = (ConfigResultsElement) scenarioResultsElement.getResultsElement(this.configName);
      if (configResultsElement != null) {
        String configBaselineName = configResultsElement.getBaselineBuildName(buildName);
        if (baselineName == null) {
          baselineName = configBaselineName;
        } else if (baselineName.indexOf(configBaselineName) < 0) {
          baselineName += ", " +configBaselineName;
        }
      }
    }

    // Set the tooltip over the build name
    if (baselineName != null) {
      createToolTip(buildName, "Baseline: "+baselineName, SWT.BALLOON | SWT.ICON_INFORMATION, new Point(0, row));
    }

    // Increment row counter
    row++;
  }
  this.rowsCount = row;
}

/*
* Get the columns name.
*/
private String[] getLayoutDataFieldNames(boolean fingerprints) {
  if (this.results == null) {
    return new String[0];
  }
  List labels = this.results.getScenariosLabels(fingerprints);
  labels.add(0, "Build");
  String[] names = new String[labels.size()];
  labels.toArray(names);
  return names;
}

/*
* The tab text is the full machine name.
*/
public String getTabText() {
  return this.configBox;
}

/*
* Init the SWT resources
*/
private void initResources() {
  // Fonts
  String fontDataName = this.gc.getFont().getFontData()[0].toString();
  FontData fdItalic = new FontData(fontDataName);
  fdItalic.setStyle(SWT.ITALIC);
  this.italicFont = new Font(this.display, fdItalic);
  FontData fdBold = new FontData(fontDataName);
  fdBold.setStyle(SWT.BOLD);
  this.boldFont = new Font(this.display, fdBold);
  FontData fdBoldItalic = new FontData(fontDataName);
  fdBoldItalic.setStyle(SWT.BOLD | SWT.ITALIC);
  this.boldItalicFont = new Font(this.display, fdBoldItalic);

  // Colors
  this.lightred = new Color(DEFAULT_DISPLAY, 220, 50, 50);
  this.lightyellow = new Color(DEFAULT_DISPLAY, 255, 255, 160);
  this.darkyellow = new Color(DEFAULT_DISPLAY, 160, 160, 0);
  this.blueref = new Color(DEFAULT_DISPLAY, 200, 200, 255);
}

/*
* Select the line corresponding to the given build.
*/
void select(BuildResultsElement buildResultsElement) {
  int count = this.table.getItemCount();
  String buildName = buildResultsElement.getName();
  TableItem[] items = this.table.getItems();
  for (int i=0; i<count; i++) {
    if (items[i].getText().endsWith(buildName)) {
      this.table.deselect(this.table.getSelectionIndex());
      this.table.select(i);
      return;
    }
  }
}
}
TOP

Related Classes of org.eclipse.test.internal.performance.results.ui.ConfigTab

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.