/*
* Open Source Physics software is free software as described near the bottom of this code file.
*
* For additional information and documentation on Open Source Physics please see:
* <http://www.opensourcephysics.org/>
*/
package org.opensourcephysics.display;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import org.opensourcephysics.controls.XML;
import org.opensourcephysics.controls.XMLControl;
import org.opensourcephysics.controls.XMLLoader;
/**
* DrawableTextLine draws short Strings with subscripts and superscripts.
*
* @author Wolfgang Christian
* @version 1.0
*/
public class DrawableTextLine extends TextLine implements Drawable {
double x, y;
double theta = 0;
protected boolean pixelXY = false; // x and y are given in pixels
/**
* Constructs a DrawableTextLine with the given text and location.
*
* @param text String
* @param x double
* @param y double
*/
public DrawableTextLine(String text, double x, double y) {
super(text);
this.x = x;
this.y = y;
color = Color.BLACK;
}
/**
* Sets the pixelPosition flag.
*
* Pixels are used to position the object.
*
* @param enable boolean
*/
public void setPixelXY(boolean enable) {
this.pixelXY = enable;
}
/**
* Sets the x coordinate.
*
* @param x double
*/
public void setX(double x) {
this.x = x;
}
/**
* Sets the angle.
*
* @param theta double
*/
public void setTheta(double theta) {
this.theta = theta;
}
/**
* Gets the x coordinate.
*
* @return double
*/
public double getX() {
return x;
}
/**
* Sets the y coordinate.
*
* @param y double
*/
public void setY(double y) {
this.y = y;
}
/**
* Gets the y coordinate.
*
* @return double
*/
public double getY() {
return y;
}
/**
* Draws the TextLine.
*
* @param panel DrawingPanel
* @param g Graphics
*/
public void draw(DrawingPanel panel, Graphics g) {
if((text==null)||text.equals("")) { //$NON-NLS-1$
return;
}
Font oldFont = g.getFont();
if(this.pixelXY) {
drawWithPix(panel, g);
} else {
drawWithWorld(panel, g);
}
g.setFont(oldFont);
}
/**
* Draws the TextLine using world units for x and y.
*
* @param panel DrawingPanel
* @param g Graphics
*/
void drawWithPix(DrawingPanel panel, Graphics g) {
if(OSPRuntime.isMac()){
drawWithPixMac( panel, g);
}else{
drawWithPixWindows( panel, g);
}
}
private void drawWithPixWindows(DrawingPanel panel, Graphics g) {
if(theta!=0) {
((Graphics2D) g).transform(AffineTransform.getRotateInstance(-theta, x, y));
drawText(g, (int) x, (int) y);
((Graphics2D) g).transform(AffineTransform.getRotateInstance(theta, x, y));
} else {
drawText(g, (int) x, (int) y);
}
}
private void drawWithPixMac(DrawingPanel panel, Graphics g) {
if(theta==0){
drawWithPixWindows( panel, g);
return;
}
int w=g.getFontMetrics().stringWidth(text)+7;
int h=g.getFontMetrics().getHeight()+10;
BufferedImage image = new BufferedImage(w,h,BufferedImage.TYPE_INT_ARGB);
Graphics2D imageGraphics=image.createGraphics();
imageGraphics.setFont(g.getFont());
//imageGraphics.setColor(Color.RED); // debug
//imageGraphics.fillRect(0, 0, w, h);
imageGraphics.setColor(Color.BLACK);
drawText(imageGraphics, w/2-2, h-5);
imageGraphics.dispose();
Graphics2D g2d=(Graphics2D) g;
g2d.translate(x-h-2,y+w/2);
AffineTransform at= AffineTransform.getRotateInstance(-theta, 0, 0);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2d.drawImage(image,at, panel);
g2d.translate(-x+h+2,-y-w/2);
}
/**
* Draws the TextLine using world units for x and y.
*
* @param panel DrawingPanel
* @param g Graphics
*/
void drawWithWorld(DrawingPanel panel, Graphics g) {
if(OSPRuntime.isMac()){
drawWithWorldMac( panel, g);
}else{ // windows
drawWithWorldWindows( panel, g);
}
}
private void drawWithWorldMac(DrawingPanel panel, Graphics g) {
if(theta==0){
drawWithWorldWindows( panel, g);
return;
}
int w=g.getFontMetrics().stringWidth(text)+7;
int h=g.getFontMetrics().getHeight()+10;
BufferedImage image = new BufferedImage(w,h,BufferedImage.TYPE_INT_ARGB);
Graphics2D imageGraphics=image.createGraphics();
imageGraphics.setColor(Color.BLACK);
imageGraphics.setFont(g.getFont());
drawText(imageGraphics, w/2-2, h-5);
imageGraphics.dispose();
Graphics2D g2d=(Graphics2D) g;
Point2D pt = new Point2D.Double(x, y);
pt = panel.getPixelTransform().transform(pt, pt);
g2d.translate(pt.getX()-h-2,pt.getY()+w/2);
AffineTransform at= AffineTransform.getRotateInstance(-theta, 0, 0);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2d.drawImage(image,at, panel);
g2d.translate(-pt.getX()+h+2,-pt.getY()-w/2);
}
/**
* Draws the TextLine using world units for x and y.
*
* @param panel DrawingPanel
* @param g Graphics
*/
private void drawWithWorldWindows(DrawingPanel panel, Graphics g) {
Point2D pt = new Point2D.Double(x, y);
pt = panel.getPixelTransform().transform(pt, pt);
if(theta!=0) {
((Graphics2D) g).transform(AffineTransform.getRotateInstance(-theta, pt.getX(), pt.getY()));
drawText(g, (int) pt.getX(), (int) pt.getY());
((Graphics2D) g).transform(AffineTransform.getRotateInstance(theta, pt.getX(), pt.getY()));
} else {
drawText(g, (int) pt.getX(), (int) pt.getY());
}
}
/**
* Gets the XML object loader for this class.
* @return ObjectLoader
*/
public static XML.ObjectLoader getLoader() {
return new DrawableTextLineLoader();
}
/**
* A class to save and load InteractiveArrow in an XMLControl.
*/
protected static class DrawableTextLineLoader extends XMLLoader {
public void saveObject(XMLControl control, Object obj) {
DrawableTextLine drawableTextLine = (DrawableTextLine) obj;
control.setValue("text", drawableTextLine.getText()); //$NON-NLS-1$
control.setValue("x", drawableTextLine.x); //$NON-NLS-1$
control.setValue("y", drawableTextLine.y); //$NON-NLS-1$
control.setValue("theta", drawableTextLine.theta); //$NON-NLS-1$
control.setValue("color", drawableTextLine.color); //$NON-NLS-1$
control.setValue("pixel position", drawableTextLine.pixelXY); //$NON-NLS-1$
}
public Object createObject(XMLControl control) {
return new DrawableTextLine("", 0, 0); //$NON-NLS-1$
}
public Object loadObject(XMLControl control, Object obj) {
DrawableTextLine drawableTextLine = (DrawableTextLine) obj;
drawableTextLine.x = control.getDouble("x"); //$NON-NLS-1$
drawableTextLine.y = control.getDouble("y"); //$NON-NLS-1$
drawableTextLine.theta = control.getDouble("theta"); //$NON-NLS-1$
drawableTextLine.pixelXY = control.getBoolean("pixel position"); //$NON-NLS-1$
drawableTextLine.setText(control.getString("text")); //$NON-NLS-1$
drawableTextLine.color = (Color) control.getObject("color"); //$NON-NLS-1$
return obj;
}
}
}
/*
* Open Source Physics software is free software; you can redistribute
* it and/or modify it under the terms of the GNU General Public License (GPL) as
* published by the Free Software Foundation; either version 2 of the License,
* or(at your option) any later version.
* Code that uses any portion of the code in the org.opensourcephysics package
* or any subpackage (subdirectory) of this package must must also be be released
* under the GNU GPL license.
*
* This software 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA
* or view the license online at http://www.gnu.org/copyleft/gpl.html
*
* Copyright (c) 2007 The Open Source Physics project
* http://www.opensourcephysics.org
*/