/** Makes the chart show category labels or not. */
 private void updateCategories() {
   if (chart != null) {
     IAxisSet axisSet = chart.getAxisSet();
     if (axisSet != null) {
       IAxis xAxis = axisSet.getXAxis(0);
       if (xAxis != null) {
         String[] series = xAxis.getCategorySeries();
         if (series != null) {
           boolean enoughSpace =
               chart.getPlotArea().getSize().x / series.length >= MIN_CATEGORY_WIDTH;
           xAxis.enableCategory(enoughSpace);
           xAxis.getTick().setVisible(enoughSpace);
         }
       }
     }
   }
 }
  @Override
  protected Composite createBody(Composite parent) {
    Composite composite = new Composite(parent, SWT.NONE);
    composite.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));

    chart = new ScatterChart(composite);
    chart.getTitle().setText(getTitle());
    chart.getTitle().setVisible(false);

    IAxis xAxis = chart.getAxisSet().getXAxis(0);
    xAxis.getTitle().setText(Messages.LabelVolatility);
    xAxis.getTick().setFormat(new DecimalFormat("0.##%")); // $NON-NLS-1$

    IAxis yAxis = chart.getAxisSet().getYAxis(0);
    yAxis.getTitle().setText(Messages.LabelPeformanceTTWROR);
    yAxis.getTick().setFormat(new DecimalFormat("0.##%")); // $NON-NLS-1$

    ((IPlotArea) chart.getPlotArea())
        .addCustomPaintListener(
            new ICustomPaintListener() {
              @Override
              public void paintControl(PaintEvent e) {
                int y = xAxis.getPixelCoordinate(0);
                e.gc.drawLine(y, 0, y, e.height);

                int x = yAxis.getPixelCoordinate(0);
                e.gc.drawLine(0, x, e.width, x);
              }

              @Override
              public boolean drawBehindSeries() {
                return true;
              }
            });

    picker = new ChartConfigurator(composite, this, ChartConfigurator.Mode.RETURN_VOLATILITY);
    picker.setListener(() -> updateChart());

    GridLayoutFactory.fillDefaults().numColumns(1).margins(0, 0).spacing(0, 0).applyTo(composite);
    GridDataFactory.fillDefaults().grab(true, true).applyTo(chart);
    GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.FILL).applyTo(picker);

    setChartSeries();

    return composite;
  }
  private void showData(List<IStoreItem> res) {
    Iterator<IStoreItem> iter = res.iterator();

    // clear the graph
    ISeries[] coll = chart.getSeriesSet().getSeries();
    for (int i = 0; i < coll.length; i++) {
      ISeries iSeries = coll[i];
      chart.getSeriesSet().deleteSeries(iSeries.getId());
    }

    while (iter.hasNext()) {
      ICollection iCollection = (ICollection) iter.next();
      TimeFrequencyBins.BinnedData bins = null;
      if (iCollection.isTemporal()) {
        if (iCollection.size() > 1) {
          if (iCollection.size() <= MAX_SIZE) {
            IBaseTemporalCollection thisQ = (IBaseTemporalCollection) iCollection;
            bins = TimeFrequencyBins.doBins(iCollection, thisQ);

            String seriesName = iCollection.getName();
            ILineSeries newSeries =
                (ILineSeries) chart.getSeriesSet().createSeries(SeriesType.LINE, seriesName);
            newSeries.setSymbolType(PlotSymbolType.NONE);
            newSeries.enableArea(true);
            newSeries.setLineColor(PlottingHelpers.colorFor(seriesName));

            Date[] xData = new Date[bins.size() * 2];
            double[] yData = new double[bins.size() * 2];

            // put the data into series
            int ctr = 0;
            Iterator<Bin> iter2 = bins.iterator();
            while (iter2.hasNext()) {
              Bin bin = (TimeFrequencyBins.Bin) iter2.next();
              xData[ctr] = new Date(bin.lowerVal);
              yData[ctr++] = bin.freqVal;
              xData[ctr] = new Date(bin.upperVal);
              yData[ctr++] = bin.freqVal;
            }

            newSeries.setXDateSeries(xData);
            newSeries.setYSeries(yData);

            newSeries.enableStack(true);
            newSeries.enableArea(true);

            // adjust the axis range
            chart.getAxisSet().adjustRange();
            IAxis xAxis = chart.getAxisSet().getXAxis(0);
            xAxis.enableCategory(false);

            // set the y axis min to be zero
            Range yRange = chart.getAxisSet().getYAxis(0).getRange();
            chart.getAxisSet().getYAxis(0).setRange(new Range(0, yRange.upper));

            chart.redraw();
          }
        }
      }
    }
  }
  /** Resets the chart */
  private void resetChart() {

    if (chart != null) {
      chart.dispose();
    }
    chart = new Chart(root, SWT.NONE);
    chart.setOrientation(SWT.HORIZONTAL);

    // Show/Hide axis
    chart.addControlListener(
        new ControlAdapter() {
          @Override
          public void controlResized(ControlEvent arg0) {
            updateCategories();
          }
        });

    // TODO: Seems to not work on GTK although it did before
    chart
        .getPlotArea()
        .addListener(
            SWT.MouseMove,
            new Listener() {
              @Override
              public void handleEvent(Event event) {
                IAxisSet axisSet = chart.getAxisSet();
                StringBuilder builder = new StringBuilder();
                if (axisSet != null) {
                  IAxis xAxis = axisSet.getXAxis(0);
                  if (xAxis != null) {
                    String[] series = xAxis.getCategorySeries();
                    ISeries[] data = chart.getSeriesSet().getSeries();
                    int x = (int) Math.round(xAxis.getDataCoordinate(event.x));
                    if (x >= 0 && x < series.length) {
                      for (int i = 0; i < data.length; i++) {
                        ISeries yseries = data[i];
                        builder.append(yseries.getId());
                        builder.append("("); // $NON-NLS-1$
                        builder.append(series[x]);
                        builder.append(", "); // $NON-NLS-1$
                        builder.append(yseries.getYSeries()[x]);
                        builder.append(")"); // $NON-NLS-1$
                        if (i < data.length - 1) {
                          builder.append(", "); // $NON-NLS-1$
                        }
                      }
                    }
                  }
                }
                if (builder.length() != 0) {
                  chart.getPlotArea().setToolTipText(builder.toString());
                } else {
                  chart.getPlotArea().setToolTipText(null);
                }
              }
            });

    // Update font
    FontData[] fd = chart.getFont().getFontData();
    fd[0].setHeight(8);
    final Font font = new Font(chart.getDisplay(), fd[0]);
    chart.setFont(font);
    chart.addDisposeListener(
        new DisposeListener() {
          public void widgetDisposed(DisposeEvent arg0) {
            if (font != null && !font.isDisposed()) {
              font.dispose();
            }
          }
        });

    // Update title
    ITitle graphTitle = chart.getTitle();
    graphTitle.setText(""); // $NON-NLS-1$
    graphTitle.setFont(chart.getFont());

    // Set colors
    chart.setBackground(root.getBackground());
    chart.setForeground(root.getForeground());

    // OSX workaround
    if (System.getProperty("os.name").toLowerCase().contains("mac")) { // $NON-NLS-1$ //$NON-NLS-2$
      int r = chart.getBackground().getRed() - 13;
      int g = chart.getBackground().getGreen() - 13;
      int b = chart.getBackground().getBlue() - 13;
      r = r > 0 ? r : 0;
      r = g > 0 ? g : 0;
      r = b > 0 ? b : 0;
      final Color background = new Color(chart.getDisplay(), r, g, b);
      chart.setBackground(background);
      chart.addDisposeListener(
          new DisposeListener() {
            public void widgetDisposed(DisposeEvent arg0) {
              if (background != null && !background.isDisposed()) {
                background.dispose();
              }
            }
          });
    }

    // Initialize axes
    IAxisSet axisSet = chart.getAxisSet();
    IAxis yAxis = axisSet.getYAxis(0);
    IAxis xAxis = axisSet.getXAxis(0);
    ITitle xAxisTitle = xAxis.getTitle();
    xAxisTitle.setText(""); // $NON-NLS-1$
    xAxis.getTitle().setFont(chart.getFont());
    yAxis.getTitle().setFont(chart.getFont());
    xAxis.getTick().setFont(chart.getFont());
    yAxis.getTick().setFont(chart.getFont());
    xAxis.getTick().setForeground(chart.getForeground());
    yAxis.getTick().setForeground(chart.getForeground());
    xAxis.getTitle().setForeground(chart.getForeground());
    yAxis.getTitle().setForeground(chart.getForeground());

    // Initialize y-axis
    ITitle yAxisTitle = yAxis.getTitle();
    yAxisTitle.setText(Resources.getMessage("ViewRisksPlotUniquenessEstimates.0")); // $NON-NLS-1$
    chart.setEnabled(false);
    updateCategories();
  }