Text.java
001 /**
002  *
003  * All content copyright (c) 2003-2008 Terracotta, Inc.,
004  * except as may otherwise be noted in a separate copyright notice.
005  * All rights reserved.
006  *
007  */
008 package demo.sharededitor.models;
009 
010 import java.awt.Color;
011 import java.awt.Font;
012 import java.awt.Graphics2D;
013 import java.awt.Image;
014 import java.awt.Rectangle;
015 import java.awt.Shape;
016 import java.awt.font.FontRenderContext;
017 import java.awt.font.TextAttribute;
018 import java.awt.font.TextLayout;
019 import java.awt.geom.AffineTransform;
020 import java.awt.geom.Rectangle2D;
021 import java.text.AttributedCharacterIterator;
022 import java.text.AttributedString;
023 
024 import demo.sharededitor.ui.Fontable;
025 import demo.sharededitor.ui.Texturable;
026 
027 /**
028  *  Description of the Class
029  *
030  *@author    Terracotta, Inc.
031  */
032 public class Text extends BaseObject implements Fontable, Texturable {
033    private Shape shape = null;
034 
035    private Shape[] anchors = new Shape[0];
036 
037    private String fontName;
038 
039    private int fontSize;
040 
041    private String text;
042 
043    private int x, y;
044 
045    private boolean isInverted;
046 
047    public Text() {
048       this.isInverted = false;
049       this.text = "";
050    }
051 
052    public synchronized void setTexture(Image image) {
053       super.setTexture(image);
054       notifyListeners(this);
055    }
056 
057    public synchronized void setFontInfo(String name, int size, String text) {
058       this.text = text;
059       this.fontName = name;
060       this.fontSize = size;
061       notifyListeners(this);
062    }
063 
064    public synchronized void setFontName(String name) {
065       this.fontName = name;
066       notifyListeners(this);
067    }
068 
069    public synchronized void setFontSize(int size) {
070       this.fontSize = size;
071       notifyListeners(this);
072    }
073 
074    public synchronized void setText(String text) {
075       this.text = text;
076       notifyListeners(this);
077    }
078 
079    public boolean isAt(int x, int y) {
080       if (shape == null) {
081          return false;
082       }
083 
084       Shape bounds = new Rectangle2D.Double(shape.getBounds().x - 5,
085             shape.getBounds().y - 5, shape.getBounds().width + 5,
086             shape.getBounds().height + 5);
087       return bounds.contains(x, y);
088    }
089 
090    public String getText() {
091       return this.text;
092    }
093 
094    public synchronized void move(int dx, int dy) {
095       this.x += dx;
096       this.y += dy;
097       notifyListeners(this);
098    }
099 
100    public synchronized void resize(int x, int y) {
101       // we purposely don't allow the resizing operation for Text objects
102    }
103 
104    public synchronized void clearTexture() {
105       super.clearTexture();
106    }
107 
108    public synchronized void appendToText(char c) {
109       if (!this.isInverted) {
110          this.text += c;
111       }
112       else {
113          this.text = c + "";
114          this.isInverted = false;
115       }
116       notifyListeners(this);
117    }
118 
119    public void draw(Graphics2D g, boolean showAnchors) {
120       renderText(g.getFontRenderContext(), showAnchors);
121       super.draw(g, showAnchors);
122       if (showAnchors) {
123          Rectangle bounds = shape.getBounds();
124          Shape border = new Rectangle2D.Double(bounds.x - 5, bounds.y - 5,
125                bounds.width + 5, bounds.height + 5);
126          if (this.isInverted) {
127             g.setXORMode(Color.LIGHT_GRAY);
128             g.fillRect(bounds.x - 5, bounds.y - 5, bounds.width + 5,
129                   bounds.height + 5);
130             g.setPaintMode();
131          }
132          g.setColor(Color.LIGHT_GRAY);
133          g.draw(border);
134       }
135    }
136 
137    public synchronized void selectAction(boolean flag) {
138       if (!this.isInverted) {
139          return;
140       }
141       this.isInverted = false;
142    }
143 
144    public synchronized void alternateSelectAction(boolean flag) {
145       if (this.isInverted) {
146          return;
147       }
148       this.isInverted = true;
149    }
150 
151    protected Shape getShape() {
152       return shape;
153    }
154 
155    protected Shape[] getAnchors() {
156       return anchors;
157    }
158 
159    private synchronized void renderText(FontRenderContext frc,
160          boolean showCursor) {
161       String text = this.text;
162       if (showCursor || (text.length() == 0)) {
163          if (text.length() 0) {
164             text = this.isInverted ? text : text + "|";
165          }
166          else {
167             text = "_";
168          }
169       }
170 
171       AttributedString as = new AttributedString(text);
172       as.addAttribute(TextAttribute.FONT, new Font(this.fontName, Font.PLAIN,
173             this.fontSize));
174       AttributedCharacterIterator aci = as.getIterator();
175       TextLayout tl = new TextLayout(aci, frc);
176       this.shape = tl.getOutline(AffineTransform.getTranslateInstance(x, y));
177    }
178 }