Package maze.gui.mazeeditor

Source Code of maze.gui.mazeeditor.MazeEditorPage$TemplateMouseAdapter

package maze.gui.mazeeditor;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.io.File;

import javax.swing.AbstractAction;
import javax.swing.ButtonGroup;
import javax.swing.DefaultComboBoxModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;

import maze.Main;
import maze.gui.MazeList;
import maze.gui.MenuControlled;
import maze.gui.PrimaryFrame;
import maze.model.MazeInfo;
import maze.model.MazeInfoModel;
import maze.model.MazeModel;

/**
* This panel creates a GUI to edit mazes.
* @author John Smith
*/
public class MazeEditorPage extends JPanel implements MenuControlled
{
   private static final String NEXT_ORIENTATION_ACTION_KEY = "nextOrientation";
   private static final String TOP_HELP = "Left-Click: Add walls, Right-Click: "
                                          + "Remove walls, Middle-Click or R Key: Change template Orientation, "
                                          + "Wheelup: Grow template, Wheeldown: Shrink template";
   private static final String POPUP_HELP = "<html><b>Left-Click</b>: Add walls<br /><b>Right-Click</b>: "
                                            + "Remove walls<br /><b>Middle-Click</b> or <b>R Key</b>: Change template "
                                            + "Orientation<br /><b>Wheelup</b>: Grow template<br />"
                                            + "<b>Wheeldown</b>: Shrink template</btml>";
   private final ImageIcon mPointIcon = Main.getImageResource("gui/mazeeditor/images/Pointer.png");
   private MazeTemplate mCurrentTemplate = null;
   private final EditableMazeView mMazeView = new EditableMazeView();
   private MazeList mOpenMazes;
   private MouseAdapter mMouseAdapter = null;
   private int mLastNew = 1;

   private static final MazeTemplate[] mTemplates =
   {
      new BoxTemplate(), new StraightTemplate(), new CornerTemplate(), new CrossTemplate(),
      new ZigZagTemplate(), new WaveTemplate(), new StaggeredTemplate(), new JungleTemplate(),
      new RungTemplate(), new GappedTemplate()
   };

   /**
    * Constructor.
    */
   public MazeEditorPage()
   {
      buildPanel();
   }

   /**
    * Bring up a dialog prompting the user to create a new maze.
    */
   public void newMaze()
   {
      NewMazeDialog dialog;
      String result;
      dialog = new NewMazeDialog(Main.getPrimaryFrameInstance());
      if ( (result = dialog.showDialog()) == null)
         return;

      MazeInfoModel mim = Main.getPrimaryFrameInstance().getMazeInfoModel();

      if (result.equals(NewMazeDialog.MAZ))
      {
         MazeInfo newMi = mim.createNew("New Maze " + mLastNew, false);
         if (newMi == null)
         {
            JOptionPane.showMessageDialog(MazeEditorPage.this,
                                          "Unable to create new maze",
                                          "Maze Creation Error",
                                          JOptionPane.OK_OPTION);
            return;
         }
         mLastNew++;
      }
      else if (result.equals(NewMazeDialog.MZ2))
      {
         MazeInfo newMi = mim.createNew(dialog.getText(), true);
         if (newMi == null)
         {
            JOptionPane.showMessageDialog(MazeEditorPage.this,
                                          "Unable to create new maze",
                                          "Maze Creation Error",
                                          JOptionPane.OK_OPTION);
            return;
         }
         MazeModel mm = newMi.getModel();
         mm.setSize(dialog.getMazeSize());
      }
   }

   /**
    * Creates the Swing GUI for this panel.
    */
   private void buildPanel()
   {
      setLayout(new BorderLayout());
      JLabel instr = new JLabel(TOP_HELP);
      instr.setToolTipText(POPUP_HELP);
      add(instr, BorderLayout.NORTH);

      final JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
      splitPane.setContinuousLayout(true);
      splitPane.setResizeWeight(.9);
      splitPane.setOneTouchExpandable(true);

      mMazeView.setMinimumSize(new Dimension(400, 200));
      splitPane.setLeftComponent(mMazeView);
      mMazeView.setModel(null);

      this.mOpenMazes = new MazeList(this.mMazeView);
      this.mOpenMazes.setMinimumSize(new Dimension(160, 0));
      JPanel rightPanel = new JPanel();
      rightPanel.setLayout(new BorderLayout());
      rightPanel.add(this.mOpenMazes, BorderLayout.CENTER);

      final JPanel rightPanelButtons = new JPanel(new BorderLayout());
      rightPanelButtons.add(makeNewMazeButton(), BorderLayout.NORTH);
      rightPanelButtons.add(makeRandomMazeButton(), BorderLayout.SOUTH);

      rightPanel.add(rightPanelButtons, BorderLayout.SOUTH);
      splitPane.setRightComponent(rightPanel);

      add(splitPane, BorderLayout.CENTER);
      splitPane.setDividerLocation(.8);

      addComponentListener(new ComponentAdapter()
      {
         boolean notShown = true;

         @Override
         public void componentShown(ComponentEvent e)
         {
            if (notShown)
            {
               splitPane.setDividerLocation(.8);
               notShown = false;
            }
         }
      });

      JToolBar tBar = new JToolBar();
      tBar.setOrientation(JToolBar.VERTICAL);
      tBar.setFloatable(false);
      ButtonGroup bg = new ButtonGroup();

      ImageIcon scaled = new ImageIcon(mPointIcon.getImage().getScaledInstance(40, 40, 0));
      JToggleButton tb = new JToggleButton(scaled);
      tb.setToolTipText("No Template");
      tb.addActionListener(new TemplateActionListener(null));
      bg.add(tb);
      bg.setSelected(tb.getModel(), true);
      tBar.add(tb);

      for (MazeTemplate mt : mTemplates)
      {
         Image iconImage = mt.getTemplateIcon().getImage();
         scaled = new ImageIcon(iconImage.getScaledInstance(40, 40, 0));
         tb = new JToggleButton(scaled);
         tb.addActionListener(new TemplateActionListener(mt));
         tb.setToolTipText(mt.getTemplateDescription());
         bg.add(tb);
         tBar.add(tb);
      }

      add(tBar, BorderLayout.WEST);

      //Add an action for the 'r' key to change the template to the next orientation.
      this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke('r'),
                                                                          NEXT_ORIENTATION_ACTION_KEY);
      this.getActionMap().put(NEXT_ORIENTATION_ACTION_KEY, new AbstractAction()
      {
         @Override
         public void actionPerformed(ActionEvent e)
         {
            if (mCurrentTemplate != null)
            {
               mCurrentTemplate.nextOrientation();
               mMazeView.repaint();
            }
         }
      });

      mMouseAdapter = new TemplateMouseAdapter();

      mMazeView.addMouseListener(mMouseAdapter);
      mMazeView.addMouseMotionListener(mMouseAdapter);
      mMazeView.addMouseWheelListener(mMouseAdapter);
   } // End building the panel.

   /**
    * Set the current template to be used by the maze editor.
    * @param mt Template to set, or null to clear template.
    */
   private void setTemplate(MazeTemplate mt)
   {
      if (mt == mCurrentTemplate)
         return;

      mCurrentTemplate = mt;
      if (mCurrentTemplate == null)
      {
         mMazeView.setEditable(true);
      }
      else
      {
         mMazeView.setEditable(false);
         mt.reset();
      }
      mMazeView.setTemplate(mt);
   }

   /**
    * Create button to add new maze.
    */
   private JButton makeNewMazeButton()
   {
      JButton newMaze = new JButton("New Maze");
      newMaze.setToolTipText("Create a new maze");
      newMaze.addActionListener(new ActionListener()
      {
         @Override
         public void actionPerformed(ActionEvent e)
         {
            newMaze();
         }
      });
      return newMaze;
   }

   /**
    * Creates a button that randomizes all the walls of the current maze.
    */
   private JButton makeRandomMazeButton()
   {
      JButton random = new JButton("Randomize Maze");
      random.setToolTipText("Randomize all the walls of the currently selected Maze.");
      random.addActionListener(new ActionListener()
      {
         @Override
         public void actionPerformed(ActionEvent e)
         {
            final MazeModel maze = mMazeView.getModel();
            if (maze != null)
            {
               maze.generateRandomMaze();
               mMazeView.repaint();
            }
         }
      });
      return random;
   }

   /**
    * Save the current maze.
    */
   @Override
   public void saveCurrent()
   {
      MazeInfo mi = (MazeInfo) mOpenMazes.getList().getSelectedValue();
      if (mi != null)
      {
         mi = mi.saveMaze();
         mOpenMazes.getList().setSelectedValue(mi, true);
      }
   }

   /**
    * Close the current maze.
    */
   @Override
   public void close()
   {
      MazeInfo mi = (MazeInfo) mOpenMazes.getList().getSelectedValue();
      if (mi != null)
      {
         if (!mi.isMutable())
         {
            JOptionPane.showMessageDialog(this,
                                          "This maze cannot be closed",
                                          "Maze Close",
                                          JOptionPane.INFORMATION_MESSAGE);
            return;
         }
         if (mi.isDirty())
            saveCurrent();
         MazeInfoModel mim = Main.getPrimaryFrameInstance().getMazeInfoModel();
         JList list = mOpenMazes.getList();
         list.setSelectedIndex(list.getSelectedIndex() - 1);
         mim.close(mi);
      }
   }

   /**
    * Sets the maze editor template when the action is performed.
    */
   private class TemplateActionListener implements ActionListener
   {
      private MazeTemplate mt;

      public TemplateActionListener(MazeTemplate mt)
      {
         this.mt = mt;
      }

      @Override
      public void actionPerformed(ActionEvent e)
      {
         setTemplate(mt);
      }
   }

   /**
    * Handles all the mouse events for the maze editor templates.
    */
   private class TemplateMouseAdapter extends MouseAdapter
   {
      @Override
      public void mouseMoved(MouseEvent e)
      {
         if (mMazeView.getModel() != null && mCurrentTemplate != null)
         {
            mCurrentTemplate.updatePosition(e.getPoint(), mMazeView.getCellSizeModel());
            mMazeView.repaint();
         }
      }

      @Override
      public void mouseDragged(MouseEvent e)
      {
         if (mMazeView.getModel() != null && mCurrentTemplate != null)
         {
            mMazeView.repaint();
         }
         mOpenMazes.repaint();
      }

      @Override
      public void mousePressed(MouseEvent e)
      {
         if (mMazeView.getModel() != null && mCurrentTemplate != null)
         {
            if (e.getButton() == MouseEvent.BUTTON2)
               mCurrentTemplate.nextOrientation();
            else if (e.getButton() == MouseEvent.BUTTON1)
               mMazeView.applyTemplate(true);
            else if (e.getButton() == MouseEvent.BUTTON3)
               mMazeView.applyTemplate(false);
            mMazeView.repaint();
         }
         mOpenMazes.repaint();
      }

      @Override
      public void mouseWheelMoved(MouseWheelEvent e)
      {
         if (mMazeView.getModel() == null || mCurrentTemplate == null)
            return;
         int amount = e.getWheelRotation();
         boolean neg = amount < 0;
         amount = Math.abs(amount);
         for (int i = 0; i < amount; i++)
         {
            if (neg)
               mCurrentTemplate.grow();
            else
               mCurrentTemplate.shrink();
         }
         mMazeView.repaint();
      }
   } // End class.

   /**
    * A description of the supported maze file types.
    */
   @Override
   public String getFileTypeDescription()
   {
      return "Maze files (.maz, .mz2)";
   }

   /**
    * Checks if the given file is a supported maze file.
    * @param file The file to check.
    */
   @Override
   public boolean isMyFileType(File file)
   {
      String lower = file.getName().toLowerCase();
      if (lower.endsWith(".maz") || lower.endsWith(".mz2"))
         return true;
      else
         return false;
   }

   /**
    * Opens the given file as a maze.
    * @param file The maze file to open. Should be a recognized format.
    */
   @Override
   public void open(File file)
   {
      MazeInfoModel mim = Main.getPrimaryFrameInstance().getMazeInfoModel();
      if (!mim.addMaze(file))
         JOptionPane.showMessageDialog(this, "<html>Unable to load " +
                                             "<br />" +
                                             file.getAbsolutePath() +
                                             "</html", "Maze Open Error", JOptionPane.ERROR_MESSAGE);

   }

   /**
    * Prompt the user to save any dirty mazes.
    */
   @Override
   public boolean canExit()
   {
      final PrimaryFrame primary = Main.getPrimaryFrameInstance();
      DefaultComboBoxModel cbm = primary.getMazeInfoModel().getMazeInfoComboBoxModel();
      for (int i = 0; i < cbm.getSize(); i++)
      {
         MazeInfo mi = (MazeInfo) cbm.getElementAt(i);
         if (mi.isDirty())
         {
            int result;
            result = JOptionPane.showConfirmDialog(this,
                                                   "Would you like to save \"" +
                                                         mi.getName() +
                                                         "\"",
                                                   "Save Maze?",
                                                   JOptionPane.YES_NO_OPTION,
                                                   JOptionPane.QUESTION_MESSAGE);
            if (result == JOptionPane.YES_OPTION)
               mi.saveMaze();
            else if (result != JOptionPane.NO_OPTION)
               return false; // Abort exit if canceled.
         }
      }
      return true;
   }

}
TOP

Related Classes of maze.gui.mazeeditor.MazeEditorPage$TemplateMouseAdapter

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.