public JPanel createDemo() {
    model = new DefaultChartModel();
    demoPanel = new JPanel();
    Axis xAxis = new CategoryAxis<Country>(countries);
    xAxis.setLabel("Countries");
    Axis yAxis = new Axis(new NumericRange(0, 25));
    yAxis.setLabel("Numbers");
    chart = new Chart();
    chart.setXAxis(xAxis);
    chart.setYAxis(yAxis);
    Font titleFont = UIManager.getFont("Label.font").deriveFont(Font.BOLD, 14f);
    chart.setTitle(
        new AutoPositionedLabel("Chart with Categorical X Values", Color.blue, titleFont));
    chart.setVerticalGridLinesVisible(false);
    chart.setShadowVisible(true);
    model
        .addPoint(usa, 22)
        .addPoint(uk, 18)
        .addPoint(france, 13.5)
        .addPoint(germany, 12)
        .addPoint(russia, 8)
        .addPoint(china, 7);
    Color green = new Color(0, 170, 0);
    ChartStyle style = new ChartStyle(green, true, true);
    style.setLineWidth(6);
    style.setPointSize(20);
    chart.addModel(model, style).setPointRenderer(new SphericalPointRenderer());
    ChartStyle redHighlightStyle =
        new ChartStyle(new Color(200, 0, 0), PointShape.DISC, 20).withPointsAndLines();
    redHighlightStyle.setLineWidth(6);
    redHighlightStyle.setLineColor(green);
    chart.setHighlightStyle(redHighlight, redHighlightStyle);
    demoPanel.setLayout(new BorderLayout());
    demoPanel.add(chart, BorderLayout.CENTER);
    chart.addMouseMotionListener(
        new MouseMotionListener() {
          // Allow the user to drag _points in the vertical direction
          public void mouseDragged(MouseEvent e) {
            rollover(e);
            if (highlighted != null) {
              Point p = e.getPoint();
              Point2D userPoint = chart.calculateUserPoint(p);
              if (userPoint != null) {
                highlighted.setY(new RealPosition(userPoint.getY()));
              }
              chart.repaint();
            }
          }

          // Add a rollover effect
          public void mouseMoved(MouseEvent e) {
            rollover(e);
          }

          private void rollover(MouseEvent e) {
            Point p = e.getPoint();
            PointSelection selection = chart.nearestPoint(p, model);
            if (highlighted != null) {
              highlighted.setHighlight(null);
            }
            Chartable selected = selection.getSelected();
            Point2D selectedCoords =
                new Point2D.Double(selected.getX().position(), selected.getY().position());
            Point dp = chart.calculatePixelPoint(selectedCoords);
            // Only activate the rollover effect when within 50 pixels of a point
            if (p.distance(dp) < 50) {
              highlighted = (ChartPoint) selection.getSelected();
              highlighted.setHighlight(redHighlight);
              ChartCategory<?> x = (ChartCategory<?>) selected.getX();
              chart.setToolTipText(
                  String.format("%s : %.1f", x.getName(), selected.getY().position()));
            } else {
              chart.setToolTipText(null);
            }
            chart.repaint();
          }
        });
    chart.addMouseListener(
        new MouseAdapter() {
          @Override
          public void mouseExited(MouseEvent e) {
            if (highlighted != null) {
              highlighted.setHighlight(null);
              chart.repaint();
            }
          }
        });
    demoPanel.setPreferredSize(new Dimension(500, 500));
    return demoPanel;
  }
  public Component getDemoPanel() {
    if (demoPanel == null) {
      chart = new Chart();
      sineModel = createSineModel();
      cosModel = createCosineModel();
      sinePreferencePanel = new ChartPreferencePanel(chart, sineModel);
      cosinePreferencePanel = new ChartPreferencePanel(chart, cosModel);
      controlPanel = new ControlPanel();
      demoPanel = new JPanel();
      NumericRange yRange = new NumericRange(0, 50);
      NumericRange yRightRange = new NumericRange(-1, 1);
      Range<?> xRange = new NumericRange(0, 360);
      final Axis xAxis = new Axis(xRange);
      final Axis yAxis = new Axis(yRange);
      final Axis yRightAxis = new Axis(yRightRange);
      yAxis.setPlacement(AxisPlacement.LEADING);
      yRightAxis.setPlacement(AxisPlacement.TRAILING);
      yRightAxis.setLabel(new AutoPositionedLabel("Cosine Wave"));
      xAxis.setLabel(new AutoPositionedLabel("Angle (Degrees)"));
      yAxis.setLabel(new AutoPositionedLabel("Modified Sine Wave"));

      chart.setHorizontalMinorGridLinesVisible(true);
      chart.setVerticalMinorGridLinesVisible(true);
      chart.setMinorGridColor(Color.lightGray);
      Stroke dashes =
          new BasicStroke(
              1f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 1f, new float[] {1f, 2f}, 0f);
      chart.setHorizontalMinorGridStroke(dashes);
      chart.setVerticalMinorGridStroke(dashes);

      chart.setXAxis(xAxis);
      chart.setYAxis(yAxis);
      chart.addYAxis(yRightAxis);
      chart.setShadowVisible(true);

      ChartStyle sineStyle = new ChartStyle(Color.green, PointShape.BOX, Color.green);
      // sineStyle.setPointSize(1);
      chart.addModel(sineModel, sineStyle);
      sinePreferencePanel.setPointSize(5);
      sinePreferencePanel.setPointShape(PointShape.BOX);
      sinePreferencePanel.setPointColors(initialSineColor);
      sinePreferencePanel.setLineWidth(1);
      sinePreferencePanel.setLineColors(initialSineColor);
      sinePreferencePanel.setUsingLines(true);
      sinePreferencePanel.setUsingPoints(false);

      chart.addModel(cosModel, yRightAxis);
      ChartStyle cosStyle = new ChartStyle(Color.red, PointShape.DISC, Color.red);
      chart.setStyle(cosModel, cosStyle);
      cosinePreferencePanel.setPointSize(5);
      cosinePreferencePanel.setPointShape(PointShape.DISC);
      cosinePreferencePanel.setPointColors(initialCosineColor);
      cosinePreferencePanel.setLineWidth(1);
      cosinePreferencePanel.setLineColors(initialCosineColor);
      cosinePreferencePanel.setUsingLines(true);
      cosinePreferencePanel.setUsingPoints(false);

      // chart.setPanelBackground(new GradientPaint(0,0,Color.white, 800,
      // 800, Color.gray));

      RubberBandZoomer rubberBand = new RubberBandZoomer(chart);
      chart.addDrawable(rubberBand);
      chart.addMouseListener(rubberBand);
      chart.addMouseMotionListener(rubberBand);

      rubberBand.addZoomListener(
          new ZoomListener() {
            public void zoomChanged(ChartSelectionEvent event) {
              if (event instanceof RectangleSelectionEvent) {
                Range<?> currentXRange = chart.getXAxis().getOutputRange();
                Range<?> currentYRange = chart.getYAxis().getOutputRange();
                ZoomFrame frame = new ZoomFrame(currentXRange, currentYRange);
                zoomStack.push(frame);
                Rectangle selection = (Rectangle) event.getLocation();
                Point topLeft = selection.getLocation();
                Point bottomRight =
                    new Point(topLeft.x + selection.width, topLeft.y + selection.height);
                assert bottomRight.x >= topLeft.x;
                Point2D rp1 = chart.calculateUserPoint(topLeft);
                Point2D rp2 = chart.calculateUserPoint(bottomRight);
                if (rp1 != null && rp2 != null) {
                  assert rp2.getX() >= rp1.getX();
                  Range<?> xRange = new NumericRange(rp1.getX(), rp2.getX());
                  assert rp1.getY() >= rp2.getY();
                  Range<?> yRange = new NumericRange(rp2.getY(), rp1.getY());
                  xAxis.setRange(xRange);
                  yAxis.setRange(yRange);
                }
              } else if (event instanceof PointSelectionEvent) {
                if (zoomStack.size() > 0) {
                  ZoomFrame frame = zoomStack.pop();
                  Range<?> xRange = frame.getXRange();
                  Range<?> yRange = frame.getYRange();
                  xAxis.setRange(xRange);
                  yAxis.setRange(yRange);
                }
              }
            }
          });
      demoPanel.setPreferredSize(new Dimension(600, 500));
      demoPanel.setLayout(new BorderLayout());
      demoPanel.add(chart, BorderLayout.CENTER);
      demoPanel.add(controlPanel, BorderLayout.SOUTH);
    }
    return demoPanel;
  }