    001    /* ===========================================================
    002     * JFreeChart : a free chart library for the Java(tm) platform
    003     * ===========================================================
    004     *
    005     * (C) Copyright 2000-2007, 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-2007, by Object Refinery Limited.
    031     *
    032     * Original Author:  David Gilbert (for Object Refinery Limited);
    033     * Contributor(s):   -;
    034     *
    035     * Changes:
    036     * --------
    037     * 08-Mar-2005 : Version 1 (DG);
    038     * ------------- JFREECHART 1.0.x ---------------------------------------------
    039     * 20-Jul-2006 : Set bounds of contained block when arranging (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((width - s.width) / 2.0,
    151                    0.0, s.width, s.height);
    152            b.setBounds(bounds);
    153            return new Size2D((width - s.width) / 2.0, s.height);
    154        }
    155
    156        /**
    157         * Arranges the blocks in the container with a fixed with and a range
    158         * constraint on the height.
    159         *
    160         * @param container  the container.
    161         * @param g2  the graphics device.
    162         * @param constraint  the constraint.
    163         *
    164         * @return The size following the arrangement.
    165         */
    166        protected Size2D arrangeFR(BlockContainer container, Graphics2D g2,
    167                                   RectangleConstraint constraint) {
    168
    169            Size2D s = arrangeFN(container, g2, constraint);
    170            if (constraint.getHeightRange().contains(s.height)) {
    171                return s;
    172            }
    173            else {
    174                RectangleConstraint c = constraint.toFixedHeight(
    175                        constraint.getHeightRange().constrain(s.getHeight()));
    176                return arrangeFF(container, g2, c);
    177            }
    178        }
    179
    180        /**
    181         * Arranges the blocks in the container with the overall height and width
    182         * specified as fixed constraints.
    183         *
    184         * @param container  the container.
    185         * @param g2  the graphics device.
    186         * @param constraint  the constraint.
    187         *
    188         * @return The size following the arrangement.
    189         */
    190        protected Size2D arrangeFF(BlockContainer container, Graphics2D g2,
    191                                   RectangleConstraint constraint) {
    192
    193            // TODO: implement this properly
    194            return arrangeFN(container, g2, constraint);
    195        }
    196
    197        /**
    198         * Arranges the blocks with the overall width and height to fit within
    199         * specified ranges.
    200         *
    201         * @param container  the container.
    202         * @param g2  the graphics device.
    203         * @param constraint  the constraint.
    204         *
    205         * @return The size after the arrangement.
    206         */
    207        protected Size2D arrangeRR(BlockContainer container, Graphics2D g2,
    208                                   RectangleConstraint constraint) {
    209
    210            // first arrange without constraints, and see if this fits within
    211            // the required ranges...
    212            Size2D s1 = arrangeNN(container, g2);
    213            if (constraint.getWidthRange().contains(s1.width)) {
    214                return s1;  // TODO: we didn't check the height yet
    215            }
    216            else {
    217                RectangleConstraint c = constraint.toFixedWidth(
    218                        constraint.getWidthRange().getUpperBound());
    219                return arrangeFR(container, g2, c);
    220            }
    221        }
    222
    223        /**
    224         * Arranges the blocks in the container with a range constraint on the
    225         * width and a fixed height.
    226         *
    227         * @param container  the container.
    228         * @param g2  the graphics device.
    229         * @param constraint  the constraint.
    230         *
    231         * @return The size following the arrangement.
    232         */
    233        protected Size2D arrangeRF(BlockContainer container, Graphics2D g2,
    234                                   RectangleConstraint constraint) {
    235
    236            Size2D s = arrangeNF(container, g2, constraint);
    237            if (constraint.getWidthRange().contains(s.width)) {
    238                return s;
    239            }
    240            else {
    241                RectangleConstraint c = constraint.toFixedWidth(
    242                        constraint.getWidthRange().constrain(s.getWidth()));
    243                return arrangeFF(container, g2, c);
    244            }
    245        }
    246
    247        /**
    248         * Arranges the block with a range constraint on the width, and no
    249         * constraint on the height.
    250         *
    251         * @param container  the container.
    252         * @param g2  the graphics device.
    253         * @param constraint  the constraint.
    254         *
    255         * @return The size following the arrangement.
    256         */
    257        protected Size2D arrangeRN(BlockContainer container, Graphics2D g2,
    258                                   RectangleConstraint constraint) {
    259            // first arrange without constraints, then see if the width fits
    260            // within the required range...if not, call arrangeFN() at max width
    261            Size2D s1 = arrangeNN(container, g2);
    262            if (constraint.getWidthRange().contains(s1.width)) {
    263                return s1;
    264            }
    265            else {
    266                RectangleConstraint c = constraint.toFixedWidth(
    267                        constraint.getWidthRange().getUpperBound());
    268                return arrangeFN(container, g2, c);
    269            }
    270        }
    271
    272        /**
    273         * Arranges the blocks without any constraints.  This puts all blocks
    274         * into a single row.
    275         *
    276         * @param container  the container.
    277         * @param g2  the graphics device.
    278         *
    279         * @return The size after the arrangement.
    280         */
    281        protected Size2D arrangeNN(BlockContainer container, Graphics2D g2) {
    282            List blocks = container.getBlocks();
    283            Block b = (Block) blocks.get(0);
    284            Size2D s = b.arrange(g2, RectangleConstraint.NONE);
    285            b.setBounds(new Rectangle2D.Double(0.0, 0.0, s.width, s.height));
    286            return new Size2D(s.width, s.height);
    287        }
    288
    289        /**
    290         * Arranges the blocks with no width constraint and a fixed height
    291         * constraint.  This puts all blocks into a single row.
    292         *
    293         * @param container  the container.
    294         * @param g2  the graphics device.
    295         * @param constraint  the constraint.
    296         *
    297         * @return The size after the arrangement.
    298         */
    299        protected Size2D arrangeNF(BlockContainer container, Graphics2D g2,
    300                                   RectangleConstraint constraint) {
    301            // TODO: for now we are ignoring the height constraint
    302            return arrangeNN(container, g2);
    303        }
    304
    305        /**
    306         * Clears any cached information.
    307         */
    308        public void clear() {
    309            // no action required.
    310        }
    311
    312        /**
    313         * Tests this instance for equality with an arbitrary object.
    314         *
    315         * @param obj  the object (<code>null</code> permitted).
    316         *
    317         * @return A boolean.
    318         */
    319        public boolean equals(Object obj) {
    320            if (obj == this) {
    321                return true;
    322            }
    323            if (!(obj instanceof CenterArrangement)) {
    324                return false;
    325            }
    326            return true;
    327        }
    328
    329    }