001 package swingui;
002
003 import java.awt.Dimension;
004 import java.awt.GridLayout;
005 import java.awt.event.ActionEvent;
006 import java.awt.event.ActionListener;
007 import java.awt.event.MouseAdapter;
008 import java.awt.event.MouseEvent;
009 import java.util.HashMap;
010 import java.util.HashSet;
011 import java.util.Map;
012 import java.util.Set;
013
014 import javax.swing.JButton;
015 import javax.swing.JPanel;
016
017 import physics3d.GameConstants;
018 import physics3d.Vect3;
019
020 import components.*;
021
022 /** AddPanel is a panel that contains a multitude of buttons for adding, moving, and deleting objects.
023 * <p>
024 * It contains a reference to the currently selected object and has private MouseListener classes
025 * for each type of action.
026 * <p>
027 * When a button on the AddPanel is clicked, the corresponding MouseListener is registered with
028 * the canvas (game play area). Then on subsequent clicks on the canvas, the action corresponsding
029 * to the button will be executed.
030 * <p>
031 * For example, if the user clicks on "Add Square Bumper", the AddSquareListener is registered with
032 * the game area. Then when the user next clicks on an empty space in the gamearea, a square bumper
033 * will be added to that spot.
034 * <p>
035 * @author ruthdhan
036 *
037 */
038 public class AddPanel extends JPanel {
039 public static final long serialVersionUID = 0;
040
041 //components
042 private JButton addBall, addSquare, addCircle, addTriangle, addLeft, addRight, addAbs;
043 //move and delete
044 private JButton move, delete, select;
045 //the main gui
046 private MainGUI gui;
047
048 //listeners
049 private ButtonListener bl;
050 private AddBallListener abl;
051 private AddSquareListener asl;
052 private AddCircleListener acl;
053 private AddTriangleListener atl;
054 private AddLeftListener all;
055 private AddRightListener arl;
056 private AddAbsListener aal;
057 private MoveListener ml;
058 private DeleteListener dl;
059 private SelectListener sl;
060
061 //the selected object
062 private GameObject selected;
063
064 //static counter
065 private static int ID_NUM = 0; //starts at zero
066
067 /** Create a new AddPanel. Adds all buttons and registers them with listeners. **/
068 public AddPanel(MainGUI gui) {
069 super();
070 this.gui = gui;
071
072 //listeners -- one per button
073 bl = new ButtonListener();
074 abl = new AddBallListener();
075 asl = new AddSquareListener();
076 acl = new AddCircleListener();
077 atl = new AddTriangleListener();
078 all = new AddLeftListener();
079 arl = new AddRightListener();
080 aal = new AddAbsListener();
081 ml = new MoveListener();
082 dl = new DeleteListener();
083 sl = new SelectListener();
084
085 //initialize components
086 addBall = new JButton("Add Ball");
087 addBall.addActionListener(bl);
088
089 addSquare = new JButton("Add Square\n Bumper");
090 addSquare.addActionListener(bl);
091
092 addCircle = new JButton("Add Circle\n Bumper");
093 addCircle.addActionListener(bl);
094
095 addTriangle = new JButton("Add Triangle\n Bumper");
096 addTriangle.addActionListener(bl);
097
098 addLeft = new JButton("Add Left\n Flipper");
099 addLeft.addActionListener(bl);
100
101 addRight = new JButton("Add Right\n Flipper");
102 addRight.addActionListener(bl);
103
104 addAbs = new JButton("Add \nAbsorber");
105 addAbs.addActionListener(bl);
106
107 move = new JButton("Move");
108 move.addActionListener(bl);
109
110 delete = new JButton("Delete");
111 delete.addActionListener(bl);
112
113 select = new JButton("Select");
114 select.addActionListener(bl);
115
116 //add to layout
117 this.setLayout(new GridLayout(0, 1)); //1 column
118 this.setPreferredSize(new Dimension(225, 300));
119 this.setMaximumSize(new Dimension(200, 300));
120
121 //row 1: ball
122 add(addBall);
123
124 //row 2-3: sq & tri
125 add(addSquare);
126 add(addTriangle);
127
128 //row 4-7: circle & abs
129 add(addCircle);
130 add(addAbs);
131 add(addLeft);
132 add(addRight);
133
134 //row 8: move & del
135 JPanel moveDelPanel = new JPanel();
136 moveDelPanel.add(move);
137 moveDelPanel.add(delete);
138 add(moveDelPanel);
139
140 //row 9: select
141 add(select);
142 }
143
144 /** enable all buttons on this panel */
145 public void activate() {
146 addBall.setEnabled(true);
147 addSquare.setEnabled(true);
148 addCircle.setEnabled(true);
149 addTriangle.setEnabled(true);
150 addLeft.setEnabled(true);
151 addRight.setEnabled(true);
152 addAbs.setEnabled(true);
153 move.setEnabled(true);
154 delete.setEnabled(true);
155 select.setEnabled(true);
156 }
157 /** disable all buttons on this panel. now the panel will not intercept keystrokes **/
158 public void deactivate() {
159 addBall.setEnabled(false);
160 addSquare.setEnabled(false);
161 addCircle.setEnabled(false);
162 addTriangle.setEnabled(false);
163 addLeft.setEnabled(false);
164 addRight.setEnabled(false);
165 addAbs.setEnabled(false);
166 move.setEnabled(false);
167 delete.setEnabled(false);
168 select.setEnabled(false);
169 }
170
171 /** This is what listens for the actual mouse clicks on AddPanel. **/
172 private class ButtonListener implements ActionListener {
173 public void actionPerformed(ActionEvent e) {
174 //unselects whatever is currently selected
175 if (selected != null) {
176 selected.setSelected(false);
177 selected = null;
178 gui.getCanvas().display();
179 }
180 gui.getDetailPanel().clear();
181 if (e.getSource().equals(addBall)) {
182 ////System.out.println("clicked ball");
183 gui.setCurrentListener(abl);
184 } else if (e.getSource().equals(addSquare)) {
185 ////System.out.println("clicked square");
186 gui.setCurrentListener(asl);
187 } else if (e.getSource().equals(addCircle)) {
188 ////System.out.println("clicked circle");
189 gui.setCurrentListener(acl);
190 } else if (e.getSource().equals(addTriangle)) {
191 ////System.out.println("clicked triangle");
192 gui.setCurrentListener(atl);
193 } else if (e.getSource().equals(addLeft)) {
194 ////System.out.println("clicked left");
195 gui.setCurrentListener(all);
196 } else if (e.getSource().equals(addRight)) {
197 ////System.out.println("clicked right");
198 gui.setCurrentListener(arl);
199 } else if (e.getSource().equals(addAbs)) {
200 ////System.out.println("clicked abs");
201 gui.setCurrentListener(aal);
202 } else if (e.getSource().equals(move)) {
203 ////System.out.println("clicked move");
204 gui.setCurrentListener(ml);
205 } else if (e.getSource().equals(delete)) {
206 ////System.out.println("clicked delete");
207 gui.setCurrentListener(dl);
208 } else if (e.getSource().equals(select)) {
209 ////System.out.println("clicked select");
210 gui.setCurrentListener(sl);
211 }
212 }
213 }
214
215 //true if gridLoc already occupied
216 private boolean gridOccupied(Vect3 gridLoc) {
217 for (GameObject obj : gui.getGameSpace().getObjectsNoWalls()) {
218 for (Vect3 p : obj.getOccupiedPositions()) {
219 if (gridLoc.equals(p)) {
220 ////System.out.println("occupied");
221 return true;
222 }
223 }
224 }
225 ////System.out.println("not occupied");
226 return false;
227 }
228
229 //true if any of gls are occupied
230 private boolean gridOccupied(Set<Vect3> gls) {
231 ////System.out.println(" gls " + gls);
232 for (GameObject obj : gui.getGameSpace().getObjectsNoWalls()) {
233 ////System.out.println("opsss: " + obj.getOccupiedPositions());
234 for (Vect3 p : obj.getOccupiedPositions()) {
235 if (gls.contains(p)) {
236 return true;
237 }
238 }
239 }
240 return false;
241 }
242
243 /////
244 private class AddBallListener extends MouseAdapter {
245 @Override
246 public void mouseClicked(MouseEvent e) {
247 ////System.out.println("add ball" + e.getX() + ", " + e.getY());
248 Vect3 p = gui.getGridLocation(e.getX(), e.getY());
249
250 //add ball "properly"
251 Map<String, String> fmap = new HashMap<String, String>();
252 fmap.put("x", String.valueOf(p.x() + .5));
253 fmap.put("y", String.valueOf(p.y() + .5));
254 fmap.put("z", String.valueOf(p.z() + .5));
255 fmap.put("orientation", "0");
256 fmap.put("name", "Ball" + ID_NUM);
257 Ball b = new Ball(fmap, gui.getGameSpace());
258
259 Set<Vect3> ballOccupied = b.getOccupiedPositions();
260 if (!gridOccupied(ballOccupied)) {
261 gui.getGameSpace().add(b);
262 //redraws
263 gui.getCanvas().display();
264
265 //increments ID_NUM
266 ID_NUM ++;
267 }
268 }
269 }
270
271 private class AddSquareListener extends MouseAdapter {
272 @Override
273 public void mouseClicked(MouseEvent e) {
274 ////System.out.println("add square " + e.getX() + ", " + e.getY());
275 ////System.out.println(gui.getGridLocation(e.getX(), e.getY()));
276 Vect3 p = gui.getGridLocation(e.getX(), e.getY());
277 // add square bumper
278 if (!gridOccupied(p)) {
279 //creates bumper and puts it in gamespace
280 Map<String, String> fmap = new HashMap<String, String>();
281 fmap.put("x", String.valueOf(p.x()));
282 fmap.put("y", String.valueOf(p.y()));
283 fmap.put("z", String.valueOf(p.z()));
284 fmap.put("orientation", "0");
285 fmap.put("name", "SquareBumper" + ID_NUM);
286 SquareBumper sb = new SquareBumper(fmap, gui.getGameSpace());
287 gui.getGameSpace().add(sb);
288 //redraws
289 gui.getCanvas().display();
290
291 //increments ID_NUM
292 ID_NUM++;
293 }
294 }
295 }
296
297 private class AddCircleListener extends MouseAdapter {
298 @Override
299 public void mouseClicked(MouseEvent e) {
300 ////System.out.println("add circle");
301 Vect3 p = gui.getGridLocation(e.getX(), e.getY());
302 if (!gridOccupied(p)) {
303 //creates bumper and puts it in gamespace
304 Map<String, String> fmap = new HashMap<String, String>();
305 fmap.put("x", String.valueOf(p.x()));
306 fmap.put("y", String.valueOf(p.y()));
307 fmap.put("z", String.valueOf(p.z()));
308 fmap.put("orientation", "0");
309 fmap.put("name", "CircleBumper" + ID_NUM);
310 CircleBumper cb = new CircleBumper(fmap, gui.getGameSpace());
311 gui.getGameSpace().add(cb);
312 //redraws
313 gui.getCanvas().display();
314
315 // increments ID_NUM
316 ID_NUM++;
317 }
318 }
319 }
320
321 private class AddTriangleListener extends MouseAdapter {
322 @Override
323 public void mouseClicked(MouseEvent e) {
324 ////System.out.println("add triangle");
325 Vect3 p = gui.getGridLocation(e.getX(), e.getY());
326 if (!gridOccupied(p)) {
327 //creates bumper and puts it in gamespace
328 Map<String, String> fmap = new HashMap<String, String>();
329 fmap.put("x", String.valueOf(p.x()));
330 fmap.put("y", String.valueOf(p.y()));
331 fmap.put("z", String.valueOf(p.z()));
332 fmap.put("orientation", "0");
333 fmap.put("name", "TriangleBumper" + ID_NUM);
334 TriangleBumper tb = new TriangleBumper(fmap, gui.getGameSpace());
335 gui.getGameSpace().add(tb);
336 //redraws
337 gui.getCanvas().display();
338
339
340 //increments ID_NUM
341 ID_NUM++;
342 }
343 }
344 }
345
346
347 private class AddLeftListener extends MouseAdapter {
348 @Override
349 public void mouseClicked(MouseEvent e) {
350 ////System.out.println("add left");
351 Vect3 p = gui.getGridLocation(e.getX(), e.getY());
352 double r = GameConstants.FLIPPER_RADIUS_FRACTION;
353 //Flipper f = new Flipper(p, p.plus(new Vect3(r, r, 0.5)), Vect3.Z_HAT, Angle.ZERO, "left flipper", gui.getGameSpace());
354
355 //creates left flipper
356 Map<String, String> fmap = new HashMap<String, String>();
357 fmap.put("x", String.valueOf(p.x()));
358 fmap.put("y", String.valueOf(p.y()));
359 fmap.put("z", String.valueOf(p.z()));
360 fmap.put("orientation", "0");
361 fmap.put("name", "LeftFlipper" + ID_NUM);
362 LeftFlipper f = new LeftFlipper(fmap, gui.getGameSpace());
363
364 //checks if occupied
365 Set<Vect3> fOccupied = f.getOccupiedPositions();
366
367 if (!gridOccupied(fOccupied)) {
368 gui.getGameSpace().add(f);
369 //redraws
370 gui.getCanvas().display();
371
372 //increments ID_NUM
373 ID_NUM++;
374 }
375 }
376 }
377
378 private class AddRightListener extends MouseAdapter {
379 @Override
380 public void mouseClicked(MouseEvent e) {
381 ////System.out.println("add left");
382 Vect3 p = gui.getGridLocation(e.getX(), e.getY());
383 double r = GameConstants.FLIPPER_RADIUS_FRACTION;
384 //Flipper f = new Flipper(p, p.plus(new Vect3(2*(1-r), r, 0.5)), Vect3.Z_HAT, Angle.ZERO, "left flipper", gui.getGameSpace());
385
386 //creates right flipper
387 Map<String, String> fmap = new HashMap<String, String>();
388 fmap.put("x", String.valueOf(p.x()));
389 fmap.put("y", String.valueOf(p.y()));
390 fmap.put("z", String.valueOf(p.z()));
391 fmap.put("orientation", "0");
392 fmap.put("name", "RightFlipper" + ID_NUM);
393 RightFlipper f = new RightFlipper(fmap, gui.getGameSpace());
394
395 //checks if occupied
396 Set<Vect3> fOccupied = f.getOccupiedPositions();
397
398 if (!gridOccupied(fOccupied)) {
399 gui.getGameSpace().add(f);
400 //redraws
401 gui.getCanvas().display();
402
403 //increments ID_NUM
404 ID_NUM++;
405 }
406 }
407 }
408
409 private class AddAbsListener extends MouseAdapter {
410 @Override
411 public void mouseClicked(MouseEvent e) {
412 ////System.out.println("add abs");
413 Vect3 p = gui.getGridLocation(e.getX(), e.getY());
414
415 //creates absorber
416 Map<String, String> fmap = new HashMap<String, String>();
417 fmap.put("x", String.valueOf(p.x()));
418 fmap.put("y", String.valueOf(p.y()));
419 fmap.put("z", String.valueOf(p.z()));
420 fmap.put("height", "1");
421 fmap.put("width", "1");
422 fmap.put("depth", "1");
423 fmap.put("orientation", "0");
424 fmap.put("name", "Absorber" + ID_NUM);
425 Absorber a = new Absorber(fmap, gui.getGameSpace());
426
427 Set<Vect3> aOccupied = a.getOccupiedPositions();
428
429 if (!gridOccupied(aOccupied)) {
430 ////System.out.println(a.getHeight() + " " + a.getWidth() + " " + a.getDepth() + "" + " absorber height");
431 gui.getGameSpace().add(a);
432 //redraws
433 gui.getCanvas().display();
434
435 //increments ID_NUM
436 ID_NUM++;
437 }
438 }
439 }
440
441 private class MoveListener extends MouseAdapter {
442 @Override
443 public void mousePressed(MouseEvent e) {
444 GameSpace gs = gui.getGameSpace();
445 if (selected == null) {
446 Vect3 gridLoc = gui.getGridLocation(e.getX(), e.getY());
447 selected = gui.getObjectInGrid(gridLoc);
448 if (selected != null) {
449 selected.setSelected(true);
450 gui.getCanvas().display();
451 }
452 } else {
453 Vect3 gridLoc = gui.getGridLocation(e.getX(), e.getY());
454 Vect3 oldLoc = selected.getTLF();
455
456 //remember old loc and move to new; we'll move back if there's a problem
457 gs.removeObject(selected);
458 if (selected instanceof Ball)
459 selected.setTLF(gridLoc.plus(new Vect3(.5, .5, .5)));
460 else
461 selected.setTLF(gridLoc);
462
463 //if there's a problem, change it back
464 if (!gridOccupied(selected.getOccupiedPositions())) {
465 selected.setSelected(false);
466 //redraws
467 gui.getCanvas().display();
468 gs.add(selected); //add back and unselect
469 selected = null;
470 } else {
471 selected.setTLF(oldLoc);
472 gs.add(selected); //add to oldloc, leave selected
473 }
474 }
475 }
476
477 }
478
479 private class DeleteListener extends MouseAdapter {
480 @Override
481 public void mouseClicked(MouseEvent e) {
482 GameSpace gs = gui.getGameSpace();
483 Vect3 gridLoc = gui.getGridLocation(e.getX(), e.getY());
484 selected = gui.getObjectInGrid(gridLoc);
485 if (selected != null) {
486 gs.removeObject(selected);
487 //redraws
488 gui.getCanvas().display();
489 ////System.out.println("deleted something");
490 }
491 }
492 }
493
494 private class SelectListener extends MouseAdapter {
495 @Override
496 public void mouseClicked(MouseEvent e) {
497 //if there's already something selected, clear it
498 if (selected != null) {
499 selected.setSelected(false);
500 gui.getDetailPanel().clear();
501 }
502 //find out if we clicked on an actual object (or just space)
503 Vect3 gridLoc = gui.getGridLocation(e.getX(), e.getY());
504 GameSpace gs = gui.getGameSpace();
505 selected = gui.getObjectInGrid(gridLoc);
506
507 //if there's an object, select & update detail panel
508 if (selected != null) {
509 selected.setSelected(true);
510 gui.getDetailPanel().update(selected);
511 }
512 gui.getCanvas().display();
513 }
514 }
515
516
517 /** the selected object, before he disaooered
518 * @return the selected
519 */
520 public GameObject getSelected() {
521 return selected;
522 }
523
524 /** change the text on that emo-boy part
525 * @param selected the selected to set
526 */
527 public void setSelected(GameObject selected) {
528 this.selected = selected;
529 }
530
531 /** @return a random six-character name **/
532 public static String randomName() {
533 return "Object"+ID_NUM++; //increment after we use it
534 }
535 }