001 /* 002 Copyright (C) 2003 Laurent Martelli <laurent@aopsys.com> 003 004 This program is free software; you can redistribute it and/or modify 005 it under the terms of the GNU Lesser General Public License as 006 published by the Free Software Foundation; either version 2 of the 007 License, or (at your option) any later version. 008 009 This program is distributed in the hope that it will be useful, 010 but WITHOUT ANY WARRANTY; without even the implied warranty of 011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 GNU Lesser General Public License for more details. 013 014 You should have received a copy of the GNU Lesser General Public 015 License along with this program; if not, write to the Free Software 016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 017 */ 018 019 package org.objectweb.jac.ide.diagrams; 020 021 import CH.ifa.draw.figures.AttributeFigure; 022 import CH.ifa.draw.figures.FontSizeHandle; 023 import CH.ifa.draw.framework.Figure; 024 import CH.ifa.draw.framework.FigureChangeEvent; 025 import CH.ifa.draw.framework.FigureChangeListener; 026 import CH.ifa.draw.standard.NullHandle; 027 import CH.ifa.draw.standard.OffsetLocator; 028 import CH.ifa.draw.standard.RelativeLocator; 029 import CH.ifa.draw.standard.TextHolder; 030 import CH.ifa.draw.util.ColorMap; 031 import java.awt.Color; 032 import java.awt.Dimension; 033 import java.awt.Font; 034 import java.awt.FontMetrics; 035 import java.awt.Graphics; 036 import java.awt.Point; 037 import java.awt.Rectangle; 038 import java.awt.Toolkit; 039 import java.util.Vector; 040 041 /** 042 * A TextFigure whose text color can be redefined with the method <code>getTextColor()</code> 043 */ 044 public class TextFigure 045 extends AttributeFigure 046 implements FigureChangeListener, TextHolder { 047 048 protected int fOriginX; 049 protected int fOriginY; 050 051 // cache of the TextFigure's size 052 transient private boolean fSizeIsDirty = true; 053 transient private int fWidth; 054 transient private int fHeight; 055 056 private String fText; 057 private Font fFont; 058 private boolean fIsReadOnly; 059 060 private Figure fObservedFigure = null; 061 private OffsetLocator fLocator = null; 062 063 private static String fgCurrentFontName = "Helvetica"; 064 private static int fgCurrentFontSize = 12; 065 private static int fgCurrentFontStyle = Font.PLAIN; 066 067 /* 068 * Serialization support. 069 */ 070 private static final long serialVersionUID = 4599820785949456124L; 071 072 public TextFigure() { 073 fOriginX = 0; 074 fOriginY = 0; 075 fFont = createCurrentFont(); 076 setAttribute("FillColor", ColorMap.color("None")); 077 fText = ""; 078 fSizeIsDirty = true; 079 } 080 081 public void moveBy(int x, int y) { 082 willChange(); 083 basicMoveBy(x, y); 084 if (fLocator != null) { 085 fLocator.moveBy(x, y); 086 } 087 changed(); 088 } 089 090 protected void basicMoveBy(int x, int y) { 091 fOriginX += x; 092 fOriginY += y; 093 } 094 095 public void basicDisplayBox(Point newOrigin, Point newCorner) { 096 fOriginX = newOrigin.x; 097 fOriginY = newOrigin.y; 098 } 099 100 public Rectangle displayBox() { 101 Dimension extent = textExtent(); 102 return new Rectangle(fOriginX, fOriginY, extent.width, extent.height); 103 } 104 105 public Rectangle textDisplayBox() { 106 return displayBox(); 107 } 108 109 /** 110 * Tests whether this figure is read only. 111 */ 112 public boolean readOnly() { 113 return fIsReadOnly; 114 } 115 116 /** 117 * Sets the read only status of the text figure. 118 */ 119 public void setReadOnly(boolean isReadOnly) { 120 fIsReadOnly = isReadOnly; 121 } 122 123 /** 124 * Gets the font. 125 */ 126 public Font getFont() { 127 return fFont; 128 } 129 130 /** 131 * Sets the font. 132 */ 133 public void setFont(Font newFont) { 134 willChange(); 135 fFont = newFont; 136 markDirty(); 137 changed(); 138 } 139 140 /** 141 * Updates the location whenever the figure changes itself. 142 */ 143 public void changed() { 144 super.changed(); 145 updateLocation(); 146 } 147 148 /** 149 * A text figure understands the "FontSize", "FontStyle", and "FontName" 150 * attributes. 151 */ 152 public Object getAttribute(String name) { 153 Font font = getFont(); 154 if (name.equals("FontSize")) { 155 return new Integer(font.getSize()); 156 } 157 if (name.equals("FontStyle")) { 158 return new Integer(font.getStyle()); 159 } 160 if (name.equals("FontName")) { 161 return font.getName(); 162 } 163 return super.getAttribute(name); 164 } 165 166 /** 167 * A text figure understands the "FontSize", "FontStyle", and "FontName" 168 * attributes. 169 */ 170 public void setAttribute(String name, Object value) { 171 Font font = getFont(); 172 if (name.equals("FontSize")) { 173 Integer s = (Integer)value; 174 setFont(new Font(font.getName(), font.getStyle(), s.intValue()) ); 175 } 176 else if (name.equals("FontStyle")) { 177 Integer s = (Integer)value; 178 int style = font.getStyle(); 179 if (s.intValue() == Font.PLAIN) { 180 style = Font.PLAIN; 181 } 182 else { 183 style = style ^ s.intValue(); 184 } 185 setFont(new Font(font.getName(), style, font.getSize()) ); 186 } 187 else if (name.equals("FontName")) { 188 String n = (String)value; 189 setFont(new Font(n, font.getStyle(), font.getSize()) ); 190 } 191 else { 192 super.setAttribute(name, value); 193 } 194 } 195 196 /** 197 * Gets the text shown by the text figure. 198 */ 199 public String getText() { 200 return fText; 201 } 202 203 /** 204 * Sets the text shown by the text figure. 205 */ 206 public void setText(String newText) { 207 if (!newText.equals(fText)) { 208 willChange(); 209 fText = newText; 210 markDirty(); 211 changed(); 212 } 213 } 214 215 /** 216 * Tests whether the figure accepts typing. 217 */ 218 public boolean acceptsTyping() { 219 return !fIsReadOnly; 220 } 221 222 public void drawBackground(Graphics g) { 223 Rectangle r = displayBox(); 224 g.fillRect(r.x, r.y, r.width, r.height); 225 } 226 227 public void drawFrame(Graphics g) { 228 g.setFont(fFont); 229 g.setColor(getTextColor()); 230 FontMetrics metrics = g.getFontMetrics(fFont); 231 g.drawString(fText, fOriginX, fOriginY + metrics.getAscent()); 232 } 233 234 protected Color getTextColor() { 235 return (Color)getAttribute("TextColor"); 236 } 237 238 private Dimension textExtent() { 239 if (!fSizeIsDirty) { 240 return new Dimension(fWidth, fHeight); 241 } 242 FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(fFont); 243 fWidth = metrics.stringWidth(fText); 244 fHeight = metrics.getHeight(); 245 fSizeIsDirty = false; 246 return new Dimension(metrics.stringWidth(fText), metrics.getHeight()); 247 } 248 249 private void markDirty() { 250 fSizeIsDirty = true; 251 } 252 253 /** 254 * Gets the number of columns to be overlaid when the figure is edited. 255 */ 256 public int overlayColumns() { 257 int length = getText().length(); 258 int columns = 20; 259 if (length != 0) { 260 columns = getText().length()+ 3; 261 } 262 return columns; 263 } 264 265 public Vector handles() { 266 Vector handles = new Vector(); 267 handles.addElement(new NullHandle(this, RelativeLocator.northWest())); 268 handles.addElement(new NullHandle(this, RelativeLocator.northEast())); 269 handles.addElement(new NullHandle(this, RelativeLocator.southEast())); 270 handles.addElement(new FontSizeHandle(this, RelativeLocator.southWest())); 271 return handles; 272 } 273 274 public void connect(Figure figure) { 275 if (fObservedFigure != null) { 276 fObservedFigure.removeFigureChangeListener(this); 277 } 278 279 fObservedFigure = figure; 280 fLocator = new OffsetLocator(figure.connectedTextLocator(this)); 281 fObservedFigure.addFigureChangeListener(this); 282 updateLocation(); 283 } 284 285 public void figureChanged(FigureChangeEvent e) { 286 updateLocation(); 287 } 288 289 public void figureRemoved(FigureChangeEvent e) { 290 if (listener() != null) { 291 listener().figureRequestRemove(new FigureChangeEvent(this)); 292 } 293 } 294 295 public void figureRequestRemove(FigureChangeEvent e) {} 296 public void figureInvalidated(FigureChangeEvent e) {} 297 public void figureRequestUpdate(FigureChangeEvent e) {} 298 299 /** 300 * Updates the location relative to the connected figure. 301 * The TextFigure is centered around the located point. 302 */ 303 protected void updateLocation() { 304 if (fLocator != null) { 305 Point p = fLocator.locate(fObservedFigure,this); 306 307 p.x -= size().width/2 + fOriginX; 308 p.y -= size().height/2 + fOriginY; 309 if (p.x != 0 || p.y != 0) { 310 willChange(); 311 basicMoveBy(p.x, p.y); 312 changed(); 313 } 314 } 315 } 316 317 public void release() { 318 super.release(); 319 disconnect(fObservedFigure); 320 fObservedFigure = null; 321 } 322 323 /** 324 * Disconnects a text holder from a connect figure. 325 */ 326 public void disconnect(Figure disconnectFigure) { 327 if (disconnectFigure != null) { 328 disconnectFigure.removeFigureChangeListener(this); 329 } 330 fLocator = null; 331 } 332 333 334 /** 335 * Creates the current font to be used for new text figures. 336 */ 337 static public Font createCurrentFont() { 338 return new Font(fgCurrentFontName, fgCurrentFontStyle, fgCurrentFontSize); 339 } 340 341 /** 342 * Sets the current font name 343 */ 344 static public void setCurrentFontName(String name) { 345 fgCurrentFontName = name; 346 } 347 348 /** 349 * Sets the current font size. 350 */ 351 static public void setCurrentFontSize(int size) { 352 fgCurrentFontSize = size; 353 } 354 355 /** 356 * Sets the current font style. 357 */ 358 static public void setCurrentFontStyle(int style) { 359 fgCurrentFontStyle = style; 360 } 361 }