/** Used to find the global attributes that another inspector has set so I can share it. */
  ChartGenerator chartToUse(final String sName, Frame parent, final GUIState simulation) {
    Bag charts = new Bag();
    if (simulation.guiObjects != null)
      for (int i = 0; i < simulation.guiObjects.numObjs; i++)
        if (simulation.guiObjects.objs[i] instanceof ChartGenerator
            && validChartGenerator((ChartGenerator) (simulation.guiObjects.objs[i])))
          charts.add(simulation.guiObjects.objs[i]);
    if (charts.numObjs == 0) return createNewChart(simulation);

    // init the dialog panel
    JPanel p = new JPanel();
    p.setLayout(new BorderLayout());

    String[] chartNames = new String[charts.numObjs + 1];

    chartNames[0] = "[Create a New Chart]";
    for (int i = 0; i < charts.numObjs; i++)
      chartNames[i + 1] = ((ChartGenerator) (charts.objs[i])).getTitle();

    // add widgets
    JPanel panel2 = new JPanel();
    panel2.setLayout(new BorderLayout());
    panel2.setBorder(new javax.swing.border.TitledBorder("Plot on Chart..."));
    JComboBox encoding = new JComboBox(chartNames);
    panel2.add(encoding, BorderLayout.CENTER);
    p.add(panel2, BorderLayout.SOUTH);

    // ask
    if (JOptionPane.showConfirmDialog(
            parent, p, "Create a New Chart...", JOptionPane.OK_CANCEL_OPTION)
        != JOptionPane.OK_OPTION) return null;

    if (encoding.getSelectedIndex() == 0) return createNewChart(simulation);
    else return (ChartGenerator) (charts.objs[encoding.getSelectedIndex() - 1]);
  }
 private IntervalXYDataset getHistrogrammedDataAttributes(
     String[] attributes, long barsize, long timesize) {
   IntervalXYDataset dataset = null;
   if (no_intervals) {
     dataset = new XYSeriesCollection();
   } else {
     dataset = new YIntervalSeriesCollection();
   }
   for (int index = 0; index < attributes.length; index++) {
     Histogram histogram = new Histogram(barsize);
     String attribute = attributes[index];
     for (ProcessInstance pi : mylog.getInstances()) {
       Date begin;
       try {
         begin = pi.getAuditTrailEntryList().get(0).getTimestamp();
       } catch (Exception e) {
         Message.add(e.getMessage(), Message.ERROR);
         return null;
       } // starting time of process instance
       int j = 0;
       for (AuditTrailEntry ate : pi.getListOfATEs()) {
         if (ate.getAttributes().containsKey(attribute)) {
           Double val;
           val = Double.valueOf(ate.getAttributes().get(attribute));
           if (xbox.getSelectedIndex() == 2) {
             histogram.addValue(j, val);
           }
           if (xbox.getSelectedIndex() == 3) {
             histogram.addValue(timediff(begin, ate.getTimestamp()), val);
           }
           j++;
         }
       }
     }
     if (no_intervals) {
       ((XYSeriesCollection) dataset).addSeries(histogram.getXYSeries(attribute, timesize));
     } else {
       ((YIntervalSeriesCollection) dataset)
           .addSeries(histogram.getYIntervalSeries(attribute, timesize));
     }
   }
   return dataset;
 }
    public GlobalAttributes() {
      setLayout(new BorderLayout());
      LabelledList list =
          new LabelledList(includeAggregationMethodAttributes() ? "Add Data..." : "Redraw");
      add(list, BorderLayout.CENTER);

      if (includeAggregationMethodAttributes()) {
        NumberTextField stepsField =
            new NumberTextField(1, true) {
              public double newValue(double value) {
                value = (long) value;
                if (value <= 0) return currentValue;
                else {
                  interval = (long) value;
                  return value;
                }
              }
            };

        list.addLabelled("Every", stepsField);
        list.addLabelled("", new JLabel("...Timesteps"));

        String[] optionsLabel = {"Current", "Maximum", "Minimum", "Mean"};
        final JComboBox optionsBox = new JComboBox(optionsLabel);
        optionsBox.setSelectedIndex(aggregationMethod);
        optionsBox.addActionListener(
            new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                aggregationMethod = optionsBox.getSelectedIndex();
              }
            });
        list.addLabelled("Using", optionsBox);
      }

      String[] optionsLabel2 =
          new String[] {
            "When Adding Data",
            "Every 0.1 Seconds",
            "Every 0.5 Seconds",
            "Every Second",
            "Every 2 Seconds",
            "Every 5 Seconds",
            "Every 10 Seconds",
            "Never"
          };
      final JComboBox optionsBox2 = new JComboBox(optionsLabel2);
      optionsBox2.setSelectedIndex(redraw);
      optionsBox2.addActionListener(
          new ActionListener() {
            public void actionPerformed(ActionEvent e) {
              redraw = optionsBox2.getSelectedIndex();
              generator.update(); // keep up-to-date
            }
          });
      if (includeAggregationMethodAttributes()) list.addLabelled("Redraw", optionsBox2);
      else list.add(optionsBox2);
    }
  @Analyzer(
      name = "Event Data Attribute Visualizer",
      names = {"Log"})
  public JComponent analyze(LogReader log) {
    /*
     * this plugin takes a log, shows a list of available data-attributes
     * and a list of cases After selecting a data-attribute (and possibly a
     * case) a graph is made of the value of the data-attribute against
     * either time or against the sequence of events.
     *
     * input: log with data attributes gui-input: select a data-attribute,
     * choose time or event-sequence, and possibly a case
     *
     * internally : if not caseselected -> scatterplot of values against
     * time/event-number else show graph for value against time/event-number
     *
     * createGraph : check number / string
     */
    mylog = log;
    mainPanel = new JPanel();
    mainPanel.setLayout(new BorderLayout());

    chartPanel = new JPanel();
    chartPanel.setLayout(new BoxLayout(chartPanel, BoxLayout.PAGE_AXIS));

    optionsPanel = new JPanel();
    optionsPanel.setLayout(new SpringLayout());

    JLabel attributelabel = new JLabel("Select attributes to use");
    attributeslist = new JList(getAttributes());
    attributeslist.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    attributeslist.setLayoutOrientation(JList.VERTICAL);
    optionsPanel.add(attributelabel);
    optionsPanel.add(attributeslist);

    JLabel xlabel = new JLabel("Chart type");
    String[] xvalues = new String[4];
    xvalues[0] = " Attribute values against event sequence";
    xvalues[1] = "Attribute values against timestamps";
    xvalues[2] = "Average attribute values against event sequence";
    xvalues[3] = "Average attribute values against timestamps";
    xbox = new JComboBox(xvalues);
    xbox.setMaximumSize(xbox.preferredSize());
    xbox.setSelectedIndex(1);

    xbox.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            JComboBox cb = (JComboBox) e.getSource();
            if (cb.getSelectedIndex() == 3) {
              BSpinner.setVisible(true);
            } else {
              BSpinner.setVisible(false);
            }
          };
        });

    optionsPanel.add(xlabel);
    optionsPanel.add(xbox);

    JLabel timelabel = new JLabel("show time by ");
    String[] timevalues = new String[4];
    timevalues[0] = "second";
    timevalues[1] = "minute";
    timevalues[2] = "hour";
    timevalues[3] = "day";
    timebox = new JComboBox(timevalues);
    timebox.setMaximumSize(timebox.preferredSize());
    timebox.setSelectedIndex(1);
    optionsPanel.add(timelabel);
    optionsPanel.add(timebox);

    SpinnerModel Bmodel = new SpinnerNumberModel(10, 2, 1000000, 1);
    BSpinner = new JSpinner(Bmodel);
    JLabel BLabel = new JLabel("Select histogram barsize");
    JLabel B2Label = new JLabel("used for average against timestamps");
    BSpinner.setMaximumSize(BSpinner.preferredSize());
    BSpinner.setVisible(false);
    optionsPanel.add(BLabel);
    optionsPanel.add(B2Label);
    optionsPanel.add(BSpinner);

    JButton updatebutton = new JButton("update");
    updatebutton.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {

            Object[] sels = attributeslist.getSelectedValues();
            String[] els = new String[sels.length];
            for (int i = 0; i < sels.length; i++) {
              els[i] = sels[i].toString();
            }

            long timesize = 1000;
            switch (timebox.getSelectedIndex()) {
              case 0:
                timesize = 1000;
                break;
              case 1:
                timesize = 1000 * 60;
                break;
              case 2:
                timesize = 1000 * 60 * 60;
                break;
              case 3:
                timesize = 1000 * 60 * 60 * 24;
                break;
            }

            String xname = null;
            JFreeChart mychart = null;
            if (xbox.getSelectedIndex() == 0) {
              data = getDataAttributes(els, false, timesize);
              xname = "Event sequence";
              mychart =
                  ChartFactory.createScatterPlot(
                      "Scatterplot of all values",
                      xname,
                      "attribute value",
                      data,
                      PlotOrientation.VERTICAL,
                      true,
                      true,
                      false);
            } else if (xbox.getSelectedIndex() == 1) {
              data = getDataAttributes(els, true, timesize);
              xname = "Time(" + timebox.getSelectedItem() + ") since beginning of the process";
              mychart =
                  ChartFactory.createScatterPlot(
                      "Scatterplot of all values",
                      xname,
                      "attribute value",
                      data,
                      PlotOrientation.VERTICAL,
                      true,
                      true,
                      false);
            } else if (xbox.getSelectedIndex() == 2) {
              xname = "Event sequence";
              data = getHistrogrammedDataAttributes(els, 1, 1);
              mychart =
                  ChartFactory.createXYLineChart(
                      "Average values",
                      xname,
                      "attribute value",
                      data,
                      PlotOrientation.VERTICAL,
                      true,
                      true,
                      false);
              mychart.setBackgroundPaint(Color.white);
              XYPlot plot = mychart.getXYPlot();

              plot.setBackgroundPaint(Color.white);
              plot.setDomainGridlinePaint(Color.white);
              plot.setRangeGridlinePaint(Color.white);

              DeviationRenderer renderer = new DeviationRenderer(true, true);
              renderer.setSeriesStroke(
                  0, new BasicStroke(3.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
              renderer.setSeriesStroke(0, new BasicStroke(2.0f));
              renderer.setSeriesStroke(1, new BasicStroke(2.0f));
              renderer.setSeriesStroke(2, new BasicStroke(2.0f));
              renderer.setSeriesStroke(3, new BasicStroke(2.0f));
              renderer.setSeriesFillPaint(0, Color.red);
              renderer.setSeriesFillPaint(1, Color.blue);
              renderer.setSeriesFillPaint(2, Color.green);
              renderer.setSeriesFillPaint(3, Color.orange);
              plot.setRenderer(renderer);
              // change the auto tick unit selection to integer units
              // only...
              NumberAxis yAxis = (NumberAxis) plot.getRangeAxis();
              // yAxis.setAutoRangeIncludesZero(false);
              yAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());

              NumberAxis xAxis = (NumberAxis) plot.getDomainAxis();
              xAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
            } else {
              xname = "Time(" + timebox.getSelectedItem() + "s) since beginning of the process";
              data =
                  getHistrogrammedDataAttributes(
                      els, ((Integer) BSpinner.getValue()) * timesize, timesize);
              mychart =
                  ChartFactory.createXYLineChart(
                      "Average values",
                      xname,
                      "attribute value",
                      data,
                      PlotOrientation.VERTICAL,
                      true,
                      true,
                      false);
              mychart.setBackgroundPaint(Color.white);
              XYPlot plot = mychart.getXYPlot();

              plot.setBackgroundPaint(Color.white);
              plot.setDomainGridlinePaint(Color.white);
              plot.setRangeGridlinePaint(Color.white);

              DeviationRenderer renderer = new DeviationRenderer(true, true);
              renderer.setSeriesStroke(
                  0, new BasicStroke(3.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
              renderer.setSeriesStroke(0, new BasicStroke(2.0f));
              renderer.setSeriesStroke(1, new BasicStroke(2.0f));
              renderer.setSeriesStroke(2, new BasicStroke(2.0f));
              renderer.setSeriesStroke(3, new BasicStroke(2.0f));
              renderer.setSeriesFillPaint(0, Color.red);
              renderer.setSeriesFillPaint(1, Color.blue);
              renderer.setSeriesFillPaint(2, Color.green);
              renderer.setSeriesFillPaint(3, Color.orange);
              plot.setRenderer(renderer);
              // change the auto tick unit selection to integer units
              // only...
              NumberAxis yAxis = (NumberAxis) plot.getRangeAxis();
              // yAxis.setAutoRangeIncludesZero(false);
              yAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
            }

            ChartPanel mychartpanel = new ChartPanel(mychart);
            mychartpanel.setBackground(Color.white);
            chartPanel.removeAll();
            chartPanel.add(mychartpanel);
            chartPanel.updateUI();
          };
        });
    optionsPanel.add(updatebutton);

    JSplitPane splitPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, optionsPanel, chartPanel);

    SpringUtils.makeCompactGrid(
        optionsPanel,
        10,
        1, // rows, cols
        6,
        2, // initX, initY
        6,
        2); // xPad, yPad

    mainPanel.add(splitPanel, BorderLayout.CENTER);
    return mainPanel;
  }