JFreeChart 1.0.17

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

JFreeChart 1.0.17

Post by david.gilbert » Sun Nov 24, 2013 7:39 am

JFreeChart 1.0.17 has been uploaded to SourceForge - here are the release notes:

Code: Select all

JFreeChart 1.0.17
-----------------
24 November 2013

Enhanced XYSplineRenderer with new area fill (contributed by Klaus Rheinwald),
added a notify flag to all datasets that extend AbstractDataset, extended 
TimeSeriesCollection to validate TimeSeries keys for uniqueness, added a new
DirectionalGradientPaintTransformer (by Peter Kolb), updated OHLCSeries, added 
HMSNumberFormat, updated JCommon to version 1.0.21 (includes rotated text 
improvements) and fixed some minor bugs.

Bug Fixes:

 977 : Multithreading issue with DateAxis;
1084 : BorderArrangement.add() possible ClassCastException;
1099 : XYSeriesCollection.removeSeries(int) does not deregister listener;
1109 : WaterfallBarRenderer uses wrong color for diff 0.
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

plusik
Posts: 28
Joined: Tue May 16, 2006 3:36 am
Location: Boston, MA, USA

Re: JFreeChart 1.0.17

Post by plusik » Mon Dec 02, 2013 4:03 am

Thanks a lot!
Is this going to be uploaded also to Maven repository?

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Re: JFreeChart 1.0.17

Post by david.gilbert » Mon Dec 02, 2013 7:11 am

I will try to get Maven sorted out, but (1) I haven't done the Maven upload before and (2) I'm quite busy this week working on another project...so it might take some time.
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

gliesian
Posts: 6
Joined: Tue Dec 03, 2013 9:50 pm
antibot: No, of course not.

Re: JFreeChart 1.0.17

Post by gliesian » Tue Dec 03, 2013 9:54 pm

Hi,

Is there a notification that you will put out after it's on the repo?

I can't see to access StandardPieSectionLabelGenerator in the current build, and am hoping that it's resolved in 1.0.17.

I'm using Maven.

Thanks,
Robert

arribaarriba
Posts: 2
Joined: Thu Dec 12, 2013 10:46 am
antibot: No, of course not.

Re: JFreeChart 1.0.17

Post by arribaarriba » Thu Dec 12, 2013 10:56 am

Hi, I would like to post modifications to your code concerning DateAxis and NumberAxis classes. Sorry I do not have time to do more than posting it here.

The problem: when you set a custom formatter for a date or a number axis you could end up with several ticks that have the same label (e.g. a "### ##0" format would produce "100" label for all the numbers between 99.5XXX and 100.4XXX). Which is ugly.

I propose to replace the following methods in both classes (unless you tell me you have another solution):

Code: Select all

  protected List refreshTicksHorizontal(Graphics2D g2, Rectangle2D dataArea, RectangleEdge edge)
  protected List refreshTicksVertical(Graphics2D g2, Rectangle2D dataArea, RectangleEdge edge)
With the following codes:

For NumberAxis.java:

Code: Select all

  protected List refreshTicksHorizontal(Graphics2D g2, Rectangle2D dataArea, RectangleEdge edge)
  {
    try { return this.refreshTheTicks(g2, dataArea, edge, false); }
    catch (Throwable ex) { ex.printStackTrace(); }
    return null;
  }

    protected List refreshTicksVertical(Graphics2D g2, Rectangle2D dataArea, RectangleEdge edge)
    {
      try { return this.refreshTheTicks(g2, dataArea, edge, true); }
      catch (Throwable ex) { ex.printStackTrace(); }
      return null;
    }

  protected List refreshTheTicks(Graphics2D g2, Rectangle2D dataArea, RectangleEdge edge, boolean vertical) throws Throwable
  {

    List result = new java.util.ArrayList();

    Font tickLabelFont = getTickLabelFont();
    g2.setFont(tickLabelFont);
    if (isAutoTickUnitSelection())
    {
      selectAutoTickUnit(g2, dataArea, edge);
    }

    TickUnit tu = getTickUnit();
    double size = tu.getSize();
    int count = calculateVisibleTickCount();
    double lowestTickValue = calculateLowestVisibleTickValue();

    if (count <= ValueAxis.MAXIMUM_TICK_COUNT)
    {
      int minorTickSpaces = getMinorTickCount();
      if (minorTickSpaces <= 0)
      {
        minorTickSpaces = tu.getMinorTickCount();
      }
      for (int minorTick = 1; minorTick < minorTickSpaces; minorTick++)
      {
        double minorTickValue = lowestTickValue - size * minorTick / minorTickSpaces;
        if (getRange().contains(minorTickValue)) result.add(new NumberTick(TickType.MINOR, minorTickValue, "", TextAnchor.TOP_CENTER, TextAnchor.CENTER, 0.0));
      }

      TextAnchor anchor;
      TextAnchor rotationAnchor;
      double angle = 0.0;
      if (vertical)
      {
        if (isVerticalTickLabels())
        {
          if (edge == RectangleEdge.LEFT)
          {
            anchor = TextAnchor.BOTTOM_CENTER;
            rotationAnchor = TextAnchor.BOTTOM_CENTER;
            angle = -Math.PI / 2.0;
          }
          else
          {
            anchor = TextAnchor.BOTTOM_CENTER;
            rotationAnchor = TextAnchor.BOTTOM_CENTER;
            angle = Math.PI / 2.0;
          }
        }
        else
        {
          if (edge == RectangleEdge.LEFT)
          {
            anchor = TextAnchor.CENTER_RIGHT;
            rotationAnchor = TextAnchor.CENTER_RIGHT;
          }
          else
          {
            anchor = TextAnchor.CENTER_LEFT;
            rotationAnchor = TextAnchor.CENTER_LEFT;
          }
        }
      }
      else
      {
        if (isVerticalTickLabels())
        {
          anchor = TextAnchor.CENTER_RIGHT;
          rotationAnchor = TextAnchor.CENTER_RIGHT;
          angle = edge == RectangleEdge.TOP ? angle = Math.PI / 2.0 : -Math.PI / 2.0;
        }
        else
        {
          if (edge == RectangleEdge.TOP)
          {
            anchor = TextAnchor.BOTTOM_CENTER;
            rotationAnchor = TextAnchor.BOTTOM_CENTER;
          }
          else
          {
            anchor = TextAnchor.TOP_CENTER;
            rotationAnchor = TextAnchor.TOP_CENTER;
          }
        }
      }
      NumberFormat formatter = getNumberFormatOverride();
      java.util.Map<String, Object> map = new java.util.LinkedHashMap(count);
      double tickValue = lowestTickValue;
      for (int i = 0; i < count; i++, tickValue+= size)
      {
        String tickLabel = formatter != null ? formatter.format(tickValue) : getTickUnit().valueToString(tickValue);
        Object obj = map.get(tickLabel);
        if (obj == null) map.put(tickLabel, tickValue);
        else if (obj instanceof Double)
        {
          List list = new java.util.ArrayList(2);
          list.add(obj);
          list.add(tickValue);
          map.put(tickLabel, list);
        }
        else if (obj instanceof List) ((List) obj).add(tickValue);
      }
      String[] labels = new String[map.size()];
      double[] values = new double[labels.length];
      int counter = 0;
      for (String tickLabel : map.keySet())
      {
        labels[counter] = tickLabel;
        Object obj = map.get(tickLabel);
        if (obj instanceof Double) values[counter] = (Double) obj;
        else
        {
          List<Double> list = (List) obj;
          double val = formatter != null ? formatter.parse(tickLabel).doubleValue() : new Double(tickLabel);
          double foundVal = list.get(list.size() - 1);
          for (double value : list)
          {
            if (val - value < 0)
            {
              foundVal = value;
              break;
            }
          }
          values[counter] = foundVal;
        }
        counter++;
      }
      for (int i=0, maxI=labels.length-1; i<labels.length; i++)
      {
        double currentTickValue = values[i];
        result.add(new NumberTick(currentTickValue, labels[i], anchor, rotationAnchor, angle));
        double nextTickValue = i < maxI ? values[i + 1] : calculateHighestVisibleTickValue();
        for (int minorTick = 1; minorTick < minorTickSpaces; minorTick++)
        {
          double minorTickValue = currentTickValue + (nextTickValue - currentTickValue) * minorTick / minorTickSpaces;
          if (getRange().contains(minorTickValue))
          {
            result.add(new NumberTick(TickType.MINOR, minorTickValue, "", TextAnchor.TOP_CENTER, TextAnchor.CENTER, 0.0));
          }
        }
      }
    }
    return result;
  }
For DateAxis.java:

Code: Select all

    protected List refreshTicksHorizontal(Graphics2D g2, Rectangle2D dataArea, RectangleEdge edge)
    {
      try { return this.refreshTheTicks(g2, dataArea, edge, false); }
      catch (Throwable ex) { ex.printStackTrace(); }
      return null;
    }

    protected List refreshTicksVertical(Graphics2D g2, Rectangle2D dataArea, RectangleEdge edge)
    {
      try { return this.refreshTheTicks(g2, dataArea, edge, true); }
      catch (Throwable ex) { ex.printStackTrace(); }
      return null;
    }


  protected List refreshTheTicks(Graphics2D g2, Rectangle2D dataArea, RectangleEdge edge, boolean vertical) throws Throwable
  {

    List result = new java.util.ArrayList();

    Font tickLabelFont = getTickLabelFont();
    g2.setFont(tickLabelFont);

    if (isAutoTickUnitSelection())
    {
      selectAutoTickUnit(g2, dataArea, edge);
    }
    DateTickUnit unit = getTickUnit();
    Date tickDate = calculateLowestVisibleTickValue(unit);
    Date upperDate = getMaximumDate();

    TextAnchor anchor, rotationAnchor;
    double angle = 0.0;
    if (vertical)
    {
      if (isVerticalTickLabels())
      {
        anchor = TextAnchor.BOTTOM_CENTER;
        rotationAnchor = TextAnchor.BOTTOM_CENTER;
        if (edge == RectangleEdge.LEFT)
        {
          angle = -Math.PI / 2.0;
        }
        else
        {
          angle = Math.PI / 2.0;
        }
      }
      else
      {
        if (edge == RectangleEdge.LEFT)
        {
          anchor = TextAnchor.CENTER_RIGHT;
          rotationAnchor = TextAnchor.CENTER_RIGHT;
        }
        else
        {
          anchor = TextAnchor.CENTER_LEFT;
          rotationAnchor = TextAnchor.CENTER_LEFT;
        }
      }
    }
    else
    {
      if (isVerticalTickLabels())
      {
        anchor = TextAnchor.CENTER_RIGHT;
        rotationAnchor = TextAnchor.CENTER_RIGHT;
        if (edge == RectangleEdge.TOP)
        {
          angle = Math.PI / 2.0;
        }
        else
        {
          angle = -Math.PI / 2.0;
        }
      }
      else
      {
        if (edge == RectangleEdge.TOP)
        {
          anchor = TextAnchor.BOTTOM_CENTER;
          rotationAnchor = TextAnchor.BOTTOM_CENTER;
        }
        else
        {
          anchor = TextAnchor.TOP_CENTER;
          rotationAnchor = TextAnchor.TOP_CENTER;
        }
      }
    }
    String prevTickLabel = null;
    DateFormat formatter = getDateFormatOverride();
    boolean hasRolled = false;
    long currentTickTime = tickDate.getTime();
    while (tickDate.before(upperDate))
    {

      // could add a flag to make the following correction optional...
      if (!hasRolled)
      {
        tickDate = correctTickDateForPosition(tickDate, unit, this.tickMarkPosition);
      }

      long lowestTickTime = tickDate.getTime();
      long distance = unit.addToDate(tickDate, this.timeZone).getTime() - lowestTickTime;
      int minorTickSpaces = getMinorTickCount();
      if (minorTickSpaces <= 0)
      {
        minorTickSpaces = unit.getMinorTickCount();
      }
      for (int minorTick = 1; minorTick < minorTickSpaces; minorTick++)
      {
        long minorTickTime = lowestTickTime - distance * minorTick / minorTickSpaces;
        if (minorTickTime > 0 && getRange().contains(minorTickTime) && (!isHiddenValue(minorTickTime)))
        {
          result.add(new DateTick(TickType.MINOR, new Date(minorTickTime), "", TextAnchor.TOP_CENTER, TextAnchor.CENTER, 0.0));
        }
      }
      if (!isHiddenValue(tickDate.getTime()))
      {
        // work out the value, label and position
        String tickLabel = formatter != null ? formatter.format(tickDate) : this.tickUnit.dateToString(tickDate);
        if (tickLabel.equals(prevTickLabel))
        {
          tickDate = unit.addToDate(tickDate, this.timeZone);
          continue;
        }
        prevTickLabel = tickLabel;
        Tick tick = new DateTick(tickDate, tickLabel, anchor, rotationAnchor, angle);
        result.add(tick);
        hasRolled = false;

        tickDate = unit.addToDate(tickDate, this.timeZone);
        long nextTickTime = tickDate.getTime();
        for (int minorTick = 1; minorTick < minorTickSpaces; minorTick++)
        {
          long minorTickTime = currentTickTime + (nextTickTime - currentTickTime) * minorTick / minorTickSpaces;
          if (getRange().contains(minorTickTime) && (!isHiddenValue(minorTickTime)))
          {
            result.add(new DateTick(TickType.MINOR, new Date(minorTickTime), "", TextAnchor.TOP_CENTER, TextAnchor.CENTER, 0.0));
          }
        }
        currentTickTime = tickDate.getTime();
      }
      else
      {
        tickDate = unit.rollDate(tickDate, this.timeZone);
        hasRolled = true;
      }
    }
    return result;
  }

josesa
Posts: 1
Joined: Thu Jan 16, 2014 1:30 pm
antibot: No, of course not.

Re: JFreeChart 1.0.17

Post by josesa » Thu Jan 16, 2014 1:35 pm

The file available for download still shows version as "1.0.17-SNAPSHOT". Releases shouldn't contain SNAPSHOT in them.

Also when can we expect it to be uploaded to maven repo?

From your pom definition it seems you are using sonatype, maybe this will help you:
https://docs.sonatype.org/display/Repos ... sage+Guide

joachimm
Posts: 1
Joined: Thu Jan 16, 2014 10:41 pm
antibot: No, of course not.

Re: JFreeChart 1.0.17

Post by joachimm » Thu Jan 16, 2014 10:47 pm

Any update on deploying this to the maven repo? JCommon is at 1.0.17 but JFreeChart is still on 1.0.15.

Thanks

matinh
Posts: 483
Joined: Fri Aug 11, 2006 10:08 am
Location: Austria

Re: JFreeChart 1.0.17

Post by matinh » Wed Feb 12, 2014 9:52 am

JFreeChart 1.0.17 and JCommon 1.0.21 have been uploaded to Maven Central. See this announcement for further details.

- martin

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Re: JFreeChart 1.0.17

Post by david.gilbert » Thu Feb 13, 2014 9:34 am

Thanks Martin!

mhilpert
Posts: 497
Joined: Wed Apr 02, 2003 1:57 pm
Location: Germany

Re: JFreeChart 1.0.17

Post by mhilpert » Tue Apr 01, 2014 4:22 pm

Oh boy, the new version paints pie charts with a bigger circle! Is this by accident or is this by intend? Why? :roll:

The problem ist, that 2 pie charts with the exact same pie size definitions have different sizes depending on the data and item labels. This was not the case in 1.0.15 (we had to skip 1.0.16 as this version had another error that ruled out 1.0.16 for us). In 1.0.15, both pie charts with the same size definitions both have the same pie (circle) size.

I can't find any infos in the release notes about this change!
Java 11, JFreeChart 1.0.15, JFreeSVG 4.0

Locked