org.squidy.designer.util.DrawableString.java Source code

Java tutorial

Introduction

Here is the source code for org.squidy.designer.util.DrawableString.java

Source

/**
 * Squidy Interaction Library is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 * 
 * Squidy Interaction Library is distributed in the hope that it will be
 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with Squidy Interaction Library. If not, see
 * <http://www.gnu.org/licenses/>.
 * 
 * 2009 Human-Computer Interaction Group, University of Konstanz.
 * <http://hci.uni-konstanz.de>
 * 
 * Please contact info@squidy-lib.de or visit our website
 * <http://www.squidy-lib.de> for further information.
 */

package org.squidy.designer.util;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Rectangle;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.squidy.designer.zoom.ActionShape;

/**
 * <code>DrawableString</code>.
 * 
 * <pre>
 * Date: 21.08.2009
 * Time: 14:06:42
 * </pre>
 * 
 * 
 * @author
 * Toni Zeitler
 * <a href="mailto:anton.zeitler@campus.lmu.de">anton.zeitler@campus.lmu.de</a>
 * Media Informatics Group
 * University of Munich (LMU)
 * 
 * @version $Id: DrawableString.java 772 2011-09-16 15:39:44Z raedle $
 * @since 1.0.0
 */
public class DrawableString {

    public enum AlignmentH {
        LEFT, CENTER, RIGHT
    }

    public enum AlignmentV {
        TOP, CENTER, BOTTOM
    }

    // input
    private String value;
    private Color color;
    private Font font;
    private Rectangle bounds;
    private AlignmentH alignmentH = AlignmentH.CENTER;
    private AlignmentV alignmentV = AlignmentV.CENTER;
    private int offsetX;
    private int offsetY;

    // calculated
    private int positionX;
    private int positionY;
    private String drawValue;
    private boolean dirty = true;

    // Logger to log info, error, debug,... messages.
    private static final Log LOG = LogFactory.getLog(DrawableString.class);

    private class Cache {

        private class Item {
            public String drawValue;
            public int positionX;

            public Item(String drawValue, int positionX) {
                super();
                this.drawValue = drawValue;
                this.positionX = positionX;
            }
        }

        private Item items[][][];

        public Cache() {
            super();
            items = new Item[100][][];
        }

        public void put(String drawValue, int positionX, double scale) {
            if (scale >= 100.0)
                return;

            int i2 = (int) (scale * 100.0);
            int i1 = i2 / 10;
            int i0 = i1 / 10;
            i2 -= i1 * 10;
            i1 -= i0 * 10;

            if (items[i0] == null)
                items[i0] = new Item[10][];
            if (items[i0][i1] == null)
                items[i0][i1] = new Item[10];
            if (items[i0][i1][i2] == null)
                items[i0][i1][i2] = new Item(drawValue, positionX);
            else {
                items[i0][i1][i2].drawValue = drawValue;
                items[i0][i1][i2].positionX = positionX;
            }
        }

        public Item get(double scale) {
            if (scale >= 100.0)
                return null;

            int i2 = (int) (scale * 100.0);
            int i1 = i2 / 10;
            int i0 = i1 / 10;
            i2 -= i1 * 10;
            i1 -= i0 * 10;

            if (items[i0] == null)
                return null;
            if (items[i0][i1] == null)
                return null;
            if (items[i0][i1][i2] == null)
                return null;
            return items[i0][i1][i2];
        }
    }

    private Cache cache;

    /**
     * 
     */
    public DrawableString() {
        super();
    }

    /**
     * @param fullString
     */
    public DrawableString(String fullString) {
        this.value = fullString;
    }

    /**
     * @param fullString
     * @param color
     * @param font
     * @param bounds
     */
    public DrawableString(String fullString, Color color, Font font, Rectangle bounds) {
        this.value = fullString;
        this.color = color;
        this.font = font;
        this.bounds = bounds;
    }

    /**
     * @param g
     */
    private void update(Graphics2D g, double viewScale) {
        Cache.Item item;

        // use screen if no bounds set
        if (bounds == null) {
            bounds = g.getDeviceConfiguration().getBounds();
        }

        // get item extents from cache or calculate
        if (cache == null || dirty) {
            cache = new Cache();
            item = null;
        } else {
            item = cache.get(viewScale);
        }

        if (item != null) {
            drawValue = item.drawValue;
            positionX = item.positionX;
        } else {
            FontMetrics fm;
            int width, height;

            // font width does not scale linear to view scale
            fm = g.getFontMetrics();
            drawValue = FontUtils.createCroppedLabelIfNecessary(fm, value, bounds.width - 50);

            positionX = bounds.x;
            if (alignmentH == AlignmentH.CENTER) {
                width = FontUtils.getWidthOfText(fm, drawValue);
                positionX += (bounds.width - width) / 2;
            } else if (alignmentH == AlignmentH.RIGHT) {
                width = FontUtils.getWidthOfText(fm, drawValue);
                positionX += (bounds.width - width);
            }

            // font height keeps the same all the time
            if (dirty) {
                positionY = bounds.y;
                if (alignmentV == AlignmentV.CENTER) {
                    height = (int) fm.getLineMetrics(drawValue, g).getHeight();
                    positionY += (bounds.height - height) / 2;
                } else if (alignmentV == AlignmentV.BOTTOM) {
                    height = (int) fm.getLineMetrics(drawValue, g).getHeight();
                    positionY += (bounds.height - height);
                }
            }

            // store extents in cache
            cache.put(drawValue, positionX, viewScale);
        }

        dirty = false;
    }

    /**
     * @param g
     */
    public void draw(Graphics2D g, double viewScale) {
        if (value == null)
            return;
        if (color != null)
            g.setColor(color);
        if (font != null)
            g.setFont(font);
        update(g, viewScale);
        if (drawValue != null)
            g.drawString(drawValue, positionX + offsetX, positionY + offsetY);
    }

    /**
     * 
     */
    public void invalidate() {
        dirty = true;
    }

    /**
     * @return
     */
    public String get() {
        return value;
    }

    /**
     * @param value
     */
    public void set(String value) {
        if (this.value != value) {
            this.value = value;
            dirty = true;
        }
    }

    /**
     * @return
     */
    public Color getColor() {
        return color;
    }

    /**
     * @param color
     */
    public void setColor(Color color) {
        this.color = color;
    }

    /**
     * @return
     */
    public Font getFont() {
        return font;
    }

    /**
     * @param font
     */
    public void setFont(Font font) {
        this.font = font;
        dirty = true;
    }

    /**
     * @return
     */
    public Rectangle getBounds() {
        return bounds;
    }

    /**
     * @param bounds
     */
    public void setBounds(Rectangle bounds) {
        if (bounds != null && !bounds.equals(this.bounds)) {
            this.bounds = bounds;
            dirty = true;
        }
    }

    /**
     * @return
     */
    public AlignmentH getAlignmentH() {
        return alignmentH;
    }

    /**
     * @param alignmentH
     */
    public void setAlignmentH(AlignmentH alignmentH) {
        this.alignmentH = alignmentH;
    }

    /**
     * @return
     */
    public AlignmentV getAlignmentV() {
        return alignmentV;
    }

    /**
     * @param alignmentV
     */
    public void setAlignmentV(AlignmentV alignmentV) {
        this.alignmentV = alignmentV;
    }

    /**
     * @return
     */
    public int getOffsetX() {
        return offsetX;
    }

    /**
     * @param offsetX
     */
    public void setOffsetX(int offsetX) {
        this.offsetX = offsetX;
    }

    /**
     * @return
     */
    public int getOffsetY() {
        return offsetY;
    }

    /**
     * @param offsetY
     */
    public void setOffsetY(int offsetY) {
        this.offsetY = offsetY;
    }
}