Package maze.gui

Source Code of maze.gui.PrimaryFrame$LookAndFeelListener

package maze.gui;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.DisplayMode;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.nio.CharBuffer;
import java.util.Enumeration;
import java.util.Properties;

import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.filechooser.FileFilter;

import maze.Main;
import maze.gui.mazeeditor.MazeEditorPage;
import maze.model.MazeInfoModel;

/**
* This is the primary frame for the application.
*/
public final class PrimaryFrame extends JFrame
{
   private static final String LATEST_REVISION_URI = "http://maze-solver.googlecode.com/svn/wiki/LatestRevision.wiki";
   private static final String PROJECT_HOMEPAGE = "http://code.google.com/p/maze-solver/";

   /**
    * An ActionListener that changes the swing look and feel.
    */
   private class LookAndFeelListener implements ActionListener
   {
      @Override
      public void actionPerformed(ActionEvent e)
      {
         try
         {
            UIManager.setLookAndFeel(e.getActionCommand());
            SwingUtilities.updateComponentTreeUI(PrimaryFrame.this);
         }
         catch (Exception ex)
         {}
      }
   }

   private static final Dimension DEFAULT_SIZE = new Dimension(1024, 768);
   private ScriptEditorPage codeEditorPanel;
   private final JMenu fileMenu = new JMenu("File");
   private final JTabbedPane mainTabs = new JTabbedPane();
   private MazeEditorPage mazeEditor;
   private MazeViewerPage mazeViewer;
   private final MazeInfoModel mMazeInfoModel = new MazeInfoModel();

   /**
    * Called when the application is closed. Perform application exit
    * cleanup.This gives us a chance to cleanup and prompt to save things.
    * @return true if it is OK for the application to exit. false if the
    *         application should about the exit.
    */
   private boolean canExitingApplication()
   {
      return this.mazeEditor.canExit() && this.codeEditorPanel.canExit();
   }

   /**
    * Bring up the open file dialog and based on the file type selected hand it
    * off to the appropriate panel. The 2 groups of files are AI scripts and
    * maze files. AI scripts are python .py files and maze maps can be .maz or
    * .mz2.
    */
   private void doOpenFile()
   {
      final MenuControlled[] panels =
      {
         codeEditorPanel, mazeEditor
      };
      final JFileChooser fc = new JFileChooser();
      fc.setAcceptAllFileFilterUsed(false);

      // Create a file filter for all our file types.
      FileFilter allFiles = new FileFilter()
      {
         @Override
         public boolean accept(File f)
         {
            if (f.isDirectory())
               return true;
            for (MenuControlled mc : panels)
            {
               if (mc.isMyFileType(f))
                  return true;
            }
            return false;
         }

         @Override
         public String getDescription()
         {
            String msg = "";
            for (MenuControlled mc : panels)
            {
               msg += mc.getFileTypeDescription() + ", ";
            }
            return msg.substring(0, msg.length() - 2);
         }
      };
      fc.addChoosableFileFilter(allFiles);

      // Add filter for each type.
      for (final MenuControlled mc : panels)
      {
         fc.addChoosableFileFilter(new FileFilter()
         {
            @Override
            public boolean accept(File f)
            {
               if (f.isDirectory())
                  return true;
               else
                  return mc.isMyFileType(f);
            }

            @Override
            public String getDescription()
            {
               return mc.getFileTypeDescription();
            }
         });
      }

      fc.setFileFilter(allFiles); // Set initially selected.

      if (fc.showOpenDialog(PrimaryFrame.this) == JFileChooser.APPROVE_OPTION)
      {
         File file = fc.getSelectedFile();
         try
         {
            if (file.exists() && file.canRead())
            {
               // Try to open the file so it throws an exception if the file can not be read.
               FileInputStream fileStream = null;
               try
               {
                  fileStream = new FileInputStream(file);
               }
               finally
               {
                  if (fileStream != null)
                     fileStream.close();
               }
               for (final MenuControlled mc : panels)
               {
                  if (mc.isMyFileType(file))
                  {
                     mainTabs.setSelectedComponent((Component) mc);
                     mc.open(file);
                     return;
                  }
               }
               // If we make it this far then nobody recognized the file type.
               throw new RuntimeException("The type of the selected file was not recognized.");
            }
            else
            {
               throw new SecurityException("File may not exist.");
            }
         }
         catch (Exception ex)
         {
            ex.printStackTrace();
            String msg = "There was an error opening the file.\n" + ex.getLocalizedMessage();
            JOptionPane.showMessageDialog(PrimaryFrame.this,
                                          msg,
                                          "File Open Error",
                                          JOptionPane.ERROR_MESSAGE);
         }
      }
   } // End open file.

   /**
    * Exits the application.
    */
   public void exit()
   {
      if (this.canExitingApplication())
      {
         this.setVisible(false);
         System.exit(0);
      }
   }

   /**
    * Get the date that this build was created on.
    * @return Date string or <code>Unknown</code>.
    */
   private String getApplicationBuildDate()
   {
      final String unknown = "Unknown";
      InputStream is = null;
      try
      {
         Properties prop = new Properties();
         // This properties file is created by Ant during the build process.
         is = Main.class.getResourceAsStream("build.properties");
         prop.load(is);
         return prop.getProperty("date", unknown);
      }
      catch (Exception e1)
      {
         return unknown;
      }
      finally
      {
         try
         {
            if (is != null)
               is.close();
         }
         catch (IOException e)
         {
            e.printStackTrace();
         }
      }
   }

   /**
    * Get the subversion revision this application was built from.
    * @return The Subversion revision number or 0 if unknown.
    */
   private int getApplicationRevision()
   {
      InputStream is = null;
      try
      {
         Properties prop = new Properties();
         // This properties file is created by Ant during the build process.
         is = Main.class.getResourceAsStream("build.properties");
         if (is != null)
         {
            prop.load(is);
            return Integer.parseInt(prop.getProperty("revision", "0"));
         }
      }
      catch (NumberFormatException e)
      {}
      catch (IOException e1)
      {}
      finally
      {
         try
         {
            if (is != null)
               is.close();
         }
         catch (IOException e)
         {
            e.printStackTrace();
         }
      }
      return 0; // On error.
   }

   /**
    * Returns a MazeInfoModel object containing all of the currently loaded
    * mazes.
    * @return said MazeInfoModel object.
    */
   public MazeInfoModel getMazeInfoModel()
   {
      return mMazeInfoModel;
   }

   /**
    * Initializes the contents of this frame.
    */
   public void init()
   {
      // Set up the application close procedure.
      this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
      this.addWindowListener(new WindowAdapter()
      {
         @Override
         public void windowClosing(WindowEvent e)
         {
            exit();
         }
      });

      this.setMinimumSize(new Dimension(750, 550)); // Set minimum to fit on an 800x600 screen.
      // If the screen is small then maximize the frame.
      DisplayMode dm = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode();
      if (dm.getWidth() <= DEFAULT_SIZE.width || dm.getHeight() <= DEFAULT_SIZE.height + 25)
      {
         this.setExtendedState(JFrame.MAXIMIZED_BOTH);
      }
      else
      {
         this.setSize(DEFAULT_SIZE);
         // Center the frame on the screen.
         this.setLocation(dm.getWidth() / 2 - DEFAULT_SIZE.width / 2, dm.getHeight() /
                                                                      2 -
                                                                      DEFAULT_SIZE.height /
                                                                      2);
      }

      this.setTitle("Micro Mouse Maze Editor and Simulator");
      this.setIconImage(Main.getImageResource("gui/images/logo.png").getImage());

      // Main menu bar.
      final JMenuBar menuBar = new JMenuBar();
      this.setJMenuBar(menuBar);
      menuBar.add(this.fileMenu);

      //New file menu.
      JMenu newMenu = new JMenu("New");
      fileMenu.add(newMenu);

      //New maze.
      JMenuItem newMaze = new JMenuItem("Maze...");
      newMaze.addActionListener(new ActionListener()
      {
         @Override
         public void actionPerformed(ActionEvent e)
         {
            mainTabs.setSelectedComponent(mazeEditor);
            mazeEditor.newMaze();
         }
      });
      newMenu.add(newMaze);

      JMenuItem newScript = new JMenuItem("AI Script...");
      newMenu.add(newScript);
      newScript.addActionListener(new ActionListener()
      {
         @Override
         public void actionPerformed(ActionEvent e)
         {
            mainTabs.setSelectedComponent(codeEditorPanel);
            codeEditorPanel.createNewEditor();
         }
      });

      // Open file.
      JMenuItem fileLoad = new JMenuItem("Open...");
      fileLoad.addActionListener(new ActionListener()
      {
         @Override
         public void actionPerformed(ActionEvent e)
         {
            doOpenFile();
         }
      });

      fileMenu.add(fileLoad);

      // Save
      JMenuItem fileSave = new JMenuItem("Save");
      fileSave.addActionListener(new ActionListener()
      {
         @Override
         public void actionPerformed(ActionEvent e)
         {
            Component c = mainTabs.getSelectedComponent();
            if (c instanceof MenuControlled)
            {
               MenuControlled mc = (MenuControlled) c;
               mc.saveCurrent();
            }
         }
      });
      fileMenu.add(fileSave);

      // Close file.
      JMenuItem fileClose = new JMenuItem("Close");
      fileClose.addActionListener(new ActionListener()
      {
         @Override
         public void actionPerformed(ActionEvent e)
         {
            Component c = mainTabs.getSelectedComponent();
            if (c instanceof MenuControlled)
            {
               MenuControlled mc = (MenuControlled) c;
               mc.close();
            }
         }
      });
      fileMenu.add(fileClose);

      // exit
      fileMenu.addSeparator();
      JMenuItem fileExit = new JMenuItem("Exit");
      fileMenu.add(fileExit);
      fileExit.addActionListener(new ActionListener()
      {
         @Override
         public void actionPerformed(ActionEvent e)
         {
            exit();
         }
      });

      // Help menu.
      JMenu helpMenu = new JMenu("Help");
      menuBar.add(helpMenu);

      //Help
      JMenuItem helpItem = new JMenuItem("Help");
      helpMenu.add(helpItem);

      helpItem.addActionListener(new ActionListener()
      {
         @Override
         public void actionPerformed(ActionEvent e)
         {
            HelpInfo.createAndShowGUI();
         }
      });

      // Look and feel menu.
      String defaultLAF = "";
      JMenu lookAndFeel = new JMenu("Look And Feel");
      helpMenu.add(lookAndFeel);
      ButtonGroup lafBG = new ButtonGroup();
      LookAndFeelListener lafal = new LookAndFeelListener();
      boolean nimbusFound = false;
      for (LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels())
      {
         JRadioButtonMenuItem jrbmi = new JRadioButtonMenuItem(laf.getName());
         lafBG.add(jrbmi);
         jrbmi.addActionListener(lafal);
         jrbmi.setActionCommand(laf.getClassName());
         lookAndFeel.add(jrbmi);
         if (laf.getName().equals("Nimbus"))
         {
            defaultLAF = laf.getClassName();
            lafBG.setSelected(jrbmi.getModel(), true);
            nimbusFound = true;
         }
      }
      if (!nimbusFound)
      {
         defaultLAF = UIManager.getSystemLookAndFeelClassName();
         Enumeration<AbstractButton> ab = lafBG.getElements();
         while (ab.hasMoreElements())
         {
            JRadioButtonMenuItem jrbmi = (JRadioButtonMenuItem) ab.nextElement();
            if (UIManager.getSystemLookAndFeelClassName().equals(jrbmi.getActionCommand()))
               lafBG.setSelected(jrbmi.getModel(), true);
         }
      }

      helpMenu.add(this.makeUpdateCheckMenuItem());
      helpMenu.add(this.makeWebsiteMenuItem());

      // Separate the about dialog.
      helpMenu.addSeparator();

      // Help->About menu item.
      helpMenu.add(this.makeAboutMenuItem());

      this.mazeViewer = new MazeViewerPage();
      this.codeEditorPanel = new ScriptEditorPage();
      this.mazeEditor = new MazeEditorPage();

      this.add(mainTabs);
      mainTabs.add("Micro Mouse Simulator", this.mazeViewer);
      mainTabs.add("Maze Editor", this.mazeEditor);
      mainTabs.add("AI Script Editor", this.codeEditorPanel);
      mainTabs.add("Statistics Display", new StatViewPage());

      try
      {
         UIManager.setLookAndFeel(defaultLAF);
      }
      catch (Exception ex)
      {
         ex.printStackTrace();
      }
      SwingUtilities.updateComponentTreeUI(this);
   } // End init.

   /**
    * Create the Help->About menu item.
    * @return Created item.
    */
   private JMenuItem makeAboutMenuItem()
   {
      final JMenuItem aboutMenuItem = new JMenuItem("About...");
      aboutMenuItem.addActionListener(new ActionListener()
      {
         @Override
         public void actionPerformed(ActionEvent e)
         {
            String m = "<html><b>Build Date:</b> " +
                       getApplicationBuildDate() +
                       "<br /><b>Revision:</b> " +
                       getApplicationRevision() +
                       "<br />You can find more information about this application " +
                       "at the following project page.<br />" +
                       "<a href=\"" +
                       PROJECT_HOMEPAGE +
                       "\">" +
                       "http://code.google.com/p/maze-solver/</a><br />" +
                       "</html>";
            JOptionPane.showMessageDialog(PrimaryFrame.this,
                                          m,
                                          "About",
                                          JOptionPane.INFORMATION_MESSAGE);
         }
      });
      return aboutMenuItem;
   }

   /**
    * Creates a menu item that checks if you have the latest revision of the
    * application.
    * @return Menu item.
    */
   private JMenuItem makeUpdateCheckMenuItem()
   {
      final JMenuItem item = new JMenuItem("Check for Update...");
      item.addActionListener(new ActionListener()
      {
         @Override
         public void actionPerformed(ActionEvent e)
         {
            Thread t = new Thread()
            {
               @Override
               public void run()
               {
                  Reader r = null;
                  try
                  {
                     r = new InputStreamReader(new URL(LATEST_REVISION_URI).openStream(), "ASCII");
                     CharBuffer cb = CharBuffer.allocate(1024);
                     r.read(cb);
                     cb.flip();
                     System.out.println(cb.toString());
                     final int revision = Integer.parseInt(cb.toString());
                     final int myRevision = getApplicationRevision();
                     if (myRevision == 0)
                     {
                        JOptionPane.showMessageDialog(PrimaryFrame.this,
                                                      "Unable to determine your current version.");
                     }
                     else if (revision == myRevision)
                     {
                        JOptionPane.showMessageDialog(PrimaryFrame.this,
                                                      "You have the latest version.");
                     }
                     else
                     {
                        JOptionPane.showMessageDialog(PrimaryFrame.this,
                                                      "There is a newer version available.\nYou have Revision: " +
                                                            myRevision +
                                                            "\nLatest Revision: " +
                                                            revision);
                     }
                  }
                  catch (Exception e)
                  {
                     e.printStackTrace();
                     JOptionPane.showMessageDialog(PrimaryFrame.this,
                                                   "An error occured while checking for the latest version.\n" +
                                                         e.toString());
                  }
                  finally
                  {
                     try
                     {
                        if (r != null)
                           r.close();
                     }
                     catch (IOException e)
                     {
                        e.printStackTrace();
                     }
                  }
               }
            };
            t.setDaemon(true);
            t.start();
         }
      });
      return item;
   }

   /**
    * Help->Project Web-site menu item launches the project web site in the
    * system browser.
    * @return Menu item.
    */
   private JMenuItem makeWebsiteMenuItem()
   {
      JMenuItem websiteMenuItem = new JMenuItem("Project Website...");
      websiteMenuItem.addActionListener(new ActionListener()
      {
         @Override
         public void actionPerformed(ActionEvent e)
         {
            Main.launchInBrowser(PROJECT_HOMEPAGE);
         }
      });
      return websiteMenuItem;
   }

   /**
    * Tells the primary frame if a simulation is currently running or not. We
    * can then disable GUI elements while animating.
    * @param simOn Set to true means the robot simulation is currently running.
    */
   public void setSimulation(boolean simOn)
   {
      this.mainTabs.setEnabled(!simOn);
      this.fileMenu.setEnabled(!simOn);
   }
}
TOP

Related Classes of maze.gui.PrimaryFrame$LookAndFeelListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.