All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nakedobjects.nos.client.dnd.viewer.AwtText Maven / Gradle / Ivy

The newest version!
package org.nakedobjects.nos.client.dnd.viewer;

import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.util.StringTokenizer;

import org.apache.log4j.Logger;
import org.nakedobjects.nof.core.context.NakedObjectsContext;
import org.nakedobjects.nof.core.util.NakedObjectConfiguration;
import org.nakedobjects.nos.client.dnd.drawing.Text;
import org.nakedobjects.nos.client.dnd.util.Properties;


public class AwtText implements Text {
    private static final String ASCENT_ADJUST = Properties.PROPERTY_BASE + "ascent-adjust";
    private static final String FONT_PROPERTY_STEM = Properties.PROPERTY_BASE + "font.";
    private static final Logger LOG = Logger.getLogger(AwtText.class);
    private static final String SPACING_PROPERTYSTEM = Properties.PROPERTY_BASE + "spacing.";
    private boolean ascentAdjust;
    private Font font;
    private Frame fontMetricsComponent = new Frame();
    private int lineSpacing;
    private int maxCharWidth;
    private FontMetrics metrics;
    private String propertyName;

    protected AwtText(final String propertyName, final String defaultFont) {
        NakedObjectConfiguration cfg = NakedObjectsContext.getConfiguration();
        font = cfg.getFont(FONT_PROPERTY_STEM + propertyName, Font.decode(defaultFont));
        LOG.info("font " + propertyName + " loaded as " + font);

        this.propertyName = propertyName;

        if (font == null) {
            font = cfg.getFont(FONT_PROPERTY_STEM + "default", new Font("SansSerif", Font.PLAIN, 12));
        }

        metrics = fontMetricsComponent.getFontMetrics(font);

        maxCharWidth = metrics.getMaxAdvance() + 1;
        if (maxCharWidth == 0) {
            maxCharWidth = (charWidth('X') + 3);
        }

        lineSpacing = cfg.getInteger(SPACING_PROPERTYSTEM + propertyName, 0);

        ascentAdjust = cfg.getBoolean(ASCENT_ADJUST, false);

        LOG.debug("font " + propertyName + " height=" + metrics.getHeight() + ", leading=" + metrics.getLeading() + ", ascent="
                + metrics.getAscent() + ", descent=" + metrics.getDescent() + ", line spacing=" + lineSpacing);
    }

    public int charWidth(final char c) {
        return metrics.charWidth(c);
    }

    public int getAscent() {
        return metrics.getAscent() - (ascentAdjust ? metrics.getDescent() : 0);
    }

    /**
     * Returns the Font from the AWT used for drawing within the AWT.
     * 
     * @see Font
     */
    public Font getAwtFont() {
        return font;
    }

    public int getDescent() {
        return metrics.getDescent();
    }

    public int getLineHeight() {
        return metrics.getHeight() + getLineSpacing();
    }

    public int getLineSpacing() {
        return lineSpacing;
    }

    public String getName() {
        return propertyName;
    }

    public int getMidPoint() {
        return getAscent() / 2;
    }

    public int getTextHeight() {
        return metrics.getHeight() - (ascentAdjust ? metrics.getDescent() : 0);
    }
    
    public int stringHeight(String text, int maxWidth) {
        int noLines = 0;       
        StringTokenizer lines = new StringTokenizer(text, "\n\r");
        while (lines.hasMoreTokens()) {
            String line = lines.nextToken();
            StringTokenizer words = new StringTokenizer(line, " ");
            StringBuffer l = new StringBuffer();
            int width = 0;
            while (words.hasMoreTokens()) {
                String nextWord = words.nextToken();
                int wordWidth = stringWidth(nextWord);
                width += wordWidth;  
                if(width >= maxWidth) {
                    noLines++;
                    l.setLength(0);
                    width = wordWidth;
                }
                l.append(nextWord);
                l.append(" ");
                width += stringWidth(" ");
            }
            noLines ++;
        }
        return noLines * getLineHeight();
    }
    
    public int stringWidth(String text, int maxWidth) {
        int width = 0;
        StringTokenizer lines = new StringTokenizer(text, "\n\r");
        while (lines.hasMoreTokens()) {
            String line = lines.nextToken();
            StringTokenizer words = new StringTokenizer(line, " ");
            StringBuffer l = new StringBuffer();
            int lineWidth = 0;
            while (words.hasMoreTokens()) {
                String nextWord = words.nextToken();
                int wordWidth = stringWidth(nextWord);
                lineWidth += wordWidth;
                if(lineWidth >= maxWidth) {
                    return maxWidth;
                }
                if (lineWidth > width) {
                    width = lineWidth;
                }
                l.append(nextWord);
                l.append(" ");
                lineWidth += stringWidth(" ");
            }
        }
        return width;
    }


    // DKH: 20060404... yes, this will grow over time, but only used client-side
    // RCM this is only a temporary solutions to help deal with titles, TODO move the caching up to the
    // views/components that use this method
    private java.util.Hashtable stringWidthByString = new java.util.Hashtable();

    // DKH 20060404: new implementation that caches
    public int stringWidth(final String text) {
        int[] cachedStringWidth = (int[]) stringWidthByString.get(text);
        if (cachedStringWidth == null) {
            cachedStringWidth = new int[] { stringWidthInternal(text) };
            stringWidthByString.put(text, cachedStringWidth);
        }
        return cachedStringWidth[0];
    }

    // DKH 20060404: previously was stringWidth, now cached, see above.
    private int stringWidthInternal(final String text) {
        int stringWidth = metrics.stringWidth(text);
        if (stringWidth > text.length() * maxCharWidth) {
            LOG.debug("spurious width of string; calculating manually: " + stringWidth + " for " + this + ": " + text);
            /*
             * This fixes an intermittent bug in .NET where stringWidth() returns a ridiculous number is
             * returned for the width.
             * 
             * TODO don't do this when running Java
             */
            stringWidth = 0;
            for (int i = 0; i < text.length(); i++) {
                int charWidth = charWidth(text.charAt(i));
                if (charWidth > maxCharWidth) {
                    LOG.debug("spurious width of character; using max width: " + charWidth + " for " + text.charAt(i));
                    charWidth = maxCharWidth;
                }
                stringWidth += charWidth;
                LOG.debug(i + " " + stringWidth);
            }
        }
        return stringWidth;
    }

    public String toString() {
        return font.toString();
    }
}
// Copyright (c) Naked Objects Group Ltd.




© 2015 - 2025 Weber Informatics LLC | Privacy Policy