1  /*  A pizza-order example, based largely on the CGI example */
  2  /*  by N.J. McCracken.  This program by Ernest Sibert   */
  3  
  4  import java.awt.*;
  5  
  6  
  7  public class Pizza extends java.applet.Applet { 
  8    public static final int  gsize = 16;  /* General font size, font */
  9    public static final Font gfont = new Font("Helvetica", Font.PLAIN, gsize);
 10  
 11    String address, city;  /* Info. about the shop (from HTML) */
 12    double tax;      /* Sales tax rate for locality      */
 13  
 14    PizzaSML sml;    /* Panel for pizza size   */
 15    Toppings tops;   /* Panel for topping selection  */
 16    Name name;     /* Panel for email address  */
 17    String email = null;   /* The email address    */
 18    Button order;    /* "Place Order" button   */
 19    boolean hasBill;   /* Have we made a bill already? */
 20    Bill bill;     /* The bill     */
 21    Button confirm;    /* "Confirm Order" button */
 22    boolean hasConfirmation; /* Have we confirmed an order?  */
 23    TextField message;   /* Confirmation message, others */
 24  
 25    public void init() { 
 26      address = getParameter("address");
 27      city    = getParameter("city");
 28      tax     = (Double.valueOf(getParameter("tax"))).doubleValue();
 29      setLayout(new FlowLayout(FlowLayout.CENTER, 10, 4));
 30      Top  top  = new Top(36);      /* Arg is font size */
 31      Loc  loc  = new Loc(address, city, gsize);
 32      add(top);  add(loc);
 33      sml = new PizzaSML(gfont);  add(sml);
 34      add(new Label("--------------------- Toppings ---------------------"));
 35      tops = new Toppings(gfont);      
 36      add(tops);
 37      name = new Name(gfont);  add(name);
 38      order   = new Button("Place Order");    add(order);
 39      confirm = new Button("Confirm Order");  add(confirm);
 40      hasBill = false;  hasConfirmation = false;   /* Neither yet */
 41      bill = new Bill(gfont);  add(bill);
 42      message = new TextField(
 43    "                          Welcome to ECStasy Pizza",
 44            60);
 45      message.setEditable(false);  add(message);
 46    }
 47  
 48    /* Deal with relevant events */
 49  
 50    public boolean action(Event evt, Object arg) { 
 51      Object tgt = evt.target;    /* The target object */
 52      boolean result = false;   /* result      */
 53      if ( tgt instanceof Button ) { 
 54        if ( tgt == order ) { 
 55          result = handleOrder();
 56        } else {
 57          if ( tgt == confirm ) { 
 58            result = handleConfirm(); 
 59          } else return false;
 60        }
 61      } else return false;
 62      return result;
 63    }
 64  
 65    /* Place order */
 66  
 67    boolean handleOrder() { 
 68      email = name.getText();  /* We could check more carefully */
 69      try { 
 70        bill.enterPrice(this, sml.pSize(), tops.countTops());
 71        message.setText(
 72          "Click Confirm or change order and click Place Order.");
 73        hasBill = true;  hasConfirmation = false;
 74      } catch (/* StringIndexOutOfBounds */ Exception ex) { 
 75        message.setText("Sorry "+ex.toString()+"try again tomorrow.");
 76        hasBill = false;
 77      }
 78      return true;
 79    }
 80  
 81    /*  Confirm order */
 82  
 83    boolean handleConfirm() { 
 84      if ( hasConfirmation ) { 
 85        message.setText(
 86          "Place another order, then click Confirm after you receive the bill.");
 87        hasConfirmation = false;
 88      } else if ( hasBill ) { 
 89        message.setText(
 90          "Thank you for your order; your account has been debited.");
 91        hasConfirmation = true;
 92      } else { 
 93        message.setText(
 94          "Place an order first; click Confirm after you receive the bill.");
 95      }
 96      return true;
 97    }
 98    
 99  } // end Pizza class
100  
101  
102  class Top extends Panel {   /* Flashy top panel */
103     Top(int size) { 
104       setLayout(new FlowLayout());
105       setFont(new Font("TimesRoman", Font.BOLD+Font.ITALIC, size));
106       setForeground(Color.orange);  setBackground(Color.blue);
107       add(new Label("ECStasy Pizza", Label.CENTER));
108     }
109  }
110  
111  
112  class Loc extends Panel {  /* Shop address, location, font size */
113     Loc(String address, String city, int size) { 
114       setLayout(new FlowLayout(FlowLayout.CENTER, 10, 10));
115       setFont(new Font("TimesRoman", Font.ITALIC, size));
116       setForeground(Color.orange);  setBackground(Color.blue);
117       add(new Label(address, Label.LEFT));
118       add(new Label(city, Label.CENTER));
119     }
120  }
121  
122  
123  class PizzaSML extends Panel { 
124    public static final int SMALL = 1, MEDIUM = 2, LARGE = 3;
125    CheckboxGroup sizeBoxes;
126  
127    PizzaSML(Font gfont) { 
128      setLayout(new FlowLayout(FlowLayout.CENTER, 10, 10));
129      setFont(gfont);
130      /* Pizza size with a group of checkboxes */
131      add(new Label("Size: "));
132      sizeBoxes = new CheckboxGroup();
133      add(new Checkbox("small",  sizeBoxes, false));
134      add(new Checkbox("medium", sizeBoxes, false));
135      add(new Checkbox("large",  sizeBoxes, true ));
136    }
137  
138    int pSize() { 
139      String clabel = sizeBoxes.getCurrent().getLabel();
140      /* clabel is label of Currently selected button */
141      if ( clabel.equals("small" )) return SMALL;  else
142      if ( clabel.equals("medium")) return MEDIUM; else
143                                    return LARGE;
144    }
145     
146  } // end PizzaSML class
147  
148  
149  class Toppings extends Panel { 
150    private static int nTop = 6; /* Number of choices */
151    Checkbox item[]; /* Topping selections */
152  
153    Toppings(Font gfont) { 
154      setLayout(new GridLayout(2, 3, 10, 10));  setFont(gfont);
155      if ( nTop > 64 ) { /* Too many toppings for bitvector */
156        add(new Label("TOO"));  add(new Label(" MANY"));
157        add(new Label("TOPPINGS"));
158      }
159      item = new Checkbox[nTop];
160      item[0] = new Checkbox("Pepperoni"   );  add(item[0]);
161      item[1] = new Checkbox("Extra Cheese");  add(item[1]);
162      item[2] = new Checkbox("Sausage");       add(item[2]);
163      item[3] = new Checkbox("Onions");        add(item[3]);
164      item[4] = new Checkbox("Peppers");       add(item[4]);
165      item[5] = new Checkbox("Dead Fish");     add(item[5]);
166    }
167  
168    int countTops() {   /* Returns number of toppings chosen */
169      int n = 0;
170      for ( int i = 0;  i < nTop;  i++ )
171        if ( item[i].getState() ) n++;
172      return n;
173    }
174  
175    /* Returns long viewed as bit vector - bit 2^i represents topping i */
176  
177    long topSelection() { 
178      long bt = 0;
179      for ( int i = 0;  i < nTop;  i++ )
180        if ( item[i].getState() ) bt |= 1<<i;
181      return bt;
182    }
183    
184  } // end Toppings class
185  
186  
187  class Name extends Panel { 
188    TextField name;
189  
190    Name(Font gfont) { 
191      setLayout(new FlowLayout());  setFont(gfont);
192      add(new Label("email address: "));
193      name = new TextField(40);
194      name.setFont(gfont);  add(name);
195    }
196  
197    String getText() { return name.getText(); }
198  }
199  
200  /********************************************************/
201  /*  Prices are recorded in pennies, printed as dollars  */
202  /********************************************************/
203  
204  class Bill extends Panel { 
205    long pPrice, tPrice, subtotal, tax, total;  /* Amounts */
206  
207    static final Label subl = new Label("Subtotal");  /* Fixed labels */
208    static final Label taxl = new Label("Tax");
209    static final Label totl = new Label("Total");
210  
211    static final int dchars = 8;  /* Spaces for amounts */
212          /* This is  $dddd.dd  */
213  
214    static final String blank  = "        ";  /* dchars blanks */
215    static final String dblank = "$       ";  /* with $  */
216    static final String errstr = "$ ERROR ";  /* For errors  */
217  
218    /* Adjustable labels */
219  
220    Label lPizza  = new Label("Your pizza");
221    Label lTops   = new Label("Your toppings");
222    Label lPPrice = new Label(dblank, Label.RIGHT);
223    Label lTPrice = new Label(blank,  Label.RIGHT);
224    Label lSubt   = new Label(blank,  Label.RIGHT);
225    Label lTax    = new Label(blank,  Label.RIGHT);
226    Label lTotal  = new Label(dblank, Label.RIGHT);
227  
228  
229    /* Create a blank bill */
230  
231    Bill (Font gfont) { 
232      setLayout(new GridLayout(5, 2, 30, 5));
233      setFont(gfont);  setBackground(Color.green);
234      add(lPizza);  add(lPPrice);
235      add(lTops);   add(lTPrice);
236      add(subl);    add(lSubt);
237      add(taxl);    add(lTax);
238      add(totl);    add(lTotal);
239    }
240  
241    public Insets insets() {  /* Specify small insets */
242      return new Insets(10, 10, 10, 10); 
243    } /* top, bot, lft rgt  */
244  
245  
246    /* Compute the bill.  TaxRate is in percent, e.g.,  */
247    /* 7.0 for a 7% tax         */
248  
249    void enterPrice(Pizza pizza, int pSize, int nTops)
250           throws StringIndexOutOfBoundsException { 
251      String plabel = (pSize == PizzaSML.SMALL ) ? "Small " :
252          (pSize == PizzaSML.MEDIUM) ? "Medium" : "Large " ;
253      lPizza.setText(plabel + " pizza");
254      pPrice = 600 + pSize*100;
255      lPPrice.setText(dollar(pPrice, true));
256      String tlabel =  (nTops == 0) ? "No toppings" :
257                       (nTops == 1) ? "1 topping"   :
258                       nTops + " toppings"   ;
259      lTops.setText(tlabel);
260      tPrice = nTops*(50 + pSize*25);
261      lTPrice.setText(dollar(tPrice, false));
262      subtotal = pPrice + tPrice;
263      lSubt.setText(dollar(subtotal, false));
264      tax = Math.round(subtotal*pizza.tax/100.0D);
265      lTax.setText(dollar(tax, false));
266      total = subtotal + tax;
267      lTotal.setText(dollar(total, true));
268    }
269  
270    /* Format long (pennies) as dollars, ( with $ ) */
271  
272    static String dollar(long amt, boolean dsign)
273           throws StringIndexOutOfBoundsException { 
274      StringBuffer dbuff = new StringBuffer("$.");
275      int i;
276      if ( !dsign ) dbuff.setCharAt(0, ' '); /* Dollar sign */
277      String ast = Long.toString(amt);
278      int slen = ast.length();   /* length of string */
279      if ( slen > dchars - 2 ) return errstr;  /* Too big */
280      if ( slen == 1 ) {  /* Very small value */
281      ast = "0" + ast;  slen = 2; }
282      int sfst = dchars - slen - 1;  /* position of 1st char */
283      /* Digits before decimal point */
284      dbuff.insert(1, ast.substring(0, slen - 2));
285      /* Initial blanks */
286      for (i = 1;  i < sfst;  i++ ) dbuff.insert(1, ' ');
287      /* Last two digits */
288      dbuff.append(ast.substring(slen-2, slen));
289      return dbuff.toString();
290    }
291  
292  } // end Bill class