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