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    }