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.BasicStroke;
009 import java.awt.Color;
010 import java.awt.Graphics2D;
011 import java.awt.Image;
012 import java.awt.Rectangle;
013 import java.awt.Shape;
014 import java.awt.Stroke;
015 import java.io.ByteArrayInputStream;
016 import java.io.ByteArrayOutputStream;
017 import java.io.ObjectInputStream;
018 import java.io.ObjectOutputStream;
019 import java.util.ArrayList;
020 import java.util.Collections;
021 import java.util.Iterator;
022 import java.util.List;
023
024 import javax.swing.ImageIcon;
025
026 import demo.sharededitor.events.ListListener;
027 import demo.sharededitor.ui.FillStyleConsts;
028 import demo.sharededitor.ui.Texturable;
029
030 public abstract class BaseObject implements FillStyleConsts {
031 private List listeners;
032
033 public void addListener(ListListener listListener) {
034 if (listeners == null) {
035 listeners = Collections.synchronizedList(new ArrayList());
036 }
037
038 if (!listeners.contains(listListener))
039 listeners.add(listListener);
040 }
041
042 public void removeListener(ListListener listListener) {
043 if ((listeners != null) && (listeners.contains(listListener))) {
044 listeners.remove(listListener);
045 }
046 }
047
048 protected void notifyListeners(Object obj) {
049 if (listeners == null)
050 return;
051
052 for (Iterator i = listeners.iterator(); i.hasNext();) {
053 ListListener listListener = (ListListener) i.next();
054 listListener.changed(this, this);
055 }
056 }
057
058 private boolean isReady() {
059 return (getShape() != null);
060 }
061
062 public boolean isAt(int x, int y) {
063 if (!isReady()) {
064 return false;
065 }
066
067 Shape shape = getShape();
068 if (shape.contains(x, y)) {
069 return true;
070 }
071
072 Shape[] anchors = getAnchors();
073 for (int i = 0; i < anchors.length; i++) {
074 if (anchors[i].contains(x, y))
075 return true;
076 }
077 return false;
078 }
079
080 private int grabbedAnchor;
081
082 public synchronized void setGrabbedAnchorAt(int x, int y) {
083 Shape[] anchors = getAnchors();
084 for (int i = 0; i < anchors.length; i++) {
085 if (anchors[i].contains(x, y)) {
086 grabbedAnchor = i;
087 return;
088 }
089 }
090 grabbedAnchor = -1;
091 }
092
093 protected int grabbedAnchor() {
094 return grabbedAnchor;
095 }
096
097 public boolean isAnchorGrabbed() {
098 return (grabbedAnchor >= 0) && (grabbedAnchor < getAnchors().length);
099 }
100
101 public abstract void resize(int x, int y);
102
103 public abstract void move(int dx, int dy);
104
105 protected Shape[] getAnchors() {
106 return new Shape[0];
107 }
108
109 protected abstract Shape getShape();
110
111 public void draw(Graphics2D g, boolean showAnchors) {
112 Shape shape = getShape();
113 Rectangle bounds = shape.getBounds();
114 g.setColor(this.background);
115
116 if (FILLSTYLE_SOLID == this.fillstyle) {
117 g.fill(shape);
118 }
119
120 if ((FILLSTYLE_TEXTURED == this.fillstyle)
121 && (this instanceof Texturable) && isTextured()
122 && (bounds.width > 0) && (bounds.height > 0)) {
123 g.drawImage(getTexture(), bounds.x, bounds.y, bounds.width,
124 bounds.height, null);
125 }
126
127 g.setStroke(this.stroke);
128 g.setColor(this.foreground);
129 g.draw(shape);
130
131 if (showAnchors) {
132 Shape[] anchors = getAnchors();
133 for (int i = 0; i < anchors.length; i++) {
134 g.fill(anchors[i]);
135 }
136 }
137 }
138
139 private int fillstyle;
140
141 public synchronized void setFillStyle(int fillstyle) {
142 this.fillstyle = fillstyle;
143 notifyListeners(this);
144 }
145
146 private Color foreground;
147
148 public synchronized void setForeground(Color color) {
149 this.foreground = color;
150 notifyListeners(this);
151 }
152
153 private Color background;
154
155 public synchronized void setBackground(Color color) {
156 this.background = color;
157 notifyListeners(this);
158 }
159
160 private Stroke stroke = new BasicStroke();
161
162 public synchronized void setStroke(Stroke stroke) {
163 this.stroke = stroke;
164 notifyListeners(this);
165 }
166
167 public static final BaseObject createObject(String name) {
168 try {
169 Class klass = Class.forName("demo.sharededitor.models." + name);
170 return (BaseObject) klass.newInstance();
171 } catch (Exception ex) {
172 throw new InternalError(ex.getMessage());
173 }
174 }
175
176 private byte[] texture = null;
177 private transient Image textureImage = null;
178
179 protected void clearTexture() {
180 this.texture = null;
181 }
182
183 protected void setTexture(Image image) {
184 try {
185 ByteArrayOutputStream bos = new ByteArrayOutputStream();
186 ObjectOutputStream oos = new ObjectOutputStream(bos);
187 int width = image.getWidth(null);
188 if (width > 640) {
189 width = 640;
190 }
191
192 int height = image.getHeight(null);
193 if (height > 480) {
194 height = 480;
195 }
196
197 Image scaledImage = image.getScaledInstance(width, height,
198 Image.SCALE_FAST);
199 oos.writeObject(new ImageIcon(scaledImage));
200
201 texture = bos.toByteArray();
202 textureImage = null;
203 } catch (Exception ex) {
204 throw new InternalError("Unable to convert Image to byte[]");
205 }
206 }
207
208 protected Image getTexture() {
209 try {
210 if (textureImage == null) {
211 ByteArrayInputStream bis = new ByteArrayInputStream(texture);
212 ObjectInputStream ois = new ObjectInputStream(bis);
213 ImageIcon image = (ImageIcon) ois.readObject();
214 textureImage = image.getImage();
215 }
216 return textureImage;
217 } catch (Exception ex) {
218 throw new InternalError("Unable to convert byte[] to Image");
219 }
220 }
221
222 protected boolean isTextured() {
223 return (texture != null);
224 }
225
226 public boolean isTransient() {
227 return false;
228 }
229
230 public synchronized void selectAction(boolean flag) {
231 // nothing to do here
232 }
233
234 public synchronized void alternateSelectAction(boolean flag) {
235 // nothing to do here
236 }
237 }
|