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