LLGraphArea.java :  » Chart » Chart2D_1.9.6k » net » sourceforge » chart2d » Java Open Source

Java Open Source » Chart » Chart2D_1.9.6k 
Chart2D_1.9.6k » net » sourceforge » chart2d » LLGraphArea.java
/**
 * Chart2D, a java library for drawing two dimensional charts.
 * Copyright (C) 2001 Jason J. Simas
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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.
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * The author of this library may be contacted at:
 * E-mail:  jjsimas@users.sourceforge.net
 * Street Address:  J J Simas, 887 Tico Road, Ojai, CA 93023-3555 USA
 */


package net.sourceforge.chart2d;


import java.awt.*;
import java.awt.geom.*;


/**
 * The area that the x axis and y axis attach to, and in which bars, lines, or
 * dots are painted to represent the data set.  The "LL" in the name of this
 * class stands for Labels Left.  This graph should always be used when the
 * data descriptors for the the graph are located on the left.  Data
 * descriptors have values such as September and November, and not like 0 or 50.
 * <b>Features:</b><br>
 * Provides bordering functionality.  Allows lines to be painted that match
 * up with y axis and x axis tick marks in order to know where the bars, dots,
 * or plot lines are in relation to the x axis values.  Supports vertical
 * bar graphs, line charts, and scatter charts (dots), and any combintation
 * thereof.  If a bars are present in any graph, then it is highly recommended
 * that the GraphArea method, allowComponentAlignment be passed the value of
 * false.  This will ensure that all the bars are visible on the graph.  For
 * graphs that do not have bars present, the opposite is advised.  The GraphArea
 * method should be passed the value of true.  This provides a more intuitive
 * representation of the data.
 */
final class LLGraphArea extends GraphArea {


  private FancyBar[][] bars;
  private FancyDot[][] dots;
  private FancyLine[] lines;
  private boolean needsUpdate;


  /**
   * Creates a graph area with GraphArea's default values, except with vertical
   * lines instead of horizontal alignment lines. The default values:<br>
   * setType (LABELSLEFT);<br>
   * setHorizontalLinesExistence (false);<br>
   * setVerticalLinesExistence (true);<br>
   * resetLLGraphAreaModel (true);<br>
   */
  LLGraphArea() {

    bars = new FancyBar[0][0];
    dots = new FancyDot[0][0];
    lines = new FancyLine[0];

    setBarRoundingRatio (.25f);

    setType (LABELSLEFT);
    setHorizontalLinesExistence (false);
    setVerticalLinesExistence (true);

    resetLLGraphAreaModel (true);
    needsUpdate = true;
  }


  /**
   * Does a quick calculation of the preferred height of the graph.
   * @param numSets The number of data series.
   * @param numComps The number of data categories per series.
   * @param numCompsPerCat  The number of data per series, per category.
   * @return The preferred width.
   */
  final int getPrefSpaceHeight (int numSets, int numCats, int numCompsPerCat) {

    float ratio = getRatio (HEIGHT);
    int barsHeight = 0, dotsHeight = 0, linesHeight = 0, prefHeight = 0;
    if (getAllowComponentAlignment()) {
      barsHeight = getBarsExistence() ?
        (int)(numCats * (1 + (1 - getBarsWithinCategoryOverlapRatio()) *
        (numCompsPerCat - 1)) *
        applyRatio (getBarsThicknessModel(), ratio)) : 0;
      dotsHeight = getDotsExistence() ?
        (int)(numCats * (1 + (1 - getDotsWithinCategoryOverlapRatio()) *
        (numCompsPerCat - 1)) *
        applyRatio (getDotsThicknessModel(), ratio)) : 0;
      linesHeight = getLinesExistence() ?
        (int)(numCats * (1 + (1 - getLinesWithinCategoryOverlapRatio()) *
        (numCompsPerCat - 1)) *
        applyRatio (getLinesThicknessModel(), ratio)) : 0;
    }
    else {
      barsHeight = getBarsExistence() ?
        (int)(numSets * numCats *
        (1 + (1 - getBarsWithinCategoryOverlapRatio()) *
        (numCompsPerCat - 1)) *
        applyRatio (getBarsThicknessModel(), ratio)) : 0;
      dotsHeight = getDotsExistence() ?
        (int)(numSets * numCats * (1 +
        (1 - getDotsWithinCategoryOverlapRatio()) *
        (numCompsPerCat - 1)) *
        applyRatio (getDotsThicknessModel(), ratio)) : 0;
      linesHeight = getLinesExistence() ?
        (int)(numSets * numCats * (1 +
        (1 - getLinesWithinCategoryOverlapRatio()) *
        (numCompsPerCat - 1)) *
        applyRatio (getLinesThicknessModel(), ratio)) : 0;

    }
    prefHeight = barsHeight > dotsHeight ? barsHeight : dotsHeight;
    prefHeight = prefHeight > linesHeight ? prefHeight : linesHeight;
    int gapsHeight = getBetweenComponentsGapExistence() ?
      numCats * applyRatio (getBetweenComponentsGapThicknessModel(), ratio) : 0;
    prefHeight = prefHeight + gapsHeight;
    prefHeight = prefHeight < getSpaceSize(MAX).height ? prefHeight : getSpaceSize(MAX).height;
    return (prefHeight);
  }


  /**
   * Indicates whether some property of this class has changed.
   * @return True if some property has changed.
   */
  final boolean getLLGraphAreaNeedsUpdate() {

    return (needsUpdate || getGraphAreaNeedsUpdate());
  }


  /**
   * Resets the model for this class.  The model is used for shrinking and
   * growing of its components based on the maximum size of this class.  If this
   * method is called, then the next time the maximum size is set, this classes
   * model maximum size will be made equal to the new maximum size.  Effectively
   * what this does is ensure that whenever this objects maximum size is equal
   * to the one given, then all of the components will take on their default
   * model sizes.  Note:  This is only useful when auto model max sizing is
   * disabled.
   * @param reset True causes the max model size to be set upon the next max
   * sizing.
   */
  final void resetLLGraphAreaModel (boolean reset) {

    needsUpdate = true;
    resetGraphAreaModel (reset);
  }


  /**
   * Updates this parent's variables, and this' variables.
   */
  final void updateLLGraphArea() {

    if (getLLGraphAreaNeedsUpdate()) {
      updateGraphArea();
      update();
    }
    needsUpdate = false;
  }


  /**
   * Paints all the components of this class.  First all variables are updated.
   * @param g2D The graphics context for calculations and painting.
   */
  final void paintComponent (Graphics2D g2D) {

    updateLLGraphArea();
    super.paintComponent (g2D);


    Shape oldClip = g2D.getClip();
    if (getClip()) g2D.setClip (new Rectangle (getSpaceSizeLocation (MIN), getSpaceSize (MIN)));

    Composite oldComposite = g2D.getComposite();
    g2D.setComposite (getComponentsAlphaComposite());

    int numBars = bars.length > 0 ? bars[0].length : 0;
    int numDots = dots.length > 0 ? dots[0].length : 0;
    int numLines = lines.length;
    int numSets = getGraphValues().length;
    if (!getAllowComponentAlignment() && numBars > 0) {
      for (int i = 0; i < numSets; ++i) {
        for (int j = 0; j < numBars; ++j) {
          bars[i][j].paint (g2D);
        }
      }
    }
    else if (numBars > 0) {
      int[][] graphValues = getGraphValues();
      graphValues = stackedBarConvert (graphValues, getBarLowValues());
      for (int j = 0; j < numBars; ++j) {
        int[] sorted = stackedBarSort (graphValues, j);
        for (int i = 0; i < numSets; ++i) {
          bars[sorted[i]][j].paint (g2D);
        }
      }
    }

    for (int i = numLines - 1; i >= 0 ; --i) lines[i].paint (g2D);

    for (int i = numSets - 1; i >= 0; --i) {
      for (int j = numDots - 1; j >= 0 ; --j) {
        dots[i][j].paint (g2D);
      }
    }

    g2D.setClip (oldClip);
    g2D.setComposite (oldComposite);
  }


  private void update() {

    if (getAllowComponentAlignment()) updateAllowAlignment();
    else updateDisallowAlignment();
  }


  private void updateDisallowAlignment() {

    int[][] graphLengths = getGraphValues();
    int numBars = 0, numDots = 0, numLinePoints = 0, numGaps = 0;
    int numSets = graphLengths.length;
    Rectangle[] yTicks = getYTicks();
    int numCompsPerCat = 0;
    int numCats = 0;
    if (numSets > 0) {
      numCats = getLabelsAxisTicksAlignment() == BETWEEN ?
        yTicks.length + 1 : yTicks.length;
      numBars = getBarsExistence() ? numCats : 0;
      numDots = getDotsExistence() ? numCats : 0;
      numLinePoints = getLinesExistence() ? numCats : 0;
      numGaps = getBetweenComponentsGapExistence() ? numCats : 0;
      numCompsPerCat =
        numCats > 0 ? (int)(graphLengths[0].length / numCats) : 0;
    }
    if (numSets > 0 && numCats > 0 && numCompsPerCat > 0) {
      float ratio = getRatio (HEIGHT);
      int availableThickness = getSpaceSize(MIN).height;

      int betweenComponentsGapThickness = 0;
      if (numGaps > 0) {
        betweenComponentsGapThickness =
          applyRatio (getBetweenComponentsGapThicknessModel(), ratio);
        betweenComponentsGapThickness =
          numGaps * betweenComponentsGapThickness <= availableThickness ?
          betweenComponentsGapThickness : availableThickness / numGaps;
        availableThickness -= numGaps * betweenComponentsGapThickness;
      }

      int barsThickness = 0;
      if (numBars > 0) {
        barsThickness = applyRatio (getBarsThicknessModel(), ratio);
        if ((numSets * numBars * numCompsPerCat) * barsThickness <=
          availableThickness) {
          float leftover =
            (availableThickness - barsThickness *
            (numSets * numBars * numCompsPerCat)) /
            (numSets * numBars * numCompsPerCat);
          barsThickness =
            barsThickness + (int)(getBarsExcessSpaceFeedbackRatio() * leftover);
        }
        else {
          float numOverlapBarsPerCat =
            (1 + (1 - getBarsWithinCategoryOverlapRatio()) *
            (numCompsPerCat - 1));
          if (numSets * numBars * numOverlapBarsPerCat * barsThickness >
            availableThickness) {
            barsThickness = (int)(availableThickness /
              (numSets * numBars * numOverlapBarsPerCat));
          }
        }
      }
      int dotsThickness = 0;
      if (numDots > 0) {
        dotsThickness = applyRatio (getDotsThicknessModel(), getRatio (LESSER));
        if ((numSets * numDots * numCompsPerCat) * dotsThickness <=
          availableThickness) {
          float leftover =
            (availableThickness - dotsThickness *
            (numSets * numDots * numCompsPerCat)) /
            (numSets * numDots * numCompsPerCat);
          dotsThickness =
            dotsThickness + (int)(getDotsExcessSpaceFeedbackRatio() * leftover);
        }
        else {
          float numOverlapDotsPerCat =
            (1 + (1 - getDotsWithinCategoryOverlapRatio()) *
            (numCompsPerCat - 1));
          if (numSets * numDots * numOverlapDotsPerCat * dotsThickness >
            availableThickness) {
            dotsThickness = (int)(availableThickness /
              (numSets * numDots * numOverlapDotsPerCat));
          }
        }
      }
      int linesThickness = 0;
      if (numLinePoints > 0) {
        linesThickness = applyRatio (getLinesThicknessModel(), getRatio (LESSER));
        if ((numSets * numLinePoints * numCompsPerCat) * linesThickness <=
          availableThickness) {
          float leftover =
            (availableThickness - linesThickness *
            (numSets * numLinePoints * numCompsPerCat)) /
            (numSets * numLinePoints * numCompsPerCat);
          linesThickness =
            linesThickness + (int)(getLinesExcessSpaceFeedbackRatio() * leftover);
        }
        else {
          float numOverlapLinesPerCat =
            (1 + (1 - getLinesWithinCategoryOverlapRatio()) *
            (numCompsPerCat - 1));
          if (numSets * numLinePoints * numOverlapLinesPerCat * linesThickness >
            availableThickness) {
            linesThickness = (int)(availableThickness /
              (numSets * numLinePoints * numOverlapLinesPerCat));
          }
        }
      }

      int componentsThickness = barsThickness;
      componentsThickness = dotsThickness > componentsThickness ?
        dotsThickness : componentsThickness;
      componentsThickness = linesThickness > componentsThickness ?
        linesThickness : componentsThickness;
      int setsThickness = componentsThickness * numSets;
      setsThickness =
        setsThickness > availableThickness / (numCats * numCompsPerCat) ?
        availableThickness / (numCats * numCompsPerCat) : setsThickness;
      componentsThickness = setsThickness / numSets;

      Rectangle2D.Float boundsGraph = new Rectangle2D.Float (
        getSpaceSizeLocation (MIN).x, getSpaceSizeLocation (MIN).y,
        getSpaceSize (MIN).width, getSpaceSize (MIN).height);

      bars = new FancyBar[numSets][numBars * numCompsPerCat];
      int[][] barLowValues = getBarLowValues();
      if (numBars > 0) {
        int x = getSpaceSizeLocation (MIN).x - (getOutlineComponents() ? 1 : 0), y = 0;
        float catDelta =
          getSpaceSize (MIN).height / (float)(numBars * numCompsPerCat);
        if (numBars == 1) {
          y = getSpaceSizeLocation (MIN).y +
            (getSpaceSize(MIN).height - setsThickness) / 2;
          y = (int)(y - ((numCompsPerCat - 1) / 2f) * catDelta);
          for (int k = 0; k < numCompsPerCat; ++k) {
            for (int j = 0; j < numSets; ++j) {
              int compY = y + j * componentsThickness +
                (componentsThickness - barsThickness) / 2;
              bars[j][k] = new FancyBar();
              bars[j][k].setDataSign (getDataSign());
              bars[j][k].setBaseValue (x + getLinesFillInteriorBaseValue());
              if (graphLengths[j][k] > barLowValues[j][k]) {
                bars[j][k].setBounds (new Rectangle2D.Float (
                  x + barLowValues[j][k], compY + k * catDelta,
                  graphLengths[j][k] - barLowValues[j][k], barsThickness));
              }
              else {
                bars[j][k].setBounds (new Rectangle2D.Float (
                  x + graphLengths[j][k], compY + k * catDelta,
                  barLowValues[j][k] - graphLengths[j][k], barsThickness));
              }
              Rectangle2D.Float clipBounds = new Rectangle2D.Float (
                bars[j][k].getBounds().x, boundsGraph.y,
                bars[j][k].getBounds().width, boundsGraph.height);
              bars[j][k].setClipBounds (clipBounds);
              bars[j][k].setLightBounds (
                getComponentsLightType() == COMPONENT ? bars[j][k].getBounds() : boundsGraph);
              bars[j][k].setLightSource (getComponentsLightSource());
              bars[j][k].setColor (!getComponentsColoringByCat() ?
                getBarColors()[j] : getComponentsColorsByCat()[0]);
              bars[j][k].setOutlineExistence (getOutlineComponents());
              bars[j][k].setOutlineColor (getOutlineComponentsColor());
              bars[j][k].setArcw (getBarRoundingRatio() * barsThickness);
              bars[j][k].setArch (getBarRoundingRatio() * barsThickness);
              bars[j][k].setWarningRegions (getWarningRegions());
              bars[j][k].setType (FancyShape.LABELSLEFT);
              bars[j][k].setGraphBounds (boundsGraph);
            }
          }
        }
        else {
          float minY, maxY, tickHalfHeight;
          minY = getSpaceSizeLocation (MIN).y;
          tickHalfHeight = getXTicks()[0].height / 2f;
          maxY = yTicks[0].y + tickHalfHeight;
          int i = 0;
          do {
            if (getLabelsAxisTicksAlignment() == this.BETWEEN) {
              y = (int)(minY + Math.floor((maxY - minY - setsThickness) / 2f));
            }
            else y = (int)Math.floor (maxY - setsThickness / 2f);
            y = (int)(y - ((numCompsPerCat - 1) / 2f) * catDelta);
            for (int k = 0; k < numCompsPerCat; ++k) {
              for (int j = 0; j < numSets; ++j) {
                int compY = y + j * componentsThickness +
                  (componentsThickness - barsThickness) / 2;
                bars[j][i * numCompsPerCat + k] = new FancyBar();
                bars[j][i * numCompsPerCat + k].setDataSign (getDataSign());
                bars[j][i * numCompsPerCat + k].setBaseValue (x + getLinesFillInteriorBaseValue());
                if (graphLengths[j][i * numCompsPerCat + k] >
                  barLowValues[j][i * numCompsPerCat + k]) {
                  bars[j][i * numCompsPerCat + k].setBounds (new Rectangle2D.Float (
                    x + barLowValues[j][i * numCompsPerCat + k], compY + k * catDelta,
                    graphLengths[j][i * numCompsPerCat + k] -
                    barLowValues[j][i * numCompsPerCat + k], barsThickness));
                }
                else {
                  bars[j][i * numCompsPerCat + k].setBounds (new Rectangle2D.Float (
                    x + graphLengths[j][i * numCompsPerCat + k], compY + k * catDelta,
                    barLowValues[j][i * numCompsPerCat + k] -
                    graphLengths[j][i * numCompsPerCat + k], barsThickness));
                }
                Rectangle2D.Float clipBounds = new Rectangle2D.Float (
                  bars[j][i * numCompsPerCat + k].getBounds().x, boundsGraph.y,
                  bars[j][i * numCompsPerCat + k].getBounds().width, boundsGraph.height);
                bars[j][i * numCompsPerCat + k].setClipBounds (clipBounds);
                bars[j][i * numCompsPerCat + k].setLightBounds (
                  getComponentsLightType() == COMPONENT ?
                  bars[j][i * numCompsPerCat + k].getBounds() : boundsGraph);
                bars[j][i * numCompsPerCat + k].setLightSource (getComponentsLightSource());
                bars[j][i * numCompsPerCat + k].setColor (!getComponentsColoringByCat() ?
                  getBarColors()[j] : getComponentsColorsByCat()[i]);
                bars[j][i * numCompsPerCat + k].setOutlineExistence (getOutlineComponents());
                bars[j][i * numCompsPerCat + k].setOutlineColor (getOutlineComponentsColor());
                bars[j][i * numCompsPerCat + k].setArcw (
                  getBarRoundingRatio() * barsThickness);
                bars[j][i * numCompsPerCat + k].setArch (
                  getBarRoundingRatio() * barsThickness);
                bars[j][i * numCompsPerCat + k].setWarningRegions (getWarningRegions());
                bars[j][i * numCompsPerCat + k].setType (FancyShape.LABELSLEFT);
                bars[j][i * numCompsPerCat + k].setGraphBounds (boundsGraph);
              }
            }
            if (i + 1 == numBars) break;
            minY = maxY;
            if (i + 2 == numBars &&
              getLabelsAxisTicksAlignment() == this.BETWEEN) {
              maxY = getSpaceSizeLocation (MIN).y + getSpaceSize (MIN).height;
            }
            else maxY = yTicks[i + 1].y + tickHalfHeight;
            ++i;
          } while (true);
        }
      }

      dots = new FancyDot[numSets][numDots * numCompsPerCat];
      if (numDots > 0) {
        int x = getSpaceSizeLocation (MIN).x - dotsThickness / 2, y;
        float catDelta =
          getSpaceSize (MIN).height / (float)(numDots * numCompsPerCat);
        if (numDots == 1) {
          y = getSpaceSizeLocation (MIN).y +
            (getSpaceSize(MIN).height - setsThickness) / 2;
          y = (int)(y - ((numCompsPerCat - 1) / 2f) * catDelta);
          for (int k = 0; k < numCompsPerCat; ++k) {
            for (int j = 0; j < numSets; ++j) {
              int compY = y + j * componentsThickness +
                (componentsThickness - dotsThickness) / 2;
              dots[j][k] = new FancyDot();
              dots[j][k].setBounds (new Rectangle2D.Float (
                x + graphLengths[j][k], compY + k * catDelta, dotsThickness, dotsThickness));
              dots[j][k].setClipBounds (dots[j][k].getBounds());
              dots[j][k].setColor (!getComponentsColoringByCat() ?
                getDotColors()[j] : getComponentsColorsByCat()[0]);
              dots[j][k].setOutlineExistence (getOutlineComponents());
              dots[j][k].setOutlineColor (getOutlineComponentsColor());
              dots[j][k].setLightBounds (
                getComponentsLightType() == COMPONENT ? dots[j][k].getBounds() : boundsGraph);
              dots[j][k].setLightSource (getComponentsLightSource());
              dots[j][k].setWarningRegions (getWarningRegions());
              dots[j][k].setType (FancyShape.LABELSLEFT);
            }
          }
        }
        else {
          float minY, maxY, tickHalfHeight;
          minY = getSpaceSizeLocation (MIN).y;
          tickHalfHeight = yTicks[0].height / 2f;
          maxY = yTicks[0].y + tickHalfHeight;
          int i = 0;
          do {
            if (getLabelsAxisTicksAlignment() == this.BETWEEN) {
              y = (int)(minY + Math.floor((maxY - minY - setsThickness) / 2f));
            }
            else y = (int)Math.floor (maxY - setsThickness / 2f);
            y = (int)(y - ((numCompsPerCat - 1) / 2f) * catDelta);
            for (int k = 0; k < numCompsPerCat; ++k) {
              for (int j = 0; j < numSets; ++j) {
                int compY = y + j * componentsThickness +
                  (componentsThickness - dotsThickness) / 2;
                dots[j][i * numCompsPerCat + k] = new FancyDot();
                dots[j][i * numCompsPerCat + k].setBounds (new Rectangle2D.Float (
                  x + graphLengths[j][i * numCompsPerCat + k], compY + k * catDelta,
                  dotsThickness, dotsThickness));
                dots[j][i * numCompsPerCat + k].setClipBounds (
                  dots[j][i * numCompsPerCat + k].getBounds());
                dots[j][i * numCompsPerCat + k].setColor (!getComponentsColoringByCat() ?
                  getDotColors()[j] : getComponentsColorsByCat()[i]);
                dots[j][i * numCompsPerCat + k].setOutlineExistence (getOutlineComponents());
                dots[j][i * numCompsPerCat + k].setOutlineColor (getOutlineComponentsColor());
                dots[j][i * numCompsPerCat + k].setLightBounds (
                  getComponentsLightType() == COMPONENT ?
                  dots[j][i * numCompsPerCat + k].getBounds() : boundsGraph);
                dots[j][i * numCompsPerCat + k].setLightSource (getComponentsLightSource());
                dots[j][i * numCompsPerCat + k].setWarningRegions (getWarningRegions());
                dots[j][i * numCompsPerCat + k].setType (FancyShape.LABELSLEFT);
              }
            }
            if (i + 1 == numDots) break;
            minY = maxY;
            if (i + 2 == numDots &&
              getLabelsAxisTicksAlignment() == this.BETWEEN) {
              maxY = getSpaceSizeLocation (MIN).y + getSpaceSize (MIN).height;
            }
            else maxY = yTicks[i + 1].y + tickHalfHeight;
            ++i;
          } while (true);
        }
      }

      if ((numCats * numCompsPerCat) < 2 || linesThickness < 1) lines = new FancyLine[0];
      else {
        lines = new FancyLine[numSets];
        for (int i = 0; i < numSets; ++i) {
          lines[i] = new FancyLine();
          lines[i].setThickness (linesThickness);
          lines[i].setFillArea (getLinesFillInterior());
          lines[i].setColor (getLineColors()[i]);
          lines[i].setOutlineExistence (getOutlineComponents());
          lines[i].setOutlineColor (getOutlineComponentsColor());
          lines[i].setLightSource (getComponentsLightSource());
          lines[i].setWarningRegions (getWarningRegions());
          lines[i].setType (FancyShape.LABELSLEFT);
        }
        Point firstPoints[] = new Point[numSets];
        int x = getSpaceSizeLocation (MIN).x, y;
        float minY, maxY, tickHalfHeight;
        minY = getSpaceSizeLocation (MIN).y;
        tickHalfHeight = yTicks[0].height / 2f;
        maxY = yTicks[0].y + tickHalfHeight;
        float catDelta =
          getSpaceSize (MIN).height / (float)(numLinePoints * numCompsPerCat);
        int i = 0;
        boolean first = true;
        do {
          if (getLabelsAxisTicksAlignment() == this.BETWEEN) {
            y = (int)(minY + Math.floor((maxY - minY - setsThickness) / 2f));
          }
          else y = (int)Math.floor (maxY - setsThickness / 2f);
          y = (int)(y - ((numCompsPerCat - 1) / 2f) * catDelta);
          for (int k = 0; k < numCompsPerCat; ++k) {
            for (int j = 0; j < numSets; ++j) {
              int compY = y + j * componentsThickness + componentsThickness / 2;
              Point thisPoint = new Point (
                (int)(x + graphLengths[j][i * numCompsPerCat + k]), (int)(compY + k * catDelta));
              if (k == 0 && i == 0) {
                if (getLinesFillInterior()) {
                  firstPoints[j] =
                    new Point (x + getLinesFillInteriorBaseValue(), (int)(compY + k * catDelta));
                  lines[j].getLine().moveTo (firstPoints[j].x, firstPoints[j].y);
                  lines[j].getLine().lineTo (thisPoint.x, thisPoint.y);
                }
                else {
                  lines[j].getLine().moveTo (thisPoint.x, thisPoint.y);
                }
              }
              else {
                lines[j].getLine().lineTo (thisPoint.x, thisPoint.y);
                if (getLinesFillInterior() &&
                  k == numCompsPerCat - 1 && i == numLinePoints - 1) {
                    lines[j].getLine().lineTo (firstPoints[j].x, thisPoint.y);
                    lines[j].getLine().lineTo (firstPoints[j].x, firstPoints[j].y);
                }
              }
            }
          }
          if (i + 1 == numLinePoints) break;
          first = false;
          minY = maxY;
          if (i + 2 == numLinePoints &&
            getLabelsAxisTicksAlignment() == this.BETWEEN) {
            maxY = getSpaceSizeLocation (MIN).y + getSpaceSize (MIN).height;
          }
          else maxY = yTicks[i + 1].y + tickHalfHeight;
          ++i;
        } while (true);
        for (int g = 0; g < numSets; ++g) {
          lines[g].setClipBounds (boundsGraph);
          Rectangle2D.Float bounds = (Rectangle2D.Float)lines[g].getLine().getBounds2D();
          lines[g].setLightBounds (getComponentsLightType() == COMPONENT ? bounds : boundsGraph);
        }
      }
    }
    else {
      bars = new FancyBar[0][0];
      dots = new FancyDot[0][0];
      lines = new FancyLine[0];
    }
  }


  private void updateAllowAlignment() {

    int[][] graphLengths = getGraphValues();
    int numBars = 0, numDots = 0, numLinePoints = 0, numGaps = 0;
    int numSets = graphLengths.length;
    Rectangle[] yTicks = getYTicks();
    int numCompsPerCat = 0;
    int numCats = 0;
    if (numSets > 0) {
      numCats = getLabelsAxisTicksAlignment() == BETWEEN ?
        yTicks.length + 1 : yTicks.length;
      numBars = getBarsExistence() ? numCats : 0;
      numDots = getDotsExistence() ? numCats : 0;
      numLinePoints = getLinesExistence() ? numCats : 0;
      numGaps = getBetweenComponentsGapExistence() ? numCats : 0;
      numCompsPerCat = numCats > 0 ? (int)(graphLengths[0].length / numCats) : 0;
    }
    if (numSets > 0 && numCats > 0 && numCompsPerCat > 0) {
      float ratio = getRatio (HEIGHT);
      int availableThickness = getSpaceSize(MIN).height;

      int betweenComponentsGapThickness = 0;
      if (numGaps > 0) {
        betweenComponentsGapThickness =
          applyRatio (getBetweenComponentsGapThicknessModel(), ratio);
        betweenComponentsGapThickness =
          numGaps * betweenComponentsGapThickness <= availableThickness ?
          betweenComponentsGapThickness : availableThickness / numGaps;
        availableThickness -= numGaps * betweenComponentsGapThickness;
      }

      int barsThickness = 0;
      if (numBars > 0) {
        barsThickness = applyRatio (getBarsThicknessModel(), ratio);
        if (numBars * numCompsPerCat * barsThickness <= availableThickness) {
          float leftover =
            (availableThickness - barsThickness *
            (numBars * numCompsPerCat)) /
            (numBars * numCompsPerCat);
          barsThickness =
            barsThickness + (int)(getBarsExcessSpaceFeedbackRatio() * leftover);
        }
        else {
          float numOverlapBarsPerCat =
            (1 + (1 - getBarsWithinCategoryOverlapRatio()) *
            (numCompsPerCat - 1));
          if (numBars * numOverlapBarsPerCat * barsThickness >
            availableThickness) {
            barsThickness =
              (int)(availableThickness / (numBars * numOverlapBarsPerCat));
          }
        }
      }
      int dotsThickness = 0;
      if (numDots > 0) {
        dotsThickness = applyRatio (getDotsThicknessModel(), getRatio (LESSER));
        if (numDots * numCompsPerCat * dotsThickness <=
          availableThickness) {
          float leftover =
            (availableThickness - dotsThickness *
            (numDots * numCompsPerCat)) /
            (numDots * numCompsPerCat);
          dotsThickness =
            dotsThickness + (int)(getDotsExcessSpaceFeedbackRatio() * leftover);
        }
        else {
          float numOverlapDotsPerCat =
            (1 + (1 - getDotsWithinCategoryOverlapRatio()) *
            (numCompsPerCat - 1));
          if (numDots * numOverlapDotsPerCat * dotsThickness >
            availableThickness) {
            dotsThickness =
              (int)(availableThickness / (numDots * numOverlapDotsPerCat));
          }
        }
      }
      int linesThickness = 0;
      if (numLinePoints > 0) {
        linesThickness = applyRatio (getLinesThicknessModel(), getRatio (LESSER));
        if (numLinePoints * numCompsPerCat * linesThickness <=
          availableThickness) {
          float leftover =
            (availableThickness - linesThickness *
            (numLinePoints * numCompsPerCat)) /
            (numLinePoints * numCompsPerCat);
          linesThickness =
            linesThickness + (int)(getLinesExcessSpaceFeedbackRatio() * leftover);
        }
        else {
          float numOverlapLinesPerCat =
            (1 + (1 - getLinesWithinCategoryOverlapRatio()) *
            (numCompsPerCat - 1));
          if (numLinePoints * numOverlapLinesPerCat * linesThickness >
            availableThickness) {
            linesThickness =
              (int)(availableThickness / (numLinePoints * numOverlapLinesPerCat));
          }
        }
      }

      Rectangle2D.Float boundsGraph = new Rectangle2D.Float (
        getSpaceSizeLocation (MIN).x, getSpaceSizeLocation (MIN).y,
        getSpaceSize (MIN).width, getSpaceSize (MIN).height);

      bars = new FancyBar[numSets][numBars * numCompsPerCat];
      int[][] barLowValues = getBarLowValues();
      if (numBars > 0) {
        int x = getSpaceSizeLocation (MIN).x, y;
        float catDelta =
          getSpaceSize (MIN).height / (float)(numBars * numCompsPerCat);
        if (numBars == 1) {
          y = getSpaceSizeLocation (MIN).y +
            (getSpaceSize(MIN).height - barsThickness) / 2;
          y = (int)(y - ((numCompsPerCat - 1) / 2f) * catDelta);
          for (int k = 0; k < numCompsPerCat; ++k) {
            for (int j = 0; j < numSets; ++j) {
              bars[j][k] = new FancyBar();
              bars[j][k].setDataSign (getDataSign());
              bars[j][k].setBaseValue (x + getLinesFillInteriorBaseValue());
              if (graphLengths[j][k] > barLowValues[j][k]) {
                bars[j][k].setBounds (new Rectangle2D.Float (
                  x + barLowValues[j][k] + (getOutlineComponents() ? -1 : 0), y + k * catDelta,
                  graphLengths[j][k] - barLowValues[j][k], barsThickness));
              }
              else {
                bars[j][k].setBounds (new Rectangle2D.Float (
                  x + graphLengths[j][k] + (getOutlineComponents() ? -1 : 0),
                  (int)(y + k * catDelta),
                  barLowValues[j][k] - graphLengths[j][k], barsThickness));
              }
              Rectangle2D.Float clipBounds = new Rectangle2D.Float (
                bars[j][k].getBounds().x, boundsGraph.y,
                bars[j][k].getBounds().width, boundsGraph.height);
              bars[j][k].setClipBounds (clipBounds);
              bars[j][k].setLightBounds (
                getComponentsLightType() == COMPONENT ? bars[j][k].getBounds() : boundsGraph);
              bars[j][k].setLightSource (getComponentsLightSource());
              bars[j][k].setColor (!getComponentsColoringByCat() ?
                getBarColors()[j] : getComponentsColorsByCat()[0]);
              bars[j][k].setOutlineExistence (getOutlineComponents());
              bars[j][k].setOutlineColor (getOutlineComponentsColor());
              bars[j][k].setArcw (getBarRoundingRatio() * barsThickness);
              bars[j][k].setArch (getBarRoundingRatio() * barsThickness);
              bars[j][k].setWarningRegions (getWarningRegions());
              bars[j][k].setType (FancyShape.LABELSLEFT);
              bars[j][k].setGraphBounds (boundsGraph);
            }
          }
        }
        else {
          float minY, maxY, tickHalfHeight;
          minY = getSpaceSizeLocation (MIN).y;
          tickHalfHeight = getXTicks()[0].height / 2f;
          maxY = yTicks[0].y + tickHalfHeight;
          int i = 0;
          do {
            if (getLabelsAxisTicksAlignment() == this.BETWEEN) {
              y = (int)(minY + Math.floor((maxY - minY - barsThickness) / 2f));
            }
            else y = (int)Math.floor (maxY - barsThickness / 2f);
            y = (int)(y - ((numCompsPerCat - 1) / 2f) * catDelta);
            for (int k = 0; k < numCompsPerCat; ++k) {
              for (int j = 0; j < numSets; ++j) {
                bars[j][i * numCompsPerCat + k] = new FancyBar();
                bars[j][i * numCompsPerCat + k].setDataSign (getDataSign());
                bars[j][i * numCompsPerCat + k].setBaseValue (x + getLinesFillInteriorBaseValue());
                if (graphLengths[j][i * numCompsPerCat + k] >
                  barLowValues[j][i * numCompsPerCat + k]) {
                  bars[j][i * numCompsPerCat + k].setBounds (new Rectangle2D.Float (
                    x + barLowValues[j][i * numCompsPerCat + k] +
                    (getOutlineComponents() ? -1 : 0), y + k * catDelta,
                    graphLengths[j][i * numCompsPerCat + k] -
                    barLowValues[j][i * numCompsPerCat + k], barsThickness));
                }
                else {
                  bars[j][i * numCompsPerCat + k].setBounds (new Rectangle2D.Float (
                    x + graphLengths[j][i * numCompsPerCat + k] +
                    (getOutlineComponents() ? -1 : 0), y + k * catDelta,
                    barLowValues[j][i * numCompsPerCat + k] -
                    graphLengths[j][i * numCompsPerCat + k], barsThickness));
                }
                Rectangle2D.Float clipBounds = new Rectangle2D.Float (
                  bars[j][i * numCompsPerCat + k].getBounds().x, boundsGraph.y,
                  bars[j][i * numCompsPerCat + k].getBounds().width, boundsGraph.height);
                bars[j][i * numCompsPerCat + k].setClipBounds (clipBounds);
                bars[j][i * numCompsPerCat + k].setLightBounds (
                  getComponentsLightType() == COMPONENT ?
                  bars[j][i * numCompsPerCat + k].getBounds() : boundsGraph);
                bars[j][i * numCompsPerCat + k].setLightSource (getComponentsLightSource());
                bars[j][i * numCompsPerCat + k].setColor (!getComponentsColoringByCat() ?
                  getBarColors()[j] : getComponentsColorsByCat()[i]);
                bars[j][i * numCompsPerCat + k].setOutlineExistence (getOutlineComponents());
                bars[j][i * numCompsPerCat + k].setOutlineColor (getOutlineComponentsColor());
                bars[j][i * numCompsPerCat + k].setArcw (getBarRoundingRatio() * barsThickness);
                bars[j][i * numCompsPerCat + k].setArch (getBarRoundingRatio() * barsThickness);
                bars[j][i * numCompsPerCat + k].setWarningRegions (getWarningRegions());
                bars[j][i * numCompsPerCat + k].setType (FancyShape.LABELSLEFT);
                bars[j][i * numCompsPerCat + k].setGraphBounds (boundsGraph);
              }
            }
            if (i + 1 == numBars) break;
            minY = maxY;
            if (i + 2 == numBars &&
              getLabelsAxisTicksAlignment() == this.BETWEEN) {
              maxY = getSpaceSizeLocation (MIN).y + getSpaceSize (MIN).height;
            }
            else maxY = yTicks[i + 1].y + tickHalfHeight;
            ++i;
          } while (true);
        }
      }

      dots = new FancyDot[numSets][numDots * numCompsPerCat];
      if (numDots > 0) {
        int x = getSpaceSizeLocation (MIN).x - dotsThickness / 2, y;
        float catDelta =
          getSpaceSize (MIN).height / (float)(numDots * numCompsPerCat);
        if (numDots == 1) {
          y = getSpaceSizeLocation (MIN).y +
            (getSpaceSize(MIN).height - dotsThickness) / 2;
          y = (int)(y - ((numCompsPerCat - 1) / 2f) * catDelta);
          for (int k = 0; k < numCompsPerCat; ++k) {
            for (int j = 0; j < numSets; ++j) {
              dots[j][k] = new FancyDot();
              dots[j][k].setBounds (new Rectangle2D.Float (
                x + graphLengths[j][k], y + k * catDelta,
                dotsThickness, dotsThickness));
              dots[j][k].setClipBounds (dots[j][k].getBounds());
              dots[j][k].setColor (!getComponentsColoringByCat() ?
                getDotColors()[j] : getComponentsColorsByCat()[0]);
              dots[j][k].setOutlineExistence (getOutlineComponents());
              dots[j][k].setOutlineColor (getOutlineComponentsColor());
              dots[j][k].setLightBounds (
                getComponentsLightType() == COMPONENT ? dots[j][k].getBounds() : boundsGraph);
              dots[j][k].setLightSource (getComponentsLightSource());
              dots[j][k].setWarningRegions (getWarningRegions());
              dots[j][k].setType (FancyShape.LABELSLEFT);
            }
          }
        }
        else {
          float minY, maxY, tickHalfHeight;
          minY = getSpaceSizeLocation (MIN).y;
          tickHalfHeight = yTicks[0].height / 2f;
          maxY = yTicks[0].y + tickHalfHeight;
          int i = 0;
          do {
            if (getLabelsAxisTicksAlignment() == BETWEEN) {
              y = (int)(minY + Math.floor((maxY - minY - dotsThickness) / 2f));
            }
            else y = (int)Math.floor (maxY - dotsThickness / 2f);
            y = (int)(y - ((numCompsPerCat - 1) / 2f) * catDelta);
            for (int k = 0; k < numCompsPerCat; ++k) {
              for (int j = 0; j < numSets; ++j) {
                dots[j][i * numCompsPerCat + k] = new FancyDot();
                dots[j][i * numCompsPerCat + k].setBounds (new Rectangle2D.Float (
                  (float)(x + graphLengths[j][i * numCompsPerCat + k]), y + k * catDelta,
                  dotsThickness, dotsThickness));
                dots[j][i * numCompsPerCat + k].setClipBounds (
                  dots[j][i * numCompsPerCat + k].getBounds());
                dots[j][i * numCompsPerCat + k].setColor (!getComponentsColoringByCat() ?
                  getDotColors()[j] : getComponentsColorsByCat()[i]);
                dots[j][i * numCompsPerCat + k].setOutlineExistence (getOutlineComponents());
                dots[j][i * numCompsPerCat + k].setOutlineColor (getOutlineComponentsColor());
                dots[j][i * numCompsPerCat + k].setLightBounds (
                  getComponentsLightType() == COMPONENT ?
                  dots[j][i * numCompsPerCat + k].getBounds() : boundsGraph);
                dots[j][i * numCompsPerCat + k].setLightSource (getComponentsLightSource());
                dots[j][i * numCompsPerCat + k].setWarningRegions (getWarningRegions());
                dots[j][i * numCompsPerCat + k].setType (FancyShape.LABELSLEFT);
              }
            }
            if (i + 1 == numDots) break;
            minY = maxY;
            if (i + 2 == numDots &&
              getLabelsAxisTicksAlignment() == this.BETWEEN) {
              maxY = getSpaceSizeLocation (MIN).y + getSpaceSize (MIN).height;
            }
            else maxY = yTicks[i + 1].y + tickHalfHeight;
            ++i;
          } while (true);
        }
      }

      if ((numCats * numCompsPerCat) < 2 || linesThickness < 1) lines = new FancyLine[0];
      else {
        lines = new FancyLine[numSets];
        for (int i = 0; i < numSets; ++i) {
          lines[i] = new FancyLine();
          lines[i].setThickness (linesThickness);
          lines[i].setFillArea (getLinesFillInterior());
          lines[i].setColor (getLineColors()[i]);
          lines[i].setOutlineExistence (getOutlineComponents());
          lines[i].setOutlineColor (getOutlineComponentsColor());
          lines[i].setLightSource (getComponentsLightSource());
          lines[i].setWarningRegions (getWarningRegions());
          lines[i].setType (FancyShape.LABELSLEFT);
        }
        Point firstPoints[] = new Point[numSets];
        int x = getSpaceSizeLocation (MIN).x, y;
        float minY, maxY, tickHalfHeight;
        minY = getSpaceSizeLocation (MIN).y;
        tickHalfHeight = yTicks[0].height / 2f;
        maxY = yTicks[0].y + tickHalfHeight;
        float catDelta = getSpaceSize (MIN).height / (float)(numLinePoints * numCompsPerCat);
        int i = 0;
        do {
          if (getLabelsAxisTicksAlignment() == this.BETWEEN) {
            y = (int)(minY + Math.floor((maxY - minY) / 2f));
          }
          else y = (int)maxY;
          y = (int)(y - ((numCompsPerCat - 1) / 2f) * catDelta);

          for (int k = 0; k < numCompsPerCat; ++k) {
            for (int j = 0; j < numSets; ++j) {

              Point thisPoint = new Point (
                (int)(x + graphLengths[j][i * numCompsPerCat + k]),
                (int)(y + k * catDelta));

              if (k == 0 && i == 0) {
                if (getLinesFillInterior()) {
                  firstPoints[j] =
                    new Point (x + getLinesFillInteriorBaseValue(), (int)(y + k * catDelta));
                  lines[j].getLine().moveTo (firstPoints[j].x, firstPoints[j].y);
                  lines[j].getLine().lineTo (thisPoint.x, thisPoint.y);
                }
                else {
                  lines[j].getLine().moveTo (thisPoint.x, thisPoint.y);
                }
              }
              else {
                lines[j].getLine().lineTo (thisPoint.x, thisPoint.y);
                if (getLinesFillInterior() &&
                  k == numCompsPerCat - 1 && i == numLinePoints - 1) {
                    lines[j].getLine().lineTo (firstPoints[j].x, thisPoint.y);
                    lines[j].getLine().lineTo (firstPoints[j].x, firstPoints[j].y);
                }
              }
            }
          }
          if (i + 1 == numLinePoints) break;
          minY = maxY;
          if (i + 2 == numLinePoints &&
            getLabelsAxisTicksAlignment() == this.BETWEEN) {
            maxY = getSpaceSizeLocation (MIN).y + getSpaceSize (MIN).height;
          }
          else maxY = yTicks[i + 1].y + tickHalfHeight;
          ++i;
        } while (true);
        for (int g = 0; g < numSets; ++g) {
          lines[g].setClipBounds (boundsGraph);
          Rectangle2D.Float bounds = (Rectangle2D.Float)lines[g].getLine().getBounds2D();
          lines[g].setLightBounds (
            getComponentsLightType() == COMPONENT ? bounds : boundsGraph);
        }
      }
    }
    else {
      bars = new FancyBar[0][0];
      dots = new FancyDot[0][0];
      lines = new FancyLine[0];
    }
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.