tags:

views:

209

answers:

2

I render text with a custom table cell renderer and I want to trim the text drawn if it would exceed the current cell width, switching to a "This text is to long..." kind of representation, where the three dots at the end never leaves the bounding box. My current algorithm is the following:

FontMetrics fm0 = g2.getFontMetrics(); 
int h = fm0.getHeight();
int ellw = fm0.stringWidth("\u2026");
int titleWidth = fm0.stringWidth(se.title);
if (titleWidth > getWidth()) {
    for (int i = se.title.length() - 1; i > 0; i--) {
        String tstr = se.title.substring(0, i);
        int tstrw = fm0.stringWidth(tstr);
        if (tstrw + ellw < getWidth()) {
            g2.drawString(tstr, 2, h);
            g2.drawString("\u2026", 2 + tstrw, h);
            break;
        }
    }
} else {
    g2.drawString(se.title, 2, h);
}

Is there a better way of determining how many characters should I drawString() before switching to the ... (u2026) character?

A: 

I can't think of another way to achieve the desired effect, but you should be able to replace the 2 drawString() calls with one. It's been a while since I've written Java but I think the following should work.

BTW, I changed the variable names so I can read the code. :p

FontMetrics metrics = g2.getFontMetrics(); 
int fontHeight = metrics.getHeight();
int titleWidth = metrics.stringWidth(se.title);

if (titleWidth > getWidth()) {
    String titleString;

    for (int i = se.title.length() - 1; i > 0; i --) {
        titleString = se.title.substring(0, i) + "\u2026";
        titleWidth = metrics.stringWidth(titleString);

        if (titleWidth < getWidth()) {
            g2.drawString(titleString, 2, fontHeight);

            break;
        }
    }
} else {
    g2.drawString(se.title, 2, fontHeight);
}
Ian Kemp
A: 

This is the default behaviour of the default renderer for a table so I'm not sure I understand the reason for doing this.

But I've created a renderer for dots on the left ("... text is too long") which shows a more complete way to do what you want since it takes into account a possible Border on the renderer and the intercell spacing of the renderer. Check out the LeftDotRenderer.

camickr
Thanks. The reason is that the first line (a title) is drawn in 16pt text and the second and third line (some details) are drawn as normal text within the cell. The LeftDotRenderer differs mainly in that it counts the size per character with instead of the entire string width. I will test it.
kd304