0001: /**
0002: * Chart2D, a java library for drawing two dimensional charts.
0003: * Copyright (C) 2001 Jason J. Simas
0004: *
0005: * This library is free software; you can redistribute it and/or
0006: * modify it under the terms of the GNU Lesser General Public
0007: * License as published by the Free Software Foundation; either
0008: * version 2.1 of the License, or (at your option) any later version.
0009: *
0010: * This library is distributed in the hope that it will be useful,
0011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0013: * Lesser General Public License for more details.
0014: * You should have received a copy of the GNU Lesser General Public
0015: * License along with this library; if not, write to the Free Software
0016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0017: *
0018: * The author of this library may be contacted at:
0019: * E-mail: jjsimas@users.sourceforge.net
0020: * Street Address: J J Simas, 887 Tico Road, Ojai, CA 93023-3555 USA
0021: */package net.sourceforge.chart2d;
0022:
0023: import java.awt.*;
0024: import java.awt.geom.*;
0025: import java.util.*;
0026:
0027: /**
0028: * A container for many variables and components relating to a graph area.
0029: * A graph area is the area that both the y axis and x axis touch, and in which
0030: * bars, lines, or dots are plotted to represent the data set.
0031: */
0032: class GraphArea extends Area {
0033:
0034: /**
0035: * Indicates the continuous.
0036: */
0037: static float[] CONTINUOUS = { 10.0f, 0.0f };
0038: /**
0039: * Indicates the dashed.
0040: */
0041: static float[] DASHED = { 7.0f, 3.0f };
0042: /**
0043: * Indicates the dotted.
0044: */
0045: static float[] DOTTED = { 3.0f, 3.0f };
0046: /**
0047: * Indicates positive.
0048: */
0049: static int POS = 1;
0050: /**
0051: * Indicates both positive and negative.
0052: */
0053: static int MIX = 0;
0054: /**
0055: * Indicates negative.
0056: */
0057: static int NEG = -1;
0058:
0059: static final int COMPONENT = 0;
0060: static final int GRAPH = 1;
0061:
0062: private int type;
0063: private boolean allowComponentAlignment;
0064:
0065: private Rectangle[] xTicks;
0066: private Rectangle[] yTicks;
0067: private int ticksAlignment;
0068: private int[][] graphValues;
0069: private int[][] barLowValues;
0070:
0071: private boolean linesThicknessAssociation;
0072: private boolean verticalLinesExistence;
0073: private Line2D.Double[] verticalLines;
0074: private int verticalLinesThicknessModel;
0075: private int verticalLinesThickness;
0076: private Color verticalLinesColor;
0077: private float[] verticalLinesStyle;
0078: private BasicStroke verticalLinesStroke;
0079:
0080: private boolean horizontalLinesExistence;
0081: private Line2D.Double[] horizontalLines;
0082: private int horizontalLinesThicknessModel;
0083: private int horizontalLinesThickness;
0084: private Color horizontalLinesColor;
0085: private float[] horizontalLinesStyle;
0086: private BasicStroke horizontalLinesStroke;
0087:
0088: private boolean barsExistence;
0089: private int barsThicknessModel;
0090: private Color[] barColors;
0091: private float barsExcessSpaceFeedbackRatio;
0092: private float barsWithinCategoryOverlapRatio;
0093:
0094: private boolean dotsExistence;
0095: private int dotsThicknessModel;
0096: private Color[] dotColors;
0097: private float dotsExcessSpaceFeedbackRatio;
0098: private float dotsWithinCategoryOverlapRatio;
0099:
0100: private boolean linesExistence;
0101: private int linesThicknessModel;
0102: private Color[] lineColors;
0103: private boolean linesFillInterior;
0104: private int linesFillInteriorBaseValue;
0105: private float linesExcessSpaceFeedbackRatio;
0106: private float linesWithinCategoryOverlapRatio;
0107:
0108: private boolean outlineComponents;
0109: private Color outlineComponentsColor;
0110:
0111: private boolean betweenComponentsGapExistence;
0112: private int betweenComponentsGapThicknessModel;
0113:
0114: private float barRoundingRatio;
0115: private int roundSide;
0116: private int lightSource;
0117: private int lightType;
0118: private Vector warningRegions;
0119: private boolean clip;
0120: private boolean componentsColoringByCat;
0121: private Color[] componentsColorsByCat;
0122:
0123: private int dataSign;
0124:
0125: private AlphaComposite componentsAlphaComposite;
0126:
0127: private boolean needsUpdate;
0128:
0129: /**
0130: * Creates a graph area with the default values of the Area class
0131: * (except where overridden here), and its own default values.
0132: */
0133: GraphArea() {
0134:
0135: setType(LABELSBOTTOM);
0136: setGraphValues(new int[0][0]);
0137: setBarLowValues(new int[0][0]);
0138: setAllowComponentAlignment(false);
0139:
0140: setAutoSizes(false, false);
0141: setAutoJustifys(false, false);
0142: setBackgroundColor(Color.lightGray);
0143: setBorderAssociations(false, false, true, true, false, false);
0144: setBorderCornerAssociations(LEFT, LEFT, RIGHT, RIGHT);
0145: setBorderColors(Color.black, Color.gray, Color.gray,
0146: Color.black);
0147:
0148: setXTicks(new Rectangle[0]);
0149: setYTicks(new Rectangle[0]);
0150:
0151: setLinesThicknessAssociation(true);
0152: setHorizontalLinesExistence(true);
0153: setHorizontalLinesThicknessModel(2);
0154: setHorizontalLinesStyle(CONTINUOUS);
0155: setHorizontalLinesColor(Color.gray);
0156: setVerticalLinesExistence(false);
0157: setVerticalLinesThicknessModel(2);
0158: setVerticalLinesStyle(CONTINUOUS);
0159: setVerticalLinesColor(Color.gray);
0160:
0161: setBarsExistence(true);
0162: setBarsThicknessModel(10);
0163: setBarColors(new Color[0]);
0164: setBarsExcessSpaceFeedbackRatio(.75f);
0165: setBarsWithinCategoryOverlapRatio(.5f);
0166:
0167: setDotsExistence(false);
0168: setDotsThicknessModel(8);
0169: setDotColors(new Color[0]);
0170: setDotsExcessSpaceFeedbackRatio(0f);
0171: setDotsWithinCategoryOverlapRatio(.5f);
0172:
0173: setLinesExistence(false);
0174: setLinesThicknessModel(4);
0175: setLineColors(new Color[0]);
0176: setLinesFillInterior(false);
0177: setLinesFillInteriorBaseValue(0);
0178: setLinesExcessSpaceFeedbackRatio(0f);
0179: setLinesWithinCategoryOverlapRatio(.5f);
0180:
0181: setBetweenComponentsGapExistence(true);
0182: setBetweenComponentsGapThicknessModel(2);
0183: setLabelsAxisTicksAlignment(BETWEEN);
0184:
0185: setGapExistence(false);
0186: setOutlineComponents(true);
0187: setOutlineComponentsColor(Color.black);
0188:
0189: setBarRoundingRatio(.25f);
0190: setComponentsLightSource(FancyShape.LEFT);
0191: setComponentsLightType(COMPONENT);
0192:
0193: setClip(true);
0194: setComponentsColoringByCat(false);
0195: setComponentsColorsByCat(new Color[0]);
0196:
0197: resetGraphAreaModel(true);
0198: needsUpdate = true;
0199: }
0200:
0201: /**
0202: * Sets the actual AlphaComposite object to use on the Graphics2D object context for painting the
0203: * graph components managed by this GraphProperties object. By passing different AlphaComposite
0204: * objects, the graph components can take on a blending or transparency effect. Underneath
0205: * components can be seen through components painted over them. This is especially useful for
0206: * "line area" or "filled line" charts because top lines can paint over underneath lines if not
0207: * using a "stacked" dataset object.
0208: * @param a The AlphaComposite object to use.
0209: */
0210: public final void setComponentsAlphaComposite(AlphaComposite a) {
0211:
0212: componentsAlphaComposite = a;
0213: needsUpdate = true;
0214: }
0215:
0216: /**
0217: * Gets the actual AlphaComposite object to use on the Graphics2D object context for painting the
0218: * graph components managed by this GraphProperties object. By passing different AlphaComposite
0219: * objects, the graph components can take on a blending or transparency effect. Underneath
0220: * components can be seen through components painted over them. This is especially useful for
0221: * "line area" or "filled line" charts because top lines can paint over underneath lines if not
0222: * using a "stacked" dataset object.
0223: * @return The AlphaComposite object to use.
0224: */
0225: public final AlphaComposite getComponentsAlphaComposite() {
0226: return componentsAlphaComposite;
0227: }
0228:
0229: /**
0230: * Sets which kinds of the data is graphed.
0231: * Use POS for non-negative data.
0232: * Use NEG for non-positive data.
0233: * Use MIX for both positive and negative data.
0234: * @param sign The sign of the data.
0235: */
0236: final void setDataSign(int sign) {
0237:
0238: dataSign = sign;
0239: needsUpdate = true;
0240: }
0241:
0242: /**
0243: * Gets which kinds of the data is graphed.
0244: * Use POS for non-negative data.
0245: * Use NEG for non-positive data.
0246: * Use MIX for both positive and negative data.
0247: * @return The sign of the data.
0248: */
0249: final int getDataSign() {
0250:
0251: return dataSign;
0252: }
0253:
0254: /**
0255: * Sets whether the graph components are colored by category or by set.
0256: * @param b If true, then colored by category.
0257: */
0258: final void setComponentsColoringByCat(boolean b) {
0259: needsUpdate = true;
0260: componentsColoringByCat = b;
0261: }
0262:
0263: /**
0264: * Sets the color array for the category coloring.
0265: * @param c The color array.
0266: */
0267: final void setComponentsColorsByCat(Color[] c) {
0268: needsUpdate = true;
0269: componentsColorsByCat = c;
0270: }
0271:
0272: /**
0273: * Sets the whether the overpaint of the graph components are clipped or not.
0274: * @param c If true then the components are clipped.
0275: */
0276: final void setClip(boolean c) {
0277: needsUpdate = true;
0278: clip = c;
0279: }
0280:
0281: /**
0282: * Sets the warning regions vector for applying to the graph background and the graph components.
0283: * @param v The warning regions vector.
0284: */
0285: final void setWarningRegions(Vector v) {
0286: warningRegions = v;
0287: needsUpdate = true;
0288: }
0289:
0290: /**
0291: * Sets the ratio of the rounding arc to the thickness of the bar.
0292: * Values need to be between zero and one. Zero is square. One is perfectly round.
0293: * @param r The ratio.
0294: */
0295: final void setBarRoundingRatio(float r) {
0296: barRoundingRatio = r;
0297: needsUpdate = true;
0298: }
0299:
0300: /**
0301: * Sets the side from which the lighting affect originates.
0302: * all components for each set).
0303: * For specifying the side, use the fields of FancyShape:
0304: * TOP, BOTTOM, LEFT, RIGHT, TOPLEFT, BOTTOMRIGHT, and NONE.
0305: * Added for Siperian.
0306: * @param s The side.
0307: */
0308: final void setComponentsLightSource(int s) {
0309: lightSource = s;
0310: needsUpdate = true;
0311: }
0312:
0313: /**
0314: * Sets the type of lighting affect.
0315: * Type refers to whether the lighting should begin and end by component or by graph (meaning
0316: * all components for each set).
0317: * For specifying the type use the fields COMPONENT and GRAPH.
0318: * Added for Siperian.
0319: * @param t The type.
0320: */
0321: final void setComponentsLightType(int t) {
0322: lightType = t;
0323: needsUpdate = true;
0324: }
0325:
0326: /**
0327: * Indicates whether bars, lines, and/or dots should have a thin black
0328: * outline around them.
0329: * @param outline If true, then there will be an outline.
0330: */
0331: final void setOutlineComponents(boolean outline) {
0332:
0333: needsUpdate = true;
0334: outlineComponents = outline;
0335: }
0336:
0337: /**
0338: * Indicates the color of the components outline if it exists.
0339: * @param color The color for the outline.
0340: */
0341: final void setOutlineComponentsColor(Color color) {
0342:
0343: needsUpdate = true;
0344: outlineComponentsColor = color;
0345: }
0346:
0347: /**
0348: * Placement of the graph components (bars, dots, or line points) depends
0349: * to some degree on placement of the ticks. (It shouldn't, but it does in
0350: * order to have things lined up within 1 pixel error). Pass the alignment
0351: * setting of the ticks of the axis that has the data description "labels".
0352: * @param alignment A value of either Area.BETWEEN or Area.CENTERED
0353: */
0354: final void setLabelsAxisTicksAlignment(int alignment) {
0355: needsUpdate = true;
0356: ticksAlignment = alignment;
0357: }
0358:
0359: /**
0360: * The type of the graph area. There exist two types of graph areas. One
0361: * has the data descriptors on the bottom (i.e. vertical bar chart); the other
0362: * has them on the left (i.e. horizontal bar chart).
0363: * @param type The type of the graph area. [LABELSBOTTOM or LABELSLEFT]
0364: */
0365: final void setType(int type) {
0366:
0367: needsUpdate = true;
0368: this .type = type;
0369: }
0370:
0371: /**
0372: * Specifies whether graph components, bars, lines, or dots are offset from
0373: * eachother. Generally, var charts are not aligned, and line and dot charts
0374: * are.
0375: * @param allow If true, then aligns the components.
0376: */
0377: final void setAllowComponentAlignment(boolean allow) {
0378:
0379: needsUpdate = true;
0380: allowComponentAlignment = allow;
0381: }
0382:
0383: /**
0384: * The heights/widths of the components. This is respective to the bottom of
0385: * the graph area, but above the border/to the left of the graph area. This
0386: * is an array of arrays of values. The first array contains data sets. The
0387: * inner arrays contains the heights/widths for each set. Heights are used
0388: * for when the type of graph area is LABELSBOTTOM. Otherwise, widths.
0389: * @param values The offsets of the components from the data descriptor axis.
0390: */
0391: final void setGraphValues(int[][] values) {
0392:
0393: needsUpdate = true;
0394: graphValues = values;
0395: }
0396:
0397: /**
0398: * Determines where bars of bar charts begin. Generally bars begin at zero,
0399: * but with stackable charts, bars sometimes need to start at the tops of
0400: * other bars. Also, bars can be used to signify uncertainty (i.e. 3+-2) can
0401: * be signified by a bar that starts at 1 and goes to 5.
0402: * @param values The low values normalized the graph area (i.e. not the actual
0403: * data set values).
0404: */
0405: final void setBarLowValues(int[][] values) {
0406:
0407: needsUpdate = true;
0408: barLowValues = values;
0409: }
0410:
0411: /**
0412: * Sets the ticks of the x axis. This is necessary in order to make sure the
0413: * components area exactly where they should be, either between the ticks or
0414: * aligned exactly respective to the middle of them.
0415: * @param ticks The bounds of the ticks, location and size.
0416: */
0417: final void setXTicks(Rectangle[] ticks) {
0418:
0419: needsUpdate = true;
0420: this .xTicks = ticks;
0421: }
0422:
0423: /**
0424: * Sets the ticks of the x axis. This is necessary in order to make sure the
0425: * components area exactly where they should be, either between the ticks or
0426: * aligned exactly respective to the middle of them.
0427: * @param ticks The bounds of the ticks, location and size.
0428: */
0429: final void setYTicks(Rectangle[] ticks) {
0430:
0431: needsUpdate = true;
0432: this .yTicks = ticks;
0433: }
0434:
0435: /**
0436: * Specifies whether the vertical and/or horizontal lines should maintain
0437: * the same size. The vertical/horizontal lines are do not represent the
0438: * data sets. These lines are either perfectly horizontal or perfectly
0439: * vertical and mark out the graph area.
0440: * @param association If true, then the lines thicknesses will be equal.
0441: */
0442: final void setLinesThicknessAssociation(boolean association) {
0443:
0444: needsUpdate = true;
0445: linesThicknessAssociation = association;
0446: }
0447:
0448: /**
0449: * Whether the horizontal lines exist.
0450: * @param existence If true, then they do.
0451: */
0452: final void setHorizontalLinesExistence(boolean existence) {
0453:
0454: needsUpdate = true;
0455: horizontalLinesExistence = existence;
0456: }
0457:
0458: /**
0459: * The model thickness for the horizontal lines. If auto maximum sizing
0460: * is enabled,
0461: * then the actual thickness size can grow and shrink; in this case a ratio
0462: * based
0463: * on the maximum area size / model area size is computed and applied to the
0464: * model thickness in order to find the actual thickness. With maximum sizing
0465: * disabled, the actual thickness is the model thickness.
0466: * @param thickness The model thickness for the horizontal lines.
0467: */
0468: final void setHorizontalLinesThicknessModel(int thickness) {
0469:
0470: needsUpdate = true;
0471: horizontalLinesThicknessModel = thickness;
0472: }
0473:
0474: /**
0475: * The style of the horizontal lines. Lines may be continuous, dashed and
0476: * dotted. Or something other. See BasicStroke for more information.
0477: * @param style The style of the lines [CONTINOUS, DASHED, DOTTED]
0478: */
0479: final void setHorizontalLinesStyle(float[] style) {
0480:
0481: needsUpdate = true;
0482: horizontalLinesStyle = style;
0483: }
0484:
0485: /**
0486: * The color of the horizontal lines.
0487: * @param color Some Color.
0488: */
0489: final void setHorizontalLinesColor(Color color) {
0490:
0491: needsUpdate = true;
0492: horizontalLinesColor = color;
0493: }
0494:
0495: /**
0496: * Whether the vertical lines exist.
0497: * @param existence If true, then they do.
0498: */
0499: final void setVerticalLinesExistence(boolean existence) {
0500:
0501: needsUpdate = true;
0502: verticalLinesExistence = existence;
0503: }
0504:
0505: /**
0506: * The model thickness for the vertical lines. If auto maximum sizing
0507: * is enabled,
0508: * then the actual thickness size can grow and shrink; in this case a ratio
0509: * based
0510: * on the maximum area size / model area size is computed and applied to the
0511: * model thickness in order to find the actual thickness. With maximum sizing
0512: * disabled, the actual thickness is the model thickness.
0513: * @param thickness The model thickness for the vertical lines.
0514: */
0515: final void setVerticalLinesThicknessModel(int thickness) {
0516:
0517: needsUpdate = true;
0518: verticalLinesThicknessModel = thickness;
0519: }
0520:
0521: /**
0522: * The style of the vertical lines. Lines may be continuous, dashed and
0523: * dotted. Or something other. See BasicStroke for more information.
0524: * @param style The style of the lines [CONTINOUS, DASHED, DOTTED]
0525: */
0526: final void setVerticalLinesStyle(float[] style) {
0527:
0528: needsUpdate = true;
0529: verticalLinesStyle = style;
0530: }
0531:
0532: /**
0533: * The color of the vertical lines.
0534: * @param color Some Color.
0535: */
0536: final void setVerticalLinesColor(Color color) {
0537:
0538: needsUpdate = true;
0539: verticalLinesColor = color;
0540: }
0541:
0542: /**
0543: * Whether to paint bars representing the graph values. If they do not exist
0544: * then they will not be included in calculations or in painting.
0545: * @param existence If true, then they exist.
0546: */
0547: final void setBarsExistence(boolean existence) {
0548:
0549: needsUpdate = true;
0550: barsExistence = existence;
0551: }
0552:
0553: /**
0554: * The model thickness for the bars. If auto maximum sizing
0555: * is enabled,
0556: * then the actual thickness size can grow and shrink; in this case a ratio
0557: * based
0558: * on the maximum area size / model area size is computed and applied to the
0559: * model thickness in order to find the actual thickness. With maximum sizing
0560: * disabled, the actual thickness is the model thickness.
0561: * @param thickness The model thickness for the bars.
0562: */
0563: final void setBarsThicknessModel(int thickness) {
0564:
0565: needsUpdate = true;
0566: barsThicknessModel = thickness;
0567: }
0568:
0569: /**
0570: * The colors of the bar sets. Each data set has its own color. In every
0571: * set of bars, the left most bar (or first bar painted when components are
0572: * aligned) will be the color in the lowest order array position.
0573: * @param colors The colors for the data sets.
0574: */
0575: final void setBarColors(Color[] colors) {
0576:
0577: needsUpdate = true;
0578: barColors = colors;
0579: }
0580:
0581: /**
0582: * Specifies the amount of the excess space to feed back to bars thickness.
0583: * Frequently the graphs are larger than necessary, the excess space can
0584: * be fedback to the bars, making them larger. The ratio is the amount of
0585: * space to feed back to the bars, to the total amount of space.
0586: * @param ratio The ratio on the total amount of space to feedback.
0587: */
0588: final void setBarsExcessSpaceFeedbackRatio(float ratio) {
0589:
0590: needsUpdate = true;
0591: barsExcessSpaceFeedbackRatio = ratio;
0592: }
0593:
0594: /**
0595: * Specifies how much the bars can overlap eachother when there are multiple
0596: * data values per data set and per data category.
0597: * @param ratio The ratio on the thickness of the bar for overlap.
0598: */
0599: final void setBarsWithinCategoryOverlapRatio(float ratio) {
0600: needsUpdate = true;
0601: barsWithinCategoryOverlapRatio = ratio;
0602: }
0603:
0604: /**
0605: * Whether to paint dots representing the graph values. If they do not exist
0606: * then they will not be included in calculations or in painting.
0607: * @param existence If true, then they exist.
0608: */
0609: final void setDotsExistence(boolean existence) {
0610:
0611: needsUpdate = true;
0612: dotsExistence = existence;
0613: }
0614:
0615: /**
0616: * The model thickness for the dots. If auto maximum sizing
0617: * is enabled,
0618: * then the actual thickness size can grow and shrink; in this case a ratio
0619: * based
0620: * on the maximum area size / model area size is computed and applied to the
0621: * model thickness in order to find the actual thickness. With maximum sizing
0622: * disabled, the actual thickness is the model thickness.
0623: * @param thickness The model thickness for the dots.
0624: */
0625: final void setDotsThicknessModel(int thickness) {
0626:
0627: needsUpdate = true;
0628: dotsThicknessModel = thickness;
0629: }
0630:
0631: /**
0632: * Specifies how much the dots can overlap eachother when there are multiple
0633: * data values per data set and per data category.
0634: * @param ratio The ratio on the thickness of the dot for overlap.
0635: */
0636: final void setDotsWithinCategoryOverlapRatio(float ratio) {
0637: needsUpdate = true;
0638: dotsWithinCategoryOverlapRatio = ratio;
0639: }
0640:
0641: /**
0642: * The colors of the dot sets. Each data set has its own color. In every
0643: * set of dots, the left most dot (or first dot painted when components are
0644: * aligned) will be the color in the lowest order array position.
0645: * @param colors The colors for the data sets.
0646: */
0647: final void setDotColors(Color[] colors) {
0648:
0649: needsUpdate = true;
0650: dotColors = colors;
0651: }
0652:
0653: /**
0654: * Specifies the amount of the excess space to feed back to dots thickness.
0655: * Frequently the graphs are larger than necessary, the excess space can
0656: * be fedback to the dots, making them larger. The ratio is the amount of
0657: * space to feed back to the dots, to the total amount of space.
0658: * @param ratio The ratio on the total amount of space to feedback.
0659: */
0660: final void setDotsExcessSpaceFeedbackRatio(float ratio) {
0661:
0662: needsUpdate = true;
0663: dotsExcessSpaceFeedbackRatio = ratio;
0664: }
0665:
0666: /**
0667: * Whether to paint lines representing the graph values. If they do not exist
0668: * then they will not be included in calculations or in painting.
0669: * @param existence If true, then they exist.
0670: */
0671: final void setLinesExistence(boolean existence) {
0672:
0673: needsUpdate = true;
0674: linesExistence = existence;
0675: }
0676:
0677: /**
0678: * The model thickness for the lines. If auto maximum sizing
0679: * is enabled,
0680: * then the actual thickness size can grow and shrink; in this case a ratio
0681: * based
0682: * on the maximum area size / model area size is computed and applied to the
0683: * model thickness in order to find the actual thickness. With maximum sizing
0684: * disabled, the actual thickness is the model thickness.
0685: * @param thickness The model thickness for the lines.
0686: */
0687: final void setLinesThicknessModel(int thickness) {
0688:
0689: needsUpdate = true;
0690: linesThicknessModel = thickness;
0691: }
0692:
0693: /**
0694: * Indicates whether the region between the lines and between its baseline
0695: * should be filled in.
0696: * @param fill If true, then the region under/above the lines will be filled.
0697: */
0698: final void setLinesFillInterior(boolean fill) {
0699:
0700: needsUpdate = true;
0701: linesFillInterior = fill;
0702: }
0703:
0704: /**
0705: * Indicates the length across the graph length, in the same direction of the
0706: * meaning of the graph values, that the forms the base for the filled region.
0707: * @param int The base value for the region.
0708: */
0709: final void setLinesFillInteriorBaseValue(int value) {
0710:
0711: needsUpdate = true;
0712: linesFillInteriorBaseValue = value;
0713: }
0714:
0715: /**
0716: * The colors of the line sets. Each data set has its own color. In every
0717: * set of lines, the left most line (or first line painted when components are
0718: * aligned) will be the color in the lowest order array position.
0719: * @param colors The colors for the data sets.
0720: */
0721: final void setLineColors(Color[] colors) {
0722:
0723: needsUpdate = true;
0724: lineColors = colors;
0725: }
0726:
0727: /**
0728: * Specifies the amount of the excess space to feed back to lines thickness.
0729: * Frequently the graphs are larger than necessary, the excess space can
0730: * be fedback to the lines, making them larger. The ratio is the amount of
0731: * space to feed back to the lines, to the total amount of space.
0732: * @param ratio The ratio on the total amount of space to feedback.
0733: */
0734: final void setLinesExcessSpaceFeedbackRatio(float ratio) {
0735:
0736: needsUpdate = true;
0737: linesExcessSpaceFeedbackRatio = ratio;
0738: }
0739:
0740: /**
0741: * Specifies how much the lines can overlap eachother when there are multiple
0742: * data values per data set and per data category.
0743: * @param ratio The ratio on the thickness of the line for overlap.
0744: */
0745: final void setLinesWithinCategoryOverlapRatio(float ratio) {
0746: needsUpdate = true;
0747: linesWithinCategoryOverlapRatio = ratio;
0748: }
0749:
0750: /**
0751: * Whether there exists a gap between plotted data sets. For instance, after
0752: * plotting a single bar from each data set, the gap between these and the
0753: * next bars from the next location within the data sets.
0754: * @param existence If true, then it does.
0755: */
0756: final void setBetweenComponentsGapExistence(boolean existence) {
0757:
0758: needsUpdate = true;
0759: betweenComponentsGapExistence = existence;
0760: }
0761:
0762: /**
0763: * The model thickness for the gap. If auto maximum sizing
0764: * is enabled,
0765: * then the actual thickness size can grow and shrink; in this case a ratio
0766: * based
0767: * on the maximum area size / model area size is computed and applied to the
0768: * model thickness in order to find the actual thickness. With maximum sizing
0769: * disabled, the actual thickness is the model thickness.
0770: * @param thickness The model thickness for the gap.
0771: */
0772: final void setBetweenComponentsGapThicknessModel(int thickness) {
0773:
0774: needsUpdate = true;
0775: betweenComponentsGapThicknessModel = thickness;
0776: }
0777:
0778: /**
0779: * Gets the ratio of the rounding arc to the thickness of the bar.
0780: * Values need to be between zero and one. Zero is square. One is perfectly round.
0781: * @return The ratio.
0782: */
0783: final float getBarRoundingRatio() {
0784: return barRoundingRatio;
0785: }
0786:
0787: /**
0788: * Gets the side from which the lighting affect originates.
0789: * Use the fields of FancyShape: TOP, BOTTOM, LEFT, RIGHT, TOPLEFT, BOTTOMRIGHT, and NONE.
0790: * Added for Siperian.
0791: * @return int The side.
0792: */
0793: final int getComponentsLightSource() {
0794: return lightSource;
0795: }
0796:
0797: /**
0798: * Gets the type of lighting affect.
0799: * Type refers to whether the lighting should begin and end by component or by graph (meaning
0800: * all components for each set).
0801: * For specifying the type use the fields COMPONENT and GRAPH.
0802: * Added for Siperian.
0803: * @return int The type.
0804: */
0805: final int getComponentsLightType() {
0806: return lightType;
0807: }
0808:
0809: /**
0810: * Gets the warning regions vector for applying to the graph background and the graph components.
0811: * @return The warning regions vector.
0812: */
0813: final Vector getWarningRegions() {
0814: return warningRegions;
0815: }
0816:
0817: /**
0818: * Gets the whether the overpaint of the graph components are clipped or not.
0819: * @return If true then the components are clipped.
0820: */
0821: final boolean getClip() {
0822: return clip;
0823: }
0824:
0825: /**
0826: * Gets the color array for the category coloring.
0827: * @return The color array.
0828: */
0829: final Color[] getComponentsColorsByCat() {
0830: return componentsColorsByCat;
0831: }
0832:
0833: /**
0834: * Gets whether the graph components are colored by category or by set.
0835: * @return If true, then colored by category.
0836: */
0837: final boolean getComponentsColoringByCat() {
0838: return componentsColoringByCat;
0839: }
0840:
0841: /**
0842: * Returns whether bars, lines, and/or dots should have a thin black
0843: * outline around them.
0844: * @return boolean If true, then outline.
0845: */
0846: final boolean getOutlineComponents() {
0847:
0848: return outlineComponents;
0849: }
0850:
0851: /**
0852: * Returns the color of the components outline if it exists.
0853: * @return Color The color of the outline.
0854: */
0855: final Color getOutlineComponentsColor() {
0856:
0857: return outlineComponentsColor;
0858: }
0859:
0860: /**
0861: * Returns the type of graph.
0862: * @return The type of graph. [LABELSBOTTOM or LABELSLEFT]
0863: */
0864: final int getType() {
0865:
0866: return type;
0867: }
0868:
0869: /**
0870: * Returns whether the bars, lines or dots are aligned.
0871: * @return If true, then they are.
0872: */
0873: final boolean getAllowComponentAlignment() {
0874:
0875: return allowComponentAlignment;
0876: }
0877:
0878: /**
0879: * Returns the graph values for the bars, dots, and lines.
0880: * @return The graph values, heights or widths respective to the bottom or
0881: * side of the graph area.
0882: */
0883: final int[][] getGraphValues() {
0884:
0885: return graphValues;
0886: }
0887:
0888: /**
0889: * Returns the low graph values for bars.
0890: * @return int[][] The low values.
0891: */
0892: final int[][] getBarLowValues() {
0893:
0894: return barLowValues;
0895: }
0896:
0897: /**
0898: * Returns the ticks of the x axis. Actually these mereley are the bounds of
0899: * the ticks, locations and sizes.
0900: * @return Bounds for the x axis ticks.
0901: */
0902: final Rectangle[] getXTicks() {
0903:
0904: return xTicks;
0905: }
0906:
0907: /**
0908: * Returns the ticks of the y axis. Actually these mereley are the bounds of
0909: * the ticks, locations and sizes.
0910: * @return Bounds for the y axis ticks.
0911: */
0912: final Rectangle[] getYTicks() {
0913:
0914: return yTicks;
0915: }
0916:
0917: /**
0918: * Indicates whether the ticks are aligned between each pair of labels or in
0919: * the center of the each label of the labels axis.
0920: * @return int With the value of either Area.CENTERED or Area.BETWEEN
0921: */
0922: final int getLabelsAxisTicksAlignment() {
0923:
0924: return ticksAlignment;
0925: }
0926:
0927: /**
0928: * Returns this property.
0929: * @return If true, then they do.
0930: */
0931: final boolean getBarsExistence() {
0932:
0933: return barsExistence;
0934: }
0935:
0936: /**
0937: * Returns this property.
0938: * @return The model thickness of the bars.
0939: */
0940: final int getBarsThicknessModel() {
0941:
0942: return barsThicknessModel;
0943: }
0944:
0945: /**
0946: * Returns this property.
0947: * @return The colors of the bars.
0948: */
0949: final Color[] getBarColors() {
0950:
0951: return barColors;
0952: }
0953:
0954: /**
0955: * Returns the amount of the excess space to feed back to bars thickness.
0956: * @return float The ratio on the total amount of space to feedback.
0957: */
0958: final float getBarsExcessSpaceFeedbackRatio() {
0959: return barsExcessSpaceFeedbackRatio;
0960: }
0961:
0962: /**
0963: * Returns how much the bars can overlap eachother when there are multiple
0964: * data values per data set and per data category.
0965: * @return float The ratio on the thickness of the bar for overlap.
0966: */
0967: final float getBarsWithinCategoryOverlapRatio() {
0968: return barsWithinCategoryOverlapRatio;
0969: }
0970:
0971: /**
0972: * Returns this property.
0973: * @return If true, then they do.
0974: */
0975: final boolean getDotsExistence() {
0976:
0977: return dotsExistence;
0978: }
0979:
0980: /**
0981: * Returns this property.
0982: * @return The model thickness of the dots.
0983: */
0984: final int getDotsThicknessModel() {
0985:
0986: return dotsThicknessModel;
0987: }
0988:
0989: /**
0990: * Returns this property.
0991: * @return The colors of the dots.
0992: */
0993: final Color[] getDotColors() {
0994:
0995: return dotColors;
0996: }
0997:
0998: /**
0999: * Returns the amount of the excess space to feed back to dots thickness.
1000: * @return float The ratio on the total amount of space to feedback.
1001: */
1002: final float getDotsExcessSpaceFeedbackRatio() {
1003: return dotsExcessSpaceFeedbackRatio;
1004: }
1005:
1006: /**
1007: * Returns how much the dots can overlap eachother when there are multiple
1008: * data values per data set and per data category.
1009: * @return float The ratio on the thickness of the dot for overlap.
1010: */
1011: final float getDotsWithinCategoryOverlapRatio() {
1012: return dotsWithinCategoryOverlapRatio;
1013: }
1014:
1015: /**
1016: * Returns this property.
1017: * @return If true, then they do.
1018: */
1019: final boolean getLinesExistence() {
1020:
1021: return linesExistence;
1022: }
1023:
1024: /**
1025: * Returns this property.
1026: * @return The model thickness of the lines.
1027: */
1028: final int getLinesThicknessModel() {
1029:
1030: return linesThicknessModel;
1031: }
1032:
1033: /**
1034: * Returns whether the region between the lines and between its baseline
1035: * should be filled in.
1036: * @return boolean If true, then the region under/above the lines will be
1037: * filled.
1038: */
1039: final boolean getLinesFillInterior() {
1040:
1041: return linesFillInterior;
1042: }
1043:
1044: /**
1045: * Returns the length across the graph length, in the same direction of the
1046: * meaning of the graph values, that the forms the base for the filled region.
1047: * @return The base value for the region.
1048: */
1049: final int getLinesFillInteriorBaseValue() {
1050:
1051: return linesFillInteriorBaseValue;
1052: }
1053:
1054: /**
1055: * Returns this property.
1056: * @return The colors of the lines.
1057: */
1058: final Color[] getLineColors() {
1059:
1060: return lineColors;
1061: }
1062:
1063: /**
1064: * Returns the amount of the excess space to feed back to lines thickness.
1065: * @return float The ratio on the total amount of space to feedback.
1066: */
1067: final float getLinesExcessSpaceFeedbackRatio() {
1068: return linesExcessSpaceFeedbackRatio;
1069: }
1070:
1071: /**
1072: * Returns how much the lines can overlap eachother when there are multiple
1073: * data values per data set and per data category.
1074: * @return float The ratio on the thickness of the line for overlap.
1075: */
1076: final float getLinesWithinCategoryOverlapRatio() {
1077: return linesWithinCategoryOverlapRatio;
1078: }
1079:
1080: /**
1081: * Returns this property.
1082: * @return If true, then it does.
1083: */
1084: final boolean getBetweenComponentsGapExistence() {
1085:
1086: return betweenComponentsGapExistence;
1087: }
1088:
1089: /**
1090: * Returns this property.
1091: * @return The model thickness of this gap.
1092: */
1093: final int getBetweenComponentsGapThicknessModel() {
1094:
1095: return betweenComponentsGapThicknessModel;
1096: }
1097:
1098: /**
1099: * Returns a value indicating existence of vertical lines on the graph.
1100: * @return True if vertical lines exist.
1101: */
1102: final boolean getVerticalLinesExistence() {
1103:
1104: return verticalLinesExistence;
1105: }
1106:
1107: /**
1108: * Returns a value of the vertical lines model thickness.
1109: * @return The model thickness of this vertical lines.
1110: */
1111: final int getVerticalLinesThicknessModel() {
1112:
1113: return verticalLinesThicknessModel;
1114: }
1115:
1116: /**
1117: * Returns a value of the vertical lines thickness.
1118: * @return The thickness of this vertical lines.
1119: */
1120: final int getVerticalLinesThickness() {
1121:
1122: updateGraphArea();
1123: return verticalLinesThickness;
1124: }
1125:
1126: /**
1127: * Returns a value of the color of the vertical lines.
1128: * @return The color of the vertical lines.
1129: */
1130: final Color getVerticalLinesColor() {
1131:
1132: return verticalLinesColor;
1133: }
1134:
1135: /**
1136: * Returns a value of the style of the vertical lines.
1137: * Possible values are CONTINUOUS, DASHED, and DOTTED.
1138: * @return The style of the vertical lines.
1139: */
1140: final float[] getVerticalLinesStyle() {
1141:
1142: return verticalLinesStyle;
1143: }
1144:
1145: /**
1146: * Returns a value indicating existence of horizontal lines on the graph.
1147: * @return True if horizontal lines exist.
1148: */
1149: final boolean getHorizontalLinesExistence() {
1150:
1151: return horizontalLinesExistence;
1152: }
1153:
1154: /**
1155: * Returns a value of the horizontal lines model thickness.
1156: * @return The model thickness of this horizontal lines.
1157: */
1158: final int getHorizontalLinesThicknessModel() {
1159:
1160: return horizontalLinesThicknessModel;
1161: }
1162:
1163: /**
1164: * Returns a value of the horizontal lines thickness.
1165: * @return The thickness of this horizontal lines.
1166: */
1167: final int getHorizontalLinesThickness() {
1168:
1169: updateGraphArea();
1170: return horizontalLinesThickness;
1171: }
1172:
1173: /**
1174: * Returns a value of the color of the horizontal lines.
1175: * @return The color of the horizontal lines.
1176: */
1177: final Color getHorizontalLinesColor() {
1178:
1179: return horizontalLinesColor;
1180: }
1181:
1182: /**
1183: * Returns a value of the style of the horizontal lines.
1184: * Possible values are CONTINUOUS, DASHED, and DOTTED.
1185: * @return The style of the horizontal lines.
1186: */
1187: final float[] getHorizontalLinesStyle() {
1188:
1189: return horizontalLinesStyle;
1190: }
1191:
1192: /**
1193: * Returns an array of the indexes, that is a sorted view of the array
1194: * graphValues[i][barIndex] i ranges from 0 to graphValues.length and
1195: * where barIndex is constant. This is used for creating stacked bar charts
1196: * where the tallest bars must be graphed first.
1197: * @param graphValues An int[][] of heights of bars...
1198: * @param barIndex The grouping of bars to work on/sort.
1199: */
1200: int[] stackedBarSort(int[][] graphValues, int barIndex) {
1201:
1202: boolean[] used = new boolean[graphValues.length];
1203: for (int i = 0; i < graphValues.length; ++i) {
1204: used[i] = false;
1205: }
1206:
1207: int[] sorted = new int[graphValues.length];
1208: for (int doing = 0; doing < graphValues.length; ++doing) {
1209:
1210: int lowestValue = Integer.MIN_VALUE;
1211: int lowestIndex = -1;
1212: for (int i = graphValues.length - 1; i >= 0; --i) {
1213: if (!used[i]
1214: && (graphValues[i][barIndex] > lowestValue)) {
1215: lowestIndex = i;
1216: lowestValue = graphValues[i][barIndex];
1217: }
1218: }
1219: sorted[doing] = lowestIndex;
1220: used[lowestIndex] = true;
1221: }
1222: return sorted;
1223: }
1224:
1225: /**
1226: * Converts an array of graph values -- values indicating how far across
1227: * a graph a bar should go into an array that the method sortStackedBar can
1228: * use. For graphs that plot negative values, the graph values that indicate
1229: * negative bars, must be converted to be negative values so that they
1230: * can be sorted properly in an array with values of positive bars.
1231: */
1232: int[][] stackedBarConvert(int[][] graphValues, int[][] lowBarValues) {
1233:
1234: int[][] convertedValues = new int[graphValues.length][graphValues[0].length];
1235: for (int i = 0; i < graphValues.length; ++i) {
1236: for (int j = 0; j < graphValues[0].length; ++j) {
1237: convertedValues[i][j] = graphValues[i][j] < lowBarValues[i][j] ? -graphValues[i][j]
1238: : graphValues[i][j];
1239: }
1240: }
1241: return convertedValues;
1242: }
1243:
1244: /**
1245: * Resets the model for this class. The model is used for shrinking and
1246: * growing of its components based on the maximum size of this class. If this
1247: * method is called, then the next time the maximum size is set, this classes
1248: * model maximum size will be made equal to the new maximum size. Effectively
1249: * what this does is ensure that whenever this objects maximum size is equal
1250: * to the one given, then all of the components will take on their default
1251: * model sizes. Note: This is only useful when auto model max sizing is
1252: * disabled.
1253: * @param reset True causes the max model size to be set upon the next max
1254: * sizing.
1255: */
1256: final void resetGraphAreaModel(boolean reset) {
1257:
1258: needsUpdate = true;
1259: resetAreaModel(reset);
1260: }
1261:
1262: /**
1263: * Indicates whether some property of this class has changed.
1264: * @return True if some property has changed.
1265: */
1266: final boolean getGraphAreaNeedsUpdate() {
1267: return (needsUpdate || getAreaNeedsUpdate());
1268: }
1269:
1270: /**
1271: * Updates this parent's variables, and this' variables.
1272: * @param g2D The graphics context to use for calculations.
1273: */
1274: final void updateGraphArea() {
1275:
1276: if (getGraphAreaNeedsUpdate()) {
1277:
1278: updateArea();
1279: update();
1280: }
1281: needsUpdate = false;
1282: }
1283:
1284: /**
1285: * Paints all the components of this class. First all variables are updated.
1286: * @param g2D The graphics context for calculations and painting.
1287: */
1288: void paintComponent(Graphics2D g2D) {
1289:
1290: updateGraphArea();
1291: super .paintComponent(g2D);
1292:
1293: Color oldColor = g2D.getColor();
1294: Stroke oldStroke = g2D.getStroke();
1295:
1296: if (horizontalLinesThickness > 0 && horizontalLinesExistence
1297: && horizontalLines.length > 0) {
1298: g2D.setColor(horizontalLinesColor);
1299: g2D.setStroke(horizontalLinesStroke);
1300: for (int i = 0; i < horizontalLines.length; ++i)
1301: g2D.draw(horizontalLines[i]);
1302: }
1303:
1304: if (verticalLinesThickness > 0 && verticalLinesExistence
1305: && verticalLines.length > 0) {
1306: g2D.setColor(verticalLinesColor);
1307: g2D.setStroke(verticalLinesStroke);
1308: for (int i = 0; i < verticalLines.length; ++i)
1309: g2D.draw(verticalLines[i]);
1310: }
1311:
1312: g2D.setColor(oldColor);
1313: g2D.setStroke(oldStroke);
1314: }
1315:
1316: private void update() {
1317:
1318: horizontalLinesThickness = 0;
1319: int numHorizontalLines = type == LABELSBOTTOM ? yTicks.length - 2
1320: : yTicks.length;
1321: int availableHeight = getSpaceSize(MIN).height;
1322: if (horizontalLinesExistence && numHorizontalLines > 0) {
1323: horizontalLinesThickness = applyRatio(
1324: horizontalLinesThicknessModel, getRatio(HEIGHT));
1325: horizontalLinesThickness = numHorizontalLines
1326: * horizontalLinesThickness <= availableHeight ? horizontalLinesThickness
1327: : availableHeight / numHorizontalLines;
1328: } else
1329: numHorizontalLines = 0;
1330:
1331: verticalLinesThickness = 0;
1332: int numVerticalLines = type == LABELSBOTTOM ? xTicks.length
1333: : xTicks.length - 2;
1334: int availableWidth = getSpaceSize(MIN).width;
1335: if (verticalLinesExistence && numVerticalLines > 0) {
1336: verticalLinesThickness = applyRatio(
1337: verticalLinesThicknessModel, getRatio(WIDTH));
1338: verticalLinesThickness = numVerticalLines
1339: * verticalLinesThickness <= availableWidth ? verticalLinesThickness
1340: : availableWidth / numVerticalLines;
1341: } else
1342: numVerticalLines = 0;
1343:
1344: if (linesThicknessAssociation) {
1345: verticalLinesThickness = horizontalLinesThickness < verticalLinesThickness
1346: && horizontalLinesExistence ? horizontalLinesThickness
1347: : verticalLinesThickness;
1348: horizontalLinesThickness = verticalLinesThickness < horizontalLinesThickness
1349: && verticalLinesExistence ? verticalLinesThickness
1350: : horizontalLinesThickness;
1351: }
1352:
1353: horizontalLinesStroke = new BasicStroke(
1354: (float) horizontalLinesThickness, BasicStroke.CAP_BUTT,
1355: BasicStroke.JOIN_MITER, 10.0f, horizontalLinesStyle,
1356: 0.0f);
1357: verticalLinesStroke = new BasicStroke(
1358: (float) verticalLinesThickness, BasicStroke.CAP_BUTT,
1359: BasicStroke.JOIN_MITER, 10.0f, verticalLinesStyle, 0.0f);
1360:
1361: int x1, x2, y1, y2;
1362:
1363: horizontalLines = new Line2D.Double[numHorizontalLines];
1364: int horizontalLinesOffset = 0;
1365: if (horizontalLinesExistence && yTicks.length > 0) {
1366: horizontalLinesOffset = +yTicks[0].height / 2;
1367: }
1368: x1 = getSpaceSizeLocation(MIN).x;
1369: x2 = x1 + getSpaceSize(MIN).width;
1370: int offsetI = type == LABELSBOTTOM ? 1 : 0;
1371: for (int i = 0; i < numHorizontalLines; ++i) {
1372: y1 = yTicks[i + offsetI].y + horizontalLinesOffset;
1373: y2 = y1;
1374: horizontalLines[i] = new Line2D.Double((double) x1,
1375: (double) y1, (double) x2, (double) y2);
1376: }
1377:
1378: verticalLines = new Line2D.Double[numVerticalLines];
1379: int verticalLinesOffset = 0;
1380: if (verticalLinesExistence && xTicks.length > 0) {
1381: verticalLinesOffset = xTicks[0].width / 2;
1382: }
1383:
1384: y1 = getSpaceSizeLocation(MIN).y;
1385: y2 = y1 + getSpaceSize(MIN).height;
1386: offsetI = type == LABELSBOTTOM ? 0 : 1;
1387: for (int i = 0; i < numVerticalLines; ++i) {
1388: x1 = xTicks[i + offsetI].x + verticalLinesOffset;
1389: x2 = x1;
1390: verticalLines[i] = new Line2D.Double((double) x1,
1391: (double) y1, (double) x2, (double) y2);
1392: }
1393: }
1394: }
|