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