1   package main;
2   
3   import simworldobjects.*;
4   import intellego.Intellego;
5   import util.*;
6   import interfaces.*;
7   import real.*;
8   import NetBeansResources.*;
9   
10  import java.awt.*;
11  import java.lang.*;
12  import java.awt.event.*;
13  import javax.swing.*;
14  import javax.swing.event.*;
15  import java.io.*;
16  import java.util.*;
17  import java.awt.geom.*;
18  
19  
20  /** Provides a user interface for a simulation
21   * @author Graham Ritchie
22   * @modifyer Simon Zienkiewicz
23   */
24  public class SimUI extends JInternalFrame implements Runnable, ItemListener
25  {
26      /** The container of this class/frame */    
27      private Container mainContainer;
28      /** The SimDisplay object associated with this frame */        
29      private SimDisplay display=null;
30      /** The main pane containing all the simulator frames */        
31      private JLayeredPane mainPane;
32      /** the list of controller files */        
33      private LinkedList controllerList;
34      /** the robot list */        
35      private LinkedList robotList;
36      /** the SimWorld currently opened in the simulator */        
37      private SimWorld world=null;
38      /** the state of the simulator */        
39      private boolean running=false;
40      /** the time between each cycle of the simulator */        
41      private int UPDATE_TIME=10;
42      /** if there is currently a SimWorld opened in the simulator */        
43      private boolean openWorld = false;
44      /** the desired width of the simulator screen */        
45      private static int screenWidth=900;
46      /** the desired height of the simulator screen */        
47      private static int screenHeight=400;
48      /** the panel containing the SimDisplay object */        
49      private JPanel jPanel2;
50      /** the panel containing the grid */        
51      private JPanel jPanel3;
52      /** the textbox indicating the X position of the mouse in the simulator */
53      private JTextField xT;
54      /** the textbox indicating the Z position of the mouse in the simulator */        
55      private JTextField  zT;
56      /** pane allowing for scrolling of mainContainer */        
57      private JScrollPane codeScrollPane;
58      /** light properties menu item */        
59      private JMenuItem lightProp;
60      /** the GridDisplay object for the simulator */        
61      private GridDisplay gridDisplay = null;
62      /** constant */        
63      private static final String NO_CLASS="__NOCLASS__";
64      /** the index of a selected object */        
65      private int objectIndex;
66      /** if a object is selected */        
67      private boolean selectedObject=false;
68      /** the offset of an object in the X direction to allow for proper object placement */
69      private int offSetX;
70      /** the offset of an object in the Y(Z) direction to allow for proper object placement */        
71      private int  offSetY;
72      /** the path of a worldobject */
73      private String path;
74      /** the file name of the current world */        
75      private String  currentWorldFile;
76      /** if a color properties dialog exists */        
77      private boolean colorPropertiesExist = false;
78      /** if a grid dialog exists */        
79      private boolean gridDialogExist=false;
80      /** if a color dialog exists */        
81      private boolean colorDialogExist=false;
82      /** if a object dialog exists */        
83      private boolean objectDialogExist=false;
84      /** the light properties dialog for the simulator */        
85      private LightSensorPropertiesDialog lightProperties=null;
86      /** the grid dialog for the simulator */        
87      private GridOptionDialog newGridOption=null;
88      /** the color dialog for the simulator */        
89      private ColorOptionDialog colorsPop=null;
90      /** the object dialog for the simulator */        
91      private ObjectEditDialog objectEdit=null;
92      /** the robot rotation dialog for the simulator */        
93      private RobotRotation robotRotation = null;
94      /** the lock checkbox for the simultor */        
95      private JCheckBox lock;
96      /** the textbox indicating the status of the simulation */        
97      private JTextField simulationStatus;
98      /** the panel containing the dialog boxes */        
99      private JPanel propertyPanel;
100     /** an array indicating the number of robotObjects */        
101     private int[] robotObjects;
102     /** the initialization of a robot dialog */        
103     private InitRobotDialog d=null;
104     /** redo menu item */
105     private JMenuItem redo;
106     /** undo menu item */        
107     private JMenuItem undo;
108     /** the undo stack */        
109     private Stack undoStack = new Stack();
110     /** the redo stack */        
111     private Stack redoStack = new Stack();
112     /** is the simulation on */        
113     private boolean simOn = false;
114     /** is the robot selected */        
115     private boolean ROBOT_IS_SELECTED = false;
116     /** did the user begin to rotate the robot */        
117     private boolean BEGIN_ROTATION = false;
118     /** initial X postition where the robot was rotated from */        
119     private int INITIAL_X_ROT;
120     /** initial Y(Z) postition where the robot was rotated from */        
121     private int INITIAL_Y_ROT;
122 
123     /** the thread on which the simulation is running */        
124     private Thread t;
125     /** to exit the thread */        
126     private boolean exit = true;
127 
128     /**
129     * Sets up the main window for an empty simulation
130     */
131     public SimUI()
132     {
133         // window setup
134         super("Simulator:",true,true,true,true);
135         this.setFrameIcon(new ImageIcon("images/execute.gif"));
136         setSize(screenWidth,screenHeight);
137         setupWindow();
138         
139         // set up a default world
140         selectWorld(0);
141 
142     }
143     
144     /** Loads a new simulation with the specified controller preloaded
145      * @param file the file name of the controller (robot)
146      */
147     public SimUI(File file)
148     {
149         // window setup
150         super("Simulator: ",true,true,true,true);
151         setSize(screenWidth,screenHeight);     
152         setupWindow();
153 
154         // set up a world
155         selectWorld(1);
156 
157         Controller c=createController(file);
158 
159         if(c!=null)
160         {
161             // and add it to the system if it is not null
162             addController(c);
163         }
164         else
165         {
166             MainInterface.displayMessage("Failed to create Controller");
167             Intellego.addToLog("SimUI.addRobot(): Failed to create Controller with name "+file);
168         }
169 
170     }
171     
172     /**
173     * Opens a controller file in the current simulator window and simworld
174     */
175     public void openCurrentController(File file){
176         
177         //world is open in the simulator
178         
179         Controller c=createController(file);
180 
181         if(c!=null)
182         {
183             // and add it to the system if it is not null
184             addController(c);
185         }
186         else
187         {
188             MainInterface.displayMessage("Failed to create Controller");
189             Intellego.addToLog("SimUI.addRobot(): Failed to create Controller with name "+file);
190         }
191     
192     }
193     
194     /**
195     * Sets up the main window
196     */
197     public void setupWindow()
198     {
199         // set up main pane
200         mainContainer=getContentPane();
201         //mainContainer.setLayout(new BorderLayout());
202 
203         //new stuff using capture the flag game
204         mainContainer.setLayout(new AbsoluteLayout());
205 
206         // put it in a scroll pane
207         codeScrollPane = new JScrollPane(mainContainer);
208         codeScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
209         codeScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
210         codeScrollPane.setPreferredSize(new Dimension(400,400));
211         codeScrollPane.setMinimumSize(new Dimension(250, 100));
212         codeScrollPane.setBackground(Color.darkGray);
213         (codeScrollPane.getVerticalScrollBar()).setBackground(Color.darkGray);
214         (codeScrollPane.getHorizontalScrollBar()).setBackground(Color.darkGray);
215         (codeScrollPane.getViewport()).setBackground(Color.yellow);
216 
217         // and add this to a main content pane
218         JPanel contentPane = new JPanel();
219         contentPane.setBackground(Color.yellow);
220         BoxLayout box = new BoxLayout(contentPane, BoxLayout.X_AXIS);
221         contentPane.setLayout(box);
222 
223         //
224         propertyPanel = new JPanel();
225         propertyPanel.setLayout(new AbsoluteLayout());
226         propertyPanel.setBackground(Color.darkGray);
227         propertyPanel.setSize(170,10000);
228         propertyPanel.setPreferredSize(new Dimension(170,750));
229         propertyPanel.setMaximumSize(new Dimension(170,750));
230         propertyPanel.setMinimumSize(new Dimension(170,750));
231 
232         JScrollPane propertyScrollPane = new JScrollPane(propertyPanel);
233         propertyScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
234         propertyScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
235         propertyScrollPane.setPreferredSize(new Dimension(180,1000));
236         propertyScrollPane.setMinimumSize(new Dimension(180, 1000));
237         propertyScrollPane.setMaximumSize(new Dimension(180, 1000));
238         propertyScrollPane.setBackground(Color.darkGray);
239         (propertyScrollPane.getVerticalScrollBar()).setBackground(Color.darkGray);
240         (propertyScrollPane.getViewport()).setBackground(Color.yellow);
241 
242         contentPane.add(propertyScrollPane);
243         contentPane.add(codeScrollPane);
244 
245         setContentPane(contentPane);
246         this.setMinimumSize(new Dimension(850, 400));
247 
248         // create and set the menu bar
249         JMenuBar mb=createMenuBar();
250         setJMenuBar(mb);
251 
252         // set up required lists
253         controllerList=new LinkedList();
254         robotList=new LinkedList();
255     }   
256     
257     /**
258     * Creates the menu bar for the main window, and adds action listeners 
259     * to the menus.
260     *
261     * @return the menu bar
262     */
263     private JMenuBar createMenuBar()
264     {
265         //deligates the appropriate function for the colors menu
266 
267         // menu bar
268         JMenuBar mb=new JMenuBar();
269 
270         // menus
271         JMenu controlMenu=new JMenu("Controls");
272         controlMenu.setMnemonic(KeyEvent.VK_C);
273         JMenu optionsMenu=new JMenu("Options");
274         optionsMenu.setMnemonic(KeyEvent.VK_N);
275 
276         //set colors
277         controlMenu.setBackground(Color.darkGray);
278         controlMenu.setForeground(Color.lightGray);
279         optionsMenu.setBackground(Color.darkGray);
280         optionsMenu.setForeground(Color.lightGray);
281 
282         // control menu items
283         JMenuItem pickWorld=new JMenuItem("Open SimWorld");
284         pickWorld.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,ActionEvent.CTRL_MASK));
285         JMenuItem saveSimWorld = new JMenuItem("Save SimWorld Instance");
286         saveSimWorld.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,ActionEvent.CTRL_MASK));
287         JMenuItem addNewRobot=new JMenuItem("Add Robot");
288         addNewRobot.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R,ActionEvent.CTRL_MASK));
289         JMenuItem startSim=new JMenuItem("Start Simulation");
290         startSim.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P,ActionEvent.ALT_MASK));
291         JMenuItem stopSim=new JMenuItem("Stop Simulation");
292         stopSim.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,ActionEvent.ALT_MASK));
293         //set colors
294         pickWorld.setBackground(Color.darkGray);
295         saveSimWorld.setForeground(Color.lightGray);
296         saveSimWorld.setBackground(Color.darkGray);
297         pickWorld.setForeground(Color.lightGray);
298         addNewRobot.setBackground(Color.darkGray);
299         addNewRobot.setForeground(Color.lightGray);
300         startSim.setBackground(Color.darkGray);
301         startSim.setForeground(Color.green);
302         stopSim.setBackground(Color.darkGray);
303         stopSim.setForeground(Color.red.darker());
304 
305         // grid sub menu'
306         JMenuItem gridC = new JMenuItem("Colour");
307         gridC.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1,ActionEvent.ALT_MASK));
308         JMenuItem gridAt = new JMenuItem("Attributes");
309         gridAt.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_G,ActionEvent.ALT_MASK));
310         //set colors
311         gridC.setBackground(Color.darkGray);
312         gridC.setForeground(Color.lightGray);
313         gridAt.setBackground(Color.darkGray);
314         gridAt.setForeground(Color.lightGray);
315 
316         //create sub-submenu
317         JMenuItem worldBG = new JMenuItem("SimWorld Background");
318         worldBG.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2,ActionEvent.ALT_MASK));
319         JMenuItem walls = new JMenuItem("Walls");
320         walls.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_3,ActionEvent.ALT_MASK));
321         JMenuItem road = new JMenuItem("Road");
322         road.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_4,ActionEvent.ALT_MASK));
323 
324         JMenuItem robot = new JMenuItem("Robot");
325         robot.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_5,ActionEvent.ALT_MASK));
326         JMenuItem lightS = new JMenuItem("Light Sensors");
327         lightS.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_6,ActionEvent.ALT_MASK));
328         JMenuItem touchS = new JMenuItem("Touch Sensors");
329         touchS.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_7,ActionEvent.ALT_MASK));
330 
331         //set colors
332         walls.setBackground(Color.darkGray);
333         walls.setForeground(Color.lightGray);
334         robot.setBackground(Color.darkGray);
335         robot.setForeground(Color.lightGray);
336         lightS.setBackground(Color.darkGray);
337         lightS.setForeground(Color.lightGray);
338         touchS.setBackground(Color.darkGray);
339         touchS.setForeground(Color.lightGray);
340         worldBG.setBackground(Color.darkGray);
341         worldBG.setForeground(Color.lightGray);
342         road.setBackground(Color.darkGray);
343         road.setForeground(Color.lightGray);
344 
345         //create sub-submenu for Add Objects
346         JMenuItem wall = new JMenuItem("Wall");
347         JMenuItem path = new JMenuItem("Ground/Intersection");
348         //set colors
349         wall.setBackground(Color.darkGray);
350         wall.setForeground(Color.lightGray);
351         path.setBackground(Color.darkGray);
352         path.setForeground(Color.lightGray);
353 
354         // add action listeners
355         pickWorld.addActionListener(new ActionListener() 
356         {
357             public void actionPerformed(ActionEvent e) 
358             {
359                 //colorsPop=null;
360                 selectWorld(1);
361             }
362         });
363 
364         saveSimWorld.addActionListener(new ActionListener() 
365         {
366             public void actionPerformed(ActionEvent e) 
367             {
368                 saveWorld();
369 
370             }
371         });
372 
373         addNewRobot.addActionListener(new ActionListener() 
374         {
375             public void actionPerformed(ActionEvent e) 
376             {
377                 addRobot();
378             }
379         });
380 
381         startSim.addActionListener(new ActionListener() 
382         {
383             public void actionPerformed(ActionEvent e) 
384             {
385                 if(!simOn){                  
386                     startSimulation();
387                     simOn=true;
388                 }
389             }
390         });
391 
392         stopSim.addActionListener(new ActionListener() 
393         {
394             public void actionPerformed(ActionEvent e) 
395             {
396                 if(simOn){
397                     stopSimulation();
398                     simOn = false;
399                 }
400             }
401         });
402 
403         //grid activation menu item action listeners
404         gridC.addActionListener(new ActionListener()
405         {
406             public void actionPerformed(ActionEvent e) 
407             {
408                 if(gridDisplay != null) popUpColorOptions(6, "Set Grid Colour:",null,gridDisplay);
409             }
410         });
411 
412 
413         gridAt.addActionListener(new ActionListener()
414         {
415             public void actionPerformed(ActionEvent e) 
416             {
417                 if(gridDisplay != null) popUpGridOptions("Grid Setup:");
418             }
419         });
420 
421 
422         //submenu direction of color methods
423         walls.addActionListener(new ActionListener()
424         {
425             public void actionPerformed(ActionEvent e) 
426             {
427                 popUpColorOptions(0, "Colour: Wall",null,null);
428             }
429         });
430         touchS.addActionListener(new ActionListener()
431         {
432             public void actionPerformed(ActionEvent e) 
433             {
434                 popUpColorOptions(3, "Colour: TouchSensor",null,null);
435             }
436         });
437         lightS.addActionListener(new ActionListener()
438         {
439             public void actionPerformed(ActionEvent e) 
440             {
441                 popUpColorOptions(4, "Colour: LightSensor",null,null);
442             }
443         });
444         robot.addActionListener(new ActionListener()
445         {
446             public void actionPerformed(ActionEvent e) 
447             {
448                 popUpColorOptions(5, "Colour: Robot",null,null);
449             }
450         });
451         road.addActionListener(new ActionListener()
452         {
453             public void actionPerformed(ActionEvent e) 
454             {
455                 popUpColorOptions(7, "Colour: Road",null,null);
456             }
457         });
458         worldBG.addActionListener(new ActionListener()
459         {
460             public void actionPerformed(ActionEvent e) 
461             {
462                 if(gridDisplay != null) popUpColorOptions(1,"Colour: SimWorld",null,gridDisplay);
463             }
464         });
465 
466         //submenu direction of add objects methods
467         wall.addActionListener(new ActionListener()
468         {
469             public void actionPerformed(ActionEvent e) 
470             {
471                 addObjectToWorld("wall");
472             }
473         });
474         path.addActionListener(new ActionListener()
475         {
476             public void actionPerformed(ActionEvent e) 
477             {
478                 addObjectToWorld("path");
479             }
480         });
481 
482         // add items to control menu
483         controlMenu.add(pickWorld);
484         controlMenu.add(saveSimWorld);
485         controlMenu.addSeparator();
486         controlMenu.add(addNewRobot);
487         controlMenu.addSeparator();
488         controlMenu.add(startSim);
489         controlMenu.add(stopSim);
490 
491         //create a submenu
492         undo = new JMenuItem("Undo");
493         redo = new JMenuItem("Redo");
494         undo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z,ActionEvent.CTRL_MASK));
495         redo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y,ActionEvent.CTRL_MASK));
496         undo.setEnabled(false);
497         redo.setEnabled(false);
498 
499         //create a submenu 
500         JMenu submenu = new JMenu("Grid");
501         JMenu submenuColors = new JMenu("Colour Code");
502         JMenu submenuAddParts = new JMenu("Build Objects");
503         lightProp = new JMenuItem("Light Sensor Prop.");
504         lightProp.setEnabled(false);
505         lightProp.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P,ActionEvent.CTRL_MASK));
506 
507         //set colors
508         undo.setBackground(Color.darkGray);
509         undo.setForeground(Color.red.darker());
510         redo.setBackground(Color.darkGray);
511         redo.setForeground(Color.yellow);   
512 
513         submenu.setBackground(Color.darkGray);
514         submenu.setForeground(Color.lightGray);
515         submenuColors.setBackground(Color.darkGray);
516         submenuColors.setForeground(Color.lightGray);
517         submenuAddParts.setBackground(Color.darkGray);
518         submenuAddParts.setForeground(Color.lightGray);
519         lightProp.setBackground(Color.darkGray);
520         lightProp.setForeground(Color.yellow);
521 
522         undo.addActionListener(new ActionListener()
523         {
524             public void actionPerformed(ActionEvent e) 
525             {
526                undoRedoSet("undo");
527             }
528         });
529 
530         redo.addActionListener(new ActionListener()
531         {
532             public void actionPerformed(ActionEvent e) 
533             {
534                 undoRedoSet("redo");
535             }
536         });
537 
538         lightProp.addActionListener(new ActionListener()
539         {
540             public void actionPerformed(ActionEvent e) 
541             {
542                 setLightSensorProperties();
543             }
544         });
545 
546         //submenu for grid options
547         submenu.add(gridC);
548         submenu.addSeparator();
549         submenu.add(gridAt);
550 
551         //submenuColor options
552         submenuColors.add(worldBG);
553         submenuColors.addSeparator();
554         submenuColors.add(walls);
555         submenuColors.add(road);
556         submenuColors.addSeparator();
557         submenuColors.add(robot);
558         submenuColors.add(lightS);
559         submenuColors.add(touchS);
560 
561         //submenuAddParts options
562         submenuAddParts.add(wall);
563         submenuAddParts.addSeparator();
564         submenuAddParts.add(path);
565 
566         //undo/redo options
567         optionsMenu.add(undo);
568         optionsMenu.add(redo);
569         optionsMenu.addSeparator();
570 
571         optionsMenu.add(submenu);
572         optionsMenu.addSeparator();
573         optionsMenu.add(submenuColors);
574         optionsMenu.addSeparator();
575         optionsMenu.add(submenuAddParts);
576         optionsMenu.addSeparator();
577         optionsMenu.add(lightProp);
578 
579         //mouse position
580         JLabel xL=new JLabel("X: ");
581         xL.setForeground(Color.yellow);
582         JLabel zL=new JLabel("Z: ");
583         zL.setForeground(Color.yellow);
584         JLabel titleL=new JLabel("  |   Mouse Position: ");
585         titleL.setForeground(Color.yellow.darker());
586         JLabel blank = new JLabel("  |  ");
587         blank.setForeground(Color.yellow.darker());
588         JLabel blank2 = new JLabel("  |  ");
589         JLabel blank3 = new JLabel("  |  ");
590         blank2.setForeground(Color.yellow.darker());
591         blank3.setForeground(Color.yellow.darker());
592         JLabel buildTools = new JLabel("Building Tools: ");
593         buildTools.setForeground(Color.yellow.darker());
594 
595         xT=new JTextField(3);
596         xT.setEditable(false);
597         xT.setBackground(Color.yellow);
598         xT.setForeground(Color.darkGray.darker());
599 
600         zT=new JTextField(3);
601         zT.setEditable(false);
602         zT.setBackground(Color.yellow);
603         zT.setForeground(Color.darkGray.darker());
604 
605         // add menus to menu bar
606         mb.setLayout(new AbsoluteLayout());
607         mb.setBackground(Color.DARK_GRAY);
608         mb.add(controlMenu,new AbsoluteConstraints(3,0));
609         mb.add(optionsMenu,new AbsoluteConstraints(68,0));
610         mb.add(titleL,new AbsoluteConstraints(128,2));
611         mb.add(xL,new AbsoluteConstraints(248,2));
612         mb.add(xT,new AbsoluteConstraints(263,0));
613         mb.add(zL,new AbsoluteConstraints(303,2));
614         mb.add(zT,new AbsoluteConstraints(318,0));
615         mb.add(blank,new AbsoluteConstraints(355,2));
616         mb.add(buildTools,new AbsoluteConstraints(372,2));
617 
618         //button handler
619         Icon iconBrick = new ImageIcon("images\\brickIcon.png");
620         JButton brickButton = new JButton(iconBrick);
621         brickButton.setBackground(Color.darkGray);
622         brickButton.setSize(new Dimension(20,10));
623         brickButton.setMargin(new Insets(1,1,1,1));
624         brickButton.setToolTipText("build wall");
625         brickButton.addActionListener(new ActionListener()
626         {
627             public void actionPerformed(ActionEvent e) 
628             {
629                 addObjectToWorld("wall");
630             }
631         });
632 
633         Icon iconPath = new ImageIcon("images\\pathIcon.png");
634         JButton pathButton = new JButton(iconPath);
635         pathButton.setBackground(Color.darkGray);
636         pathButton.setSize(new Dimension(20,10));
637         pathButton.setMargin(new Insets(1,1,1,1));
638         pathButton.setToolTipText("build ground/intersection");
639         pathButton.addActionListener(new ActionListener()
640         {
641             public void actionPerformed(ActionEvent e) 
642             {
643                 addObjectToWorld("path");
644             }
645         });
646 
647         (lock = new JCheckBox()).addItemListener(this);
648         JLabel lockL = new JLabel("Lock:");
649         lockL.setForeground(Color.yellow.darker());
650         lock.setBackground(Color.yellow);
651         lock.setMargin(new Insets(0,0,0,0));
652 
653         JLabel simStat = new JLabel("  Simulation Status:");
654         simStat.setForeground(Color.yellow.darker());
655         this.simulationStatus = new JTextField(3);
656         this.simulationStatus.setForeground(Color.gray.darker());
657         this.simulationStatus.setEditable(false);
658         this.simulationStatus.setFont(new Font("Arial", Font.BOLD, 8));
659         this.simulation_is_OFF();
660 
661         mb.add(brickButton,new AbsoluteConstraints(465,0));
662         mb.add(pathButton,new AbsoluteConstraints(499,0));
663         mb.add(blank2,new AbsoluteConstraints(537,2));
664         mb.add(lockL,new AbsoluteConstraints(555,2));
665         mb.add(lock,new AbsoluteConstraints(595,2));
666         mb.add(blank3,new AbsoluteConstraints(615,2));
667         mb.add(simStat,new AbsoluteConstraints(625,2));
668         mb.add(this.simulationStatus,new AbsoluteConstraints(745,3));
669 
670         return mb;
671     }
672         
673     /** Internal method informing the user the simulation is OFF or not running. */        
674     private void simulation_is_OFF(){
675         this.simulationStatus.setBackground(Color.RED);
676         this.simulationStatus.setText(" OFF");
677     }
678 
679     /** Internal method informing the user the simulation is ON or running. */        
680     private void simulation_is_ON(){
681         this.simulationStatus.setBackground(Color.GREEN);
682         this.simulationStatus.setText(" ON");
683 
684     }
685     
686     /**
687     * Main loop: updates the world and repaints the screen 
688     */
689     public void run()
690     {
691         if(world==null || display==null)
692         {
693             MainInterface.displayMessage("You must select a SimWorld and a SimDisplay first");
694         }
695         else
696         {
697             while (exit)
698             {
699                 if(running){
700 
701                     // update SimWorld
702                     world.tick();
703 
704                     // repaint the display screen
705                     display.repaint();   
706 
707                     // sleep for a bit
708                     try{Thread.sleep(UPDATE_TIME);}catch(Exception e){}
709                 }
710 
711             }
712 
713         }
714     }
715 
716     /** Allows the user to pick a simworld for their simulation, and loads it
717          * @param index indicates whether default world load or user selected world loading
718          */
719     public void selectWorld(int index)
720     {
721         // create simworld by getting the class name from the user
722         try{
723             
724             File file;
725             
726             //default
727             if(index ==0)
728             {
729                 file = new File("simworlds/defaultSe101.class");
730                 currentWorldFile = file.getName();
731                 path = ((file.getAbsolutePath()).substring(0,(((file.getAbsolutePath()).length()) - ((file.getName()).length()))));
732             }
733             
734             //user selection
735             else
736             {
737                 file = getClassName("Pick a SimWorld class file:","simworlds");
738             }
739             
740             
741             
742             String className=file.getName();
743             className=className.substring(0,file.getName().length() - 6);
744 
745 
746             // if there is already a world open, stop the current sim and get rid of it.
747             if(world!=null)
748             {
749                 stopSimulation();
750 
751                 objectEdit.hide();
752                 newGridOption.hide();
753                 colorsPop.hide();
754                 robotRotation.hide();
755 
756                 world=null;
757                 mainContainer.removeAll();
758 
759                 jPanel2=null;
760                 display=null;
761                 lightProperties = null;
762                 newGridOption = null;
763                 objectEdit = null;
764                 colorsPop = null;
765                 robotRotation = null;
766 
767                 colorPropertiesExist = false;
768                 gridDialogExist=false;
769                 colorDialogExist=false;
770                 objectDialogExist=false;
771 
772                 if(d != null)d.setVisible(false);
773 
774             }
775 
776             // try to create a simworld from this class
777             SimWorld s=createSimWorld(className);
778 
779             // check simworld creation was successful
780             if(s!=null)
781             {
782 
783                 // set s as the world for this simulation
784                 world=s;
785 
786                 // and create a new display with this simworld
787                 display=new SimpleDisplay(world,this);
788                 jPanel2=display;
789                 jPanel2.setLayout(new AbsoluteLayout());
790 
791                 //Mouse events for the jPanel2 display frame
792                 jPanel2.addMouseListener(new java.awt.event.MouseAdapter() 
793                 {
794                     public void mouseClicked(java.awt.event.MouseEvent evt) 
795                     {
796                         if(!lock.isSelected())jPanel2MouseClicked(evt);
797                     }
798                     public void mousePressed(java.awt.event.MouseEvent evt) 
799                     {
800                         if(!lock.isSelected())jPanel2MousePressed(evt);
801                     }
802                     public void mouseReleased(java.awt.event.MouseEvent evt) 
803                     {
804                         if(!lock.isSelected())jPanel2MouseReleased(evt);
805                     }
806 
807                 });
808 
809                 jPanel2.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() 
810                 {
811                     public void mouseDragged(java.awt.event.MouseEvent evt) 
812                     {
813                         if(!lock.isSelected())jPanel2MouseDragged(evt);
814                     }
815                     public void mouseMoved(java.awt.event.MouseEvent evt) 
816                     {
817                         jPanel2MouseMoved(evt);
818                     }
819                 });
820 
821                 this.gridDisplay = new GridDisplay(25,((BasicSimWorld)world).getWorldDimensions()[0],((BasicSimWorld)world).getWorldDimensions()[2], Color.black, ((BasicSimWorld)world).getWorldColor(),false);
822                 jPanel3 =  this.gridDisplay;
823                 jPanel3.setLayout(new AbsoluteLayout());
824 
825                // add the simdisplay and griddisplay to the main pane
826                 mainContainer.add(jPanel2, new AbsoluteConstraints(0, 0, ((BasicSimWorld)world).getWorldDimensions()[0], ((BasicSimWorld)world).getWorldDimensions()[2]));
827                 mainContainer.add(jPanel3, new AbsoluteConstraints(0, 0, ((BasicSimWorld)world).getWorldDimensions()[0], ((BasicSimWorld)world).getWorldDimensions()[2]));
828 
829                 //create a light properties dialog
830                 lightProperties = new LightSensorPropertiesDialog();
831                 newGridOption = new GridOptionDialog();
832                 objectEdit = new ObjectEditDialog(this);
833                 colorsPop = new ColorOptionDialog(this);
834                 robotRotation = new RobotRotation(this);
835                 robotRotation.createRobotRotation();
836 
837                 newGridOption.setVisible(false);
838                 colorsPop.setVisible(false);
839                 objectEdit.setVisible(false);
840                 robotRotation.setVisible(false);
841 
842                 JTextField propTitle = new JTextField(" Property Settings: ");
843                 propTitle.setEditable(false);
844                 propTitle.setBackground(Color.darkGray);
845                 propTitle.setForeground(Color.yellow);
846 
847                 JTextField divider2 = new JTextField(" ");
848                 divider2.setEditable(false);
849                 divider2.setBackground(Color.darkGray);
850 
851                 mainContainer.add(divider2,new AbsoluteConstraints(((BasicSimWorld)world).getWorldDimensions()[0],0,15,((BasicSimWorld)world).getWorldDimensions()[2]));
852 
853                 propertyPanel.add(propTitle,new AbsoluteConstraints(10,10,140,20));
854                 propertyPanel.add(colorsPop,new AbsoluteConstraints(10,40,140,240));
855                 propertyPanel.add(objectEdit,new AbsoluteConstraints(10,40,140,375));
856                 propertyPanel.add(newGridOption,new AbsoluteConstraints(10,425,140,155));
857                 //propertyPanel.add(robotRotation,new AbsoluteConstraints(10,590,140,115));
858                 propertyPanel.add(robotRotation,new AbsoluteConstraints(10,40,140,115));
859 
860                 //set the display panel to not be transparent
861                 this.setGrid(false);
862 
863                 // set size to force display to repaint
864                 setSize(this.getWidth(),this.getHeight());
865 
866                 // initialize the stack
867                 this.undoStack.clear();
868                 this.redoStack.clear();
869                 this.pushUndoItem(copyList((LinkedList)world.getObjectList()));
870 
871                 //allows the grid to be draw
872                 this.openWorld = true;
873                 super.setTitle("Simulator: "+this.path+ this.currentWorldFile);
874 
875 
876 
877             }
878             else // simworld creation failed, so just bail out
879             {
880                 //MainInterface.displayMessage("Failed to create SimWorld");
881                 Intellego.addToLog("SimUI.selectWorld(): Failed to create SimWorld with name "+className);
882             }
883         }
884 
885         catch(Exception e){
886             //MainInterface.displayMessage("Failed to create SimWorld");
887             Intellego.addToLog("SimUI.selectWorld(): Failed to create SimWorld");
888         }
889     }
890     
891         
892     /** Handles the clicking of objects
893     * @param evt Mouse event.
894     */
895     private void jPanel2MouseClicked(java.awt.event.MouseEvent evt) 
896     {
897         int x= evt.getX();
898         int y= evt.getY();
899         int b=9999;
900         Point2D mouseClicked = new Point(x,y);
901 
902         LinkedList objectList = ((BasicSimWorld)world).getObjectList();
903 
904         for(int a=0;a<objectList.size();a++){
905             SimObject sim = (SimObject)(objectList.get(a));
906             if(sim instanceof SimGround || sim instanceof SimWall || sim instanceof SimRCX){
907                 Shape newShape = (new Rectangle2D.Double((sim.getXCoord()-sim.getWidth()/2),(sim.getZCoord()-sim.getLength()/2),sim.getWidth(),sim.getLength()));
908                 Shape newShape2 = rotateShape(newShape,sim.getActualBearingXZ(),sim.getXCoord(),sim.getZCoord());
909                 if(newShape2.contains(mouseClicked))b=a; 
910             }
911         }
912 
913         if(b!=9999){
914             SimObject sim = (SimObject)(objectList.get(b)); 
915             if((sim instanceof SimGround && evt.getButton() == evt.BUTTON3) || (sim instanceof SimGround && evt.getButton() == evt.BUTTON1)){
916                 SimGround ground = (SimGround)sim;
917                 deselectOtherObjects();
918                 robotRotation.hide();
919                 setSize(this.getWidth(),this.getHeight());
920                 ground.setOutlineColor(Color.yellow);
921                 ground.setSelected(true);
922                 display.repaint();
923                 if(evt.getButton() == evt.BUTTON3) this.popUpColorOptions(2, "Colour: Ground "+b, ground,null);
924                 else if(evt.getButton() == evt.BUTTON1) {
925                     objectEdit.setVisible(true);
926                     colorsPop.setVisible(false);
927                     if(!this.objectDialogExist){
928                         objectEdit.createObjectEditorPopUp();
929                         this.objectDialogExist = true;
930                     }
931                     objectEdit.updateObjectPopUp(ground,display,b,world);
932                 }
933             }
934             else if(sim instanceof SimWall){
935                 if(evt.getButton() == evt.BUTTON1) {
936                     SimWall wall = (SimWall)sim;
937                     deselectOtherObjects();
938                     robotRotation.hide();
939                     setSize(this.getWidth(),this.getHeight());
940                     wall.setOutlineColor(Color.yellow);
941                     wall.setSelected(true);
942                     display.repaint();
943                     objectEdit.setVisible(true);
944                     colorsPop.setVisible(false);
945                     if(!this.objectDialogExist){
946                         objectEdit.createObjectEditorPopUp();
947                         this.objectDialogExist = true;
948                     }
949                     objectEdit.updateObjectPopUp(wall,display,b,world);
950                 }
951             }
952             else if(sim instanceof SimRCX){
953                if(evt.getButton() == evt.BUTTON1){
954                     SimRCX robot = (SimRCX)sim;
955                     deselectOtherObjects();
956                     robot.setSelected(true);
957                     display.repaint();
958                     this.robotRotation.updateRotation(robot,world);
959                     ROBOT_IS_SELECTED = true;
960                }
961            }
962 
963         }
964         else{
965             deselectOtherObjects();
966             objectEdit.hide();
967             colorsPop.hide();
968             robotRotation.hide();
969             setSize(this.getWidth(),this.getHeight());
970         }
971 
972     }
973      
974     /** Initializes the item desiring dragging
975     * @param evt Mouse event.
976     */
977     private void jPanel2MousePressed(java.awt.event.MouseEvent evt) 
978     { 
979     
980         int x= evt.getX();
981         int y= evt.getY();
982         int b=9999;
983         Point2D mouseClicked = new Point(x,y);
984 
985         LinkedList objectList = ((BasicSimWorld)world).getObjectList();
986 
987         for(int a=0;a<objectList.size();a++){
988 
989             SimObject sim = (SimObject)(objectList.get(a));
990 
991             if(sim instanceof SimGround || sim instanceof SimWall || sim instanceof SimRCX){
992 
993                 Shape newShape = (new Rectangle2D.Double((sim.getXCoord()-sim.getWidth()/2),(sim.getZCoord()-sim.getLength()/2),sim.getWidth(),sim.getLength()));
994                 Shape newShape2 = rotateShape(newShape,sim.getActualBearingXZ(),sim.getXCoord(),sim.getZCoord());
995                 if(newShape2.contains(mouseClicked))b=a;
996             }
997         }
998 
999         if(evt.getButton() == evt.BUTTON1){  
1000            if(b!=9999){
1001                this.robotObjects=null;
1002                SimObject sim = (SimObject)(objectList.get(b));
1003                if(sim instanceof SimGround) {
1004                    SimGround ground = (SimGround)sim;
1005                    deselectOtherObjects();
1006                    ground.setOutlineColor(Color.yellow);
1007                    ground.setSelected(true);
1008                }
1009                else if(sim instanceof SimWall){ 
1010                    SimWall wall = (SimWall)sim;
1011                    deselectOtherObjects();
1012                    wall.setOutlineColor(Color.yellow);
1013                    wall.setSelected(true);
1014                }
1015                else if(sim instanceof SimRCX){ 
1016                    SimRCX robot = (SimRCX)sim;
1017                    deselectOtherObjects();
1018                    robot.setSelected(true);
1019                }
1020
1021                display.repaint();
1022
1023                //stores the status denoting an object is to be dragged
1024                selectedObject=true;
1025
1026                //stores the index of the to be dragged item for the Linked List of Objects
1027                objectIndex=b;
1028
1029                //allow the user to grab and drag an item from any point on the object
1030                offSetX=(int)sim.getXCoord()-evt.getX();
1031                offSetY=(int)sim.getZCoord()-evt.getY();
1032             }
1033        }
1034
1035        else if(evt.getButton() == evt.BUTTON3 && this.ROBOT_IS_SELECTED){
1036            if(b!=9999){
1037                this.robotObjects=null;
1038                SimObject sim = (SimObject)(objectList.get(b));
1039                if(sim instanceof SimRCX){
1040                    display.repaint();
1041                    BEGIN_ROTATION = true;
1042                    objectIndex=b;
1043                    offSetX=(int)sim.getXCoord()-evt.getX();
1044                    offSetY=(int)sim.getZCoord()-evt.getY();
1045
1046                    INITIAL_X_ROT = (int)evt.getX();
1047                    INITIAL_Y_ROT = (int)evt.getY();
1048                    
1049                }
1050            }
1051
1052        }
1053    }
1054    
1055    /** Controls the dragged item
1056     * @param evt Mouse event.
1057    */    
1058    private void jPanel2MouseDragged(java.awt.event.MouseEvent evt) 
1059    {
1060        if(selectedObject){
1061            
1062            BasicSimObject moveMe = (BasicSimObject)world.getObjectList().get(objectIndex);
1063            if(evt.getX() >= 0 && evt.getX() <= ((BasicSimWorld)world).getWorldDimensions()[0]) moveMe.setXCoord(evt.getX()+offSetX);
1064            if(evt.getY() >= 0 && evt.getY() <= ((BasicSimWorld)world).getWorldDimensions()[2])moveMe.setZCoord(evt.getY()+offSetY);
1065            display.repaint();
1066           
1067        }
1068        
1069        else if(BEGIN_ROTATION){
1070            try
1071            {
1072                int VALUE = (int)(((SimRCX)(world.getObjectList().get(objectIndex))).getActualBearingXZ())+(int)(evt.getX() - this.INITIAL_X_ROT);
1073                
1074                ((SimRCX)(world.getObjectList().get(objectIndex))).setActualBearingXZ(VALUE);
1075                robotRotation.updateValue(((SimRCX)(world.getObjectList().get(objectIndex))));
1076                display.repaint();
1077            }
1078            catch(Exception e2){}
1079        
1080        }
1081        
1082        //mouse coordinate display
1083         if(evt.getX() >= 0 && evt.getX() <= ((BasicSimWorld)world).getWorldDimensions()[0]) this.xT.setText(""+evt.getX());
1084         if(evt.getY() >= 0 && evt.getY() <= ((BasicSimWorld)world).getWorldDimensions()[2])this.zT.setText(""+evt.getY()); 
1085    }
1086    
1087    /** Positions the dragged item in the desired location
1088     * @param evt Mouse event.
1089     */    
1090    private void jPanel2MouseReleased(java.awt.event.MouseEvent evt) {
1091         if(selectedObject){
1092            
1093             //undo/redo purposes *****
1094            this.pushUndoItem(copyList((LinkedList)world.getObjectList()));
1095             
1096            BasicSimObject moveMe = (BasicSimObject)world.getObjectList().get(objectIndex);
1097
1098            if(moveMe instanceof SimGround) {
1099                SimGround ground = (SimGround)moveMe;
1100                ground.setOutlineColor(Color.black);
1101                ground.setSelected(false);
1102            }
1103            else if(moveMe instanceof SimWall){ 
1104                SimWall wall = (SimWall)moveMe;
1105                wall.setOutlineColor(Color.black);
1106                wall.setSelected(false);
1107            }
1108            else if(moveMe instanceof SimRCX){ 
1109                SimRCX robot = (SimRCX)moveMe;
1110                robot.setSelected(false);
1111                this.robotRotation.hide();
1112            }
1113                    
1114               
1115            display.repaint();
1116            selectedObject = false;
1117            deselectOtherObjects();
1118            objectEdit.hide();
1119            colorsPop.hide();
1120            robotRotation.hide();
1121            setSize(this.getWidth(),this.getHeight());
1122            
1123        }
1124         
1125    }
1126   
1127    /** Positions the dragged item in the desired location
1128    * @param evt Mouse event.
1129    */    
1130    private void jPanel2MouseMoved(java.awt.event.MouseEvent evt) {
1131         if(evt.getX() >= 0 && evt.getX() <= ((BasicSimWorld)world).getWorldDimensions()[0]) this.xT.setText(""+evt.getX());
1132         if(evt.getY() >= 0 && evt.getY() <= ((BasicSimWorld)world).getWorldDimensions()[2]) this.zT.setText(""+evt.getY());    
1133    }
1134    
1135    /** Rotates a shape so that selection of a rotated shape may occur.
1136     * @param shape the name of the shape
1137     * @param angle the angle that it has been rotated
1138     * @param X the X position
1139     * @param Z the X position
1140     * @return the new oriented shape
1141     */    
1142    private Shape rotateShape(Shape shape, double angle, double X, double Z)
1143    {
1144        // convert the angle to radians
1145        double theta=Math.toRadians(angle);
1146
1147        // create a new affine transform rotator
1148        AffineTransform  atx = AffineTransform.getRotateInstance(theta,X,Z); 
1149
1150        // create a rotated version of the shape
1151        shape = atx.createTransformedShape(shape);
1152
1153        // return the shape
1154        return shape;
1155    }
1156
1157    /** Dynamically loads a simworld class
1158     * @param name the name of the simworld as a string
1159     * @return the simworld, or null if unsuccessful
1160     */
1161    public SimWorld createSimWorld(String name)
1162    {
1163        SimWorld s=null;
1164
1165        try
1166        {
1167            // try to create the class
1168            Class simworldClass=Class.forName(name);
1169
1170            try
1171            {
1172                // try to cast the class to a SimWorld, this will fail if the class
1173                // is not a valid Intellego SimWorld
1174                s=(SimWorld)simworldClass.newInstance();
1175            }
1176            catch (Exception e)
1177            {
1178                MainInterface.displayMessage("Error: this class is not a valid Intellego SimWorld");
1179            }
1180        }
1181
1182        catch (Exception e)
1183        {
1184            // failed to create the class, so return null
1185            //MainInterface.displayMessage("Error creating class");
1186            Intellego.addToLog("SimUI.createSimWorld(): Error creating class: "+name+": "+e);
1187            return null;
1188        }
1189
1190        // return the simworld
1191        return s;
1192    }
1193    
1194    /**
1195    * Allows the user to pick a robot class, and loads it into this simulation
1196    */
1197    public void addRobot()
1198    {
1199        if(world==null || display==null)
1200        {
1201            MainInterface.displayMessage("You must select a SimWorld and a SimDisplay first");
1202        }
1203        else
1204        {
1205            try{this.stopSimulation();}
1206            catch(Exception e2){}
1207            try{
1208                // get the name of the class from the user
1209                File file = getClassName("Pick a Controller class file:","controllers");
1210                String className = file.getName();
1211                className=className.substring(0,file.getName().length() - 6);
1212                
1213                // check user actually selected a class name
1214                if (className.equals(NO_CLASS))
1215                {
1216                     // do nothing
1217                }
1218                else
1219                {
1220                    Controller c=createController(file);
1221
1222                    if(c!=null)
1223                    {
1224                        // and add it to the system if it is not null
1225                        addController(c);
1226                    }
1227                    else
1228                    {
1229                        MainInterface.displayMessage("Failed to create Controller");
1230                        Intellego.addToLog("SimUI.addRobot(): Failed to create Controller with name "+className);
1231                    }
1232                }
1233            }
1234            catch(Exception e){}
1235        }
1236    }
1237    
1238    /**
1239    * Gets the class name of the required class from the user 
1240    * using a JFileChooser
1241    * @param title the title to display in the FileChooser window
1242    * @param base_dir the directory to start looking in
1243    * @return the classname as string
1244    */
1245    public File getClassName(String title,String base_dir)
1246    {
1247        //String className=" ";
1248        File file = null;
1249        // pop up a file chooser dialog
1250        JFileChooser chooser=new JFileChooser(new File(System.getProperties().getProperty("user.dir"),base_dir));
1251
1252        // add a filename filter for class files
1253        String[] extensions={".class"};
1254        chooser.addChoosableFileFilter(new FileChooserFilter(extensions,"Compiled Class File"));
1255
1256        //set color
1257        for(int a=0;a<chooser.getComponentCount();a++){
1258            Container a1 =(Container)chooser.getComponent(a);
1259                if(a1 instanceof JTextField ||a1 instanceof JComboBox || a1 instanceof JButton ){
1260                    a1.setBackground(Color.darkGray);
1261                    a1.setForeground(Color.lightGray);
1262                 }
1263            for(int b=0;b<((Container)chooser.getComponent(a)).getComponentCount();b++){
1264                Container b1 =(Container)((Container)chooser.getComponent(a)).getComponent(b);
1265                if(b1 instanceof JTextField ||b1 instanceof JComboBox || b1 instanceof JButton ){
1266                    b1.setBackground(Color.darkGray);
1267                    b1.setForeground(Color.lightGray);
1268                }
1269                 for(int c=0;c<((Container)((Container)chooser.getComponent(a)).getComponent(b)).getComponentCount();c++){
1270                    Container c1 =(Container)((Container)((Container)chooser.getComponent(a)).getComponent(b)).getComponent(c);
1271                    if(c1 instanceof JTextField ||c1 instanceof JComboBox || c1 instanceof JButton ){
1272                        c1.setBackground(Color.darkGray);
1273                        c1.setForeground(Color.lightGray);
1274                     }
1275                }
1276            }
1277        }
1278
1279        int returnVal=chooser.showOpenDialog(this);
1280
1281        try
1282        {
1283            if (returnVal==JFileChooser.APPROVE_OPTION) // user has selected a file
1284            {
1285                // get the user's selected file
1286                file=chooser.getSelectedFile();
1287
1288
1289                //sets the path only for worldobjects
1290                if(base_dir.equals("simworlds")){    
1291                    path = ((file.getPath()).substring(0,(((file.getPath()).length()) - ((file.getName()).length()))));
1292                    currentWorldFile = file.getName();
1293                }
1294
1295                // return the file
1296                return (file);
1297            }
1298
1299            else // user selected cancel or some other button we are going to ignore
1300            {
1301                return null;//NO_CLASS;
1302            }
1303
1304        }
1305        catch(Exception e)
1306        {
1307            return null;
1308        }
1309    }
1310    
1311    /** Dynamically loads a controller class
1312     * Modified by: Simon Zienkiewicz
1313     * @return the controller, or null if unsuccessful
1314     * @param file the name of the file
1315     */
1316    public Controller createController(File file)
1317    {
1318        Controller c=null;
1319        Class controllerClass=null;
1320        String name = file.getName();
1321        name=name.substring(0,file.getName().length() - 6);
1322
1323        try
1324        {   // try to create the class
1325            AdaptiveClassLoader extra = new AdaptiveClassLoader(new Vector());
1326            controllerClass = extra.loadClass(file,false);
1327
1328            try
1329            {
1330                // try to cast the class to a Controller, this will fail if the class
1331                // is not a valid Intellego Controller
1332                c=(Controller)controllerClass.newInstance();
1333                Intellego.addToLog("SimUI.createController(): class "+name+": CREATED SUCCESSFULLY");
1334            }
1335            catch (Exception e)
1336            {
1337                MainInterface.displayMessage("Error: class is not a valid Intellego Controller class");
1338                Intellego.addToLog("SimUI.createController(): Attempt to create Intellego Controller "+name+" failed. Not a valid Controller.");
1339            }
1340        }
1341        catch (Exception e)
1342        {
1343            // failed to create the class, so return null
1344            MainInterface.displayMessage("Error creating class");
1345            Intellego.addToLog("SimUI.createController(): Error creating class "+name+": "+e);
1346            return null;
1347        }
1348
1349        // return the controller
1350        return c;
1351    }
1352    
1353    /**
1354    * Adds a controller to this simulation
1355    * @param c the controller to be added
1356    */
1357    public void addController(Controller c)
1358    {
1359        // check if controller creation was successsful
1360        if(c!=null)
1361        {   Intellego.addToLog("SimUI.addController: C is not null");
1362            // ... if so then add this controller to the list
1363            controllerList.add(c);
1364
1365            // and get robot details
1366            d=new InitRobotDialog();
1367                        
1368            //possible future improvements could use hard coded simulation
1369            //values such as battery voltage
1370            //this is beyond the scope of the current version
1371            //d.setVisible(true);
1372
1373            // create the robot
1374            d.createRobot(world,c,display,this);
1375            d.callOK();
1376            d.hide();
1377            
1378            colorsPop.hide();
1379            objectEdit.hide();
1380
1381            propertyPanel.add(d,new AbsoluteConstraints(10,40,140,300));
1382            setSize(this.getWidth(),this.getHeight());
1383            //initialize light sensor readings if the robot possesses any light sensors
1384            this.setLightSensorProperties();
1385            lightProp.setEnabled(true);
1386
1387            // and repaint the display
1388            repaint();
1389        }
1390        else // failed to create controller
1391        {
1392            MainInterface.displayMessage("Failed to add controller");
1393            Intellego.addToLog("SimUI.addController: Failed to add controller");
1394        }
1395    }
1396
1397    /**
1398    * Starts this simulation (by starting a new thread for this instance)
1399    */
1400    public void startSimulation()
1401    {
1402        // check there is a simworld and a simdisplay open
1403        if (world==null || display==null)
1404        {
1405            // if not display an error message
1406            MainInterface.displayMessage("You must pick a SimWorld and a SimDisplay first");
1407        }
1408        else
1409        {
1410
1411           // set this sim running in a new thread
1412            running=true;
1413            t =new Thread(this);
1414            exit = true;
1415            t.start();
1416
1417            this.simulation_is_ON();
1418
1419            super.setTitle("Simulation State: PLAYING");
1420
1421            Thread clean = new Thread(new GarbageCleanUp());
1422            clean.setPriority(Thread.MAX_PRIORITY);
1423            clean.start();
1424
1425            // start up all the controllers
1426            for (int i=0;i<controllerList.size();i++)
1427            {
1428                Controller c=(Controller)controllerList.get(i);
1429                Thread u=new Thread(c);
1430                u.setPriority(Thread.MIN_PRIORITY);
1431                u.start();
1432                Intellego.addToLog("SimUI.run(): Started controller");
1433            }
1434
1435        }
1436    }
1437        
1438    /** A class that runs a thread in order to initiate the garbage collector and recycle memory. */    
1439    private class GarbageCleanUp extends Thread{
1440
1441        /** A method that runs a thread in order to initiate the garbage collector and
1442         * recycle memory.
1443         */        
1444        public GarbageCleanUp(){
1445            System.gc();
1446        }
1447    }
1448    
1449    /**
1450    * Stops this simulation
1451    */
1452    public void stopSimulation()
1453    {
1454        // check there is a simworld and a simdisplay open
1455        if (world==null || display==null)
1456        {
1457            // if not display an error message
1458            MainInterface.displayMessage("No simulation to stop");
1459        }
1460        else
1461        {
1462            this.simulation_is_OFF();
1463            exit = false;
1464            running = false;
1465            super.setTitle("Simulator: "+this.path+ this.currentWorldFile);
1466
1467        }
1468    }
1469                      
1470    /** Creates a dialog window from where the user can alter simulation colors
1471     * @param index the index of the object
1472     * @param name the name of the object
1473     * @param simg the name if the object is an instance of SimGround, otherwise NULL
1474     * @param grid the name if the object is an instance of SimGrid, otherwise NULL
1475     */       
1476    private void popUpColorOptions(int index, String name, SimGround simg, GridDisplay grid){
1477        if(openWorld){
1478            colorsPop.setVisible(true);
1479            objectEdit.setVisible(false);
1480            if(!colorDialogExist){
1481                colorsPop.createColorPopUp();
1482                colorDialogExist = true;
1483            }
1484            if(index != 2)deselectOtherObjects();
1485            
1486            switch(index){
1487                case 0: colorsPop.updateColorPopUp(name, index,display,world,"wall",simg, grid);
1488                        break;
1489                case 1: colorsPop.updateColorPopUp(name, index,display,world,null,simg, grid);
1490                        break;
1491                case 2: colorsPop.updateColorPopUp(name, index,display,world,null,simg, grid);
1492                        break;
1493                case 3: colorsPop.updateColorPopUp(name, 0,display,world,"sensorTouch",simg, grid);
1494                        break;
1495                case 4: colorsPop.updateColorPopUp(name, 0,display,world,"sensorLight",simg, grid);
1496                        break;
1497                case 5: colorsPop.updateColorPopUp(name, 0,display,world,"robot",simg, grid);
1498                         break;
1499                case 6: colorsPop.updateColorPopUp(name, index,display,world,null,simg, grid);
1500                         break;
1501                case 7: colorsPop.updateColorPopUp(name, 0,display,world,"road",simg, grid);
1502                         break;
1503             }
1504        }
1505    }
1506    
1507    /** Deselects all the objects except the selected object. */    
1508    private void deselectOtherObjects(){
1509        
1510        LinkedList newList = ((BasicSimWorld)world).getObjectList();
1511        
1512        for(int i=0;i<newList.size();i++){
1513            SimObject simObject2 = (SimObject)newList.get(i);
1514            if(simObject2 instanceof SimGround){
1515                ((SimGround)simObject2).setSelected(false);
1516                ((SimGround)simObject2).setOutlineColor(Color.black);
1517                display.repaint();
1518            }
1519            else if(simObject2 instanceof SimWall){
1520                ((SimWall)simObject2).setSelected(false);
1521                ((SimWall)simObject2).setOutlineColor(Color.black);
1522                display.repaint();
1523            }
1524            else if(simObject2 instanceof SimRCX){
1525                ((SimRCX)simObject2).setSelected(false);
1526                this.robotRotation.hide();
1527                 display.repaint();   
1528            }
1529        }
1530        
1531        ROBOT_IS_SELECTED = false;
1532        BEGIN_ROTATION = false;
1533        display.repaint();
1534        
1535    }
1536    
1537    /** Adds a SimGround or SimWall object to the world
1538     * @param type the type of object
1539     */     
1540    private void addObjectToWorld(String type){
1541        if(!lock.isSelected()){
1542            if(openWorld){
1543                if(type.equals("wall")){
1544                    SimWall newWall = new SimWall(150.0,0.0,50.0,0.0,200.0,30.0);
1545                    ((BasicSimWorld)world).addObjecttoFront(newWall);
1546
1547                }
1548                else{
1549                    Random randomColor = new Random();
1550                    double colorIndex = randomColor.nextDouble();
1551                    Color groundColor=Color.blue;
1552                    if(colorIndex >= 0.5) groundColor=Color.black;
1553
1554                    SimGround newGround = new SimGround(450.0,0.0,150.0,0.0,(int)(50+(50*colorIndex)*2),(int)(50+(50*colorIndex)*2),groundColor);
1555                    ((BasicSimWorld)world).addObjecttoFront(newGround);
1556                }
1557               display.repaint();
1558               
1559               //undo/redo purposes *****
1560               this.pushUndoItem(copyList((LinkedList)world.getObjectList()));
1561            }
1562        }
1563       
1564      }
1565     
1566    /** Creates a dialog window from where the user can alter grid Options
1567     * @param title the title of the grid options dialog
1568     */  
1569    private void popUpGridOptions(String title){
1570        if(openWorld){
1571        newGridOption.setVisible(true);
1572            if(!gridDialogExist){
1573                newGridOption.createGridPopUp(title, gridDisplay, display, this);
1574                gridDialogExist=true;
1575            }
1576            else newGridOption.show();
1577        }
1578    }
1579    
1580    /**
1581    * Allows the saving of a designed world
1582    */  
1583    private void saveWorld(){
1584        if(world != null){
1585            SaveWorldDialog saveWorld = new SaveWorldDialog();
1586            saveWorld.createSaveWorldPopUp(path,world,this.currentWorldFile);
1587        }
1588        else{
1589            MainInterface.displayMessage("Cannot save an empty world");
1590            Intellego.addToLog("SimUI.saveWorld(): Save to file failed: ");
1591        }
1592    }
1593    
1594    /** Determines if the grid is turned on or off
1595     * @return true if gird is on, false otherwise
1596     */  
1597    public boolean isGridOn(){
1598        return jPanel3.isVisible();
1599    }
1600    
1601    /** Sets the grid on if true, off if false
1602     * @param a true to set grid on, false otherwise
1603     */  
1604    public void setGrid(boolean a){
1605        if(a){
1606            jPanel2.setOpaque(false);
1607            display.repaint();
1608            jPanel3.setVisible(true);
1609            
1610        }
1611        else{ 
1612            jPanel3.setVisible(false);  
1613            jPanel2.setOpaque(true);
1614            display.repaint();
1615            
1616        }
1617    }
1618    
1619    /**
1620    * Sets the Light Sensor Proptertises
1621    */  
1622    private void setLightSensorProperties(){
1623        
1624        if(!colorPropertiesExist){
1625            lightProperties.createLightSensorPropertiesPopUp();
1626            colorPropertiesExist=true;
1627            
1628        }
1629        else{
1630            lightProperties.call();
1631        }
1632    
1633    }
1634    
1635    /** Executes is an item has changed state.
1636     * @param e event
1637     */    
1638    public void itemStateChanged(ItemEvent e) {
1639        Object source = e.getItemSelectable();
1640        if(source == lock){
1641            if(lock.isSelected()){
1642                deselectOtherObjects();
1643                objectEdit.hide();
1644                colorsPop.hide();
1645                setSize(this.getWidth(),this.getHeight());
1646            }
1647        }
1648    }
1649    
1650    /** Puts objects in the undo, redo stack accordingly.
1651     * @param a the indicator, either "undo" or "redo"
1652     */    
1653    private void undoRedoSet(String a){
1654    
1655        if(a.equals("undo")){
1656            
1657            enableUndo(2);
1658            LinkedList b = (LinkedList) this.undoStack.pop();
1659            
1660            this.redoStack.push(b);
1661            ((BasicSimWorld)world).updateObjectList(copyList((LinkedList)this.undoStack.peek()));
1662            this.redo.setEnabled(true);
1663       }
1664        
1665        else{
1666    
1667            if(redoStack.size() >=1){
1668                //push onto undo stack
1669                LinkedList b = (LinkedList) this.redoStack.pop();
1670                this.undoStack.push(b);
1671                //update the screen
1672                ((BasicSimWorld)world).updateObjectList(copyList(b));
1673                
1674                if(redoStack.isEmpty())this.redo.setEnabled(false);
1675                }
1676            enableUndo(1);
1677        }
1678        
1679        this.objectEdit.hide();
1680        setSize(this.getWidth(),this.getHeight());
1681        display.repaint();
1682    
1683    }
1684    
1685    /** Enables the undo stack if its possible.
1686     * @param i the test to see if the undo stack can be enabled
1687     */    
1688    private void enableUndo(int i){
1689    
1690        if(this.undoStack.size()<= i) this.undo.setEnabled(false);
1691        else this.undo.setEnabled(true);
1692        
1693    }
1694    
1695    /** Pushes an item into the undo stack.
1696     * @param a the linklist which contains the item
1697     */    
1698    public void pushUndoItem(LinkedList a){
1699        
1700        //check for clone
1701        try{ 
1702            if(a.size() == ((LinkedList)this.undoStack.peek()).size())
1703
1704                for(int i=0;i<a.size();i++){
1705                    
1706                    BasicSimObject c = (BasicSimObject)a.get(i);
1707                    BasicSimObject d = (BasicSimObject)((LinkedList)this.undoStack.peek()).get(i);
1708
1709                    if(c instanceof SimWall){
1710                        if(c.getXCoord() == d.getXCoord() && c.getYCoord() == d.getYCoord() && c.getZCoord() == d.getZCoord()
1711                                && c.getActualBearingXZ() == d.getActualBearingXZ() && c.getLength() == d.getLength() && c.getWidth() == c.getWidth())
1712                        {
1713                            //do nothing since they are the same   
1714                        }
1715                        
1716                        else{
1717                            this.undoStack.push(a);
1718                            break;
1719                        }
1720                    }
1721                    else if(c instanceof SimGround){
1722                        
1723                        SimGround e = (SimGround)c;
1724                        SimGround f = (SimGround)d;
1725                        
1726                        if(e.getXCoord() == f.getXCoord() && e.getYCoord() == f.getYCoord() && e.getZCoord() == f.getZCoord()
1727                                && e.getActualBearingXZ() == f.getActualBearingXZ() && e.getLength() == f.getLength() && e.getWidth() == f.getWidth() && e.getColor().getRGB() == f.getColor().getRGB())
1728                        {
1729                            //do nothing since they are the same  
1730                            
1731                        }
1732                        
1733                        else{
1734                            this.undoStack.push(a);
1735                            break;
1736                        }
1737                    }
1738                }
1739            else this.undoStack.push(a);
1740          
1741        }
1742        catch(Exception e){this.undoStack.push(a);}
1743        
1744        this.redoStack.clear();
1745        this.redo.setEnabled(false);
1746        enableUndo(1);
1747    }
1748    
1749    /** Copies the entire contents of one linked list and returns a new linked list of
1750     * the same size and contents.
1751     * @param a the linklist requiring duplication (ORIGINAL)
1752     * @return a new linklist mirroring the original (COPY)
1753     */    
1754    public LinkedList copyList(LinkedList a){
1755        
1756        LinkedList b = new LinkedList();
1757        for(int i=0;i<a.size();i++){
1758            
1759            SimObject c = (SimObject)a.get(i);
1760            
1761            if(c instanceof SimWall){
1762                b.add(new SimWall(c.getXCoord(),c.getYCoord(),c.getZCoord(),c.getActualBearingXZ(),c.getLength(),c.getWidth()));
1763            }
1764            
1765            else if(c instanceof SimGround){
1766                b.add(new SimGround(c.getXCoord(),c.getYCoord(),c.getZCoord(),c.getActualBearingXZ(),c.getLength(),c.getWidth(),((SimGround)c).getColor()));
1767            }
1768            
1769            else b.add(c);
1770            
1771        }
1772        return b;
1773    }
1774     
1775}