    001    /* ===========================================================
    002     * JFreeChart : a free chart library for the Java(tm) platform
    003     * ===========================================================
    004     *
    005     * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
    006     *
    007     * Project Info:  http://www.jfree.org/jfreechart/index.html
    008     *
    009     * This library is free software; you can redistribute it and/or modify it
    010     * under the terms of the GNU Lesser General Public License as published by
    011     * the Free Software Foundation; either version 2.1 of the License, or
    012     * (at your option) any later version.
    013     *
    014     * This library is distributed in the hope that it will be useful, but
    015     * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    016     * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
    017     * License for more details.
    018     *
    019     * You should have received a copy of the GNU Lesser General Public
    020     * License along with this library; if not, write to the Free Software
    021     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
    022     * USA.
    023     *
    024     * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
    025     * in the United States and other countries.]
    026     *
    027     * ----------------------
    028     * CenterArrangement.java
    029     * ----------------------
    030     * (C) Copyright 2005, by Object Refinery Limited.
    031     *
    032     * Original Author:  David Gilbert (for Object Refinery Limited);
    033     * Contributor(s):   -;
    034     *
    035     * $Id: CenterArrangement.java,v 1.3.2.1 2005/10/25 20:39:38 mungady Exp $
    036     *
    037     * Changes:
    038     * --------
    039     * 08-Mar-2005 : Version 1 (DG);
    040     *
    041     */
    042
    043    package org.jfree.chart.block;
    044
    045    import java.awt.Graphics2D;
    046    import java.awt.geom.Rectangle2D;
    047    import java.io.Serializable;
    048    import java.util.List;
    049
    050    import org.jfree.ui.Size2D;
    051
    052    /**
    053     * Arranges a block in the center of its container.  This class is immutable.
    054     */
    055    public class CenterArrangement implements Arrangement, Serializable {
    056
    057        /** For serialization. */
    058        private static final long serialVersionUID = -353308149220382047L;
    059
    060        /**
    061         * Creates a new instance.
    062         */
    063        public CenterArrangement() {
    064        }
    065
    066        /**
    067         * Adds a block to be managed by this instance.  This method is usually
    068         * called by the {@link BlockContainer}, you shouldn't need to call it
    069         * directly.
    070         *
    071         * @param block  the block.
    072         * @param key  a key that controls the position of the block.
    073         */
    074        public void add(Block block, Object key) {
    075            // since the flow layout is relatively straightforward,
    076            // no information needs to be recorded here
    077        }
    078
    079        /**
    080         * Calculates and sets the bounds of all the items in the specified
    081         * container, subject to the given constraint.  The <code>Graphics2D</code>
    082         * can be used by some items (particularly items containing text) to
    083         * calculate sizing parameters.
    084         *
    085         * @param container  the container whose items are being arranged.
    086         * @param g2  the graphics device.
    087         * @param constraint  the size constraint.
    088         *
    089         * @return The size of the container after arrangement of the contents.
    090         */
    091        public Size2D arrange(BlockContainer container, Graphics2D g2,
    092                              RectangleConstraint constraint) {
    093
    094            LengthConstraintType w = constraint.getWidthConstraintType();
    095            LengthConstraintType h = constraint.getHeightConstraintType();
    096            if (w == LengthConstraintType.NONE) {
    097                if (h == LengthConstraintType.NONE) {
    098                    return arrangeNN(container, g2);
    099                }
    100                else if (h == LengthConstraintType.FIXED) {
    101                    throw new RuntimeException("Not implemented.");
    102                }
    103                else if (h == LengthConstraintType.RANGE) {
    104                    throw new RuntimeException("Not implemented.");
    105                }
    106            }
    107            else if (w == LengthConstraintType.FIXED) {
    108                if (h == LengthConstraintType.NONE) {
    109                    return arrangeFN(container, g2, constraint);
    110                }
    111                else if (h == LengthConstraintType.FIXED) {
    112                    throw new RuntimeException("Not implemented.");
    113                }
    114                else if (h == LengthConstraintType.RANGE) {
    115                    throw new RuntimeException("Not implemented.");
    116                }
    117            }
    118            else if (w == LengthConstraintType.RANGE) {
    119                if (h == LengthConstraintType.NONE) {
    120                    return arrangeRN(container, g2, constraint);
    121                }
    122                else if (h == LengthConstraintType.FIXED) {
    123                    return arrangeRF(container, g2, constraint);
    124                }
    125                else if (h == LengthConstraintType.RANGE) {
    126                    return arrangeRR(container, g2, constraint);
    127                }
    128            }
    129            throw new IllegalArgumentException("Unknown LengthConstraintType.");
    130
    131        }
    132
    133        /**
    134         * Arranges the blocks in the container with a fixed width and no height
    135         * constraint.
    136         *
    137         * @param container  the container.
    138         * @param g2  the graphics device.
    139         * @param constraint  the constraint.
    140         *
    141         * @return The size.
    142         */
    143        protected Size2D arrangeFN(BlockContainer container, Graphics2D g2,
    144                                   RectangleConstraint constraint) {
    145
    146            List blocks = container.getBlocks();
    147            Block b = (Block) blocks.get(0);
    148            Size2D s = b.arrange(g2, RectangleConstraint.NONE);
    149            double width = constraint.getWidth();
    150            Rectangle2D bounds = new Rectangle2D.Double(
    151                (width - s.width) / 2.0, 0.0, s.width, s.height
    152            );
    153            b.setBounds(bounds);
    154            return new Size2D((width - s.width) / 2.0, s.height);
    155        }
    156
    157        /**
    158         * Arranges the blocks in the container with a fixed with and a range
    159         * constraint on the height.
    160         *
    161         * @param container  the container.
    162         * @param g2  the graphics device.
    163         * @param constraint  the constraint.
    164         *
    165         * @return The size following the arrangement.
    166         */
    167        protected Size2D arrangeFR(BlockContainer container, Graphics2D g2,
    168                                   RectangleConstraint constraint) {
    169
    170            Size2D s = arrangeFN(container, g2, constraint);
    171            if (constraint.getHeightRange().contains(s.height)) {
    172                return s;
    173            }
    174            else {
    175                RectangleConstraint c = constraint.toFixedHeight(
    176                    constraint.getHeightRange().constrain(s.getHeight())
    177                );
    178                return arrangeFF(container, g2, c);
    179            }
    180        }
    181
    182        /**
    183         * Arranges the blocks in the container with the overall height and width
    184         * specified as fixed constraints.
    185         *
    186         * @param container  the container.
    187         * @param g2  the graphics device.
    188         * @param constraint  the constraint.
    189         *
    190         * @return The size following the arrangement.
    191         */
    192        protected Size2D arrangeFF(BlockContainer container, Graphics2D g2,
    193                                   RectangleConstraint constraint) {
    194
    195            // TODO: implement this properly
    196            return arrangeFN(container, g2, constraint);
    197        }
    198
    199        /**
    200         * Arranges the blocks with the overall width and height to fit within
    201         * specified ranges.
    202         *
    203         * @param container  the container.
    204         * @param g2  the graphics device.
    205         * @param constraint  the constraint.
    206         *
    207         * @return The size after the arrangement.
    208         */
    209        protected Size2D arrangeRR(BlockContainer container, Graphics2D g2,
    210                                   RectangleConstraint constraint) {
    211
    212            // first arrange without constraints, and see if this fits within
    213            // the required ranges...
    214            Size2D s1 = arrangeNN(container, g2);
    215            if (constraint.getWidthRange().contains(s1.width)) {
    216                return s1;  // TODO: we didn't check the height yet
    217            }
    218            else {
    219                RectangleConstraint c = constraint.toFixedWidth(
    220                    constraint.getWidthRange().getUpperBound()
    221                );
    222                return arrangeFR(container, g2, c);
    223            }
    224        }
    225
    226        /**
    227         * Arranges the blocks in the container with a range constraint on the
    228         * width and a fixed height.
    229         *
    230         * @param container  the container.
    231         * @param g2  the graphics device.
    232         * @param constraint  the constraint.
    233         *
    234         * @return The size following the arrangement.
    235         */
    236        protected Size2D arrangeRF(BlockContainer container, Graphics2D g2,
    237                                   RectangleConstraint constraint) {
    238
    239            Size2D s = arrangeNF(container, g2, constraint);
    240            if (constraint.getWidthRange().contains(s.width)) {
    241                return s;
    242            }
    243            else {
    244                RectangleConstraint c = constraint.toFixedWidth(
    245                    constraint.getWidthRange().constrain(s.getWidth())
    246                );
    247                return arrangeFF(container, g2, c);
    248            }
    249        }
    250
    251        /**
    252         * Arranges the block with a range constraint on the width, and no
    253         * constraint on the height.
    254         *
    255         * @param container  the container.
    256         * @param g2  the graphics device.
    257         * @param constraint  the constraint.
    258         *
    259         * @return The size following the arrangement.
    260         */
    261        protected Size2D arrangeRN(BlockContainer container, Graphics2D g2,
    262                                   RectangleConstraint constraint) {
    263            // first arrange without constraints, then see if the width fits
    264            // within the required range...if not, call arrangeFN() at max width
    265            Size2D s1 = arrangeNN(container, g2);
    266            if (constraint.getWidthRange().contains(s1.width)) {
    267                return s1;
    268            }
    269            else {
    270                RectangleConstraint c = constraint.toFixedWidth(
    271                    constraint.getWidthRange().getUpperBound()
    272                );
    273                return arrangeFN(container, g2, c);
    274            }
    275        }
    276
    277        /**
    278         * Arranges the blocks without any constraints.  This puts all blocks
    279         * into a single row.
    280         *
    281         * @param container  the container.
    282         * @param g2  the graphics device.
    283         *
    284         * @return The size after the arrangement.
    285         */
    286        protected Size2D arrangeNN(BlockContainer container, Graphics2D g2) {
    287            List blocks = container.getBlocks();
    288            Block b = (Block) blocks.get(0);
    289            Size2D s = b.arrange(g2, RectangleConstraint.NONE);
    290            return new Size2D(s.width, s.height);
    291        }
    292
    293        /**
    294         * Arranges the blocks with no width constraint and a fixed height
    295         * constraint.  This puts all blocks into a single row.
    296         *
    297         * @param container  the container.
    298         * @param g2  the graphics device.
    299         * @param constraint  the constraint.
    300         *
    301         * @return The size after the arrangement.
    302         */
    303        protected Size2D arrangeNF(BlockContainer container, Graphics2D g2,
    304                                   RectangleConstraint constraint) {
    305            // TODO: for now we are ignoring the height constraint
    306            return arrangeNN(container, g2);
    307        }
    308
    309        /**
    310         * Clears any cached information.
    311         */
    312        public void clear() {
    313            // no action required.
    314        }
    315
    316        /**
    317         * Tests this instance for equality with an arbitrary object.
    318         *
    319         * @param obj  the object (<code>null</code> permitted).
    320         *
    321         * @return A boolean.
    322         */
    323        public boolean equals(Object obj) {
    324            if (obj == this) {
    325                return true;
    326            }
    327            if (!(obj instanceof CenterArrangement)) {
    328                return false;
    329            }
    330            return true;
    331        }
    332
    333    }