/*
 * Burton Rosenberg
 * June 2004
 */

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

class TreeController extends JPanel
implements ActionListener, MouseListener, Runnable {

  // menu prototype is a sequence of pairs ( type, index )
  // Rules:
  //   creating a JMenu makes it the current JMenu
  //   menu items are added to the current JMenu
  //   consecutive JRadioBoxMenuItems are added to a same
  //   ButtonGroup. any other than a radio box stops the grouping.
  //   The next radio box will start a new button group.

  // the types
  private static final int M_TYPE_IGNORE = 0 ;
  private static final int M_TYPE_JMENU = 1 ;
  private static final int M_TYPE_JMENUITEM = 2 ;
  private static final int M_TYPE_JRADIOBUTTON = 3 ;
  private static final int M_TYPE_JSPACER = 4 ;
  private static final int M_TYPE_JCHECKBOX = 5 ;
  private static final int M_TYPE_JCHECKBOX_T = 6 ;


  // the strings
  private static final String [] MENU_STRINGS = 
  {
     "" ,
     "File", "New Tree...", "Add...", 
     "Edit", "Insert", "Remove",
     "View", "Text", "Geometric", "Spaced",
     "Clear", "Interpret Integers", "Reject Strings",
  } ;


  // indices for prototype, must agree with MENU_STRINGS

  public static final int M_FILE = 1 ;
  public static final int M_FILE_OPEN = 2 ;
  public static final int M_FILE_ADD = 3 ;
  public static final int M_EDIT = 4 ;
  public static final int M_EDIT_CLEAR = 11 ;
  public static final int M_EDIT_INSERT = 5 ;
  public static final int M_EDIT_REMOVE = 6 ;
  public static final int M_VIEW = 7 ;
  public static final int M_VIEW_TEXT = 8 ;
  public static final int M_VIEW_GEOMETRIC = 9 ;
  public static final int M_VIEW_EQUAL_SPACE = 10 ;
  public static final int M_VIEW_INTERPRET_INTEGERS = 12 ;
  public static final int M_VIEW_REJECT_STRINGS = 13 ; // unimplemented

  // the prototype
  private static final int [] MENU_PROTO = 
  { 
     M_TYPE_JMENU, M_FILE,
     M_TYPE_JMENUITEM, M_FILE_OPEN,
     M_TYPE_JMENUITEM, M_FILE_ADD,
     M_TYPE_JMENU, M_EDIT,
     M_TYPE_JMENUITEM, M_EDIT_CLEAR,
     M_TYPE_JSPACER, 0,
     M_TYPE_JMENUITEM, M_EDIT_INSERT,
     M_TYPE_JMENUITEM, M_EDIT_REMOVE,
     M_TYPE_JMENU, M_VIEW,
     M_TYPE_JRADIOBUTTON, M_VIEW_GEOMETRIC,
     M_TYPE_JRADIOBUTTON, M_VIEW_EQUAL_SPACE,
     M_TYPE_JRADIOBUTTON, M_VIEW_TEXT,
     M_TYPE_JSPACER, 0,
     M_TYPE_JCHECKBOX_T, M_VIEW_INTERPRET_INTEGERS,
  } ;

  Object [] menuItems ;

  Thread chooserThread ;
  JButton insertButton ;
  int buttonMode = M_EDIT_INSERT ;
  JTextField textBox ;
  TreeModel tm ; 
  
   
  TreeController( TreeModel tm ) {
     this.tm = tm ;

     insertButton = new JButton(MENU_STRINGS[M_EDIT_INSERT]) ;
     insertButton.addActionListener(this) ;
     add(insertButton) ;
     add(textBox = new JTextField(15)) ;
     textBox.addActionListener(this) ;
  }
  
  JMenuBar makeMenuBar() {
    
      JMenuBar jmb = new JMenuBar() ;
      JMenu jm = null ;
      JMenuItem jmi ;
      JRadioButtonMenuItem jrbmi ;
      JCheckBoxMenuItem jcbmi ;
      ButtonGroup bg = null ;
      boolean checkBoxState = false ;

      menuItems = new Object[MENU_PROTO.length/2] ;

      for ( int i=0; i<MENU_PROTO.length; i+=2 ) {
      switch( MENU_PROTO[i] ) {
      case M_TYPE_JMENU:
          jm = new JMenu( MENU_STRINGS[MENU_PROTO[i+1]] ) ;
          jmb.add(jm) ;
          menuItems[MENU_PROTO[i+1]] = jm ;
          break ;
      case M_TYPE_JMENUITEM:
          jmi = new JMenuItem( MENU_STRINGS[MENU_PROTO[i+1]] ) ;
          jmi.addActionListener(this) ;
          jm.add(jmi) ;
          menuItems[MENU_PROTO[i+1]] = jmi ;
          break ;
      case M_TYPE_JSPACER:
          jm.addSeparator() ;
          break ;
      case M_TYPE_JRADIOBUTTON:
          boolean checked = false ;
          if ( bg==null ) {
              bg = new ButtonGroup() ;
              checked = true ;
          }
          jrbmi = new JRadioButtonMenuItem( 
                  MENU_STRINGS[MENU_PROTO[i+1]], checked ) ;
          bg.add(jrbmi) ;
          jrbmi.addActionListener(this) ;
          menuItems[MENU_PROTO[i+1]] = jrbmi ;
          jm.add(jrbmi) ;
          break ;
      case M_TYPE_JCHECKBOX_T:
          checkBoxState = true ;
      case M_TYPE_JCHECKBOX:
          jcbmi = new JCheckBoxMenuItem(MENU_STRINGS 
                       [MENU_PROTO[i+1]], checkBoxState) ;
          jcbmi.addActionListener(this) ;
          menuItems[MENU_PROTO[i+1]] = jcbmi ;
          jm.add(jcbmi) ;
          break ;
          
      } // end switch
      if ( MENU_PROTO[i]!=M_TYPE_JRADIOBUTTON ) bg = null ;
      checkBoxState = false ;
      } // end for
      return jmb ;
  }

   public void actionPerformed( ActionEvent ae ) {
      StringTokenizer st ;
      Object o = ae.getSource() ;
      // identify source
      if ( o==insertButton || o==textBox ) {
          switch ( buttonMode ) {
          case M_EDIT_INSERT:
             st = new StringTokenizer(textBox.getText()) ;
             while ( st.hasMoreTokens() ) {
                tm.insert(st.nextToken()) ;
             }
             break ;
          case M_EDIT_REMOVE:
             st = new StringTokenizer(textBox.getText()) ;
             while ( st.hasMoreTokens() ) {
                tm.remove(st.nextToken()) ;
             }
             break ;
          }
          return ;
      }
      int mi_x ;
      for ( mi_x=0; mi_x< menuItems.length; mi_x++ ) 
         if (menuItems[mi_x]==o) break ;
      switch( mi_x ) {
      case M_FILE_OPEN:
         if ( chooserThread != null ) break ;
         chooserThread = new Thread(this) ;
         shouldNewTree = true ;
	 chooserThread.start() ;
	 break ;
      case M_FILE_ADD:
         if ( chooserThread != null ) break ;
         chooserThread = new Thread(this) ;
         shouldNewTree = false ;
	 chooserThread.start() ;
	 break ;
      case M_EDIT_CLEAR:
         tm.clearTree() ;
         break ;
      case M_EDIT_INSERT:
         insertButton.setText(MENU_STRINGS[M_EDIT_INSERT]) ;
         buttonMode = M_EDIT_INSERT ;
         break ;
      case M_EDIT_REMOVE:
         insertButton.setText(MENU_STRINGS[M_EDIT_REMOVE]) ;
         buttonMode = M_EDIT_REMOVE ;
         break ;
      case M_VIEW_TEXT:
         tm.setViewStyle(TreeViewer.VIEW_STYLE_TEXT) ;
         break ;
      case M_VIEW_GEOMETRIC:
         tm.setViewStyle(TreeViewer.VIEW_STYLE_GEOMETRIC) ;
         break ;
      case M_VIEW_EQUAL_SPACE:
         tm.setViewStyle(TreeViewer.VIEW_STYLE_EQUAL_SPACED) ;
         break ;
      case M_VIEW_INTERPRET_INTEGERS:
         tm.setInterpretIntegers( 
             ((JCheckBoxMenuItem)menuItems[M_VIEW_INTERPRET_INTEGERS])
             .getState() ) ;
         break ;
      }
   }

   boolean shouldNewTree ;

   public void run() {
        // called to open a dialog
        JFileChooser jfc = new JFileChooser() ;
        if ( jfc.showOpenDialog(null)==JFileChooser.APPROVE_OPTION ) 
        {
           if ( shouldNewTree) tm.clearTree() ;
           File file = jfc.getSelectedFile() ;
           tm.loadFromFile(file) ;
        }
        chooserThread = null ;
   }

   //implement MouseListener
   public void mouseClicked(MouseEvent me) {
   }
   public void mouseEntered(MouseEvent me) {
   }
   public void mouseExited(MouseEvent me) {
   }
   public void mousePressed(MouseEvent me) {
        tm.mousePick( me.getX(), me.getY(), true ) ;
   }
   public void mouseReleased(MouseEvent me) {
        textBox.setText(tm.pickedString) ;
        tm.mousePick( 0, 0, false ) ;
   }

}

