Revision: 623
Author: heuermh
Date: Wed Jul 29 19:55:26 2009
Log: Issue 114 ; minor API improvements to PText
http://code.google.com/p/piccolo2d/source/detail?r=623
Modified:
/piccolo2d.java/trunk/core/src/main/java/edu/umd/cs/piccolo/nodes/PText.java
/piccolo2d.java/trunk/core/src/test/java/edu/umd/cs/piccolo/nodes/PTextTest.java
=======================================
---
/piccolo2d.java/trunk/core/src/main/java/edu/umd/cs/piccolo/nodes/PText.java
Tue Jul 28 13:58:25 2009
+++
/piccolo2d.java/trunk/core/src/main/java/edu/umd/cs/piccolo/nodes/PText.java
Wed Jul 29 19:55:26 2009
@@ -46,7 +46,6 @@
/**
* <b>PText</b> is a multi-line text node. The text will flow to base on
the
* width of the node's bounds.
- * <P>
*
* @version 1.1
* @author Jesse Grosjean
@@ -75,87 +74,170 @@
public static final String PROPERTY_FONT = "font";
public static final int PROPERTY_CODE_FONT = 1 << 20;
- public static Font DEFAULT_FONT = new Font("Helvetica", Font.PLAIN,
12);
- public static double DEFAULT_GREEK_THRESHOLD = 5.5;
-
- private String text;
- private Paint textPaint;
- private Font font;
+ /**
+ * The property name that identifies a change of this node's text
paint (see
+ * {...@link #getTextPaint getTextPaint}). Both old and new value will be
set in any
+ * property change event.
+ */
+ public static final String PROPERTY_TEXT_PAINT = "text paint";
+ public static final int PROPERTY_CODE_TEXT_PAINT = 1 << 21;
+
+ /** Default font, 12 point <code>"SansSerif"</code>. Will be made
final in version 2.0. */
+ //public static final Font DEFAULT_FONT = new Font(Font.SANS_SERIF,
Font.PLAIN, 12); jdk 1.6+
+ public static Font DEFAULT_FONT = new Font("SansSerif", Font.PLAIN,
12);
+
+ /** Default greek threshold, <code>5.5d</code>. Will be made final in
version 2.0. */
+ public static double DEFAULT_GREEK_THRESHOLD = 5.5d;
+
+ /** Default horizontal alignment,
<code>Component.LEFT_ALIGNMENT</code>. */
+ public static final float DEFAULT_HORIZONTAL_ALIGNMENT =
Component.LEFT_ALIGNMENT;
+
+ /** Default text, <code>""</code>. */
+ public static final String DEFAULT_TEXT = "";
+
+ /** Default text paint, <code>Color.BLACK</code>. */
+ public static final Paint DEFAULT_TEXT_PAINT = Color.BLACK;
+
+ private static final TextLayout[] EMPTY_TEXT_LAYOUT_ARRAY = new
TextLayout[0];
+ private String text = DEFAULT_TEXT;
+ private Paint textPaint = DEFAULT_TEXT_PAINT;
+ private Font font = DEFAULT_FONT;
+ /** Will be made private in version 2.0. */
protected double greekThreshold = DEFAULT_GREEK_THRESHOLD;
- private float justification = Component.LEFT_ALIGNMENT;
+ private float horizontalAlignment = DEFAULT_HORIZONTAL_ALIGNMENT;
private boolean constrainHeightToTextHeight = true;
private boolean constrainWidthToTextWidth = true;
private transient TextLayout[] lines;
+
+ /**
+ * Create a new text node with no text (<code>""</code>).
+ */
public PText() {
super();
- setTextPaint(Color.BLACK);
- text = "";
}
- public PText(final String aText) {
+ /**
+ * Create a new text node with the specified text.
+ *
+ * @param text text for this text node
+ */
+ public PText(final String text) {
this();
- setText(aText);
+ setText(text);
+ }
+
+
+ /** @deprecated by {...@link #getHorizontalAlignment()} */
+ public float getJustification() {
+ return getHorizontalAlignment();
+ }
+
+ /** @deprecated by {...@link #setHorizontalAlignment(float)} */
+ public void setJustification(final float justification) {
+ setHorizontalAlignment(justification);
}
/**
- * Return the justificaiton of the text in the bounds.
- *
- * @return float
+ * Return the horizontal alignment for this text node. The horizontal
alignment will be one of
+ * <code>Component.LEFT_ALIGNMENT</code>,
<code>Component.CENTER_ALIGNMENT</code>,
+ * or <code>Component.RIGHT_ALIGNMENT</code>. Defaults to {...@link
#DEFAULT_HORIZONTAL_ALIGNMENT}.
+ *
+ * @return the horizontal alignment for this text node
*/
- public float getJustification() {
- return justification;
+ public float getHorizontalAlignment() {
+ return horizontalAlignment;
}
/**
- * Sets the justificaiton of the text in the bounds.
- *
- * @param just
+ * Set the horizontal alignment for this text node to
<code>horizontalAlignment</code>.
+ *
+ * @param horizontalAlignment horizontal alignment, must be one of
+ * <code>Component.LEFT_ALIGNMENT</code>,
<code>Component.CENTER_ALIGNMENT</code>,
+ * or <code>Component.RIGHT_ALIGNMENT</code>
*/
- public void setJustification(final float just) {
- justification = just;
- recomputeLayout();
+ public void setHorizontalAlignment(final float horizontalAlignment) {
+ if (!validHorizontalAlignment(horizontalAlignment)) {
+ throw new IllegalArgumentException("horizontalAlignment must
be one of Component.LEFT_ALIGNMENT, "
+ + "Component.CENTER_ALIGNMENT, or
Component.RIGHT_ALIGNMENT");
+ }
+ this.horizontalAlignment = horizontalAlignment;
}
/**
- * Get the paint used to paint this nodes text.
+ * Return true if the specified horizontal alignment is one of
<code>Component.LEFT_ALIGNMENT</code>,
+ * <code>Component.CENTER_ALIGNMENT</code>, or
<code>Component.RIGHT_ALIGNMENT</code>.
+ *
+ * @param horizontalAlignment horizontal alignment
+ * @return true if the specified horizontal alignment is one of
<code>Component.LEFT_ALIGNMENT</code>,
+ * <code>Component.CENTER_ALIGNMENT</code>, or
<code>Component.RIGHT_ALIGNMENT</code>
+ */
+ private static boolean validHorizontalAlignment(final float
horizontalAlignment) {
+ return Component.LEFT_ALIGNMENT == horizontalAlignment
+ || Component.CENTER_ALIGNMENT == horizontalAlignment
+ || Component.RIGHT_ALIGNMENT == horizontalAlignment;
+ }
+
+ /**
+ * Return the paint used to paint this node's text.
*
- * @return Paint
+ * @return the paint used to paint this node's text
*/
public Paint getTextPaint() {
return textPaint;
}
/**
- * Set the paint used to paint this node's text background.
- *
- * @param textPaint
+ * Set the paint used to paint this node's text to
<code>textPaint</code>.
+ *
+ * <p>This is a <b>bound</b> property.</p>
+ *
+ * @param textPaint text paint
*/
public void setTextPaint(final Paint textPaint) {
+ if (textPaint == this.textPaint) {
+ return;
+ }
+ final Paint oldTextPaint = this.textPaint;
this.textPaint = textPaint;
invalidatePaint();
+ firePropertyChange(PROPERTY_CODE_TEXT_PAINT, PROPERTY_TEXT_PAINT,
oldTextPaint, this.textPaint);
}
+ /**
+ * Return true if this text node should constrain its width to the
width of its text.
+ * Defaults to <code>true</code>.
+ *
+ * @return true if this text node should constrain its width to the
width of its text
+ */
public boolean isConstrainWidthToTextWidth() {
return constrainWidthToTextWidth;
}
/**
- * Controls whether this node changes its width to fit the width of its
- * text. If flag is true it does; if flag is false it doesn't
+ * Set to <code>true</code> if this text node should constrain its
width the width of its text.
+ *
+ * @param constrainWidthToTextWidth true if this text node should
constrain its width to the width of its text
*/
public void setConstrainWidthToTextWidth(final boolean
constrainWidthToTextWidth) {
this.constrainWidthToTextWidth = constrainWidthToTextWidth;
recomputeLayout();
}
+ /**
+ * Return true if this text node should constrain its height to the
height of its text.
+ * Defaults to <code>true</code>.
+ *
+ * @return true if this text node should constrain its height to the
height of its text
+ */
public boolean isConstrainHeightToTextHeight() {
return constrainHeightToTextHeight;
}
/**
- * Controls whether this node changes its height to fit the height of
its
- * text. If flag is true it does; if flag is false it doesn't
+ * Set to <code>true</code> if this text node should constrain its
height the height of its text.
+ *
+ * @param constrainHeightToTextHeight true if this text node should
constrain its height to the width of its height
*/
public void setConstrainHeightToTextHeight(final boolean
constrainHeightToTextHeight) {
this.constrainHeightToTextHeight = constrainHeightToTextHeight;
@@ -163,71 +245,86 @@
}
/**
- * Returns the current greek threshold. When the screen font size will
be
+ * Return the greek threshold in screen font size. When the screen
font size will be
* below this threshold the text is rendered as 'greek' instead of
drawing
- * the text glyphs.
+ * the text glyphs. Defaults to {...@link DEFAULT_GREEK_THRESHOLD}.
+ *
+ * @return the current greek threshold in screen font size
*/
public double getGreekThreshold() {
return greekThreshold;
}
/**
- * Sets the current greek threshold. When the screen font size will be
below
- * this threshold the text is rendered as 'greek' instead of drawing
the
+ * Set the greek threshold in screen font size to
<code>greekThreshold</code>. When the
+ * screen font size will be below this threshold the text is rendered
as 'greek' instead of drawing the
* text glyphs.
*
- * @param threshold minimum screen font size.
+ * @param greekThreshold greek threshold in screen font size
*/
- public void setGreekThreshold(final double threshold) {
- greekThreshold = threshold;
+ public void setGreekThreshold(final double greekThreshold) {
+ this.greekThreshold = greekThreshold;
invalidatePaint();
}
+ /**
+ * Return the text for this text node. Defaults to {...@link
#DEFAULT_TEXT}.
+ *
+ * @return the text for this text node
+ */
public String getText() {
return text;
}
/**
- * Set the text for this node. The text will be broken up into multiple
+ * Set the text for this node to <code>text</code>. The text will be
broken up into multiple
* lines based on the size of the text and the bounds width of this
node.
+ *
+ * <p>This is a <b>bound</b> property.</p>
+ *
+ * @param text text for this text node
*/
- public void setText(final String aText) {
- final String old = text;
- text = aText == null ? "" : aText;
+ public void setText(final String text) {
+ if (text == this.text) {
+ return;
+ }
+ final String oldText = this.text;
+ this.text = text == null ? DEFAULT_TEXT : text;
lines = null;
recomputeLayout();
invalidatePaint();
- firePropertyChange(PROPERTY_CODE_TEXT, PROPERTY_TEXT, old, text);
+ firePropertyChange(PROPERTY_CODE_TEXT, PROPERTY_TEXT, oldText,
this.text);
}
/**
- * Returns the font of this PText.
- *
- * @return the font of this PText.
+ * Return the font for this text node. Defaults to {...@link
#DEFAULT_FONT}.
+ *
+ * @return the font for this text node
*/
public Font getFont() {
- if (font == null) {
- font = DEFAULT_FONT;
- }
return font;
}
/**
- * Set the font of this PText. Note that in Piccolo if you want to
change
- * the size of a text object it's often a better idea to scale the
PText
- * node instead of changing the font size to get that same effect.
Using
- * very large font sizes can slow performance.
+ * Set the font for this text node to <code>font</code>. Note that in
Piccolo if you want to change
+ * the size of a text object it's often a better idea to scale the
PText node instead of changing the font
+ * size to get that same effect. Using very large font sizes can slow
performance.
+ *
+ * <p>This is a <b>bound</b> property.</p>
+ *
+ * @param font font for this text node
*/
- public void setFont(final Font aFont) {
- final Font old = font;
- font = aFont;
+ public void setFont(final Font font) {
+ if (font == this.font) {
+ return;
+ }
+ final Font oldFont = this.font;
+ this.font = font == null ? DEFAULT_FONT : font;
lines = null;
recomputeLayout();
invalidatePaint();
- firePropertyChange(PROPERTY_CODE_FONT, PROPERTY_FONT, old, font);
- }
-
- private static final TextLayout[] EMPTY_TEXT_LAYOUT_ARRAY = new
TextLayout[0];
+ firePropertyChange(PROPERTY_CODE_FONT, PROPERTY_FONT, oldFont,
this.font);
+ }
/**
* Compute the bounds of the text wrapped by this node. The text
layout is
@@ -291,21 +388,36 @@
}
}
- // provided in case someone needs to override the way that lines are
- // wrapped.
- protected TextLayout computeNextLayout(final LineBreakMeasurer
measurer, final float availibleWidth,
+ /**
+ * Compute the next layout using the specified line break measurer,
available width,
+ * and next line break offset.
+ *
+ * @param lineBreakMeasurer line break measurer
+ * @param availableWidth available width
+ * @param nextLineBreakOffset next line break offset
+ * @return the next layout computed using the specified line break
measurer, available width,
+ * and next line break offset
+ */
+ protected TextLayout computeNextLayout(final LineBreakMeasurer
lineBreakMeasurer, final float availableWidth,
final int nextLineBreakOffset) {
- return measurer.nextLayout(availibleWidth, nextLineBreakOffset,
false);
+ return lineBreakMeasurer.nextLayout(availableWidth,
nextLineBreakOffset, false);
}
- protected void paint(final PPaintContext paintContext) {
- super.paint(paintContext);
-
- final float screenFontSize = getFont().getSize() * (float)
paintContext.getScale();
- if (textPaint == null || screenFontSize <= greekThreshold) {
- return;
- }
-
+ /**
+ * Paint greek with the specified paint context
+ *
+ * @param paintContext paint context
+ */
+ protected void paintGreek(final PPaintContext paintContext) {
+ // empty
+ }
+
+ /**
+ * Paint text with the specified paint context.
+ *
+ * @param paintContext paint context
+ */
+ protected void paintText(final PPaintContext paintContext) {
final float x = (float) getX();
float y = (float) getY();
final float bottomY = (float) getHeight() + y;
@@ -328,12 +440,24 @@
return;
}
- final float offset = (float) (getWidth() - tl.getAdvance()) *
justification;
+ final float offset = (float) (getWidth() - tl.getAdvance()) *
horizontalAlignment;
tl.draw(g2, x + offset, y);
y += tl.getDescent() + tl.getLeading();
}
}
+
+ protected void paint(final PPaintContext paintContext) {
+ super.paint(paintContext);
+ if (textPaint == null) {
+ return;
+ }
+ final float screenFontSize = getFont().getSize() * (float)
paintContext.getScale();
+ if (screenFontSize <= greekThreshold) {
+ paintGreek(paintContext);
+ }
+ paintText(paintContext);
+ }
protected void internalUpdateBounds(final double x, final double y,
final double width, final double height) {
recomputeLayout();
=======================================
---
/piccolo2d.java/trunk/core/src/test/java/edu/umd/cs/piccolo/nodes/PTextTest.java
Tue Jul 28 12:46:54 2009
+++
/piccolo2d.java/trunk/core/src/test/java/edu/umd/cs/piccolo/nodes/PTextTest.java
Wed Jul 29 19:55:26 2009
@@ -102,6 +102,54 @@
textNode.setJustification(Component.RIGHT_ALIGNMENT);
assertEquals(Component.RIGHT_ALIGNMENT,
textNode.getJustification(), 0.000001);
}
+
+ public void testHorizontalAlignmentIsLeftByDefault() {
+ assertEquals(Component.LEFT_ALIGNMENT,
textNode.getHorizontalAlignment(), 0.000001);
+ }
+
+ public void testSetHorizontalAlignmentPersists() {
+ textNode.setHorizontalAlignment(Component.RIGHT_ALIGNMENT);
+ assertEquals(Component.RIGHT_ALIGNMENT,
textNode.getHorizontalAlignment(), 0.000001);
+ }
+
+ public void testSetHorizontalAlignmentInvalidValues() {
+ try {
+ textNode.setHorizontalAlignment(-2.0f);
+ }
+ catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ textNode.setHorizontalAlignment(2.0f);
+ }
+ catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ textNode.setHorizontalAlignment(-Float.MAX_VALUE);
+ }
+ catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ textNode.setHorizontalAlignment(Float.MAX_VALUE);
+ }
+ catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ textNode.setHorizontalAlignment(-1.00f);
+ }
+ catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ textNode.setHorizontalAlignment(1.00f);
+ }
+ catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
public void testTextPaintIsBlackByDefault() {
assertEquals(Color.BLACK, textNode.getTextPaint());
--~--~---------~--~----~------------~-------~--~----~
Piccolo2D Developers Group: http://groups.google.com/group/piccolo2d-dev?hl=en
-~----------~----~----~----~------~----~------~--~---