Added support for rendering label text with a shadow or bold text style.

Fixed MultiLineLabel.getPreferredSize() to attempt to lay out the label
before obtaining its preferred size, and to lay out a dirtied label lazily
rather than each time a setXXX() method is called.


git-svn-id: https://samskivert.googlecode.com/svn/trunk@842 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
shaper
2002-09-23 21:19:06 +00:00
parent 09f035de30
commit 0aac64cdd5
3 changed files with 178 additions and 41 deletions
@@ -1,5 +1,5 @@
//
// $Id: Label.java,v 1.18 2002/07/23 03:06:59 shaper Exp $
// $Id: Label.java,v 1.19 2002/09/23 21:19:06 shaper Exp $
//
// samskivert library - useful routines for java programs
// Copyright (C) 2002 Michael Bayne
@@ -55,7 +55,7 @@ import com.samskivert.util.Tuple;
* text at hand. It is not a component, but is intended for use by
* components and other more heavyweight entities.
*/
public class Label implements SwingConstants
public class Label implements SwingConstants, LabelStyleConstants
{
/**
* Constructs a blank label.
@@ -119,15 +119,14 @@ public class Label implements SwingConstants
}
/**
* Instructs the label to render the text outlined in the specified
* Instructs the label to render the text with the specified alternate
* color when rendering. The text itself will be rendered in whatever
* color is currently set in the graphics context, but the outline
* will always be in the specified color. Set the outline color to
* <code>null</code> to disable outlining (which is the default).
* color is currently set in the graphics context, but the outline or
* shadow (if any) will always be in the specified color.
*/
public void setOutlineColor (Color color)
public void setAlternateColor (Color color)
{
_outlineColor = color;
_alternateColor = color;
}
/**
@@ -149,6 +148,15 @@ public class Label implements SwingConstants
_align = align;
}
/**
* Sets the style of the text within the label to one of the styles
* defined in {@link LabelStyleConstants}.
*/
public void setStyle (int style)
{
_style = style;
}
/**
* Sets the target width for this label. Text will be wrapped to fit
* into this width, forcibly breaking words on character boundaries if
@@ -248,11 +256,26 @@ public class Label implements SwingConstants
layouts.add(new Tuple(layout, bounds));
}
// if we have an outline color, we need to be two pixels bigger in
// both directions to account for stealthy, hack outline mode
if (_outlineColor != null) {
switch (_style) {
case OUTLINE:
// we need to be two pixels bigger in both directions
_size.width += 2;
_size.height += 2;
break;
case SHADOW:
// we need to be one pixel bigger in both directions
_size.width += 1;
_size.height += 1;
break;
case BOLD:
// we need to be one pixel bigger horizontally
_size.width += 1;
break;
default:
break;
}
// create our layouts array
@@ -269,10 +292,10 @@ public class Label implements SwingConstants
/**
* Computes the lines of text for this label given the specified
* target width. The overall size of the computed lines is stored into
* the size parameter.
* the <code>size</code> parameter.
*
* @return an ArrayList or null if keepWordsWhole was true and
* the lines could not be layed out in the target width.
* @return an {@link ArrayList} or null if <code>keepWordsWhole</code>
* was true and the lines could not be layed out in the target width.
*/
protected ArrayList computeLines (
LineBreakMeasurer measurer, int targetWidth, Dimension size,
@@ -325,10 +348,27 @@ public class Label implements SwingConstants
gfx.setColor(_textColor);
}
// shift everything over and down by one pixel if we're outlining
if (_outlineColor != null) {
switch (_style) {
case OUTLINE:
// shift everything over and down by one pixel if we're outlining
x += 1;
y += 1;
break;
case SHADOW:
// shift everything over and up by one pixel if we're drawing
// with a shadow
x += 1;
y -= 1;
break;
case BOLD:
// shift everything over one pixel if we're drawing in bold
x -= 1;
break;
default:
break;
}
// render our text
@@ -338,10 +378,22 @@ public class Label implements SwingConstants
y += layout.getAscent();
float dx = 0, extra = (float)(_size.width - lbounds.getWidth());
// if we're outlining, we really have two pixels less space
// than we think we do
if (_outlineColor != null) {
switch (_style) {
case OUTLINE:
// if we're outlining, we really have two pixels less space
// than we think we do
extra -= 2;
break;
case SHADOW:
case BOLD:
// if we're rendering shadowed or bolded text, we really
// have one pixel less space than we think we do
extra -= 1;
break;
default:
break;
}
switch (_align) {
@@ -358,11 +410,12 @@ public class Label implements SwingConstants
// "position" part of their bounds
float rx = (float)(x + dx - lbounds.getX());
// render the outline using the hacky, but much nicer than
// using "real" outlines (via TextLayout.getOutline), method
if (_outlineColor != null) {
switch (_style) {
case OUTLINE:
// render the outline using the hacky, but much nicer than
// using "real" outlines (via TextLayout.getOutline), method
Color textColor = gfx.getColor();
gfx.setColor(_outlineColor);
gfx.setColor(_alternateColor);
layout.draw(gfx, rx - 1, y - 1);
layout.draw(gfx, rx - 1, y);
layout.draw(gfx, rx - 1, y + 1);
@@ -372,6 +425,21 @@ public class Label implements SwingConstants
layout.draw(gfx, rx + 1, y);
layout.draw(gfx, rx + 1, y + 1);
gfx.setColor(textColor);
break;
case SHADOW:
textColor = gfx.getColor();
gfx.setColor(_alternateColor);
layout.draw(gfx, rx - 1, y + 1);
gfx.setColor(textColor);
break;
case BOLD:
layout.draw(gfx, rx + 1, y);
break;
default:
break;
}
// and draw the text itself
@@ -409,6 +477,9 @@ public class Label implements SwingConstants
/** The text of the label. */
protected String _text;
/** The text style. */
protected int _style;
/** The text alignment. */
protected int _align = -1; // -1 means default according to locale
@@ -428,9 +499,9 @@ public class Label implements SwingConstants
/** Formatted text layout instances that contain each line of text. */
protected Rectangle2D[] _lbounds;
/** The color in which to outline the text when rendering or null if
* the text should not be outlined. */
protected Color _outlineColor = null;
/** The color in which to render the text outline or shadow if we're
* rendering in outline or shadow mode. */
protected Color _alternateColor = null;
/** The color in which to render the text or null if the text should
* be rendered with the graphics context color. */
@@ -0,0 +1,40 @@
//
// $Id: LabelStyleConstants.java,v 1.1 2002/09/23 21:19:06 shaper Exp $
//
// samskivert library - useful routines for java programs
// Copyright (C) 2002 Walter Korman
//
// This 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 2.1 of the License, or
// (at your option) any later version.
//
// This 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 this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.samskivert.swing;
/**
* Defines text style constants for use with the {@link Label} and {@link
* MultiLineLabel}.
*/
public interface LabelStyleConstants
{
/** Constant denoting normal text style. */
public static final int NORMAL = 0;
/** Constant denoting bold text style. */
public static final int BOLD = 1;
/** Constant denoting outline text style. */
public static final int OUTLINE = 2;
/** Constant denoting shadow text style. */
public static final int SHADOW = 3;
}
@@ -1,5 +1,5 @@
//
// $Id: MultiLineLabel.java,v 1.2 2002/09/18 01:19:26 shaper Exp $
// $Id: MultiLineLabel.java,v 1.3 2002/09/23 21:19:06 shaper Exp $
//
// samskivert library - useful routines for java programs
// Copyright (C) 2002 Walter Korman
@@ -30,12 +30,13 @@ import javax.swing.JComponent;
import javax.swing.SwingConstants;
import com.samskivert.Log;
import com.samskivert.util.StringUtil;
/**
* A Swing component that displays a {@link Label}.
*/
public class MultiLineLabel extends JComponent
implements SwingConstants
implements SwingConstants, LabelStyleConstants
{
/**
* Constructs an empty multi line label.
@@ -65,7 +66,7 @@ public class MultiLineLabel extends JComponent
}
/**
* Constructs a multi line label that displays the supplied text and
* Constructs a multi line label that displays the supplied text with
* the specified constraints and alignment. Constraints should be one
* of {@link #HORIZONTAL}, {@link #VERTICAL}, or <code>-1</code> if no
* constraints are desired.
@@ -84,6 +85,7 @@ public class MultiLineLabel extends JComponent
public void setAntiAliased (boolean antialiased)
{
_antialiased = antialiased;
_dirty = true;
}
/**
@@ -92,17 +94,16 @@ public class MultiLineLabel extends JComponent
public void setText (String text)
{
_label.setText(text);
dirty();
_dirty = true;
}
/**
* Sets the outline color used to display the label text if the text
* style is currently set to outline mode.
* Sets the alternate color used to display the label text.
*/
public void setOutlineColor (Color color)
public void setAlternateColor (Color color)
{
_label.setOutlineColor(color);
dirty();
_label.setAlternateColor(color);
_dirty = true;
}
/**
@@ -111,7 +112,7 @@ public class MultiLineLabel extends JComponent
public void setAlignment (int align)
{
_label.setAlignment(align);
dirty();
_dirty = true;
}
/**
@@ -120,7 +121,16 @@ public class MultiLineLabel extends JComponent
public void setOffAxisAlignment (int align)
{
_offalign = align;
dirty();
_dirty = true;
}
/**
* Sets the text style used to render this label.
*/
public void setStyle (int style)
{
_label.setStyle(style);
_dirty = true;
}
// documentation inherited
@@ -128,6 +138,11 @@ public class MultiLineLabel extends JComponent
{
super.paintComponent(g);
// if we're dirty, re-lay things out before painting ourselves
if (_dirty) {
layoutLabel();
}
Graphics2D gfx = (Graphics2D)g;
int align = _label.getAlignment();
int dx = 0, dy = 0;
@@ -154,11 +169,12 @@ public class MultiLineLabel extends JComponent
public void doLayout ()
{
super.doLayout();
switch (_constrain) {
case HORIZONTAL: _label.setTargetWidth(getWidth()); break;
case VERTICAL: _label.setTargetHeight(getHeight()); break;
}
dirty();
layoutLabel();
}
/**
@@ -166,7 +182,7 @@ public class MultiLineLabel extends JComponent
* accordingly like to re-layout the label, update our component's
* size, and repaint everything to suit.
*/
protected void dirty ()
protected void layoutLabel ()
{
Graphics2D gfx = (Graphics2D)getGraphics();
if (gfx != null) {
@@ -178,15 +194,22 @@ public class MultiLineLabel extends JComponent
_label.layout(gfx);
gfx.dispose();
// update our size and force a layout and repaint
// update our size and force a layout
revalidate();
repaint();
// note that we're no longer dirty
_dirty = false;
}
}
// documentation inherited
public Dimension getPreferredSize ()
{
if (_dirty) {
// attempt to lay out the label before obtaining its preferred
// dimensions
layoutLabel();
}
Dimension size = _label.getSize();
return (size == null) ? new Dimension(10, 10) : size;
}
@@ -205,4 +228,7 @@ public class MultiLineLabel extends JComponent
/** Whether to render the label with anti-aliasing. */
protected boolean _antialiased;
/** Whether this label is dirty and should be re-layed out. */
protected boolean _dirty;
}