001: package com.xoetrope.swing;
002:
003: import java.awt.Color;
004: import java.awt.Font;
005: import java.awt.FontMetrics;
006: import java.awt.Graphics2D;
007: import java.awt.font.FontRenderContext;
008: import java.awt.font.LineBreakMeasurer;
009: import java.awt.font.TextLayout;
010: import java.awt.geom.AffineTransform;
011: import java.awt.geom.Area;
012: import java.awt.geom.Rectangle2D;
013: import java.text.AttributedString;
014: import java.text.BreakIterator;
015: import net.xoetrope.xui.XAttributedComponent;
016:
017: /**
018: * Display text at a user defined angle
019: *
020: * <p> Copyright (c) Xoetrope Ltd., 2001-2006, This software is licensed under
021: * the GNU Public License (GPL), please see license.txt for more details. If
022: * you make commercial use of this software you must purchase a commercial
023: * license from Xoetrope.</p>
024: * <p> $Revision: 1.2 $</p>
025: */
026: public class XReflectedText extends XFlowedTextComponent implements
027: XAttributedComponent {
028: /** The shear factor */
029: protected double shear;
030:
031: /**
032: * Create a new XReflectedTExt component
033: */
034: public XReflectedText() {
035: shear = 0;
036: }
037:
038: /**
039: * Sets the degree of shear of the control's text.
040: * The range is 0 to 3600.
041: * @param value the new shear factor
042: */
043: public void setShear(int value) {
044: shear = value;
045: repaint();
046: }
047:
048: /**
049: * Gets the degree of shear of the control's text.
050: * The range is 0 to 3600.
051: * @return the new shear factor
052: */
053: public int getShear() {
054: return (int) shear;
055: }
056:
057: /**
058: * Set one or more attributes of the component. Currently this handles the
059: * attributes
060: * <OL>
061: * <LI>shear, value=the amount of shear, 100 approx = 45 degrees</LI>
062: * </OL>
063: * @param attribName the attribute name
064: * @param attribValue the attribute value
065: * @return 0 for success, non zero otherwise
066: */
067: public int setAttribute(String attribName, Object attribValue) {
068: if (attribName.equalsIgnoreCase("shear"))
069: shear = new Integer((String) attribValue).intValue();
070:
071: return super .setAttribute(attribName, attribValue);
072: }
073:
074: /**
075: * Render a text that wraps within the client area
076: * @param g2 the graphics context
077: * @param localCopy the string to render
078: * @param currentPos the current starting y position
079: * @param y the y offset into the client area
080: * @param columns the column areas
081: * @return the latest y position
082: */
083: protected double wrapString(Graphics2D g2, String localCopy,
084: double currentPos, double y, Area[] columns) {
085: if ((localCopy.length() <= 0) || (currentPos > 0.0))
086: return y;
087:
088: currentPos = 1000;
089: AffineTransform oldTransform = g2.getTransform();
090: TextLayout layout;
091: AffineTransform atReflected = AffineTransform.getScaleInstance(
092: 1, -1);
093: if (shear > 0)
094: atReflected.shear(-shear / 100.0, 0.0);
095: Font plainFont = getFont();
096: Font reflectedFont = plainFont.deriveFont(atReflected);
097: FontMetrics fm = g2.getFontMetrics(plainFont);
098: FontRenderContext frc = g2.getFontRenderContext();
099: Color color = getForeground();
100: Color altColor = new Color(color.getRed(), color.getGreen(),
101: color.getBlue(), 128);
102:
103: for (int i = 0; i < 2; i++) {
104: int[] lengths = new int[1];
105: g2.setColor(i == 0 ? color : altColor);
106: AttributedString as = getAttributedString(localCopy,
107: i == 0 ? plainFont : reflectedFont, lengths);
108: LineBreakMeasurer measurer = new LineBreakMeasurer(as
109: .getIterator(), BreakIterator.getWordInstance(),
110: frc);
111: int len = lengths[0];
112: try {
113: double colX = columns[0].getBounds().getX();
114: // Take a big horizontal stripe to allow for the rotation and translation
115: Rectangle2D.Double rLine = new Rectangle2D.Double(0.0,
116: oY + ascent, oW, ascent);
117: Area aArea = new Area(rLine);
118: aArea.intersect(flowArea);
119:
120: Rectangle2D r = aArea.getBounds2D();
121: double w = r.getWidth();
122: if (w > 0.0)
123: layout = measurer.nextLayout((float) (w));
124: else
125: return oH;
126:
127: layout.draw(g2, 0.0F, (float) (ascent));
128: } catch (Exception ex1) {
129: ex1.printStackTrace();
130: }
131: }
132: return oH;
133: }
134: }
|