import java.io.*;
import java.awt.*;
import java.util.*;
/* import custom layout managers */
/* import custom controls */
//import Multiline.*;
/**
this draws menu chosen components
@author Arthur Sulger asulger@ibm.net
*/
public class Screen extends Frame
   {
   Menu menu_file, menu_tool, menu_layout, menu_help,
      menu_grid, edit_tool;
   MenuBar menubar;
   private int height, width, init_x, init_y, last_w, last_h;
   private boolean inAnApplet = true;
   private boolean hasGridLines = true;
   Button[] buttons;
   Choice[] choices;
   Checkbox[] checkboxes;
   Label[] labels;
   /* arrays of custom controls */
//   MultiLineLabel[] multilinelabels;
   /* end */
   List[] lists;
   Panel[] panels;
   Scrollbar[] scrollbars;
   TextField[] textfields;
   TextArea[] textareas;
   int button_count=0;
   int choice_count=0;
   int checkbox_count=0;
   int label_count=0;
   int list_count=0;
   /* custom control counter */
//   int multilinelabel_count=0;
   /* end */
   int panel_count=0;
   int scrollbar_count=0;
   int textfield_count=0;
   int textarea_count=0;
   StringBuffer layoutConstruct;
   static final int BUTTON=1;
   static final int CHOICE=2;
   static final int CHECKBOX=3;
   static final int LABEL=4;
   static final int LIST=5;
   /* custom control constants */
//   static final int MULTILINELABEL=6;
   /* end */
   static final int TEXTFIELD=7;
   static final int TEXTAREA=8;
   static final int PANEL=9;
   static final int HSCROLLBAR=10;
   static final int VSCROLLBAR=11;
   int TOOL=BUTTON;
   static final int BORDER = 1;
   static final int GRIDBAG = 2;
   int LAYOUT=0;
   /**
   The constructor builds empty arrays for potential components.
   It builds the menus and sets the layout to null.
   */
   public Screen()
      {
      super("Screen Designer");
      setLayout(null);
      //setLayout(new FlowLayout());
      this.resize(300,300);
      //this.setBounds(20,20,300,300);
      menubar = new MenuBar();
      this.setMenuBar(menubar);
      menu_file = new Menu("File");
      menu_file.add(new MenuItem("Create Source"));
      menu_file.add(new MenuItem("Import 'XXX'"));
      menu_file.add(new MenuItem("Exit"));
      menubar.add(menu_file);
      menu_tool = new Menu("Widgets");
      menu_tool.add(new MenuItem("Button"));
      menu_tool.add(new MenuItem("Choice"));
      menu_tool.add(new MenuItem("CheckBox"));
      menu_tool.add(new MenuItem("Label"));
      menu_tool.add(new MenuItem("Panel"));
      menu_tool.add(new MenuItem("Horizontal Scrollbar"));
      menu_tool.add(new MenuItem("Vertical Scrollbar"));
      /* custom control menu items */
//      menu_tool.add(new MenuItem("MultiLineLabel"));
      /* end */
      menu_tool.add(new MenuItem("List"));
      menu_tool.add(new MenuItem("TextField"));
      menu_tool.add(new MenuItem("TextArea"));
      menubar.add(menu_tool);
      edit_tool = new Menu("Edit");
      edit_tool.add(new MenuItem("Undo"));
      edit_tool.add(new MenuItem("Clear"));
      edit_tool.add(new MenuItem("Show Grid Lines"));
      menubar.add(edit_tool);
      menu_layout = new Menu("Layout");
      menu_layout.add(new MenuItem("Border"));
      menu_layout.add(new MenuItem("Flow"));
      /* custom layout manager menu item */
//      menu_layout.add(new MenuItem("Custom"));
      /* end */
      // grid has a sub-menu of grid choices:
      menu_grid = new Menu("Grids");
      menu_layout.add(menu_grid);
      menu_grid.add(new MenuItem("grid_2x2"));
      menu_grid.add(new MenuItem("grid_2x3"));
      menu_grid.add(new MenuItem("grid_2x4"));
      menu_grid.add(new MenuItem("grid_2x5"));
      menu_grid.add(new MenuItem("grid_2x10"));
      menu_grid.add(new MenuItem("grid_3x2"));
      menu_grid.add(new MenuItem("grid_3x3"));
      menu_grid.add(new MenuItem("grid_3x4"));
      menu_grid.add(new MenuItem("grid_3x5"));
      menu_grid.add(new MenuItem("grid_3x10"));
      menu_grid.add(new MenuItem("grid_4x5"));
      menu_grid.add(new MenuItem("grid_5x5"));
      menu_grid.add(new MenuItem("grid_5x10"));
      menu_grid.add(new MenuItem("grid_10x5"));
      menu_grid.add(new MenuItem("grid_10x10"));

      menu_layout.add(new MenuItem("GridBag"));
      menu_layout.add(new MenuItem("None"));
      menubar.add(menu_layout);

      menu_help = new Menu("Help");
      menu_help.add(new MenuItem("Create Source"));
      menu_help.add(new MenuItem("Show Components"));
      menubar.add(menu_help);
      menubar.setHelpMenu(menu_help);
      height = width = last_w = last_h = init_x = init_y = 0;
      // the canvas of components
      buttons = new Button[256];
      choices = new Choice[256];
      checkboxes = new Checkbox[256];
      labels = new Label[256];
      /* instantiate arrays of custom controls */
//      multilinelabels = new MultiLineLabel[256];
      /* end */
      lists = new List[256];
      panels = new Panel[64];
      scrollbars = new Scrollbar[256];
      textfields = new TextField[256];
      textareas = new TextArea[256];
      layoutConstruct = new StringBuffer("setLayout(new FlowLayout());");
      }
   /**
   handleEvent() is over-ridden to get menus.
   It has to return super.handleEvent()
   so the other action events are handled
@return super.handleEvent(Event)
   */
   public boolean handleEvent(Event e)
      {
      switch(e.id)
         {
/*
         case Event.MOUSE_DOWN:
            init_x = e.x;
            init_y = e.y;
            break;
         case Event.MOUSE_DRAG:
            width =  e.x - init_x;
            height = e.y - init_y;
            repaint();
            break;
*/
         case Event.WINDOW_DESTROY:
            if (inAnApplet)
               {
               dispose();
               return true;
               }
            else
               System.exit(0);
         case Event.ACTION_EVENT:
            if (e.target instanceof MenuItem)
               {
               if (((String)e.arg).equals("Button"))
                  TOOL=BUTTON;
               else
               if  (((String)e.arg).equals("Choice"))
                  TOOL=CHOICE;
               else
               if  (((String)e.arg).equals("CheckBox"))
                  TOOL=CHECKBOX;
               else
               if  (((String)e.arg).equals("Label"))
                  TOOL=LABEL;
               else
               if  (((String)e.arg).equals("Panel"))
                  TOOL=PANEL;
               else
               if  (((String)e.arg).equals("Horizontal Scrollbar"))
                  TOOL=HSCROLLBAR;
               else
               if  (((String)e.arg).equals("Vertical Scrollbar"))
                  TOOL=VSCROLLBAR;
               else
/*
               if  (((String)e.arg).equals("MultiLineLabel"))
                  TOOL=MULTILINELABEL;
               else
*/
               if  (((String)e.arg).equals("List"))
                  TOOL=LIST;
               else
               if  (((String)e.arg).equals("TextField"))
                  TOOL=TEXTFIELD;
               else
               if  (((String)e.arg).equals("TextArea"))
                  TOOL=TEXTAREA;
               else
               if  (((String)e.arg).equals("Clear"))
                  this.removeAll();
               else
               if  (((String)e.arg).equals("Undo"))
                  {
                  try{
                     this.remove
                     (this.getComponent
                     (this.countComponents()-1));
                     }
                  catch(ArrayIndexOutOfBoundsException ex){;}
                  }
               /*
               else
               custom layout manager menu invoked
               if  (((String)e.arg).equals("MyCustomLayout"))
                  SetMyCustomLayout();
                 end */
               else
               if  (((String)e.arg).equals("Border"))
                  SetBorder();
               else
               if  (((String)e.arg).equals("Flow"))
                  SetFlow();
               else
               if  (((String)e.arg).startsWith("grid_"))
                  SetGrid((String)e.arg);
               else
               if  (((String)e.arg).equals("GridBag"))
                  SetGridBag();
               else
               if  (((String)e.arg).equals("None"))
                  SetNull();
               else
               if  (((String)e.arg).equals("Create Source"))
                  createSource();
               else
               if  (((String)e.arg).equals("Import 'XXX'"))
                  importXXX();
               else
               if  (((String)e.arg).equals("Show Components"))
                  ShowComponents();
               else
               if  (((String)e.arg).equals("Show Grid Lines"))
                  {
                  if(hasGridLines)hasGridLines=false;
                  else hasGridLines=true;
                  repaint();
                  }
               else
               if  (((String)e.arg).equals("Exit"))
                  {
                  if (inAnApplet)
                     {
                     dispose();
                     return true;
                     }
                  else
                     System.exit(0);
                  }
               return true; // finished processing this event
               }
            else
            // when jdk components give us mouse clicks here
            // we will not need this code:
            if
            ((e.target instanceof Button) ||
             (e.target instanceof Checkbox) ||
             (e.target instanceof Choice) ||
             (e.target instanceof TextComponent) ||
             (e.target instanceof List))
               {
               if (LAYOUT == GRIDBAG)
                  new GridbagDialog
                  (this, "Gridbag Constraints",
                  (Component)e.target,
                  TOOL, init_x, init_y, LAYOUT);
               }

         default:break;
      }
   // must return super.handleEvent()
   // so action events (mouseUp(),mouseDrag() etc.) get called:
   return super.handleEvent(e);
   }
   /**
   Use the XXX generated previously.
   */
   public void importXXX()
      {
      String layout;
      Component[] comp = new Component[512];
      if (this.getLayout() != null){
        layout = this.getLayout().toString();
      } else
        layout = "";

      if (layout.indexOf("GridBag") > 0)
         {
         SetGridBag(this.getLayout());
         //LAYOUT = GRIDBAG;
         }
      else
      if (layout.indexOf("Border") > 0)
         {
         SetBorder();
         //LAYOUT = BORDER;
         }
      else
         {
         LAYOUT = 0;
         }
      new XXX(this, comp);
      }
   /**
   Create java source for a class which will layout the screen.
   */
   public void createSource()
      {
      new BuildIt(this, "XXX", layoutConstruct.toString());
      }
   /**
   Dump all components, starting with size of the frame.
   This information can be used to layout the components
   in another java program.
   */
   public void ShowComponents()
      {
      System.out.println("Layout:"+getLayout());
      System.out.println("Size:"+this.size());
      try{
         for (int i = 0; i < countComponents(); i++)
            System.out.println(getComponent(i));
         }catch(ArrayIndexOutOfBoundsException e)
            {System.out.println(e.getMessage());}
      }
   /**
   This arranges the existing components into different grids.
   */
   public void SetGrid(String grid_size)
      {
      LAYOUT = 0;
      String grids = grid_size.substring(5);
      String str_r, str_c;
      StringTokenizer tok = new StringTokenizer(grids, "x");
      try{
         str_r = tok.nextElement().toString();
         str_c = tok.nextElement().toString();
         int grid_r = new Integer(str_r).intValue();
         int grid_c = new Integer(str_c).intValue();
         setLayout(new GridLayout(grid_r,grid_c));
         layoutConstruct = new StringBuffer(
         "setLayout( new GridLayout("+
         grid_r + ", " + grid_c + "));");
         }
      catch(NoSuchElementException e){;}
      validate();
      repaint();
      }
   /**
   This turns off the layout manager. You can layout
   components this way. If you do the layout on the
   same architecture as the target application will run.
   */
   public void SetNull()
      {
      LAYOUT = 0;
      setLayout(null);
      layoutConstruct = new StringBuffer("setLayout(null);");
      validate();
      repaint();
      }
   /*
   public void MyCustomLayout()
      {
      LAYOUT = MYCUSTOMLAYOUT;
      setLayout(new MyCustomLayout());
      layoutConstruct = new StringBuffer(
      "setLayout(new MyCustomLayout());");
      validate();
      repaint();
      }
   */ // end Custom Layout function
   public void SetBorder()
      {
      LAYOUT = BORDER;
      setLayout(new BorderLayout(5,5));
      layoutConstruct = new StringBuffer(
      "setLayout(new BorderLayout(5,5));");
      validate();
      repaint();
      }
   /**
   This sets the layout manager to Flow, which is the
   default for html applications. It is a good choice
   for architecture independent screens.
   */
   public void SetFlow()
      {
      LAYOUT = 0;
      setLayout(new FlowLayout());
      layoutConstruct = new StringBuffer(
      "setLayout(new FlowLayout());");
      validate();
      repaint();
      }
   /**
   This sets the layout manager to gridbag, the most flexible.
   Components have to be added with various constraints for the
   gridbag layout to look correct, so this invokes a Constraints
   dialog.
   */
   public void SetGridBag(LayoutManager layout)
      {
      LAYOUT = GRIDBAG;
      setLayout(layout);
      layoutConstruct = new StringBuffer(
      "setLayout(new GridBagLayout());");
      validate();
      repaint();
      }
   public void SetGridBag()
      {
      SetGridBag(new GridBagLayout());
      }

   public boolean mouseDown(Event e, int x, int y)
      {
      init_x = x;
      init_y = y;
      return true;
      }

   public boolean mouseDrag(Event e, int x, int y)
      {
      width =  x - init_x;
      height = y - init_y;
      repaint();
      return true;
      }

   /**
   After a mouseDrag, the component is instantiated at mouseUp()
   */
   public boolean mouseUp(Event e, int x, int y)
      {
      Component comp = null;
      String where;
      // remove the rectangle outline:
      Graphics g = getGraphics();
      int w =  x - init_x;
      int h = y - init_y;
      g.setXORMode(getBackground());
      g.drawRect(init_x, init_y, last_w, last_h);
      g.setColor(getForeground());
      g.setPaintMode();
      if (LAYOUT == BORDER)
         {
         FontMetrics fm = this.getFontMetrics(menubar.getFont());
         int menu_height = fm.getHeight();
         menu_height *= 3;
         Rectangle r = bounds();
         if (x < r.width / 3)
            where = "West";
         else
         if (x > r.width/3*2)
            where = "East";
         else
         if (y < ((r.height-menu_height)/3)+menu_height)
            where = "North";
         else
         if (y > ((r.height-menu_height)/3*2)+menu_height)
            where = "South";
         else
            where = "Center";
         }
      else
         where = null;
      switch(TOOL)
         {
         case BUTTON:
            buttons[button_count]=
               new Button("Btn:"+String.valueOf(button_count));
            comp = buttons[button_count];
            button_count++;
            break;
         case CHOICE:
            choices[choice_count]=new Choice();
            choices[choice_count].addItem
               ("ChoiceA:"+String.valueOf(choice_count));
            choices[choice_count].addItem
               ("ChoiceB:"+String.valueOf(choice_count));
            comp = choices[choice_count];
            choice_count++;
            break;
         case CHECKBOX:
            checkboxes[checkbox_count]=
               new Checkbox("Checkbox:"+String.valueOf
               (checkbox_count));
            comp = checkboxes[checkbox_count];
            checkbox_count++;
            break;
         case LABEL:
            labels[label_count]=
               new Label("Label:"+String.valueOf(label_count));
            comp = labels[label_count];
            label_count++;
            break;

         /* instantiate custom control
         case MULTILINELABEL:
            multilinelabels[multilinelabel_count]=
               new MultiLineLabel("MultiLabelLabel:"+
               String.valueOf(multilinelabel_count));
            comp = multilinelabels[multilinelabel_count];
            multilinelabel_count++;
            break;
          end */
         case LIST:
            lists[list_count]=new List();
            lists[list_count].addItem("ListA:"+String.valueOf
            (list_count));
            lists[list_count].addItem("ListA:"+String.valueOf
            (list_count));
            lists[list_count].select(1);
            comp = lists[list_count];
            list_count++;
            break;
         case PANEL:
            panels[panel_count]=
               new Panel();
            comp = panels[panel_count];
            panel_count++;
            break;
         case VSCROLLBAR:
            scrollbars[scrollbar_count]=
               new Scrollbar(Scrollbar.VERTICAL);
            comp = scrollbars[scrollbar_count];
            scrollbar_count++;
            break;
         case HSCROLLBAR:
            scrollbars[scrollbar_count]=
               new Scrollbar(Scrollbar.HORIZONTAL);
            comp = scrollbars[scrollbar_count];
            scrollbar_count++;
            break;
         case TEXTFIELD:
            textfields[textfield_count]=
               new TextField("TextField:"+String.valueOf
               (textfield_count));
            comp = textfields[textfield_count];
            textfield_count++;
            break;
         case TEXTAREA:
            textareas[textarea_count]=
               new TextArea("TextArea:"+String.valueOf
               (textarea_count));
            comp = textareas[textarea_count];
            textarea_count++;
            break;
         default:break;
         }
      if (LAYOUT == BORDER)
         this.add(where,comp);
      else
         {
         this.add(comp);
         comp.reshape(init_x, init_y, last_w, last_h);
         }
      validate();
      if (LAYOUT == GRIDBAG)
         new GridbagDialog
         (this, "Gridbag Constraints", comp, TOOL,
         init_x, init_y, LAYOUT);
      last_w = last_h = init_x = init_y = 0;
      return true;
      }
   public void paint(Graphics g)
      {
      if (hasGridLines)
         {
         Rectangle r = bounds();
         if (LAYOUT == BORDER)
            {
            FontMetrics fm =
            this.getFontMetrics(menubar.getFont());
            int menu_height = fm.getHeight();
            menu_height *= 3;
            g.drawLine(r.width/3, 0, r.width/3, r.height);
            g.drawLine(r.width/3*2, 0, r.width/3*2, r.height);
            g.drawLine(
               r.width/3,((r.height-menu_height)/3)+menu_height,
               r.width/3*2,
               ((r.height-menu_height)/3)+menu_height);
            g.drawLine(
               r.width/3,
               ((r.height-menu_height)/3*2)+menu_height,
               r.width/3*2,
               ((r.height-menu_height)/3*2)+menu_height);
            }
         else
            {
            int h = this.getFont().getSize();
            for (int x = 0; x < r.width; x += h)
               g.drawLine(x, 0, x, r.height);
            for (int y = 0; y < r.height; y += h)
               g.drawLine(0, y, r.width, y);
            }
         }
      // erase old lines:
      g.setXORMode(getBackground());
      g.drawRect(init_x, init_y, last_w, last_h);
      // draw new lines:
      g.setColor(getForeground());
      g.setPaintMode();
      g.drawRect(init_x, init_y, width, height);
      last_w = width;
      last_h = height;
      }
   public static void main(String[] args)
     {
     Screen s = new Screen();
     s.inAnApplet = false;
     s.pack();
     s.show();
     }
   }

class GridbagDialog extends Dialog
   {
   private boolean inAnApplet = true;
   // Controls:
   Component component;
   Component[] comp = new Component[64];
   List[] list = new List[32];
   Choice[] choice = new Choice[32];
   GridBagConstraints c;
   TextField field;
   Screen parent;
   Button setButton;
   int TOOL, LAYOUT;

   GridbagDialog
      (Frame scr, String title, Component component, int TOOL,
      int x, int y, int LAYOUT)
      {
      super(scr, title, false);
      parent = (Screen)scr;
      this.component = component;
      this.TOOL = TOOL;
      this.LAYOUT = LAYOUT;
      Panel p = new Panel();
      this.setLayout(new BorderLayout());
      this.add("Center", p);
      new ConstraintsDialog
         (p, comp, component, TOOL, x, y, LAYOUT);
      this.pack();
      this.show();
      }
   public boolean action(Event event, Object arg)
      {
      c = new GridBagConstraints();
      if (event.target == comp[29])
         {
         this.hide();
         this.dispose();
         return true;
         }
      else
      if (event.target == comp[28])
         {
         parent.remove(component);
         choice[0] =  (Choice)comp[19];
         if (choice[0].getSelectedItem().equals("RELATIVE"))
            c.gridx = GridBagConstraints.RELATIVE;
         else
            c.gridx =
            new Integer(choice[0].getSelectedItem()).intValue();
         choice[0] =  (Choice)comp[20];
         if (choice[0].getSelectedItem().equals("RELATIVE"))
            c.gridy = GridBagConstraints.RELATIVE;
         else
            c.gridy =
            new Integer(choice[0].getSelectedItem()).intValue();
         choice[0] =  (Choice)comp[0];
         c.insets.top = new Integer
            (choice[0].getSelectedItem()).intValue();
         choice[0] =  (Choice)comp[1];
         c.insets.left = new Integer
            (choice[0].getSelectedItem()).intValue();
         choice[0] =  (Choice)comp[2];
         c.insets.right = new Integer
            (choice[0].getSelectedItem()).intValue();
         choice[0] =  (Choice)comp[3];
         c.insets.bottom = new Integer
            (choice[0].getSelectedItem()).intValue();
         choice[0] =  (Choice)comp[6];
         String anchor = choice[0].getSelectedItem();
         if (anchor.equals("CENTER"))
            c.anchor = GridBagConstraints.CENTER;
         else if (anchor.equals("EAST"))
            c.anchor = GridBagConstraints.EAST;
         else if (anchor.equals("WEST"))
            c.anchor = GridBagConstraints.WEST;
         else if (anchor.equals("NORTH"))
            c.anchor = GridBagConstraints.NORTH;
         else if (anchor.equals("NORTHEAST"))
            c.anchor = GridBagConstraints.NORTHEAST;
         else if (anchor.equals("NORTHWEST"))
            c.anchor = GridBagConstraints.NORTHWEST;
         else if (anchor.equals("SOUTHWEST"))
            c.anchor = GridBagConstraints.SOUTHWEST;
         else if (anchor.equals("SOUTHEAST"))
            c.anchor = GridBagConstraints.SOUTHEAST;
         else if (anchor.equals("SOUTH"))
            c.anchor = GridBagConstraints.SOUTH;

         choice[0] =  (Choice)comp[8];
         String fill = choice[0].getSelectedItem();
         if (fill.equals("BOTH"))
            c.fill = GridBagConstraints.BOTH;
         else if (fill.equals("NONE"))
            c.fill = GridBagConstraints.NONE;
         else if (fill.equals("HORIZONTAL"))
            c.fill = GridBagConstraints.HORIZONTAL;
         else if (fill.equals("VERTICAL"))
            c.fill = GridBagConstraints.VERTICAL;

         choice[0] =  (Choice)comp[10];
         if (choice[0].getSelectedItem().equals("REMAINDER"))
            c.gridwidth = GridBagConstraints.REMAINDER;
         else
            c.gridwidth = new Integer(choice[0].getSelectedItem()).intValue();
         choice[0] =  (Choice)comp[12];
         if (choice[0].getSelectedItem().equals("REMAINDER"))
            c.gridheight = GridBagConstraints.REMAINDER;
         else
            c.gridheight = new Integer(choice[0].getSelectedItem()).intValue();

         choice[0] =  (Choice)comp[21];
         c.ipadx =
         new Integer(choice[0].getSelectedItem()).intValue();
         choice[0] =  (Choice)comp[22];
         c.ipady =
         new Integer(choice[0].getSelectedItem()).intValue();
         choice[0] =  (Choice)comp[23];
         c.weightx =
         new Double(choice[0].getSelectedItem()).doubleValue();
         choice[0] =  (Choice)comp[24];
         c.weighty =
         new Double(choice[0].getSelectedItem()).doubleValue();

         TextField textField = (TextField)comp[26];
         if (TOOL == parent.BUTTON)
            {
            Button button = (Button)component;
            button.setLabel(textField.getText());
            }
                        else
         if (TOOL == parent.LABEL)
            {
            Label label = (Label)component;
            label.setText(textField.getText());
            }
         ((GridBagLayout)parent.getLayout()).
            setConstraints(component, c);
         parent.add(component);
         parent.validate();
         parent.repaint();
         }
      //hide();
      return true;
      }
   }

