    001    /* ===========================================================
    002     * JFreeChart : a free chart library for the Java(tm) platform
    003     * ===========================================================
    004     *
    005     * (C) Copyright 2000-2006, 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, 2006, 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.2 2006/07/20 16:21:58 mungady Exp $
    036     *
    037     * Changes:
    038     * --------
    039     * 08-Mar-2005 : Version 1 (DG);
    040     * ------------- JFREECHART 1.0.0 ---------------------------------------------
    041     * 20-Jul-2006 : Set bounds of contained block when arranging (DG);
    042     *
    043     */
    044
    045    package org.jfree.chart.block;
    046
    047    import java.awt.Graphics2D;
    048    import java.awt.geom.Rectangle2D;
    049    import java.io.Serializable;
    050    import java.util.List;
    051
    052    import org.jfree.ui.Size2D;
    053
    054    /**
    055     * Arranges a block in the center of its container.  This class is immutable.
    056     */
    057    public class CenterArrangement implements Arrangement, Serializable {
    058
    059        /** For serialization. */
    060        private static final long serialVersionUID = -353308149220382047L;
    061
    062        /**
    063         * Creates a new instance.
    064         */
    065        public CenterArrangement() {
    066        }
    067
    068        /**
    069         * Adds a block to be managed by this instance.  This method is usually
    070         * called by the {@link BlockContainer}, you shouldn't need to call it
    071         * directly.
    072         *
    073         * @param block  the block.
    074         * @param key  a key that controls the position of the block.
    075         */
    076        public void add(Block block, Object key) {
    077            // since the flow layout is relatively straightforward,
    078            // no information needs to be recorded here
    079        }
    080
    081        /**
    082         * Calculates and sets the bounds of all the items in the specified
    083         * container, subject to the given constraint.  The <code>Graphics2D</code>
    084         * can be used by some items (particularly items containing text) to
    085         * calculate sizing parameters.
    086         *
    087         * @param container  the container whose items are being arranged.
    088         * @param g2  the graphics device.
    089         * @param constraint  the size constraint.
    090         *
    091         * @return The size of the container after arrangement of the contents.
    092         */
    093        public Size2D arrange(BlockContainer container, Graphics2D g2,
    094                              RectangleConstraint constraint) {
    095
    096            LengthConstraintType w = constraint.getWidthConstraintType();
    097            LengthConstraintType h = constraint.getHeightConstraintType();
    098            if (w == LengthConstraintType.NONE) {
    099                if (h == LengthConstraintType.NONE) {
    100                    return arrangeNN(container, g2);
    101                }
    102                else if (h == LengthConstraintType.FIXED) {
    103                    throw new RuntimeException("Not implemented.");
    104                }
    105                else if (h == LengthConstraintType.RANGE) {
    106                    throw new RuntimeException("Not implemented.");
    107                }
    108            }
    109            else if (w == LengthConstraintType.FIXED) {
    110                if (h == LengthConstraintType.NONE) {
    111                    return arrangeFN(container, g2, constraint);
    112                }
    113                else if (h == LengthConstraintType.FIXED) {
    114                    throw new RuntimeException("Not implemented.");
    115                }
    116                else if (h == LengthConstraintType.RANGE) {
    117                    throw new RuntimeException("Not implemented.");
    118                }
    119            }
    120            else if (w == LengthConstraintType.RANGE) {
    121                if (h == LengthConstraintType.NONE) {
    122                    return arrangeRN(container, g2, constraint);
    123                }
    124                else if (h == LengthConstraintType.FIXED) {
    125                    return arrangeRF(container, g2, constraint);
    126                }
    127                else if (h == LengthConstraintType.RANGE) {
    128                    return arrangeRR(container, g2, constraint);
    129                }
    130            }
    131            throw new IllegalArgumentException("Unknown LengthConstraintType.");
    132
    133        }
    134
    135        /**
    136         * Arranges the blocks in the container with a fixed width and no height
    137         * constraint.
    138         *
    139         * @param container  the container.
    140         * @param g2  the graphics device.
    141         * @param constraint  the constraint.
    142         *
    143         * @return The size.
    144         */
    145        protected Size2D arrangeFN(BlockContainer container, Graphics2D g2,
    146                                   RectangleConstraint constraint) {
    147
    148            List blocks = container.getBlocks();
    149            Block b = (Block) blocks.get(0);
    150            Size2D s = b.arrange(g2, RectangleConstraint.NONE);
    151            double width = constraint.getWidth();
    152            Rectangle2D bounds = new Rectangle2D.Double((width - s.width) / 2.0,
    153                    0.0, s.width, s.height);
    154            b.setBounds(bounds);
    155            return new Size2D((width - s.width) / 2.0, s.height);
    156        }
    157
    158        /**
    159         * Arranges the blocks in the container with a fixed with and a range
    160         * constraint on the height.
    161         *
    162         * @param container  the container.
    163         * @param g2  the graphics device.
    164         * @param constraint  the constraint.
    165         *
    166         * @return The size following the arrangement.
    167         */
    168        protected Size2D arrangeFR(BlockContainer container, Graphics2D g2,
    169                                   RectangleConstraint constraint) {
    170
    171            Size2D s = arrangeFN(container, g2, constraint);
    172            if (constraint.getHeightRange().contains(s.height)) {
    173                return s;
    174            }
    175            else {
    176                RectangleConstraint c = constraint.toFixedHeight(
    177                        constraint.getHeightRange().constrain(s.getHeight()));
    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                return arrangeFR(container, g2, c);
    222            }
    223        }
    224
    225        /**
    226         * Arranges the blocks in the container with a range constraint on the
    227         * width and a fixed height.
    228         *
    229         * @param container  the container.
    230         * @param g2  the graphics device.
    231         * @param constraint  the constraint.
    232         *
    233         * @return The size following the arrangement.
    234         */
    235        protected Size2D arrangeRF(BlockContainer container, Graphics2D g2,
    236                                   RectangleConstraint constraint) {
    237
    238            Size2D s = arrangeNF(container, g2, constraint);
    239            if (constraint.getWidthRange().contains(s.width)) {
    240                return s;
    241            }
    242            else {
    243                RectangleConstraint c = constraint.toFixedWidth(
    244                        constraint.getWidthRange().constrain(s.getWidth()));
    245                return arrangeFF(container, g2, c);
    246            }
    247        }
    248
    249        /**
    250         * Arranges the block with a range constraint on the width, and no
    251         * constraint on the height.
    252         *
    253         * @param container  the container.
    254         * @param g2  the graphics device.
    255         * @param constraint  the constraint.
    256         *
    257         * @return The size following the arrangement.
    258         */
    259        protected Size2D arrangeRN(BlockContainer container, Graphics2D g2,
    260                                   RectangleConstraint constraint) {
    261            // first arrange without constraints, then see if the width fits
    262            // within the required range...if not, call arrangeFN() at max width
    263            Size2D s1 = arrangeNN(container, g2);
    264            if (constraint.getWidthRange().contains(s1.width)) {
    265                return s1;
    266            }
    267            else {
    268                RectangleConstraint c = constraint.toFixedWidth(
    269                        constraint.getWidthRange().getUpperBound());
    270                return arrangeFN(container, g2, c);
    271            }
    272        }
    273
    274        /**
    275         * Arranges the blocks without any constraints.  This puts all blocks
    276         * into a single row.
    277         *
    278         * @param container  the container.
    279         * @param g2  the graphics device.
    280         *
    281         * @return The size after the arrangement.
    282         */
    283        protected Size2D arrangeNN(BlockContainer container, Graphics2D g2) {
    284            List blocks = container.getBlocks();
    285            Block b = (Block) blocks.get(0);
    286            Size2D s = b.arrange(g2, RectangleConstraint.NONE);
    287            b.setBounds(new Rectangle2D.Double(0.0, 0.0, s.width, s.height));
    288            return new Size2D(s.width, s.height);
    289        }
    290
    291        /**
    292         * Arranges the blocks with no width constraint and a fixed height
    293         * constraint.  This puts all blocks into a single row.
    294         *
    295         * @param container  the container.
    296         * @param g2  the graphics device.
    297         * @param constraint  the constraint.
    298         *
    299         * @return The size after the arrangement.
    300         */
    301        protected Size2D arrangeNF(BlockContainer container, Graphics2D g2,
    302                                   RectangleConstraint constraint) {
    303            // TODO: for now we are ignoring the height constraint
    304            return arrangeNN(container, g2);
    305        }
    306
    307        /**
    308         * Clears any cached information.
    309         */
    310        public void clear() {
    311            // no action required.
    312        }
    313
    314        /**
    315         * Tests this instance for equality with an arbitrary object.
    316         *
    317         * @param obj  the object (<code>null</code> permitted).
    318         *
    319         * @return A boolean.
    320         */
    321        public boolean equals(Object obj) {
    322            if (obj == this) {
    323                return true;
    324            }
    325            if (!(obj instanceof CenterArrangement)) {
    326                return false;
    327            }
    328            return true;
    329        }
    330
    331    }