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 javax.swing.*;
0024: import java.awt.*;
0025: import java.util.*;
0026:
0027: /**
0028: * An Advanced Bordered Area. Allows auto and manual resizing and
0029: * auto and manual positioning. Contains many public static variables for use
0030: * when extending this class.
0031: * <p><b>Basic Sizing and Colors:</b><br>
0032: * The typical bordered area class will simply paint a border of a specified
0033: * thickness within an area, where the inner edges of the area touch the outer
0034: * edges of the border. This class can do much more. Each border can be set
0035: * to a different thickness and color. This introduces the problem of handling
0036: * the corners of the borders. If the left border has color green, and the top
0037: * border has color red, which color is the top left corner? Each corner can
0038: * be associated with any adjacent border.
0039: * <p><b>Inner Space And Gaps:</b><br>
0040: * Sometimes, some space between the thing bordered and the border is desired.
0041: * That is, if bordering some text, then having some space between the
0042: * text and the border may be desirable. The thickness of the gap between the
0043: * the left, right, top, and bottom borders may each be individually set.
0044: * The location and size of this inner space may be obtained directly.
0045: * <p><b>Resizing And Growing Borders And Gaps:</b><br>
0046: * The borders and gaps can automatically grow when the size is changed. In
0047: * order to maintain the look of zooming in on something, the borders and gaps
0048: * can grow with the resizing of the area. For example, if the area grows in
0049: * the horizontal direction, then the left and right borders and gaps will
0050: * grow respective of the amount of change in the area width, depending
0051: * on this classes settings. If keeping any of the borders equal to any of the
0052: * others is desireable, such as a "grow only when all grow" policy, then
0053: * any border may be associated with any other border. The sizes of the
0054: * associated borders will be equal to the least of them.
0055: * <p><b>More Basics:</b><br>
0056: * This area can have a background color, or no background at all. And
0057: * each border and gap can be set to not exist, individually.
0058: * <p><b>Locating: Automatically and Manually:</b><br>
0059: * Sometimes the size of component to be bordered cannot be known until after
0060: * the borders and gaps have been calculated (relevant when using growing
0061: * borders and gaps). This class allows the available space, after subtracting
0062: * borders and gaps, to obtained. The size of the component to be bordered can
0063: * then be calculated, making sure it fits within this space. The size of the
0064: * component can be passed to this class, this class will place the gaps and
0065: * borderes around the component for a (near) perfect fit. This means that
0066: * where to place this bordered area within the maximum area is an open
0067: * question. This class allows options of automatic centering (both
0068: * horizontally and vertically, justifying to the left, right, top, and/or
0069: * bottom edges of the maximum area, and doing nothing such that the area can
0070: * be manually set, and any combination thereof.
0071: * <p><b>Examples:</b><br>
0072: * <ul>
0073: * <li>No Growing And Border Encloses Maximum Area:<br>
0074: * <code>setAutoSizes (true, true);</code>
0075: * <li>Growing And Border Encloses Maximum Area:<br>
0076: * <code>setAutoSizes (false, true);</code>
0077: * <li>No Growing, Border Encloses Minimum Area, And Centered:<br>
0078: * <code>setAutoSizes (true, false);<br>
0079: * setAutoJustifys (true, true);<br>
0080: * setJustifications (CENTER, CENTER);</code>
0081: * <li>Growing, Border Encloses Minimum Area, And Manually Located:<br>
0082: * <code>setAutoSizes (false, false);<br>
0083: * setAutoJustifys (false, false);</code>
0084: * </ul>
0085: * <p><b>Details Of Growing:</b><br>
0086: * Growing is based on "model" sizes. By default, everything has a
0087: * model size (the area, the borders, and the gaps). The defaults
0088: * currently are the first maximum size setting for the area,
0089: * 2 (for all borders), and 2 (for all gaps). Growing
0090: * is accomplished by dividing the maximum area size by the model area size
0091: * and applying this ratio the border and gap thicknesses.
0092: * If growing in the horizontal direction, the width sizes are used. If
0093: * growing in the vertical direction, the height sizes are used. If growing
0094: * in both directions, then both are calculated and the lesser is used.
0095: * However, all of these values can be changed. Ideally, one would set
0096: * the model area size to your normal viewing size, and all of the
0097: * inner components model sizes (borders and thicknesses) to the best sizes
0098: * at this model area size. However, just setting the model area size to the
0099: * normal viewing size of the area most likely will be sufficient. Generally,
0100: * the initial size is the normal size, do set the model size to the initial
0101: * size, use the resetAreaModel method before setting the maximum size. When
0102: * you set the maximum size, the area model size will automatically reset
0103: * itself to this size.
0104: * <p><b>Notes:</b><br>
0105: * <ul>
0106: * <li>This class assumes no null values. Pass zero based values intead. For
0107: * example, <code>new Point()</code> instead of <code>null</code>.
0108: * <li>Both Growing and shrinking are supported, and are the same. When
0109: * is written, in these comments, gowing and shrinking is meant.
0110: * </ul>
0111: */
0112: class Area {
0113:
0114: /**
0115: * Indicates the maximum.
0116: */
0117: static final int MAX = 0;
0118: /**
0119: * Indicates the model or maximum model.
0120: */
0121: static final int MAXMODEL = 1;
0122: /**
0123: * Indicates the minimum.
0124: */
0125: static final int MIN = 2;
0126: /**
0127: * Indicates the width.
0128: */
0129: static final int WIDTH = 0;
0130: /**
0131: * Indicates the height.
0132: */
0133: static final int HEIGHT = 1;
0134: /**
0135: * Indicates the lesser.
0136: */
0137: static final int LESSER = 2;
0138: /**
0139: * Indicates the left.
0140: */
0141: static final int LEFT = 0;
0142: /**
0143: * Indicates the right.
0144: */
0145: static final int RIGHT = 1;
0146: /**
0147: * Indicates the top.
0148: */
0149: static final int TOP = 2;
0150: /**
0151: * Indicates the bottom.
0152: */
0153: static final int BOTTOM = 3;
0154: /**
0155: * Indicates the center.
0156: */
0157: static final int CENTER = 4;
0158: /**
0159: * Indicates the left right.
0160: */
0161: static final int LEFTRIGHT = 0;
0162: /**
0163: * Indicates the left top.
0164: */
0165: static final int LEFTTOP = 1;
0166: /**
0167: * Indicates the right bottom.
0168: */
0169: static final int LEFTBOTTOM = 2;
0170: /**
0171: * Indicates the right top.
0172: */
0173: static final int RIGHTTOP = 3;
0174: /**
0175: * Indicates the right bottom.
0176: */
0177: static final int RIGHTBOTTOM = 4;
0178: /**
0179: * Indicates the top bottom.
0180: */
0181: static final int TOPBOTTOM = 5;
0182: /**
0183: * Indicates the horizontal.
0184: */
0185: static final int HORIZONTAL = 0;
0186: /**
0187: * Indicates the vertical.
0188: */
0189: static final int VERTICAL = 1;
0190: /**
0191: * Indicates the centered.
0192: */
0193: static final int CENTERED = 0;
0194: /**
0195: * Indicates the betweem.
0196: */
0197: static final int BETWEEN = 1;
0198: /**
0199: * Indicates the labels bottom.
0200: */
0201: static final int LABELSBOTTOM = 0;
0202: /**
0203: * Indicates the labels left.
0204: */
0205: static final int LABELSLEFT = 1;
0206: /**
0207: * Indicates the continuous.
0208: */
0209: static float[] CONTINUOUS = { 10.0f, 0.0f };
0210: /**
0211: * Indicates the dashed.
0212: */
0213: static float[] DASHED = { 7.0f, 3.0f };
0214: /**
0215: * Indicates the dotted.
0216: */
0217: static float[] DOTTED = { 3.0f, 3.0f };
0218: /**
0219: * Indicates none.
0220: */
0221: static int NONE = 6;
0222:
0223: private Point[] sizeLocations;
0224: private Dimension[] sizes;
0225: private boolean[] autoSizes;
0226:
0227: private Point[] spaceSizeLocations;
0228: private Dimension[] spaceSizes;
0229: private boolean[] autoJustifys;
0230: private int[] justifications;
0231:
0232: private boolean backgroundExistence;
0233: private Rectangle background;
0234: private Color backgroundColor;
0235:
0236: private float[] ratios;
0237: private boolean[] customizeRatios;
0238:
0239: private boolean[] borderExistences;
0240: private Rectangle[] borders;
0241: private int[] borderThicknessModels;
0242: private int[] borderThicknesses;
0243: private int[] borderCornerAssociations;
0244: private boolean[] borderAssociations;
0245: private Color[] borderColors;
0246:
0247: private boolean[] gapExistences;
0248: private int[] gapThicknessModels;
0249: private int[] gapThicknesses;
0250: private boolean[] gapAssociations;
0251:
0252: private boolean lockRatios;
0253: private int lightSource;
0254: private Paint backgroundPaint;
0255:
0256: private boolean resetAreaModel;
0257: private boolean unsetAreaModelOnUpdate;
0258: private boolean needsUpdate;
0259:
0260: /**
0261: * Creates a new Area.
0262: */
0263: Area() {
0264:
0265: createObjects();
0266:
0267: setAutoSizes(true, true);
0268: setAutoJustifys(true, true);
0269: setJustifications(CENTER, CENTER);
0270:
0271: setBackgroundExistence(true);
0272: setBackgroundColor(Color.white);
0273:
0274: setBorderExistences(true, true, true, true);
0275: setBorderThicknessModels(2, 2, 2, 2);
0276: setBorderAssociations(true, true, true, true, true, true);
0277: setBorderCornerAssociations(LEFT, BOTTOM, TOP, RIGHT);
0278: setBorderColors(Color.black, Color.black, Color.black,
0279: Color.black);
0280:
0281: setGapExistences(true, true, true, true);
0282: setGapThicknessModels(5, 5, 5, 5);
0283:
0284: setLockRatios(true);
0285: setCustomRatio(WIDTH, false, 0f);
0286: setCustomRatio(HEIGHT, false, 0f);
0287: setCustomRatio(LESSER, false, 0f);
0288:
0289: setLightSource(NONE);
0290:
0291: resetAreaModel(true);
0292:
0293: unsetAreaModelOnUpdate = false;
0294: needsUpdate = true;
0295: }
0296:
0297: /**
0298: * Sets the source of light for gradient paint of the background.
0299: * Possible values for the source parameter are: LEFT, RIGHT, TOP, BOTTOM, and NONE.
0300: * @param source Which side the light is coming from.
0301: */
0302: void setLightSource(int source) {
0303: lightSource = source;
0304: needsUpdate = true;
0305: }
0306:
0307: /**
0308: * Sets the location of a size/area.
0309: * @param which Which area to relocate. MAX is the only possible accepted
0310: * value.
0311: * @param location The new point of the top left of the area. The outer
0312: * edges of the left and top borders will touch this. Must not be null.
0313: */
0314: final void setSizeLocation(int which, Point location) {
0315:
0316: needsUpdate = true;
0317: sizeLocations[MAX] = location;
0318: }
0319:
0320: /**
0321: * Sets the location of an internal space area of a size area.
0322: * @param which Which space area to relocate. MIN is the only possible
0323: * value. If horizontal justification is true, then the x value will be
0324: * ignored. If vertical justification is true, then the y value will be
0325: * ignored.
0326: * @param location The new point of the top left of the space area. The
0327: * inner edges of the top and left gaps will touch this. Must not be null.
0328: */
0329: final void setSpaceSizeLocation(int which, Point location) {
0330:
0331: needsUpdate = true;
0332: int x = autoJustifys[HORIZONTAL] ? spaceSizeLocations[MIN].x
0333: : location.x;
0334: int y = autoJustifys[VERTICAL] ? spaceSizeLocations[MIN].y
0335: : location.y;
0336: spaceSizeLocations[MIN] = new Point(x, y);
0337: }
0338:
0339: /**
0340: * Adjusts settings to enable/disable auto justification of a minimum area
0341: * that is less than a maximum area.
0342: * @param horizontal If true, then horizontal justification is
0343: * enabled.
0344: * @param vertical If true, then vertical justification is enabled.
0345: */
0346: final void setAutoJustifys(boolean horizontal, boolean vertical) {
0347:
0348: needsUpdate = true;
0349: autoJustifys[HORIZONTAL] = horizontal;
0350: autoJustifys[VERTICAL] = vertical;
0351: }
0352:
0353: /**
0354: * Adjusts the actual justifications of minimum areas that are less than
0355: * maximum areas. Justifications effect the locations of minimum areas.
0356: * Either are only respected when their auto justification is enabled.
0357: * For example, if horizontal justify is center, then the minimum area will
0358: * be horizontally centered within the maximum area.
0359: * @param horizontal Sets the horizontal justification for the minimum
0360: * area. Possible values are LEFT, RIGHT and CENTER.
0361: * @param vertical Sets the vertical justification for the minimum
0362: * area. Possible values are LEFT, RIGHT and CENTER.
0363: */
0364: final void setJustifications(int horizontal, int vertical) {
0365:
0366: needsUpdate = true;
0367: justifications[HORIZONTAL] = horizontal;
0368: justifications[VERTICAL] = vertical;
0369: }
0370:
0371: /**
0372: * Adjusts the settings that allow automatic (or default) sizing. Both are
0373: * on the maximum size which is required, and must be set to be useful.
0374: * @param maxModel If true, then the maximum model size will always
0375: * be equal to the maximum size. This disables growing because it keeps the
0376: * resizing ratios at 1. If false, then maximum model is constant; so if the
0377: * maximum size changes then the ratios will adjust accordingly.
0378: * @param min If true, then the minimum size will be kept equal to
0379: * the maximum size. This means that the borders' outer edges will touch
0380: * the maximum size.
0381: */
0382: final void setAutoSizes(boolean maxModel, boolean min) {
0383:
0384: needsUpdate = true;
0385: autoSizes[MAXMODEL] = maxModel;
0386: autoSizes[MIN] = min;
0387: }
0388:
0389: /**
0390: * Makes such that the widh and the heighh ratios are the same as the
0391: * lesser ratio. If you want components to grow only if all of them grow,
0392: * then lock ratios, true, will cause this.
0393: * @param lock True causes all the ratios to equal the lesser ratio.
0394: */
0395: final void setLockRatios(boolean lock) {
0396:
0397: lockRatios = lock;
0398: }
0399:
0400: /**
0401: * Specifies whether to customize a particular ratio, overriding the
0402: * calculation of it.
0403: * @param which Which ratio to customize.
0404: * @param customize Whether to customize the ratio.
0405: * @param ratio The custom ratio.
0406: */
0407: final void setCustomRatio(int which, boolean customize, float ratio) {
0408:
0409: needsUpdate = true;
0410: customizeRatios[which] = customize;
0411: ratios[which] = ratio;
0412: }
0413:
0414: /**
0415: * Sets the sizes of the areas. If setting the maximum size and if
0416: * resetAreaModel was called previously, then the maximum model size will
0417: * be made equal to the maximum size; this ensures that all the default sizes
0418: * of borders and gaps will be used at this maximum size; at this maximum size
0419: * the resizing ratio will be 1.
0420: * @param which Which size to change. Possible values are MAX and
0421: * MAXMODEL.
0422: * @param size The new size. Must not be null.
0423: */
0424: final void setSize(int which, Dimension size) {
0425:
0426: needsUpdate = true;
0427: sizes[which] = size;
0428: if (resetAreaModel && !unsetAreaModelOnUpdate && which == MAX) {
0429: unsetAreaModelOnUpdate = true;
0430: sizes[MAXMODEL] = size;
0431: }
0432: }
0433:
0434: /**
0435: * Sets the size of the space; that is the area less the borders and gaps.
0436: * @param which Which space size to change. Possible values are MIN.
0437: * @param size The new size. Must not be null.
0438: */
0439: final void setSpaceSize(int which, Dimension size) {
0440:
0441: needsUpdate = true;
0442: spaceSizes[which] = size;
0443: }
0444:
0445: /**
0446: * Adjusts whether there exists a background or not.
0447: * @param existence If true, then there is.
0448: */
0449: final void setBackgroundExistence(boolean existence) {
0450:
0451: needsUpdate = true;
0452: backgroundExistence = existence;
0453: }
0454:
0455: /**
0456: * Adjusts the color of the background. Doesn't change the background's
0457: * existence.
0458: * @param color The color of the background.
0459: */
0460: final void setBackgroundColor(Color color) {
0461:
0462: needsUpdate = true;
0463: backgroundColor = color;
0464: }
0465:
0466: /**
0467: * Adjusts whether there exists borders, each individually. If a border does
0468: * not exist, then its is not used in calculations or in painting.
0469: * @param left If true, then the left border does exist.
0470: * @param right If true, then the right border does exist.
0471: * @param top If true, then the top border does exist.
0472: * @param bottom If true, then the bottom border does exist.
0473: */
0474: final void setBorderExistences(boolean left, boolean right,
0475: boolean top, boolean bottom) {
0476:
0477: needsUpdate = true;
0478: borderExistences[LEFT] = left;
0479: borderExistences[RIGHT] = right;
0480: borderExistences[TOP] = top;
0481: borderExistences[BOTTOM] = bottom;
0482: }
0483:
0484: /**
0485: * Adjusts whether there exists borders. If borders do
0486: * not exist, then they are not used in calculations or in painting.
0487: * @param existences If true, then the borders do not exist.
0488: */
0489: final void setBorderExistence(boolean existences) {
0490:
0491: needsUpdate = true;
0492: borderExistences[LEFT] = existences;
0493: borderExistences[RIGHT] = existences;
0494: borderExistences[TOP] = existences;
0495: borderExistences[BOTTOM] = existences;
0496: }
0497:
0498: /**
0499: * Adjusts the thickness of the border models. These values will be
0500: * applied to a ratio to determine their final thicknesses. The ratio is the
0501: * maximum size divided by the maximum model size. More information is in the
0502: * introductory notes for this class.
0503: * @param left The model thickness for the left border.
0504: * @param right The model thickness for the right border.
0505: * @param top The model thickness for the top border.
0506: * @param bottom The model thickness for the bottom border.
0507: */
0508: final void setBorderThicknessModels(int left, int right, int top,
0509: int bottom) {
0510:
0511: needsUpdate = true;
0512: borderThicknessModels[LEFT] = left;
0513: borderThicknessModels[RIGHT] = right;
0514: borderThicknessModels[TOP] = top;
0515: borderThicknessModels[BOTTOM] = bottom;
0516: }
0517:
0518: /**
0519: * Adjusts the thickness of the border models. These values will be
0520: * applied to a ratio to determine their final thicknesses. The ratio is the
0521: * maximum size divided by the maximum model size. More information is in the
0522: * introductory notes for this class.
0523: * @param thickness The model thickness for the border.
0524: */
0525: final void setBorderThicknessModel(int thickness) {
0526:
0527: needsUpdate = true;
0528: borderThicknessModels[LEFT] = thickness;
0529: borderThicknessModels[RIGHT] = thickness;
0530: borderThicknessModels[TOP] = thickness;
0531: borderThicknessModels[BOTTOM] = thickness;
0532: }
0533:
0534: /**
0535: * Associates each corner with one border. The corner will take on the same
0536: * color as the border associated with it.
0537: * @param leftTop The border to associate with the leftTop corner.
0538: * Possible values are LEFT and TOP.
0539: * @param rightTop The border to associate with the rightTop corner.
0540: * Possible values are RIGHT and TOP.
0541: * @param leftBottomThe border to associate with the leftBottom corner.
0542: * Possible values are LEFT and BOTTOM.
0543: * @param rightBottom The border to associate with the rightBottom corner.
0544: * Possible values are RIGHT and BOTTOM.
0545: */
0546: final void setBorderCornerAssociations(int leftTop, int leftBottom,
0547: int rightTop, int rightBottom) {
0548:
0549: needsUpdate = true;
0550: borderCornerAssociations[LEFTTOP] = leftTop;
0551: borderCornerAssociations[RIGHTTOP] = rightTop;
0552: borderCornerAssociations[LEFTBOTTOM] = leftBottom;
0553: borderCornerAssociations[RIGHTBOTTOM] = rightBottom;
0554: }
0555:
0556: /**
0557: * Associates border thicknesses with other border thicknesses. Each possible
0558: * association between the four borders can be represented by setting six
0559: * booleans. When a border is associated with another border, then their
0560: * thickness is equal to the lesser thickness between the two.
0561: * @param leftRight If true, then associates the left and right
0562: * borders.
0563: * @param leftTop If true, then associates the left and top borders.
0564: * @param leftBottom If true, then associates the left and bottom
0565: * borders.
0566: * @param rightTop If true, then associates the right and top borders.
0567: * @param rightBottom If true, then associates the right and bottom
0568: * borders.
0569: * @param topBottom If true, then associates the top and bottom
0570: * borders.
0571: */
0572: final void setBorderAssociations(boolean leftRight,
0573: boolean leftTop, boolean leftBottom, boolean rightTop,
0574: boolean rightBottom, boolean topBottom) {
0575:
0576: needsUpdate = true;
0577: borderAssociations[LEFTRIGHT] = leftRight;
0578: borderAssociations[LEFTTOP] = leftTop;
0579: borderAssociations[LEFTBOTTOM] = leftBottom;
0580: borderAssociations[RIGHTTOP] = rightTop;
0581: borderAssociations[RIGHTBOTTOM] = rightBottom;
0582: borderAssociations[TOPBOTTOM] = topBottom;
0583: }
0584:
0585: /**
0586: * Sets the color of each border, individually.
0587: * @param left The color of the left border.
0588: * @param right The color of the right border.
0589: * @param top The color of the top border.
0590: * @param bottom The color of the bottom border.
0591: */
0592: final void setBorderColors(Color left, Color right, Color top,
0593: Color bottom) {
0594:
0595: needsUpdate = true;
0596: borderColors[LEFT] = left;
0597: borderColors[RIGHT] = right;
0598: borderColors[TOP] = top;
0599: borderColors[BOTTOM] = bottom;
0600: }
0601:
0602: /**
0603: * Sets the color of the border (each border).
0604: * @param color The color of the border.
0605: */
0606: final void setBorderColor(Color color) {
0607:
0608: needsUpdate = true;
0609: borderColors[LEFT] = color;
0610: borderColors[RIGHT] = color;
0611: borderColors[TOP] = color;
0612: borderColors[BOTTOM] = color;
0613: }
0614:
0615: /**
0616: * Adjusts whether there exists gaps, each individually. If a gap does
0617: * not exist, then its is not used in calculations.
0618: * @param left If true, then the left gap does exist.
0619: * @param right If true, then the right gap does exist.
0620: * @param top If true, then the top gap does exist.
0621: * @param bottom If true, then the bottom gap does exist.
0622: */
0623: final void setGapExistences(boolean left, boolean right,
0624: boolean top, boolean bottom) {
0625:
0626: needsUpdate = true;
0627: gapExistences[LEFT] = left;
0628: gapExistences[RIGHT] = right;
0629: gapExistences[TOP] = top;
0630: gapExistences[BOTTOM] = bottom;
0631: }
0632:
0633: /**
0634: * Adjusts whether there exists gaps. If a gap does
0635: * not exist, then its is not used in calculations.
0636: * This is equivalent to calling
0637: * setGapExistences (boolean, boolean, boolean, boolean).
0638: * @param existence If true, then the gap exists.
0639: */
0640: final void setGapExistence(boolean existence) {
0641:
0642: setGapExistences(existence, existence, existence, existence);
0643: }
0644:
0645: /**
0646: * Adjusts the thickness of the gap models. These values will be
0647: * applied to a ratio to determine their final thicknesses. The ratio is the
0648: * maximum size divided by the maximum model size. More information is in the
0649: * introductory notes for this class.
0650: * @param left The model thickness for the left gap.
0651: * @param right The model thickness for the right gap.
0652: * @param top The model thickness for the top gap.
0653: * @param bottom The model thickness for the bottom gap.
0654: */
0655: final void setGapThicknessModels(int left, int right, int top,
0656: int bottom) {
0657:
0658: needsUpdate = true;
0659: gapThicknessModels[LEFT] = left;
0660: gapThicknessModels[RIGHT] = right;
0661: gapThicknessModels[TOP] = top;
0662: gapThicknessModels[BOTTOM] = bottom;
0663: }
0664:
0665: /**
0666: * Adjusts the thickness of the gap models. These values will be
0667: * applied to a ratio to determine their final thicknesses. The ratio is the
0668: * maximum size divided by the maximum model size. More information is in the
0669: * introductory notes for this class.
0670: * @param thickness The model thickness for the gap.
0671: */
0672: final void setGapThicknessModel(int thickness) {
0673:
0674: needsUpdate = true;
0675: gapThicknessModels[LEFT] = thickness;
0676: gapThicknessModels[RIGHT] = thickness;
0677: gapThicknessModels[TOP] = thickness;
0678: gapThicknessModels[BOTTOM] = thickness;
0679: }
0680:
0681: /**
0682: * Associates gap thicknesses with other gap thicknesses. Each possible
0683: * association between the four gaps can be represented by setting six
0684: * booleans. When a gap is associated with another gap, then their
0685: * thickness is equal to the lesser thickness between the two.
0686: * @param leftRight If true, then associates the left and right gaps.
0687: * @param leftTop If true, then associates the left and top gaps.
0688: * @param leftBottom If true, then associates the left and bottom
0689: * gaps.
0690: * @param rightTop If true, then associates the right and top gaps.
0691: * @param rightBottom If true, then associates the right and bottom
0692: * gaps.
0693: * @param topBottom If true, then associates the top and bottom gaps.
0694: */
0695: final void setGapAssociations(boolean leftRight, boolean leftTop,
0696: boolean leftBottom, boolean rightTop, boolean rightBottom,
0697: boolean topBottom) {
0698:
0699: needsUpdate = true;
0700: gapAssociations[LEFTRIGHT] = leftRight;
0701: gapAssociations[LEFTTOP] = leftTop;
0702: gapAssociations[LEFTBOTTOM] = leftBottom;
0703: gapAssociations[RIGHTTOP] = rightTop;
0704: gapAssociations[RIGHTBOTTOM] = rightBottom;
0705: gapAssociations[TOPBOTTOM] = topBottom;
0706: }
0707:
0708: /**
0709: * Gets the source of light for gradient paint of the background.
0710: * Possible values for the source parameter are: LEFT, RIGHT, TOP, BOTTOM, and NONE.
0711: * @return Which side the light is coming from.
0712: */
0713: int getLightSource() {
0714: return lightSource;
0715: }
0716:
0717: /**
0718: * Returns the space area location. The space area is the area within the
0719: * bordered area. It is the area (max or min) less borderss and gaps.
0720: * Updates everything before returning the value.
0721: * @param which Which space area location to return. Posible values are MAX
0722: * and MIN.
0723: * @return The location of the space area.
0724: */
0725: final Point getSpaceSizeLocation(int which) {
0726:
0727: updateArea();
0728: return spaceSizeLocations[which];
0729: }
0730:
0731: /**
0732: * Returns the auto sizing properties. Both the max model area size and the
0733: * min area size can be auto sized. Autosizing is based on the max area size.
0734: * If autosizing, then the area is equal to the max area size.
0735: * @param which Which auto size property to return. Possible values are
0736: * MAXMODEL and MIN.
0737: * @return True, if this area is auto sizing.
0738: */
0739: final boolean getAutoSize(int which) {
0740:
0741: return autoSizes[which];
0742: }
0743:
0744: /**
0745: * Returns the size of the area. The area size is the dimension enclosing the
0746: * border.
0747: * Updates everything before returning the value.
0748: * @param which Which size to return. Possible values are MAX, MAXMODEL, and
0749: * MIN.
0750: * @return The size of the area.
0751: */
0752: final Dimension getSize(int which) {
0753:
0754: updateArea();
0755: return sizes[which];
0756: }
0757:
0758: /**
0759: * Returns the location of the area. The location is the top left corner of
0760: * the area enclosing the border.
0761: * Updates everything before returning the value.
0762: * @param which Which size location to return. Possible values are MAX and MIN.
0763: * @return The loation of the area.
0764: */
0765: final Point getSizeLocation(int which) {
0766:
0767: updateArea();
0768: return sizeLocations[which];
0769: }
0770:
0771: /**
0772: * Returns the size of the space area. The size of the space area is the
0773: * area size less the borders and gaps.
0774: * Updates everything before returning the value.
0775: * @param which Which space area size to return. Possible values are MAX and
0776: * MIN.
0777: * @return The size of the space area.
0778: */
0779: final Dimension getSpaceSize(int which) {
0780:
0781: updateArea();
0782: return spaceSizes[which];
0783: }
0784:
0785: /**
0786: * Returns the specified ratio. Ratios area based on maximum area size
0787: * divided by model area size. The width ratio uses the area widths. The
0788: * height ratio uses the area heights. And the lesser ratio returns the
0789: * lesser of these two.
0790: * Updates everything before returning the value.
0791: * @param which Which ratio to return. Possible values are WIDTH, HEIGHT, and
0792: * LESSER.
0793: * @return The ratio; value is between 0 and 1.
0794: */
0795: final float getRatio(int which) {
0796: updateArea();
0797: return ratios[which];
0798: }
0799:
0800: /**
0801: * Returns the current justifications for the minimum area. Justifications
0802: * are used only when justifications are enabled. Justifications auto
0803: * locate the minimum area within the maximum area. This is only used when
0804: * auto minimum area sizing is disabled.
0805: * @param which Which justification to return. Possible values are HORIZONTAL
0806: * and VERTICAL.
0807: * @return The justification. Possible values for a horizontal
0808: * justification are LEFT, RIGHT, and CENTER; values for a vertical
0809: * justification are TOP, BOTTOM, and CENTER.
0810: */
0811: final int getJustifications(int which) {
0812:
0813: return justifications[which];
0814: }
0815:
0816: /**
0817: * Returns whether there exists a background or not.
0818: * @return If there is, then true.
0819: */
0820: final boolean getBackgroundExistence() {
0821:
0822: return backgroundExistence;
0823: }
0824:
0825: /**
0826: * Returns the color of the background.
0827: * @return The color of the background.
0828: */
0829: final Color getBackgroundColor() {
0830:
0831: return backgroundColor;
0832: }
0833:
0834: /**
0835: * Gets whether there exists borders. All must exist for this to return true.
0836: * @return If true, then the borders do not exist.
0837: */
0838: final boolean getBorderExistence() {
0839:
0840: return (borderExistences[LEFT] && borderExistences[RIGHT]
0841: && borderExistences[TOP] && borderExistences[BOTTOM]);
0842: }
0843:
0844: final boolean getBorderExistence(int which) {
0845:
0846: return (borderExistences[which]);
0847: }
0848:
0849: /**
0850: * Returns the color of the border (each border).
0851: * @return The color of the border.
0852: */
0853: final Color getBorderColor() {
0854:
0855: return borderColors[LEFT];
0856: }
0857:
0858: /**
0859: * Returns the color of the border (specific border).
0860: * @param which Which border you want the color of (BOTTOM, TOP, LEFT, RIGHT).
0861: * @return The color of the chosen border.
0862: */
0863: final Color getBorderColor(int which) {
0864:
0865: return borderColors[which];
0866: }
0867:
0868: /**
0869: * Gets the thickness of the gap model. These values will be
0870: * applied to a ratio to determine their final thicknesses. The ratio is the
0871: * maximum size divided by the maximum model size. More information is in the
0872: * introductory notes for this class.
0873: * @return The model thickness for the gap.
0874: */
0875: final int getGapThicknessModel() {
0876:
0877: return gapThicknessModels[LEFT];
0878: }
0879:
0880: /**
0881: * Gets whether there exists gaps. All must exist for this to return true.
0882: * @return If true, then the gaps do not exist.
0883: */
0884: final boolean getGapExistence() {
0885:
0886: return (gapExistences[LEFT] && gapExistences[RIGHT]
0887: && gapExistences[TOP] && gapExistences[BOTTOM]);
0888: }
0889:
0890: final boolean getGapExistence(int which) {
0891: return (gapExistences[which]);
0892: }
0893:
0894: /**
0895: * Returns the thickness of one of the gaps. Should be used only when all
0896: * gaps have same thickness model.
0897: * @return The thickness of the gap.
0898: */
0899: final int getGapThickness() {
0900: updateArea();
0901: return gapThicknesses[LEFT];
0902: }
0903:
0904: /**
0905: * Returns the thickness of one of the gaps. Should be used only when all
0906: * gaps have same thickness model.
0907: * @param which Which gap to return the thickness of.
0908: * @return The thickness of the gap.
0909: */
0910: final int getGapThickness(int which) {
0911: updateArea();
0912: return gapThicknesses[which];
0913: }
0914:
0915: /**
0916: * Gets the thickness of the border model. These values will be
0917: * applied to a ratio to determine their final thicknesses. The ratio is the
0918: * maximum size divided by the maximum model size. More information is in the
0919: * introductory notes for this class.
0920: * @return The model thickness for the border.
0921: */
0922: final int getBorderThicknessModel() {
0923:
0924: return borderThicknessModels[LEFT];
0925: }
0926:
0927: /**
0928: * Gets the thickness of a border model. These values will be
0929: * applied to a ratio to determine their final thicknesses. The ratio is the
0930: * maximum size divided by the maximum model size. More information is in the
0931: * introductory notes for this class.
0932: * @return The model thickness for this border.
0933: */
0934: final int getBorderThicknessModel(int which) {
0935: return borderThicknessModels[which];
0936: }
0937:
0938: /**
0939: * Returns the thickness of a border.
0940: * @return The thickness of the particular border.
0941: */
0942: final int getBorderThickness(int which) {
0943: updateArea();
0944: return borderThicknesses[which];
0945: }
0946:
0947: /**
0948: * Returns the thickness of a border + the gap.
0949: * @return The thickness of the border + the gap.
0950: */
0951: final int getOffsetThickness() {
0952: updateArea();
0953: return borderThicknesses[LEFT] + gapThicknesses[LEFT];
0954: }
0955:
0956: /**
0957: * Returns the thickness of the border.
0958: * @return The thickness of the border.
0959: */
0960: final int getBorderThickness() {
0961: updateArea();
0962: return borderThicknesses[TOP];
0963: }
0964:
0965: /**
0966: * Indicates whether some property of this class has changed.
0967: * @return True if some property has changed.
0968: */
0969: final boolean getAreaNeedsUpdate() {
0970:
0971: return needsUpdate;
0972: }
0973:
0974: /**
0975: * Applies the given ratio to the given integer.
0976: * @param model The integer.
0977: * @param ratio The ratio.
0978: * @return The ratio multiplied by the integer.
0979: */
0980: final int applyRatio(int model, float ratio) {
0981:
0982: int applied = (int) (ratio * model);
0983: applied = applied < 1 && model > 0 ? 1 : applied;
0984: return applied;
0985: }
0986:
0987: /**
0988: * Returns whether the max model will be reset, in the next max sizing.
0989: * @return True if the max model size needs to be reset.
0990: */
0991: final boolean getResetAreaModel() {
0992:
0993: return resetAreaModel;
0994: }
0995:
0996: /**
0997: * Updates this area. This area maintains many variables. Calling this
0998: * methods assures they are all updates with respect to eachother.
0999: */
1000: final void updateArea() {
1001:
1002: if (getAreaNeedsUpdate()) {
1003: update();
1004: }
1005: needsUpdate = false;
1006: }
1007:
1008: /**
1009: * Resets the model for this class. The model is used for shrinking and
1010: * growing of its components based on the maximum size of this class. If this
1011: * method is called, then the next time the maximum size is set, this classes
1012: * model maximum size will be made equal to the new maximum size. Effectively
1013: * what this does is ensure that whenever this objects maximum size is equal
1014: * to the one given, then all of the components will take on their default
1015: * model sizes. Note: This is only useful when auto model max sizing is
1016: * disabled.
1017: * @param reset True causes the max model size to be set upon the next max
1018: * sizing.
1019: */
1020: final void resetAreaModel(boolean reset) {
1021:
1022: if (reset != resetAreaModel) {
1023: needsUpdate = true;
1024: resetAreaModel = reset;
1025: unsetAreaModelOnUpdate = false;
1026: }
1027: }
1028:
1029: /**
1030: * Paints this bordered area. Paints borders and background if they exist.
1031: * Updates everything before painting.
1032: * @param g2D The graphics context for calculations and painting.
1033: */
1034: void paintComponent(Graphics2D g2D) {
1035:
1036: updateArea();
1037: Paint oldPaint = g2D.getPaint();
1038: g2D.setPaint(backgroundPaint);
1039: g2D.fill(background);
1040: g2D.setPaint(borderColors[LEFT]);
1041: g2D.fill(borders[LEFT]);
1042: g2D.setPaint(borderColors[RIGHT]);
1043: g2D.fill(borders[RIGHT]);
1044: g2D.setPaint(borderColors[TOP]);
1045: g2D.fill(borders[TOP]);
1046: g2D.setPaint(borderColors[BOTTOM]);
1047: g2D.fill(borders[BOTTOM]);
1048: g2D.setPaint(oldPaint);
1049: }
1050:
1051: private void createObjects() {
1052:
1053: sizeLocations = new Point[3];
1054: sizeLocations[MAX] = new Point();
1055: sizeLocations[MIN] = new Point();
1056:
1057: spaceSizeLocations = new Point[3];
1058: spaceSizeLocations[MAX] = new Point();
1059: spaceSizeLocations[MIN] = new Point();
1060:
1061: autoSizes = new boolean[3];
1062: sizes = new Dimension[3];
1063: sizes[MAX] = new Dimension();
1064: sizes[MAXMODEL] = new Dimension();
1065: sizes[MIN] = new Dimension();
1066:
1067: spaceSizes = new Dimension[3];
1068: spaceSizes[MAX] = new Dimension();
1069: spaceSizes[MIN] = new Dimension();
1070:
1071: autoJustifys = new boolean[2];
1072: justifications = new int[2];
1073:
1074: ratios = new float[3];
1075: customizeRatios = new boolean[3];
1076:
1077: background = new Rectangle();
1078:
1079: borderExistences = new boolean[4];
1080: borders = new Rectangle[4];
1081: borders[LEFT] = new Rectangle();
1082: borders[RIGHT] = new Rectangle();
1083: borders[TOP] = new Rectangle();
1084: borders[BOTTOM] = new Rectangle();
1085: borderThicknesses = new int[4];
1086: borderThicknessModels = new int[4];
1087: borderCornerAssociations = new int[6];
1088: borderAssociations = new boolean[6];
1089: borderColors = new Color[6];
1090:
1091: gapExistences = new boolean[4];
1092: gapThicknesses = new int[4];
1093: gapThicknessModels = new int[4];
1094: gapAssociations = new boolean[6];
1095: }
1096:
1097: private void update() {
1098:
1099: if (unsetAreaModelOnUpdate)
1100: resetAreaModel = false;
1101: updateMaxSizeObjects();
1102: updateRatios();
1103: updateBorderThicknesses();
1104: updateGapThicknesses();
1105: updateMaxSpaceSizeObjects();
1106: updateMinObjects();
1107: updateBackground();
1108: updateBorderRectangles();
1109: updateBackgroundPaint();
1110: }
1111:
1112: private void updateMaxSizeObjects() {
1113:
1114: sizes[MAXMODEL] = autoSizes[MAXMODEL] ? sizes[MAX]
1115: : sizes[MAXMODEL];
1116: }
1117:
1118: private void updateRatios() {
1119:
1120: if (!customizeRatios[WIDTH]) {
1121: ratios[WIDTH] = sizes[MAXMODEL].width == 0 ? 0f
1122: : (float) sizes[MAX].width / sizes[MAXMODEL].width;
1123: }
1124: if (!customizeRatios[HEIGHT]) {
1125: ratios[HEIGHT] = sizes[MAXMODEL].height == 0 ? 0f
1126: : (float) sizes[MAX].height
1127: / sizes[MAXMODEL].height;
1128: }
1129: if (!customizeRatios[LESSER]) {
1130: ratios[LESSER] = ratios[WIDTH] < ratios[HEIGHT] ? ratios[WIDTH]
1131: : ratios[HEIGHT];
1132: }
1133: if (lockRatios) {
1134: ratios[WIDTH] = ratios[LESSER];
1135: ratios[HEIGHT] = ratios[LESSER];
1136: }
1137: }
1138:
1139: private void updateBorderThicknesses() {
1140:
1141: if (borderExistences[LEFT]) {
1142: if ((borderAssociations[LEFTTOP] && borderExistences[TOP])
1143: || (borderAssociations[LEFTBOTTOM] && borderExistences[BOTTOM])) {
1144: borderThicknesses[LEFT] = applyRatio(
1145: borderThicknessModels[LEFT], ratios[LESSER]);
1146: } else {
1147: borderThicknesses[LEFT] = applyRatio(
1148: borderThicknessModels[LEFT], ratios[WIDTH]);
1149: }
1150: } else
1151: borderThicknesses[LEFT] = 0;
1152:
1153: if (borderExistences[RIGHT]) {
1154: if ((borderAssociations[RIGHTTOP] && borderExistences[TOP])
1155: || (borderAssociations[RIGHTBOTTOM] && borderExistences[BOTTOM])) {
1156: borderThicknesses[RIGHT] = applyRatio(
1157: borderThicknessModels[RIGHT], ratios[LESSER]);
1158: } else {
1159: borderThicknesses[RIGHT] = applyRatio(
1160: borderThicknessModels[RIGHT], ratios[WIDTH]);
1161: }
1162: } else
1163: borderThicknesses[RIGHT] = 0;
1164:
1165: if (borderExistences[TOP]) {
1166: if ((borderAssociations[LEFTTOP] && borderExistences[LEFT])
1167: || (borderAssociations[RIGHTTOP] && borderExistences[RIGHT])) {
1168: borderThicknesses[TOP] = applyRatio(
1169: borderThicknessModels[TOP], ratios[LESSER]);
1170: } else {
1171: borderThicknesses[TOP] = applyRatio(
1172: borderThicknessModels[TOP], ratios[HEIGHT]);
1173: }
1174: } else
1175: borderThicknesses[TOP] = 0;
1176:
1177: if (borderExistences[BOTTOM]) {
1178: if ((borderAssociations[LEFTBOTTOM] && borderExistences[LEFT])
1179: || (borderAssociations[RIGHTBOTTOM] && borderExistences[RIGHT])) {
1180: borderThicknesses[BOTTOM] = applyRatio(
1181: borderThicknessModels[BOTTOM], ratios[LESSER]);
1182: } else {
1183: borderThicknesses[BOTTOM] = applyRatio(
1184: borderThicknessModels[BOTTOM], ratios[HEIGHT]);
1185: }
1186: } else
1187: borderThicknesses[BOTTOM] = 0;
1188:
1189: int availableWidth = sizes[MAX].width;
1190: if (borderExistences[LEFT]) {
1191: if (borderAssociations[LEFTTOP] && borderExistences[TOP]) {
1192: borderThicknesses[LEFT] = borderThicknesses[LEFT] > borderThicknesses[TOP] ? borderThicknesses[TOP]
1193: : borderThicknesses[LEFT];
1194: }
1195: if (borderAssociations[LEFTBOTTOM]
1196: && borderExistences[BOTTOM]) {
1197: borderThicknesses[LEFT] = borderThicknesses[LEFT] > borderThicknesses[BOTTOM] ? borderThicknesses[BOTTOM]
1198: : borderThicknesses[LEFT];
1199: }
1200: borderThicknesses[LEFT] = borderThicknesses[LEFT] > availableWidth ? availableWidth
1201: : borderThicknesses[LEFT];
1202: availableWidth -= borderThicknesses[LEFT];
1203: }
1204:
1205: if (borderExistences[RIGHT]) {
1206: if (borderAssociations[RIGHTTOP] && borderExistences[TOP]) {
1207: borderThicknesses[RIGHT] = borderThicknesses[RIGHT] > borderThicknesses[TOP] ? borderThicknesses[TOP]
1208: : borderThicknesses[RIGHT];
1209: }
1210: if (borderAssociations[RIGHTBOTTOM]
1211: && borderExistences[BOTTOM]) {
1212: borderThicknesses[RIGHT] = borderThicknesses[RIGHT] > borderThicknesses[BOTTOM] ? borderThicknesses[BOTTOM]
1213: : borderThicknesses[RIGHT];
1214: }
1215: borderThicknesses[RIGHT] = borderThicknesses[RIGHT] > availableWidth ? availableWidth
1216: : borderThicknesses[RIGHT];
1217: }
1218:
1219: int availableHeight = sizes[MAX].height;
1220: if (borderExistences[TOP]) {
1221: if (borderAssociations[LEFTTOP] && borderExistences[LEFT]) {
1222: borderThicknesses[TOP] = borderThicknesses[TOP] > borderThicknesses[LEFT] ? borderThicknesses[TOP]
1223: : borderThicknesses[TOP];
1224: }
1225: if (borderAssociations[RIGHTTOP] && borderExistences[RIGHT]) {
1226: borderThicknesses[TOP] = borderThicknesses[TOP] > borderThicknesses[RIGHT] ? borderThicknesses[BOTTOM]
1227: : borderThicknesses[TOP];
1228: }
1229: borderThicknesses[TOP] = borderThicknesses[TOP] > availableHeight ? availableHeight
1230: : borderThicknesses[TOP];
1231: availableHeight -= borderThicknesses[TOP];
1232: }
1233:
1234: if (borderExistences[BOTTOM]) {
1235: if (borderAssociations[LEFTBOTTOM]
1236: && borderExistences[LEFT]) {
1237: borderThicknesses[BOTTOM] = borderThicknesses[BOTTOM] > borderThicknesses[LEFT] ? borderThicknesses[BOTTOM]
1238: : borderThicknesses[BOTTOM];
1239: }
1240: if (borderAssociations[RIGHTBOTTOM]
1241: && borderExistences[RIGHT]) {
1242: borderThicknesses[BOTTOM] = borderThicknesses[BOTTOM] > borderThicknesses[RIGHT] ? borderThicknesses[BOTTOM]
1243: : borderThicknesses[BOTTOM];
1244: }
1245: borderThicknesses[BOTTOM] = borderThicknesses[BOTTOM] > availableHeight ? availableHeight
1246: : borderThicknesses[BOTTOM];
1247: }
1248: }
1249:
1250: private void updateGapThicknesses() {
1251:
1252: if (gapExistences[LEFT]) {
1253: if ((gapAssociations[LEFTTOP] && gapExistences[TOP])
1254: || (gapAssociations[LEFTBOTTOM] && gapExistences[BOTTOM])) {
1255: gapThicknesses[LEFT] = applyRatio(
1256: gapThicknessModels[LEFT], ratios[LESSER]);
1257: } else {
1258: gapThicknesses[LEFT] = applyRatio(
1259: gapThicknessModels[LEFT], ratios[WIDTH]);
1260: }
1261: } else
1262: gapThicknesses[LEFT] = 0;
1263:
1264: if (gapExistences[RIGHT]) {
1265: if ((gapAssociations[RIGHTTOP] && gapExistences[TOP])
1266: || (gapAssociations[RIGHTBOTTOM] && gapExistences[BOTTOM])) {
1267: gapThicknesses[RIGHT] = applyRatio(
1268: gapThicknessModels[RIGHT], ratios[LESSER]);
1269: } else {
1270: gapThicknesses[RIGHT] = applyRatio(
1271: gapThicknessModels[RIGHT], ratios[WIDTH]);
1272: }
1273: } else
1274: gapThicknesses[RIGHT] = 0;
1275:
1276: if (gapExistences[TOP]) {
1277: if ((gapAssociations[LEFTTOP] && gapExistences[LEFT])
1278: || (gapAssociations[RIGHTTOP] && gapExistences[RIGHT])) {
1279: gapThicknesses[TOP] = applyRatio(
1280: gapThicknessModels[TOP], ratios[LESSER]);
1281: } else {
1282: gapThicknesses[TOP] = applyRatio(
1283: gapThicknessModels[TOP], ratios[HEIGHT]);
1284: }
1285: } else
1286: gapThicknesses[TOP] = 0;
1287:
1288: if (gapExistences[BOTTOM]) {
1289: if ((gapAssociations[LEFTBOTTOM] && gapExistences[LEFT])
1290: || (gapAssociations[RIGHTBOTTOM] && gapExistences[RIGHT])) {
1291: gapThicknesses[BOTTOM] = applyRatio(
1292: gapThicknessModels[BOTTOM], ratios[LESSER]);
1293: } else {
1294: gapThicknesses[BOTTOM] = applyRatio(
1295: gapThicknessModels[BOTTOM], ratios[HEIGHT]);
1296: }
1297: } else
1298: gapThicknesses[BOTTOM] = 0;
1299:
1300: int availableWidth = sizes[MAX].width - borderThicknesses[LEFT]
1301: - borderThicknesses[RIGHT];
1302: if (gapExistences[LEFT]) {
1303: if (gapAssociations[LEFTTOP] && gapExistences[TOP]) {
1304: gapThicknesses[LEFT] = gapThicknesses[LEFT] > gapThicknesses[TOP] ? gapThicknesses[TOP]
1305: : gapThicknesses[LEFT];
1306: }
1307: if (gapAssociations[LEFTBOTTOM] && gapExistences[BOTTOM]) {
1308: gapThicknesses[LEFT] = gapThicknesses[LEFT] > gapThicknesses[BOTTOM] ? gapThicknesses[BOTTOM]
1309: : gapThicknesses[LEFT];
1310: }
1311: gapThicknesses[LEFT] = gapThicknesses[LEFT] > availableWidth ? availableWidth
1312: : gapThicknesses[LEFT];
1313: availableWidth -= gapThicknesses[LEFT];
1314: }
1315:
1316: if (gapExistences[RIGHT]) {
1317: if (gapAssociations[RIGHTTOP] && gapExistences[TOP]) {
1318: gapThicknesses[RIGHT] = gapThicknesses[RIGHT] > gapThicknesses[TOP] ? gapThicknesses[TOP]
1319: : gapThicknesses[RIGHT];
1320: }
1321: if (gapAssociations[RIGHTBOTTOM] && gapExistences[BOTTOM]) {
1322: gapThicknesses[RIGHT] = gapThicknesses[RIGHT] > gapThicknesses[BOTTOM] ? gapThicknesses[BOTTOM]
1323: : gapThicknesses[RIGHT];
1324: }
1325: gapThicknesses[RIGHT] = gapThicknesses[RIGHT] > availableWidth ? availableWidth
1326: : gapThicknesses[RIGHT];
1327: }
1328:
1329: int availableHeight = sizes[MAX].height
1330: - borderThicknesses[TOP] - borderThicknesses[BOTTOM];
1331: if (gapExistences[TOP]) {
1332: if (gapAssociations[LEFTTOP] && gapExistences[LEFT]) {
1333: gapThicknesses[TOP] = gapThicknesses[TOP] > gapThicknesses[LEFT] ? gapThicknesses[TOP]
1334: : gapThicknesses[TOP];
1335: }
1336: if (gapAssociations[RIGHTTOP] && gapExistences[RIGHT]) {
1337: gapThicknesses[TOP] = gapThicknesses[TOP] > gapThicknesses[RIGHT] ? gapThicknesses[BOTTOM]
1338: : gapThicknesses[TOP];
1339: }
1340: gapThicknesses[TOP] = gapThicknesses[TOP] > availableHeight ? availableHeight
1341: : gapThicknesses[TOP];
1342: availableHeight -= gapThicknesses[TOP];
1343: }
1344:
1345: if (gapExistences[BOTTOM]) {
1346: if (gapAssociations[LEFTBOTTOM] && gapExistences[LEFT]) {
1347: gapThicknesses[BOTTOM] = gapThicknesses[BOTTOM] > gapThicknesses[LEFT] ? gapThicknesses[BOTTOM]
1348: : gapThicknesses[BOTTOM];
1349: }
1350: if (gapAssociations[RIGHTBOTTOM] && gapExistences[RIGHT]) {
1351: gapThicknesses[BOTTOM] = gapThicknesses[BOTTOM] > gapThicknesses[RIGHT] ? gapThicknesses[BOTTOM]
1352: : gapThicknesses[BOTTOM];
1353: }
1354: gapThicknesses[BOTTOM] = gapThicknesses[BOTTOM] > availableHeight ? availableHeight
1355: : gapThicknesses[BOTTOM];
1356: }
1357: }
1358:
1359: private void updateMaxSpaceSizeObjects() {
1360:
1361: spaceSizeLocations[MAX] = new Point(sizeLocations[MAX].x
1362: + borderThicknesses[LEFT] + gapThicknesses[LEFT],
1363: sizeLocations[MAX].y + borderThicknesses[TOP]
1364: + gapThicknesses[TOP]);
1365: spaceSizes[MAX] = new Dimension(
1366: sizes[MAX].width
1367: - (borderThicknesses[LEFT] + borderThicknesses[RIGHT])
1368: - (gapThicknesses[LEFT] + gapThicknesses[RIGHT]),
1369: sizes[MAX].height
1370: - (borderThicknesses[TOP] + borderThicknesses[BOTTOM])
1371: - (gapThicknesses[TOP] + gapThicknesses[BOTTOM]));
1372: }
1373:
1374: private void updateMinObjects() {
1375:
1376: if (autoSizes[MIN]) {
1377: sizeLocations[MIN] = sizeLocations[MAX];
1378: sizes[MIN] = sizes[MAX];
1379: spaceSizeLocations[MIN] = spaceSizeLocations[MAX];
1380: spaceSizes[MIN] = spaceSizes[MAX];
1381: }
1382:
1383: else {
1384:
1385: //spaceSizes[MIN] is set by sub-class
1386: sizes[MIN] = new Dimension(spaceSizes[MIN].width
1387: + borderThicknesses[LEFT]
1388: + borderThicknesses[RIGHT] + gapThicknesses[LEFT]
1389: + gapThicknesses[RIGHT], spaceSizes[MIN].height
1390: + borderThicknesses[TOP]
1391: + borderThicknesses[BOTTOM] + gapThicknesses[TOP]
1392: + gapThicknesses[BOTTOM]);
1393:
1394: //find locations
1395: int x = -1, y = -1;
1396: if (autoJustifys[HORIZONTAL]) {
1397: if (justifications[HORIZONTAL] == LEFT) {
1398: x = sizeLocations[MAX].x;
1399: } else if (justifications[HORIZONTAL] == RIGHT) {
1400: x = sizeLocations[MAX].x + sizes[MAX].width
1401: - sizes[MIN].width;
1402: } else if (justifications[HORIZONTAL] == CENTER) {
1403: x = sizeLocations[MAX].x
1404: + (int) ((sizes[MAX].width - sizes[MIN].width) / 2);
1405: }
1406: } else
1407: x = spaceSizeLocations[MIN].x - borderThicknesses[LEFT]
1408: - gapThicknesses[LEFT];
1409: if (autoJustifys[VERTICAL]) {
1410: if (justifications[VERTICAL] == TOP) {
1411: y = sizeLocations[MAX].y;
1412: } else if (justifications[VERTICAL] == BOTTOM) {
1413: y = sizeLocations[MAX].y + sizes[MAX].height
1414: - sizes[MIN].height;
1415: } else if (justifications[VERTICAL] == CENTER) {
1416: y = sizeLocations[MAX].y
1417: + (int) ((sizes[MAX].height - sizes[MIN].height) / 2);
1418: }
1419: } else
1420: y = spaceSizeLocations[MIN].y - borderThicknesses[TOP]
1421: - gapThicknesses[TOP];
1422: sizeLocations[MIN] = new Point(x, y);
1423:
1424: spaceSizeLocations[MIN] = new Point(x
1425: + borderThicknesses[LEFT] + gapThicknesses[LEFT], y
1426: + borderThicknesses[TOP] + gapThicknesses[TOP]);
1427: }
1428: }
1429:
1430: private void updateBackground() {
1431:
1432: if (backgroundExistence) {
1433: background = new Rectangle(sizeLocations[MIN].x,
1434: sizeLocations[MIN].y, sizes[MIN].width,
1435: sizes[MIN].height);
1436: } else
1437: background = new Rectangle();
1438: }
1439:
1440: private void updateBorderRectangles() {
1441:
1442: boolean[] usedCorner = new boolean[4];
1443:
1444: if (borderCornerAssociations[LEFTTOP] == LEFT) {
1445:
1446: borders[LEFT].setLocation(sizeLocations[MIN]);
1447: borders[TOP].setLocation(sizeLocations[MIN].x
1448: + borderThicknesses[LEFT], sizeLocations[MIN].y);
1449: } else {
1450: borders[LEFT].setLocation(sizeLocations[MIN].x,
1451: sizeLocations[MIN].y + borderThicknesses[TOP]);
1452: borders[TOP].setLocation(sizeLocations[MIN]);
1453: }
1454:
1455: if (borderCornerAssociations[RIGHTTOP] == RIGHT) {
1456:
1457: borders[RIGHT].setLocation(sizeLocations[MIN].x
1458: + sizes[MIN].width - borderThicknesses[RIGHT],
1459: sizeLocations[MIN].y);
1460: } else {
1461:
1462: borders[RIGHT].setLocation(sizeLocations[MIN].x
1463: + sizes[MIN].width - borderThicknesses[RIGHT],
1464: sizeLocations[MIN].y + borderThicknesses[TOP]);
1465: }
1466:
1467: if (borderCornerAssociations[LEFTBOTTOM] == BOTTOM) {
1468: borders[BOTTOM].setLocation(sizeLocations[MIN].x,
1469: sizeLocations[MIN].y + sizes[MIN].height
1470: - borderThicknesses[BOTTOM]);
1471: } else {
1472: borders[BOTTOM].setLocation(sizeLocations[MIN].x
1473: + borderThicknesses[LEFT], sizeLocations[MIN].y
1474: + sizes[MIN].height - borderThicknesses[BOTTOM]);
1475: }
1476:
1477: int delta = 0;
1478: delta += (borderCornerAssociations[LEFTTOP] == LEFT ? 0
1479: : borderThicknesses[TOP]);
1480: delta += (borderCornerAssociations[LEFTBOTTOM] == LEFT ? 0
1481: : borderThicknesses[BOTTOM]);
1482: borders[LEFT].setSize(borderThicknesses[LEFT],
1483: sizes[MIN].height - delta);
1484:
1485: delta = 0;
1486: delta += (borderCornerAssociations[RIGHTTOP] == RIGHT ? 0
1487: : borderThicknesses[TOP]);
1488: delta += (borderCornerAssociations[RIGHTBOTTOM] == RIGHT ? 0
1489: : borderThicknesses[BOTTOM]);
1490: borders[RIGHT].setSize(borderThicknesses[RIGHT],
1491: sizes[MIN].height - delta);
1492:
1493: delta = 0;
1494: delta += (borderCornerAssociations[LEFTTOP] == TOP ? 0
1495: : borderThicknesses[LEFT]);
1496: delta += (borderCornerAssociations[RIGHTTOP] == TOP ? 0
1497: : borderThicknesses[RIGHT]);
1498: borders[TOP].setSize(sizes[MIN].width - delta,
1499: borderThicknesses[TOP]);
1500:
1501: delta = 0;
1502: delta += (borderCornerAssociations[LEFTBOTTOM] == BOTTOM ? 0
1503: : borderThicknesses[LEFT]);
1504: delta += (borderCornerAssociations[RIGHTBOTTOM] == BOTTOM ? 0
1505: : borderThicknesses[RIGHT]);
1506: borders[BOTTOM].setSize(sizes[MIN].width - delta,
1507: borderThicknesses[BOTTOM]);
1508: }
1509:
1510: private void updateBackgroundPaint() {
1511:
1512: if (lightSource == TOP) {
1513: backgroundPaint = new GradientPaint(sizeLocations[MIN].x,
1514: sizeLocations[MIN].y, backgroundColor.brighter(),
1515: sizeLocations[MIN].x, sizeLocations[MIN].y
1516: + sizes[MIN].height, backgroundColor);
1517: } else if (lightSource == BOTTOM) {
1518: backgroundPaint = new GradientPaint(sizeLocations[MIN].x,
1519: sizeLocations[MIN].y, backgroundColor,
1520: sizeLocations[MIN].x, sizeLocations[MIN].y
1521: + sizes[MIN].height, backgroundColor
1522: .brighter());
1523: } else if (lightSource == LEFT) {
1524: backgroundPaint = new GradientPaint(sizeLocations[MIN].x,
1525: sizeLocations[MIN].y, backgroundColor.brighter(),
1526: sizeLocations[MIN].x + sizes[MIN].width,
1527: sizeLocations[MIN].y, backgroundColor);
1528: } else if (lightSource == RIGHT) {
1529: backgroundPaint = new GradientPaint(sizeLocations[MIN].x,
1530: sizeLocations[MIN].y, backgroundColor,
1531: sizeLocations[MIN].x + sizes[MIN].width,
1532: sizeLocations[MIN].y, backgroundColor.brighter());
1533: } else {
1534: backgroundPaint = backgroundColor;
1535: }
1536: }
1537: }
|