    001    /* ========================================================================
    002     * JCommon : a free general purpose class 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/jcommon/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     * TextBox.java
    029     * ------------
    030     * (C) Copyright 2004, by Object Refinery Limited and Contributors.
    031     *
    032     * Original Author:  David Gilbert (for Object Refinery Limited);
    033     * Contributor(s):   -;
    034     *
    035     * $Id: TextBox.java,v 1.11 2005/10/18 13:17:16 mungady Exp $
    036     *
    037     * Changes
    038     * -------
    039     * 09-Mar-2004 : Version 1 (DG);
    040     * 22-Mar-2004 : Added equals() method and implemented Serializable (DG);
    041     * 09-Nov-2004 : Renamed getAdjustedHeight() --> calculateExtendedHeight() in
    042     *               Spacer class (DG);
    043     * 22-Feb-2005 : Replaced Spacer with RectangleInsets (DG);
    044     *
    045     */
    046
    047    package org.jfree.text;
    048
    049    import java.awt.BasicStroke;
    050    import java.awt.Color;
    051    import java.awt.Font;
    052    import java.awt.Graphics2D;
    053    import java.awt.Paint;
    054    import java.awt.Stroke;
    055    import java.awt.geom.Rectangle2D;
    056    import java.io.IOException;
    057    import java.io.ObjectInputStream;
    058    import java.io.ObjectOutputStream;
    059    import java.io.Serializable;
    060
    061    import org.jfree.io.SerialUtilities;
    062    import org.jfree.ui.RectangleAnchor;
    063    import org.jfree.ui.RectangleInsets;
    064    import org.jfree.ui.Size2D;
    065    import org.jfree.util.ObjectUtilities;
    066
    067    /**
    068     * A box containing a text block.
    069     *
    070     * @author David Gilbert
    071     */
    072    public class TextBox implements Serializable {
    073
    074        /** For serialization. */
    075        private static final long serialVersionUID = 3360220213180203706L;
    076
    077        /** The outline paint. */
    078        private transient Paint outlinePaint;
    079
    080        /** The outline stroke. */
    081        private transient Stroke outlineStroke;
    082
    083        /** The interior space. */
    084        private RectangleInsets interiorGap;
    085
    086        /** The background paint. */
    087        private transient Paint backgroundPaint;
    088
    089        /** The shadow paint. */
    090        private transient Paint shadowPaint;
    091
    092        /** The shadow x-offset. */
    093        private double shadowXOffset = 2.0;
    094
    095        /** The shadow y-offset. */
    096        private double shadowYOffset = 2.0;
    097
    098        /** The text block. */
    099        private TextBlock textBlock;
    100
    101        /**
    102         * Creates an empty text box.
    103         */
    104        public TextBox() {
    105            this((TextBlock) null);
    106        }
    107
    108        /**
    109         * Creates a text box.
    110         *
    111         * @param text  the text.
    112         */
    113        public TextBox(final String text) {
    114            this((TextBlock) null);
    115            if (text != null) {
    116                this.textBlock = new TextBlock();
    117                this.textBlock.addLine(
    118                    text, new Font("SansSerif", Font.PLAIN, 10),
    119                    Color.black
    120                );
    121            }
    122        }
    123
    124        /**
    125         * Creates a new text box.
    126         *
    127         * @param block  the text block.
    128         */
    129        public TextBox(final TextBlock block) {
    130            this.outlinePaint = Color.black;
    131            this.outlineStroke = new BasicStroke(1.0f);
    132            this.interiorGap = new RectangleInsets(1.0, 3.0, 1.0, 3.0);
    133            this.backgroundPaint = new Color(255, 255, 192);
    134            this.shadowPaint = Color.gray;
    135            this.shadowXOffset = 2.0;
    136            this.shadowYOffset = 2.0;
    137            this.textBlock = block;
    138        }
    139
    140        /**
    141         * Returns the outline paint.
    142         *
    143         * @return The outline paint.
    144         */
    145        public Paint getOutlinePaint() {
    146            return this.outlinePaint;
    147        }
    148
    149        /**
    150         * Sets the outline paint.
    151         *
    152         * @param paint  the paint.
    153         */
    154        public void setOutlinePaint(final Paint paint) {
    155            this.outlinePaint = paint;
    156        }
    157
    158        /**
    159         * Returns the outline stroke.
    160         *
    161         * @return The outline stroke.
    162         */
    163        public Stroke getOutlineStroke() {
    164            return this.outlineStroke;
    165        }
    166
    167        /**
    168         * Sets the outline stroke.
    169         *
    170         * @param stroke  the stroke.
    171         */
    172        public void setOutlineStroke(final Stroke stroke) {
    173            this.outlineStroke = stroke;
    174        }
    175
    176        /**
    177         * Returns the interior gap.
    178         *
    179         * @return The interior gap.
    180         */
    181        public RectangleInsets getInteriorGap() {
    182            return this.interiorGap;
    183        }
    184
    185        /**
    186         * Sets the interior gap.
    187         *
    188         * @param gap  the gap.
    189         */
    190        public void setInteriorGap(final RectangleInsets gap) {
    191            this.interiorGap = gap;
    192        }
    193
    194        /**
    195         * Returns the background paint.
    196         *
    197         * @return The background paint.
    198         */
    199        public Paint getBackgroundPaint() {
    200            return this.backgroundPaint;
    201        }
    202
    203        /**
    204         * Sets the background paint.
    205         *
    206         * @param paint  the paint.
    207         */
    208        public void setBackgroundPaint(final Paint paint) {
    209            this.backgroundPaint = paint;
    210        }
    211
    212        /**
    213         * Returns the shadow paint.
    214         *
    215         * @return The shadow paint.
    216         */
    217        public Paint getShadowPaint() {
    218            return this.shadowPaint;
    219        }
    220
    221        /**
    222         * Sets the shadow paint.
    223         *
    224         * @param paint  the paint.
    225         */
    226        public void setShadowPaint(final Paint paint) {
    227            this.shadowPaint = paint;
    228        }
    229
    230        /**
    231         * Returns the x-offset for the shadow effect.
    232         *
    233         * @return The offset.
    234         */
    235        public double getShadowXOffset() {
    236            return this.shadowXOffset;
    237        }
    238
    239        /**
    240         * Sets the x-offset for the shadow effect.
    241         *
    242         * @param offset  the offset (in Java2D units).
    243         */
    244        public void setShadowXOffset(final double offset) {
    245            this.shadowXOffset = offset;
    246        }
    247
    248        /**
    249         * Returns the y-offset for the shadow effect.
    250         *
    251         * @return The offset.
    252         */
    253        public double getShadowYOffset() {
    254            return this.shadowYOffset;
    255        }
    256
    257        /**
    258         * Sets the y-offset for the shadow effect.
    259         *
    260         * @param offset  the offset (in Java2D units).
    261         */
    262        public void setShadowYOffset(final double offset) {
    263            this.shadowYOffset = offset;
    264        }
    265
    266        /**
    267         * Returns the text block.
    268         *
    269         * @return The text block.
    270         */
    271        public TextBlock getTextBlock() {
    272            return this.textBlock;
    273        }
    274
    275        /**
    276         * Sets the text block.
    277         *
    278         * @param block  the block.
    279         */
    280        public void setTextBlock(final TextBlock block) {
    281            this.textBlock = block;
    282        }
    283
    284        /**
    285         * Draws the text box.
    286         *
    287         * @param g2  the graphics device.
    288         * @param x  the x-coordinate.
    289         * @param y  the y-coordinate.
    290         * @param anchor  the anchor point.
    291         */
    292        public void draw(final Graphics2D g2,
    293                         final float x, final float y,
    294                         final RectangleAnchor anchor) {
    295            final Size2D d1 = this.textBlock.calculateDimensions(g2);
    296            final double w = this.interiorGap.extendWidth(d1.getWidth());
    297            final double h = this.interiorGap.extendHeight(d1.getHeight());
    298            final Size2D d2 = new Size2D(w, h);
    299            final Rectangle2D bounds
    300                = RectangleAnchor.createRectangle(d2, x, y, anchor);
    301
    302            if (this.shadowPaint != null) {
    303                final Rectangle2D shadow = new Rectangle2D.Double(
    304                    bounds.getX() + this.shadowXOffset,
    305                    bounds.getY() + this.shadowYOffset,
    306                    bounds.getWidth(), bounds.getHeight()
    307                );
    308                g2.setPaint(this.shadowPaint);
    309                g2.fill(shadow);
    310            }
    311            if (this.backgroundPaint != null) {
    312                g2.setPaint(this.backgroundPaint);
    313                g2.fill(bounds);
    314            }
    315
    316            if (this.outlinePaint != null && this.outlineStroke != null) {
    317                g2.setPaint(this.outlinePaint);
    318                g2.setStroke(this.outlineStroke);
    319                g2.draw(bounds);
    320            }
    321
    322            this.textBlock.draw(
    323                g2, (float) bounds.getCenterX(), (float) bounds.getCenterY(),
    324                TextBlockAnchor.CENTER
    325            );
    326
    327        }
    328
    329        /**
    330         * Returns the height of the text box.
    331         *
    332         * @param g2  the graphics device.
    333         *
    334         * @return The height (in Java2D units).
    335         */
    336        public double getHeight(final Graphics2D g2) {
    337            final Size2D d = this.textBlock.calculateDimensions(g2);
    338            return this.interiorGap.extendHeight(d.getHeight());
    339        }
    340
    341        /**
    342         * Tests this object for equality with an arbitrary object.
    343         *
    344         * @param obj  the object to test against (<code>null</code> permitted).
    345         *
    346         * @return A boolean.
    347         */
    348        public boolean equals(final Object obj) {
    349            if (obj == this) {
    350                return true;
    351            }
    352            if (!(obj instanceof TextBox)) {
    353                return false;
    354            }
    355            final TextBox that = (TextBox) obj;
    356            if (!ObjectUtilities.equal(this.outlinePaint, that.outlinePaint)) {
    357                return false;
    358            }
    359            if (!ObjectUtilities.equal(this.outlineStroke, that.outlineStroke)) {
    360                return false;
    361            }
    362            if (!ObjectUtilities.equal(this.interiorGap, that.interiorGap)) {
    363                return false;
    364            }
    365            if (!ObjectUtilities.equal(this.backgroundPaint,
    366                    that.backgroundPaint)) {
    367                return false;
    368            }
    369            if (!ObjectUtilities.equal(this.shadowPaint, that.shadowPaint)) {
    370                return false;
    371            }
    372            if (this.shadowXOffset != that.shadowXOffset) {
    373                return false;
    374            }
    375            if (this.shadowYOffset != that.shadowYOffset) {
    376                return false;
    377            }
    378            if (!ObjectUtilities.equal(this.textBlock, that.textBlock)) {
    379                return false;
    380            }
    381
    382            return true;
    383        }
    384
    385        /**
    386         * Returns a hash code for this object.
    387         *
    388         * @return A hash code.
    389         */
    390        public int hashCode() {
    391            int result;
    392            long temp;
    393            result = (this.outlinePaint != null ? this.outlinePaint.hashCode() : 0);
    394            result = 29 * result + (this.outlineStroke != null
    395                    ? this.outlineStroke.hashCode() : 0);
    396            result = 29 * result + (this.interiorGap != null
    397                    ? this.interiorGap.hashCode() : 0);
    398            result = 29 * result + (this.backgroundPaint != null
    399                    ? this.backgroundPaint.hashCode() : 0);
    400            result = 29 * result + (this.shadowPaint != null
    401                    ? this.shadowPaint.hashCode() : 0);
    402            temp = this.shadowXOffset != +0.0d
    403                    ? Double.doubleToLongBits(this.shadowXOffset) : 0l;
    404            result = 29 * result + (int) (temp ^ (temp >>> 32));
    405            temp = this.shadowYOffset != +0.0d
    406                    ? Double.doubleToLongBits(this.shadowYOffset) : 0l;
    407            result = 29 * result + (int) (temp ^ (temp >>> 32));
    408            result = 29 * result + (this.textBlock != null
    409                    ? this.textBlock.hashCode() : 0);
    410            return result;
    411        }
    412
    413        /**
    414         * Provides serialization support.
    415         *
    416         * @param stream  the output stream.
    417         *
    418         * @throws IOException  if there is an I/O error.
    419         */
    420        private void writeObject(final ObjectOutputStream stream)
    421                throws IOException {
    422            stream.defaultWriteObject();
    423            SerialUtilities.writePaint(this.outlinePaint, stream);
    424            SerialUtilities.writeStroke(this.outlineStroke, stream);
    425            SerialUtilities.writePaint(this.backgroundPaint, stream);
    426            SerialUtilities.writePaint(this.shadowPaint, stream);
    427        }
    428
    429        /**
    430         * Provides serialization support.
    431         *
    432         * @param stream  the input stream.
    433         *
    434         * @throws IOException  if there is an I/O error.
    435         * @throws ClassNotFoundException  if there is a classpath problem.
    436         */
    437        private void readObject(final ObjectInputStream stream)
    438            throws IOException, ClassNotFoundException {
    439            stream.defaultReadObject();
    440            this.outlinePaint = SerialUtilities.readPaint(stream);
    441            this.outlineStroke = SerialUtilities.readStroke(stream);
    442            this.backgroundPaint = SerialUtilities.readPaint(stream);
    443            this.shadowPaint = SerialUtilities.readPaint(stream);
    444        }
    445
    446
    447    }