/* * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * Copyright (c) 2006 - 2017 Pentaho Corporation.. All rights reserved. */ package org.pentaho.plugin.jfreereport.reportcharts; import java.awt.Font; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.Locale; import org.jfree.chart.axis.CategoryLabelPosition; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.axis.TickUnits; import org.jfree.chart.axis.ValueAxis; import org.jfree.chart.plot.CategoryPlot; import org.jfree.text.TextBlockAnchor; import org.jfree.ui.RectangleAnchor; import org.jfree.ui.TextAnchor; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.pentaho.plugin.jfreereport.reportcharts.CategoricalChartExpression.PlaneDirection; import org.pentaho.reporting.engine.classic.core.ClassicEngineBoot; import org.pentaho.reporting.engine.classic.core.testsupport.DebugExpressionRuntime; /** * @author Andrey Khayrutdinov */ public class CategoricalChartExpressionTest { /** * To make some methods public. */ class TestableCategoricalChartExpression extends CategoricalChartExpression { @Override public PlaneDirection getTextAnchorDirectionOfAngle( double angle ) { return super.getTextAnchorDirectionOfAngle( angle ); } @Override public CategoryLabelPosition createUpRotationCategoryLabelPosition( PlaneDirection axisPosition, double labelAngle ) { return super.createUpRotationCategoryLabelPosition( axisPosition, labelAngle ); } } @BeforeClass public static void ensureBootIsDone() { ClassicEngineBoot.getInstance().start(); } private CategoricalChartExpression expression; @Before public void setUp() { expression = new DummyCategoricalChartExpression(); expression.setRuntime( new DebugExpressionRuntime() ); expression.setAutoRange( false ); expression.setScaleFactor( 1.1 ); } @Test public void configureRangeAxis_PositiveValues() { final double lower = 10; final double upper = 20; NumberAxis axis = new NumberAxis(); axis.setRange( lower, upper ); expression.configureRangeAxis( createCategoryPlotWith( axis ), createFont() ); Assert.assertTrue( axis.getLowerBound() < lower ); Assert.assertTrue( axis.getLowerBound() > 0 ); Assert.assertTrue( axis.getUpperBound() > upper ); } @Test public void configureRangeAxis_NegativeValues() { final double lower = -20; final double upper = -10; NumberAxis axis = new NumberAxis(); axis.setRange( lower, upper ); expression.configureRangeAxis( createCategoryPlotWith( axis ), createFont() ); Assert.assertTrue( axis.getLowerBound() < lower ); Assert.assertTrue( axis.getUpperBound() > upper ); Assert.assertTrue( axis.getUpperBound() < 0 ); } @Test public void configureRangeAxis_AnyValues() { final double lower = -20; final double upper = 20; NumberAxis axis = new NumberAxis(); axis.setRange( lower, upper ); expression.configureRangeAxis( createCategoryPlotWith( axis ), createFont() ); Assert.assertTrue( axis.getLowerBound() < lower ); Assert.assertTrue( axis.getUpperBound() > upper ); } private static CategoryPlot createCategoryPlotWith( ValueAxis rangeAxis ) { CategoryPlot plot = new CategoryPlot(); plot.setRangeAxis( rangeAxis ); return plot; } private static Font createFont() { return new Font( "Arial", Font.PLAIN, 12 ); } @Test public void testGetTextAnchorDirectionOfAngle() { TestableCategoricalChartExpression e = new TestableCategoricalChartExpression(); // Do not check exact change points, due to double-precision calculations don't provide sufficient accuracy. Assert.assertEquals( PlaneDirection.RIGHT, e.getTextAnchorDirectionOfAngle( 0.0 ) ); Assert.assertEquals( PlaneDirection.RIGHT, e.getTextAnchorDirectionOfAngle( 45.0 * Math.PI / 180.0 ) ); Assert.assertEquals( PlaneDirection.RIGHT, e.getTextAnchorDirectionOfAngle( 56.0 * Math.PI / 180.0 ) ); // change at 56.25 (5/32) Assert.assertEquals( PlaneDirection.TOP_RIGHT, e.getTextAnchorDirectionOfAngle( 57.0 * Math.PI / 180.0 ) ); Assert.assertEquals( PlaneDirection.TOP_RIGHT, e.getTextAnchorDirectionOfAngle( 78.0 * Math.PI / 180.0 ) ); // change at 78.75 (7/32) Assert.assertEquals( PlaneDirection.TOP, e.getTextAnchorDirectionOfAngle( 79.0 * Math.PI / 180.0 ) ); Assert.assertEquals( PlaneDirection.TOP, e.getTextAnchorDirectionOfAngle( 90.0 * Math.PI / 180.0 ) ); Assert.assertEquals( PlaneDirection.TOP, e.getTextAnchorDirectionOfAngle( 101.0 * Math.PI / 180.0 ) ); // change at 101.25 (9/32) Assert.assertEquals( PlaneDirection.TOP_LEFT, e.getTextAnchorDirectionOfAngle( 102.0 * Math.PI / 180.0 ) ); Assert.assertEquals( PlaneDirection.TOP_LEFT, e.getTextAnchorDirectionOfAngle( 123.0 * Math.PI / 180.0 ) ); // change at 123.75 (11/32) Assert.assertEquals( PlaneDirection.LEFT, e.getTextAnchorDirectionOfAngle( 124.0 * Math.PI / 180.0 ) ); Assert.assertEquals( PlaneDirection.LEFT, e.getTextAnchorDirectionOfAngle( 180.0 * Math.PI / 180.0 ) ); Assert.assertEquals( PlaneDirection.LEFT, e.getTextAnchorDirectionOfAngle( 236.0 * Math.PI / 180.0 ) ); // change at 236.25 (21/32) Assert.assertEquals( PlaneDirection.BOTTOM_LEFT, e.getTextAnchorDirectionOfAngle( 237.0 * Math.PI / 180.0 ) ); Assert.assertEquals( PlaneDirection.BOTTOM_LEFT, e.getTextAnchorDirectionOfAngle( 258.0 * Math.PI / 180.0 ) ); // change at 258.75 (23/32) Assert.assertEquals( PlaneDirection.BOTTOM, e.getTextAnchorDirectionOfAngle( 259.0 * Math.PI / 180.0 ) ); Assert.assertEquals( PlaneDirection.BOTTOM, e.getTextAnchorDirectionOfAngle( 270.0 * Math.PI / 180.0 ) ); Assert.assertEquals( PlaneDirection.BOTTOM, e.getTextAnchorDirectionOfAngle( 281.0 * Math.PI / 180.0 ) ); // change at 281.25 (25/32) Assert.assertEquals( PlaneDirection.BOTTOM_RIGHT, e.getTextAnchorDirectionOfAngle( 282.0 * Math.PI / 180.0 ) ); Assert.assertEquals( PlaneDirection.BOTTOM_RIGHT, e.getTextAnchorDirectionOfAngle( 303.0 * Math.PI / 180.0 ) ); // change at 303.75 (27/32) Assert.assertEquals( PlaneDirection.RIGHT, e.getTextAnchorDirectionOfAngle( 304.0 * Math.PI / 180.0 ) ); Assert.assertEquals( PlaneDirection.RIGHT, e.getTextAnchorDirectionOfAngle( 315.0 * Math.PI / 180.0 ) ); Assert.assertEquals( PlaneDirection.RIGHT, e.getTextAnchorDirectionOfAngle( 360.0 * Math.PI / 180.0 ) ); // check some negative angles Assert.assertEquals( PlaneDirection.BOTTOM, e.getTextAnchorDirectionOfAngle( -90.0 * Math.PI / 180.0 ) ); Assert.assertEquals( PlaneDirection.RIGHT, e.getTextAnchorDirectionOfAngle( -45.0 * Math.PI / 180.0 ) ); Assert.assertEquals( PlaneDirection.LEFT, e.getTextAnchorDirectionOfAngle( -135.0 * Math.PI / 180.0 ) ); } @Test public void testCreateUpRotationCategoryLabelPosition() { TestableCategoricalChartExpression e = new TestableCategoricalChartExpression(); { CategoryLabelPosition c = e.createUpRotationCategoryLabelPosition( PlaneDirection.BOTTOM, 0.0 ); Assert.assertEquals( RectangleAnchor.TOP, c.getCategoryAnchor() ); Assert.assertEquals( TextBlockAnchor.TOP_CENTER, c.getLabelAnchor() ); Assert.assertEquals( TextAnchor.TOP_CENTER, c.getRotationAnchor() ); } { CategoryLabelPosition c = e.createUpRotationCategoryLabelPosition( PlaneDirection.BOTTOM, 90.0 * Math.PI / 180.0 ); Assert.assertEquals( RectangleAnchor.TOP, c.getCategoryAnchor() ); Assert.assertEquals( TextBlockAnchor.CENTER_RIGHT, c.getLabelAnchor() ); Assert.assertEquals( TextAnchor.CENTER_RIGHT, c.getRotationAnchor() ); } { CategoryLabelPosition c = e.createUpRotationCategoryLabelPosition( PlaneDirection.BOTTOM, -90.0 * Math.PI / 180.0 ); Assert.assertEquals( RectangleAnchor.TOP, c.getCategoryAnchor() ); Assert.assertEquals( TextBlockAnchor.CENTER_LEFT, c.getLabelAnchor() ); Assert.assertEquals( TextAnchor.CENTER_LEFT, c.getRotationAnchor() ); } { CategoryLabelPosition c = e.createUpRotationCategoryLabelPosition( PlaneDirection.BOTTOM, 180.0 * Math.PI / 180.0 ); Assert.assertEquals( RectangleAnchor.TOP, c.getCategoryAnchor() ); Assert.assertEquals( TextBlockAnchor.BOTTOM_CENTER, c.getLabelAnchor() ); Assert.assertEquals( TextAnchor.BOTTOM_CENTER, c.getRotationAnchor() ); } { CategoryLabelPosition c = e.createUpRotationCategoryLabelPosition( PlaneDirection.LEFT, 0.0 ); Assert.assertEquals( RectangleAnchor.RIGHT, c.getCategoryAnchor() ); Assert.assertEquals( TextBlockAnchor.CENTER_RIGHT, c.getLabelAnchor() ); Assert.assertEquals( TextAnchor.CENTER_RIGHT, c.getRotationAnchor() ); } { CategoryLabelPosition c = e.createUpRotationCategoryLabelPosition( PlaneDirection.LEFT, 90.0 * Math.PI / 180.0 ); Assert.assertEquals( RectangleAnchor.RIGHT, c.getCategoryAnchor() ); Assert.assertEquals( TextBlockAnchor.BOTTOM_CENTER, c.getLabelAnchor() ); Assert.assertEquals( TextAnchor.BOTTOM_CENTER, c.getRotationAnchor() ); } { CategoryLabelPosition c = e.createUpRotationCategoryLabelPosition( PlaneDirection.LEFT, -90.0 * Math.PI / 180.0 ); Assert.assertEquals( RectangleAnchor.RIGHT, c.getCategoryAnchor() ); Assert.assertEquals( TextBlockAnchor.TOP_CENTER, c.getLabelAnchor() ); Assert.assertEquals( TextAnchor.TOP_CENTER, c.getRotationAnchor() ); } { CategoryLabelPosition c = e.createUpRotationCategoryLabelPosition( PlaneDirection.LEFT, 180.0 * Math.PI / 180.0 ); Assert.assertEquals( RectangleAnchor.RIGHT, c.getCategoryAnchor() ); Assert.assertEquals( TextBlockAnchor.CENTER_LEFT, c.getLabelAnchor() ); Assert.assertEquals( TextAnchor.CENTER_LEFT, c.getRotationAnchor() ); } { CategoryLabelPosition c = e.createUpRotationCategoryLabelPosition( PlaneDirection.TOP, 0.0 ); Assert.assertEquals( RectangleAnchor.BOTTOM, c.getCategoryAnchor() ); Assert.assertEquals( TextBlockAnchor.BOTTOM_CENTER, c.getLabelAnchor() ); Assert.assertEquals( TextAnchor.BOTTOM_CENTER, c.getRotationAnchor() ); } { CategoryLabelPosition c = e.createUpRotationCategoryLabelPosition( PlaneDirection.TOP, 90.0 * Math.PI / 180.0 ); Assert.assertEquals( RectangleAnchor.BOTTOM, c.getCategoryAnchor() ); Assert.assertEquals( TextBlockAnchor.CENTER_LEFT, c.getLabelAnchor() ); Assert.assertEquals( TextAnchor.CENTER_LEFT, c.getRotationAnchor() ); } { CategoryLabelPosition c = e.createUpRotationCategoryLabelPosition( PlaneDirection.RIGHT, 0.0 ); Assert.assertEquals( RectangleAnchor.LEFT, c.getCategoryAnchor() ); Assert.assertEquals( TextBlockAnchor.CENTER_LEFT, c.getLabelAnchor() ); Assert.assertEquals( TextAnchor.CENTER_LEFT, c.getRotationAnchor() ); } { CategoryLabelPosition c = e.createUpRotationCategoryLabelPosition( PlaneDirection.RIGHT, 90.0 * Math.PI / 180.0 ); Assert.assertEquals( RectangleAnchor.LEFT, c.getCategoryAnchor() ); Assert.assertEquals( TextBlockAnchor.TOP_CENTER, c.getLabelAnchor() ); Assert.assertEquals( TextAnchor.TOP_CENTER, c.getRotationAnchor() ); } } @Test public void testStandardTickUnitsApplyFormat() throws Exception{ NumberAxis axis = new NumberAxis(); final TickUnits standardTickUnits = (TickUnits)axis.getStandardTickUnits(); final double initialFirstTickUnitSize = standardTickUnits.get( 0 ).getSize(); assertTickUnitSizeByPattern( "", initialFirstTickUnitSize); assertTickUnitSizeByPattern( "#,###", 1.0 ); assertTickUnitSizeByPattern( "#", 1.0 ); assertTickUnitSizeByPattern( "#.#", 0.1 ); assertTickUnitSizeByPattern( "#.####", 1.0E-4 ); } private void assertTickUnitSizeByPattern( String pattern, double tickUnitSize) { NumberAxis axis = new NumberAxis(); DecimalFormat formatter = new DecimalFormat( pattern, new DecimalFormatSymbols(new Locale( "en_US" ) ) ); expression.standardTickUnitsApplyFormat( axis, formatter ); final TickUnits standardTickUnits = (TickUnits)axis.getStandardTickUnits(); // first n standard tick unit elements should be removed Assert.assertEquals( tickUnitSize, standardTickUnits.get( 0 ).getSize(), 0.0000000001 ); } }