1 package org.xpilot.jxpmap;
2 
3 import java.awt.AWTEvent;
4 import java.awt.BasicStroke;
5 import java.awt.Color;
6 import java.awt.Graphics2D;
7 import java.awt.Image;
8 import java.awt.Point;
9 import java.awt.Rectangle;
10 import java.awt.Shape;
11 import java.awt.Stroke;
12 import java.awt.event.MouseEvent;
13 import java.awt.geom.AffineTransform;
14 import java.io.IOException;
15 import java.io.PrintWriter;
16 import java.util.Map;
17 import java.util.Comparator;
18 
19 import javax.swing.ImageIcon;
20 
21 
22 public abstract class MapObject extends ModelObject {
23 
24     public static final Stroke SELECTED_STROKE = new BasicStroke(1);
25 
26     public static final Comparator Z_ORDER = new Comparator() {
27         public int compare(Object o1, Object o2) {
28             return ((MapObject)o1).getZOrder() - ((MapObject)o2).getZOrder();
29         }
30     };
31 
32     protected Rectangle bounds;
33     protected Stroke previewStroke;
34     protected Image img;
35     protected MapObjectPopup popup;
36     protected int team;
37     protected boolean selected;
38     protected Group parent;
39 
deepClone(Map context)40     public Object deepClone (Map context) {
41         MapObject clone = (MapObject)super.deepClone(context);
42         clone.bounds = new Rectangle(bounds);
43         clone.popup = null;
44         return clone;
45     }
46 
copy()47     public MapObject copy() {
48         MapObject copy = (MapObject)clone();
49         copy.bounds = new Rectangle(bounds);
50         copy.popup = null;
51         return copy;
52     }
53 
MapObject()54     public MapObject () {
55         this(null, 0, 0, 0, 0);
56     }
57 
58 
MapObject(int width, int height)59     public MapObject (int width, int height) {
60         this(null, 0, 0, width, height);
61     }
62 
63 
MapObject(String imgName, int width, int height)64     public MapObject (String imgName, int width, int height) {
65         this(imgName, 0, 0, width, height);
66     }
67 
68 
MapObject(String imgName, int x, int y, int width, int height)69     public MapObject (String imgName, int x, int y, int width, int height) {
70         bounds = new Rectangle(x, y, width, height);
71         if (imgName != null) setImage(imgName);
72     }
73 
74 
newInstance()75     public MapObject newInstance() {
76         try {
77             return (MapObject)getClass().newInstance();
78         } catch (Exception e) {
79             throw new RuntimeException("MapObject creation failed: " + e);
80         }
81     }
82 
isSelected()83     public boolean isSelected() {
84         return selected;
85     }
86 
setSelected(boolean value)87     public void setSelected(boolean value) {
88         this.selected = value;
89     }
90 
getTeam()91     public int getTeam () {
92         return team;
93     }
94 
setTeam(int team)95     public void setTeam (int team) {
96         this.team = team;
97     }
98 
getParent()99     public Group getParent () {
100         return parent;
101     }
102 
setParent(Group parent)103     public void setParent (Group parent) {
104         this.parent = parent;
105     }
106 
getBounds()107     public Rectangle getBounds () {
108         return bounds;
109     }
110 
111 
setBounds(Rectangle bounds)112     public void setBounds (Rectangle bounds) {
113         this.bounds = bounds;
114     }
115 
116 
contains(Point p)117     public boolean contains (Point p) {
118         return getBounds().contains(p);
119     }
120 
getZOrder()121     public int getZOrder () {
122         return 10;
123     }
124 
125 
getImage()126     protected Image getImage () {
127         return img;
128     }
129 
130 
setImage(Image img)131     protected void setImage (Image img) {
132         this.img = img;
133     }
134 
135 
setImage(String fileName)136     protected void setImage (String fileName) {
137         this.img =
138             (new ImageIcon
139                 (getClass().getResource
140                  ("/images/" + fileName))).getImage();
141     }
142 
143 
getPreviewShape()144     protected Shape getPreviewShape () {
145         return getBounds();
146     }
147 
getPopup()148     private MapObjectPopup getPopup() {
149         if (popup == null) popup = createPopup();
150         return popup;
151     }
152 
createPopup()153     protected MapObjectPopup createPopup() {
154         return new MapObjectPopup(this);
155     }
156 
getPreviewStroke(float scale)157     protected Stroke getPreviewStroke (float scale) {
158         if (previewStroke == null) {
159             float dash[] = { 10 / scale };
160             previewStroke =
161                 new BasicStroke
162                     (1, BasicStroke.CAP_BUTT,
163                      BasicStroke.JOIN_MITER,
164                      10 / scale, dash, 0.0f);
165         }
166         return previewStroke;
167     }
168 
169 
getCreateHandler(Runnable r)170     public CanvasEventHandler getCreateHandler (Runnable r) {
171         return new CreateHandler(r);
172     }
173 
174 
getPropertyEditor(MapCanvas canvas)175     public EditorPanel getPropertyEditor (MapCanvas canvas) {
176         EditorPanel editor = new EditorPanel();
177         editor.add(new javax.swing.JLabel("No editable properties"));
178         return editor;
179     }
180 
181 
checkAwtEvent(MapCanvas canvas, AWTEvent evt)182     public boolean checkAwtEvent (MapCanvas canvas, AWTEvent evt) {
183 
184         if (evt instanceof MouseEvent) {
185             MouseEvent me = (MouseEvent)evt;
186 
187             if (canvas.containsWrapped(this, me.getPoint())) {
188                 if (me.isPopupTrigger()) {
189                     Point p = me.getPoint();
190                     canvas.getTransform().transform(p, p);
191                     getPopup().show(canvas, p.x, p.y);
192                     return true;
193 
194                 } else {
195                     if (evt.getID() == MouseEvent.MOUSE_PRESSED
196                     && (me.getModifiers() & MouseEvent.BUTTON1_MASK) != 0) {
197                         if (canvas.getMode() == MapCanvas.MODE_ERASE) {
198                             canvas.removeMapObject(this);
199                         } else if (canvas.getMode() == MapCanvas.MODE_COPY) {
200                             canvas.setCanvasEventHandler(
201                                 copy().new CopyHandler(me));
202                         } else {
203                             if ((me.getModifiersEx()
204                             & MouseEvent.CTRL_DOWN_MASK) != 0) {
205                                 canvas.addSelectedObject(this);
206                             } else {
207                                 canvas.setSelectedObject(this);
208                             }
209                             canvas.setCanvasEventHandler(new MoveHandler(me));
210                         }
211                     }
212                     return true;
213                 }
214             }
215         }
216         return false;
217     }
218 
219 
moveTo(int x, int y)220     public void moveTo (int x, int y) {
221         bounds.x = x;
222         bounds.y = y;
223     }
224 
225 
paint(Graphics2D g, float scale)226     public void paint (Graphics2D g, float scale) {
227         if (img != null) {
228             Rectangle r = getBounds();
229             AffineTransform at = AffineTransform.getTranslateInstance
230                 (r.x, r.y + r.height);
231             at.scale(64, -64);
232             g.drawImage(img, at, null);
233         }
234         if (isSelected()) {
235             g.setColor(Color.white);
236             g.draw(getBounds());
237         }
238     }
239 
240 
printXml(PrintWriter out)241     public abstract void printXml (PrintWriter out) throws IOException;
242 
243 
244 
245     //---------------------------------------------------------------------
246     // Inner classes
247 
248 
249 
250     protected class CreateHandler extends CanvasEventAdapter {
251 
252         private Runnable cmd;
253         private Point offset;
254         private Shape preview;
255         private Shape toBeRemoved;
256         private Stroke stroke;
257 
258 
CreateHandler(Runnable cmd)259         public CreateHandler (Runnable cmd) {
260             this.cmd = cmd;
261             Rectangle ob = MapObject.this.getBounds();
262             offset = new Point(ob.width / 2, ob.height / 2);
263             preview = getPreviewShape();
264         }
265 
266 
mouseMoved(MouseEvent evt)267         public void mouseMoved (MouseEvent evt) {
268 
269             Rectangle ob = MapObject.this.getBounds();
270             MapCanvas c = (MapCanvas)evt.getSource();
271 
272             Graphics2D g = (Graphics2D)c.getGraphics();
273             g.setXORMode(Color.black);
274             g.setColor(Color.white);
275             if (stroke == null) stroke = getPreviewStroke(c.getScale());
276             //g.setStroke(stroke);
277 
278             if (toBeRemoved != null) c.drawShape(g, toBeRemoved);
279 
280             AffineTransform tx = AffineTransform.getTranslateInstance
281                 (evt.getX() - offset.x - ob.x, evt.getY() - offset.y - ob.y);
282             c.drawShape(g, toBeRemoved = tx.createTransformedShape(preview));
283         }
284 
285 
mousePressed(MouseEvent evt)286         public void mousePressed (MouseEvent evt) {
287 
288             MapCanvas c = (MapCanvas)evt.getSource();
289             MapObject.this.moveTo(evt.getX() - offset.x,
290                                   evt.getY() - offset.y);
291             c.addMapObject(MapObject.this);
292             c.setCanvasEventHandler(newInstance().getCreateHandler(cmd));
293             if (cmd != null) cmd.run();
294         }
295     }
296 
297 
298 
299     protected class MoveHandler extends CanvasEventAdapter {
300 
301 
302         protected Point offset;
303         protected Shape preview;
304         protected Shape toBeRemoved;
305         protected Stroke stroke;
306 
307 
MoveHandler(MouseEvent evt)308         public MoveHandler (MouseEvent evt) {
309             Rectangle ob = MapObject.this.getBounds();
310             offset = new Point(evt.getX() - ob.x, evt.getY() - ob.y);
311             preview = getPreviewShape();
312         }
313 
314 
mouseDragged(MouseEvent evt)315         public void mouseDragged (MouseEvent evt) {
316 
317             Rectangle ob = MapObject.this.getBounds();
318             MapCanvas c = (MapCanvas)evt.getSource();
319 
320             Graphics2D g = (Graphics2D)c.getGraphics();
321             g.setXORMode(Color.black);
322             g.setColor(Color.white);
323             if (stroke == null) stroke = getPreviewStroke(c.getScale());
324             //g.setStroke(stroke);
325 
326             if (toBeRemoved != null) c.drawShape(g, toBeRemoved);
327 
328             AffineTransform tx = AffineTransform.getTranslateInstance
329                 (evt.getX() - offset.x - ob.x, evt.getY() - offset.y - ob.y);
330             c.drawShape(g, toBeRemoved = tx.createTransformedShape(preview));
331         }
332 
333 
mouseReleased(MouseEvent evt)334         public void mouseReleased (MouseEvent evt) {
335             MapCanvas c = (MapCanvas)evt.getSource();
336             c.moveMapObject(MapObject.this,
337                             evt.getX() - offset.x,
338                             evt.getY() - offset.y);
339             c.setCanvasEventHandler(null);
340         }
341     }
342 
343     protected class CopyHandler extends MoveHandler {
344 
CopyHandler(MouseEvent me)345         public CopyHandler(MouseEvent me) {
346             super(me);
347         }
348 
mouseReleased(MouseEvent evt)349         public void mouseReleased (MouseEvent evt) {
350             MapCanvas c = (MapCanvas)evt.getSource();
351             MapObject.this.moveTo(
352                 evt.getX() - offset.x,
353                 evt.getY() - offset.y);
354             c.addMapObject(MapObject.this);
355             c.setCanvasEventHandler(null);
356         }
357     }
358 }
359