// ShapesWindow1B.java

// This version uses just one class, a window
// which listens to its own menu items.

// Shape text format error messages are sent to
// dialog boxes as one-line error messages.
// Other RuntineException error messages are sent,
// with stack traces, to console.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ShapesWindow1B extends JFrame implements ActionListener
{
   // To store ShapeOutline data:
   private ShapeBoundedBuffer shapes;

   // Dialog box to display error messages
   // for bad input file data:
   private ErrorDialog errorsInFile = null;

   // Menu items:
   private JMenuItem mOpen;
   private JMenuItem mQuit;
   private JMenuItem mAdd;

   // Displayed regions of the window:
   private JTextField messageField;
   private JTextArea shapesTextArea;
   private ShapesPanel shapesDisplay;

   public ShapesWindow1B()
   {
      shapes = new ShapeBoundedBuffer(5);

      //  Create menu items for the "File" menu:
      mOpen = new JMenuItem ("Open");
      mQuit = new JMenuItem ("Quit");

      //  Create "File" menu:
      JMenu fileMenu = new JMenu ("File", /*tearoff =*/ false);
      fileMenu.add(mOpen);
      fileMenu.addSeparator();
      fileMenu.add(mQuit);

      //  Create menu items for the "Edit" menu:
      mAdd = new JMenuItem ("Add");

      //  Create "Edit" menu:
      JMenu editMenu = new JMenu ("Edit", /*tearoff =*/ false);
      editMenu.add(mAdd);

      // Create menu bar:
      JMenuBar mainMenuBar = new JMenuBar();
      mainMenuBar.add(fileMenu);
      mainMenuBar.add(editMenu);

      // Put menu bar on this window:
      setJMenuBar(mainMenuBar);

      // Enable this window to respond when menu items are clicked:
      mOpen.addActionListener(this);
      mQuit.addActionListener(this);
      mAdd.addActionListener(this);

      // Components to display on window:
      messageField = new JTextField();
      messageField.setEditable(false);
      shapesTextArea = new JTextArea();
      shapesTextArea.setEditable(false);
      shapesDisplay = new ShapesPanel(shapes);
      
      // Arrange components on window:
      Container contentPane = getContentPane();
      contentPane.add(messageField, BorderLayout.SOUTH);
      JPanel centerPanel = new JPanel();
      contentPane.add(centerPanel, BorderLayout.CENTER);
      centerPanel.setLayout(new GridLayout(2,1));
      centerPanel.add(shapesDisplay);
      centerPanel.add(new JScrollPane(shapesTextArea));

      // Routine necessities with JFrame windows:
      setSize(600, 400);
      setLocation(100, 50);
      setTitle("Interactive GUI example");
      setDefaultCloseOperation(EXIT_ON_CLOSE);
      setVisible(true);
   } // constructor

   public void actionPerformed(ActionEvent e)
   {
      if (e.getSource() == mOpen) {
         FileDialog fDialog = new FileDialog(this, "Input File");
         fDialog.setVisible(true);
         String filename = fDialog.getFile();
         if ( filename != null )
            open(filename);
      } // if mOpen
      else if ( e.getSource() == mQuit ) {
         System.exit(0);
      } // if mQuit
      else if ( e.getSource() == mAdd ) {
         addEnteredShape();
      } // if mQuit
      else
         throw new IllegalStateException("Unaccounted for: "
                                         + e.getActionCommand());
   }  // method actionPerformed

   private void open(String filename)
   {
      TextFileInput in = new TextFileInput(filename);

      String line = in.readLine();
      while ( line != null )
      {
         try {
            shapes.add(ShapeOutline.parseShape(line));
         }  // try
         catch (ShapeTextFormatException stfe)  {
            if ( errorsInFile == null )  {
               errorsInFile = new ErrorDialog(this,
                                              "Errors in input data file");
               errorsInFile.printShortOneLineMessage("Bad shapes data");
            }  // if
            errorsInFile.println(stfe.getMessage());
         }  // catch
         catch (RuntimeException re)  {
            re.printStackTrace();
         }  // catch
         line = in.readLine();
      }  // while
      updateDisplay();
   }  // method open

   private void addEnteredShape()
   {
      String line;

      // Between two rows of asterisks below are two statements
      // obtaining line from a dialog box of some kind.
      // Exactly one of the two statements should be uncommented.

      // ****************************************************************
      //
      line = JOptionPane.showInputDialog(
                           this,
                           "Enter a string representation of a shape");
      //
      // line = ShapeInputTextDialog.showDialog(this);
      //
      // ****************************************************************

      if ( line == null )
      {
         repaint();
         return;
      }  // if

      try {
         shapes.add(ShapeOutline.parseShape(line));
      }  // try
      catch (ShapeTextFormatException stfe)  {
         JOptionPane.showMessageDialog(this,
                                       stfe.getMessage(),
                                       "Invalid shape data",
                                       JOptionPane.ERROR_MESSAGE);
      }  // catch
      catch (RuntimeException re)  {
         re.printStackTrace();
      }  // catch
      updateDisplay();
   }  // method addEnteredShape()

   private void updateDisplay()
   {
      String lineBreak = System.getProperty("line.separator");

      shapesTextArea.setText("");
      for ( int i = 0; i < shapes.getLengthFilled(); i++ )
         shapesTextArea.append(shapes.getShapeAt(i) + lineBreak);

      messageField.setText("Created so far:  "
                           + RightTriangle.getCount()
                           + " right triangles, "
                           + Wheel.getCount() + " wheels, "
                           + (Circle.getCount() - Wheel.getCount())
                           + " non-wheel circles, "
                           + ShapeOutline.getCount()
                           + " shapes total.");

      repaint();  // to force shapes display panel to update
   }  // method updateDisplay;

   public static void main(String[] args)
   {
      new ShapesWindow1B();
   }  // method main
} // class ShapesWindow1B