001: /***********************************************************************************************
002: * Copyright 2002 (C) Nathaniel G. Auvil. All Rights Reserved.
003: *
004: * Redistribution and use of this software and associated documentation ("Software"), with or
005: * without modification, are permitted provided that the following conditions are met:
006: *
007: * 1. Redistributions of source code must retain copyright statements and notices.
008: * Redistributions must also contain a copy of this document.
009: *
010: * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
011: * conditions and the following disclaimer in the documentation and/or other materials
012: * provided with the distribution.
013: *
014: * 3. The name "jCharts" or "Nathaniel G. Auvil" must not be used to endorse or promote
015: * products derived from this Software without prior written permission of Nathaniel G.
016: * Auvil. For written permission, please contact nathaniel_auvil@users.sourceforge.net
017: *
018: * 4. Products derived from this Software may not be called "jCharts" nor may "jCharts" appear
019: * in their names without prior written permission of Nathaniel G. Auvil. jCharts is a
020: * registered trademark of Nathaniel G. Auvil.
021: *
022: * 5. Due credit should be given to the jCharts Project (http://jcharts.sourceforge.net/).
023: *
024: * THIS SOFTWARE IS PROVIDED BY Nathaniel G. Auvil AND CONTRIBUTORS ``AS IS'' AND ANY
025: * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
026: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
027: * jCharts OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
028: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
029: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
030: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,STRICT LIABILITY, OR TORT
031: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
032: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
033: ************************************************************************************************/package org.krysalis.jcharts.chartText;
034:
035: import org.krysalis.jcharts.test.HTMLGenerator;
036: import org.krysalis.jcharts.test.HTMLTestable;
037:
038: import java.awt.*;
039: import java.awt.font.FontRenderContext;
040: import java.awt.font.TextLayout;
041: import java.awt.geom.Rectangle2D;
042: import java.io.Serializable;
043: import java.lang.reflect.Field;
044: import java.util.Hashtable;
045:
046: /*************************************************************************************
047: *
048: * @author John Thomsen, Nathaniel Auvil
049: * @version $Id: TextTag.java,v 1.2 2004/05/31 16:27:21 nathaniel_auvil Exp $
050: ************************************************************************************/
051: public class TextTag implements HTMLTestable, Serializable {
052: //---Strangely, we don't need to store the text itself. (yet)
053:
054: private float xPosition = 0;
055: private float yPosition = 0;
056:
057: private TextLayout textLayout = null;
058: private Hashtable attributes = null;
059:
060: private boolean isHidden = false;
061:
062: //---derived values
063:
064: private float width = 0;
065: private float height = 0;
066: private float fontAscent = 0;
067: private float fontDescent = 0;
068:
069: private boolean isDerived = false;
070: private Font derivedFont = null;
071:
072: private String text; //for toString();
073: private Font font; //for toString();
074:
075: /*********************************************************************************************
076: * Default constructor - for untransformed fonts.
077: *
078: **********************************************************************************************/
079: public TextTag(String text, Font baseFont,
080: FontRenderContext fontRenderContext) {
081: this (text, baseFont, null, fontRenderContext);
082: }
083:
084: /*********************************************************************************************
085: * Constructor when using transformed (derived) fonts
086: *
087: * The need for this arises because the java metrics classes return either 0 or very strange
088: * values for the width and height of a string (TextLayout, LineMetrics, etc..) when
089: * the font is derived
090: *
091: * @param text
092: * @param baseFont is the original (untransformed) font.
093: * @param derivedFont is the transformed font
094: * @param fontRenderContext
095: **********************************************************************************************/
096: public TextTag(String text, Font baseFont, Font derivedFont,
097: FontRenderContext fontRenderContext) {
098: this .textLayout = new TextLayout(text, baseFont,
099: fontRenderContext);
100:
101: this .isDerived = (derivedFont != null);
102: this .derivedFont = derivedFont;
103:
104: //---Dimensions
105: this .width = this .textLayout.getAdvance();
106: this .height = this .textLayout.getAscent()
107: + this .textLayout.getDescent();
108:
109: //---need this to offset font rendering, as rendering is at the baseline not bottom or top,
110: this .fontAscent = this .textLayout.getAscent();
111: this .fontDescent = this .textLayout.getDescent();
112:
113: this .font = (this .isDerived) ? derivedFont : baseFont;
114: this .text = text;
115:
116: // System.out.println(">"+text+" Bounds:"+textLayout.getBounds() );
117: // System.out.println(" >Ascent "+textLayout.getAscent()+" Descent:"+textLayout.getDescent() );
118: // System.out.println(" >isVertical "+textLayout.isVertical());
119: //
120: // LineMetrics lm = font.getLineMetrics(text, fontRenderContext);
121:
122: // System.out.println(" Metrics:" + lm.getHeight() + " " + lm.getAscent() + lm.getDescent());
123:
124: }
125:
126: /********************************************************************************************
127: *
128: ********************************************************************************************/
129: public float getWidth() {
130: return this .width;
131: }
132:
133: /********************************************************************************************
134: *
135: ********************************************************************************************/
136: public float getHeight() {
137: return this .height;
138: }
139:
140: /********************************************************************************************
141: *
142: ********************************************************************************************/
143: public float getFontAscent() {
144: return this .fontAscent;
145: }
146:
147: /********************************************************************************************
148: *
149: ********************************************************************************************/
150: public float getFontDescent() {
151: return this .fontDescent;
152: }
153:
154: /********************************************************************************************
155: *
156: ********************************************************************************************/
157: public void setPosition(float x, float y) {
158: this .xPosition = x;
159: this .yPosition = y;
160:
161: //System.out.println("TEXT:==>"+text+"< at "+x+","+y);
162: }
163:
164: /********************************************************************************************
165: *
166: ********************************************************************************************/
167: public void setXPosition(float x) {
168: this .xPosition = x;
169: }
170:
171: /********************************************************************************************
172: *
173: ********************************************************************************************/
174: public void setYPosition(float y) {
175: this .yPosition = y;
176: }
177:
178: /********************************************************************************************
179: *
180: ********************************************************************************************/
181: public float getXPosition() {
182: return this .xPosition;
183: }
184:
185: /********************************************************************************************
186: *
187: ********************************************************************************************/
188: public float getYPosition() {
189: return this .yPosition;
190: }
191:
192: /********************************************************************************************
193: *
194: ********************************************************************************************/
195: public float getRightSide() {
196: return this .xPosition + this .width;
197: }
198:
199: /********************************************************************************************
200: *
201: ********************************************************************************************/
202: public float getBottomSide() {
203: return this .yPosition + this .height;
204: }
205:
206: /********************************************************************************************
207: *
208: ********************************************************************************************/
209: public Rectangle2D.Float getRectangle() {
210: return new Rectangle2D.Float(this .xPosition, this .yPosition,
211: this .width, this .height);
212: }
213:
214: /********************************************************************************************
215: *
216: ********************************************************************************************/
217: public void setHidden(boolean b) {
218: this .isHidden = b;
219: }
220:
221: /********************************************************************************************
222: *
223: ********************************************************************************************/
224: public boolean getHidden() {
225: return this .isHidden;
226: }
227:
228: public String getText() {
229: return text;
230: }
231:
232: /********************************************************************************************
233: *
234: ********************************************************************************************/
235: public void addAttribute(String name, Object o) {
236: if (attributes == null) {
237: attributes = new Hashtable();
238: }
239:
240: attributes.put(name, o);
241: }
242:
243: /********************************************************************************************
244: *
245: ********************************************************************************************/
246: public Object getAttribute(String name) {
247: if (attributes == null) {
248: return null;
249: }
250:
251: return attributes.get(name);
252: }
253:
254: /**********************************************************************************************
255: * Renders the text, at the position - renders from the top (instead of baseline)
256: *
257: * @param g2d
258: * @param fontColor
259: **********************************************************************************************/
260: public void render(Graphics2D g2d, Paint fontColor) {
261: if (fontColor != null) {
262: g2d.setPaint(fontColor);
263: }
264:
265: if (this .isHidden == false) {
266: if (isDerived) {
267: g2d.setFont(this .derivedFont);
268: g2d.drawString(this .text, this .xPosition,
269: this .yPosition);
270: } else {
271: textLayout.draw(g2d, this .xPosition, this .yPosition);
272: }
273:
274: //---Debug comparison code.
275: //g2d.setFont( this.font );
276: //g2d.drawString(this.text, this.xPosition, this.yPosition);
277:
278: /* Interesting...
279: System.out.println("Ascent:"+this.fontAscent);
280: System.out.println("Descent:"+this.fontDescent);
281: System.out.println("Height:"+this.heightNeeded);
282: System.out.println("Width:"+this.widthNeeded);
283: */
284: }
285: }
286:
287: /**********************************************************************************************
288: * Renders the text, at the position - renders from the top (instead of baseline)
289: *
290: * @param g2d
291:
292: **********************************************************************************************/
293: public void render(Graphics2D g2d, float x, float y) {
294: textLayout.draw(g2d, x, y);
295:
296: /*
297:
298: if( fontColor != null )
299: {
300: g2d.setPaint( fontColor );
301: }
302:
303: if( this.isHidden == false )
304: {
305: if( isDerived )
306: {
307: g2d.drawString( this.text, x, y );
308: }
309: else
310: {
311: textLayout.draw( g2d, x, y );
312: }
313: }
314: */
315: }
316:
317: /*********************************************************************************************
318: * Enables the testing routines to display the contents of this Object.
319: *
320: * @param htmlGenerator
321: **********************************************************************************************/
322: public void toHTML(HTMLGenerator htmlGenerator) {
323: htmlGenerator.propertiesTableStart(this .getClass().getName());
324:
325: Field[] fields = this .getClass().getDeclaredFields();
326: for (int i = 0; i < fields.length; i++) {
327: try {
328: htmlGenerator.addField(fields[i].getName(), fields[i]
329: .get(this ));
330: } catch (IllegalAccessException illegalAccessException) {
331: illegalAccessException.printStackTrace();
332: }
333: }
334:
335: htmlGenerator.propertiesTableEnd();
336: }
337:
338: /********************************************************************************************
339: *
340: * @return String
341: ********************************************************************************************/
342: public String toString()
343: {
344: String str = "TextTag: '" + this.text + "',x=" + this.xPosition + ",y=" + this.yPosition;
345:
346: str += "width=" + this.width + ",height=" + this.height;
347: str += ",font=" + this.font.getName() + "," + this.font.getSize();
348:
349: if( attributes != null && attributes.size() > 0 )
350: {
351: java.util.Enumeration enum = attributes.keys();
352: str += "\nAttributes:";
353: while( enum.hasMoreElements() )
354: {
355: Object ob = enum.nextElement();
356: str += " [" + ob.toString() + "]=[" + attributes.get( ob ).toString() + "]\n";
357: }
358: }
359:
360: return str;
361: }
362: }
|