pizza.sa
Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
---------------------------> Sather 1.1 source file <--------------------------
-- File: pizza.sa
-- Author: Holger Klawitter <holger@icsi.berkeley.edu>
-- Date: 6/12/96
-- Demonstration program for the Sather Gui.
-- Simulating a pizza ordering tool.
-- Compile with
-- cs -gui -main PIZZA_MAIN -o pizza
class TOPPING < $TK_WIDGET
class TOPPING < $TK_WIDGET
-- Toppings are mainly buttons on which van click to select that
-- topping for your pizza. They also store the name of the topping
-- the the value factor.
is
include TK_CHECK
create->private create;
readonly attr name: STR;
private attr var: TK_VAR;
create(frame:$TK_WIDGET,n:STR,updfunc:ROUT): SAME
-- Creates a new topping button in the frame 'frame'. 'n' is the name
-- of the topping. 'updfunc' will be called when the button is pressed.
is
screenname: STR;
variable: TK_VAR;
-- If the topping has double value, it will be displayed with a star.
if PIZZA_DATA::topping_factor(n) /= 1.0 then
screenname := n + "*"
else
screenname := n
end;
variable := #TK_VAR;
res ::= create(frame,
TK_CHECK_CFG::std.text(screenname).variable(variable),
TK_PACK::top.anchor(TK_ANCHOR::w) );
res.command(updfunc);
res.name := n;
res.var := variable;
return res
end;
price: FLT is return PIZZA_DATA::price(name); end;
-- Returns the price for this topping on the current pizza.
is_selected: BOOL is return var.query = "1"; end;
-- Returns true if button is selected.
end; -- class TOPPING
class PIZZA_MAIN
class PIZZA_MAIN
is
include GUI_UTIL;
private shared pizzalist: TK_LISTBOX;
-- Listbox with specials.
private shared toppingframe: TK_FRAME;
-- Master frame for list of toppings.
shared size: TK_VAR; -- TK variable containing the size of the pizza.
shared price: TK_LABEL; -- Area to display the price.
shared extras: TK_ENTRY; -- Area to enter extra requests.
shared toppingboxes: SET{TOPPING}; -- List of all toppings.
init
-- The main program of this application.
-- Sets up display.
is
-- First get all data for the application from the model class
-- PIZZA_DATA.
specialnames: ARRAY{STR} := void;
toppingnames: SET{STR} := void;
PIZZA_DATA::init(out specialnames,out toppingnames);
dummy: $OB := void;
radio: TK_RADIO := void;
TK_WINDOW_MGR::title(root_window,"The Sather Pizza Blitz");
-- 1.) The top line
top ::= #TK_FRAME(root_window, TK_PACK::top);
-- 1.1.) The Pizza Specials selector box with title and listbox.
pizzaframe ::= #TK_FRAME(top, TK_PACK::left);
dummy := #TK_LABEL(pizzaframe,
TK_LABEL_CFG::std.text("Select a pizza")
.justify_left,
TK_PACK::top_grow_horiz);
pizzalist := #TK_LISTBOX(pizzaframe,
TK_LISTBOX_CFG::std.height(5.0).width(40.0),
TK_PACK::top_grow_horiz
);
loop pizzalist.insert(1.up!,specialnames.elt!); end;
pizzalist.bind_event(TK_BUTTON_EVENT::B1,bind(select_pizza(_)));
-- 1.2.) The list of sizes
size := #TK_VAR;
sizeframe ::= #TK_FRAME(top, TK_PACK::right);
dummy := #TK_LABEL(sizeframe,
TK_LABEL_CFG::std.text("Select pizza size"),
TK_PACK::top);
-- 1.2.1.) Left column
sizeleft ::= #TK_FRAME(sizeframe,TK_PACK::left);
radio := #TK_RADIO(sizeleft,
TK_RADIO_CFG::std.variable(size)
.text("12\"").justify_left.val("12"),
TK_PACK::top);
radio.command(bind(compute_price));
-- Remember radio for 14 to select it later.
size14 ::= #TK_RADIO(sizeleft,
TK_RADIO_CFG::std.variable(size)
.text("14\"").justify_left.val("14"),
TK_PACK::top);
size14.command(bind(compute_price));
-- 1.2.2.) Right column
sizeright ::= #TK_FRAME(sizeframe,TK_PACK::right);
radio := #TK_RADIO(sizeright,
TK_RADIO_CFG::std.variable(size)
.text("16\"").justify_left.val("16"),
TK_PACK::top);
radio.command(bind(compute_price));
radio := #TK_RADIO(sizeright,
TK_RADIO_CFG::std.variable(size)
.text("18\"").justify_left.val("18"),
TK_PACK::top);
radio.command(bind(compute_price));
-- 2.) In the middle there go the toppings.
toppingframe := #TK_FRAME(root_window, TK_PACK::top);
toppingboxes := #;
init_toppings(toppingnames);
-- 3.) The line for extra requests
extraframe ::= #TK_FRAME(root_window, TK_PACK::top);
-- 3.1.) A label for it
extralbl ::= #TK_LABEL(extraframe,
TK_LABEL_CFG::std.text("Extra requests ? :"),
TK_PACK::left);
-- 3.2.) The user can enter the text here
extras := #TK_ENTRY(extraframe,
TK_ENTRY_CFG::std.variable(#TK_VAR)
.width(40.0),
TK_PACK::right);
extras.set_text("none");
-- 4.) Bottom line
bottom ::= #TK_FRAME(root_window, TK_PACK::bot_grow_horiz);
-- 4.1.) The 'Order' button
order ::= #TK_BUTTON(bottom,
TK_BUTTON_CFG::std.text("Order(quits)"),
TK_PACK::left);
order.command(quit_routine); -- The quit_routine is included from GUI_UTIL
-- 4.2.) The 'Clear' button
clear ::= #TK_BUTTON(bottom,
TK_BUTTON_CFG::std.text("Unselect toppings"),
TK_PACK::left);
clear.command(bind(unselect_all));
-- 4.3.) The price information
price := #TK_LABEL(bottom,
TK_LABEL_CFG::std
.justify_right
.font("-*-screen-*-r-*-*-*-160-*-*-*-*-*-*"),
TK_PACK::right);
-- 4.4.) Some fixed text for the price information
dummy := #TK_LABEL(bottom,
TK_LABEL_CFG::std.text("This Pizza costs: "),
TK_PACK::right);
-- Selecting some defaults.
size14.invoke;
pizzalist.set_selection(0);
end; -- init
private init_toppings(toppings:SET{STR})
-- Puts the set of toppings vertically alphabetically (4 columns)
-- into the toppingframe.
is
-- Create the frames for the columns.
subframes: ARRAY{TK_FRAME} := #(4);
loop
subframes[0.upto!(3)] :=
#TK_FRAME(toppingframe,TK_PACK::left_grow_vert);
end;
-- Sort the list of toppings.
n ::= toppings.size;
sorted_top ::= #ARRAY{STR}(n);
loop sorted_top.set!(toppings.elt!) end;
sorted_top.sort;
-- Put them vertiacally sorted in the colums.
bound ::= (n/4)*4;
if n%4>0 then bound := bound + 4; end;
loop
cur ::= 0.upto!(bound);
tp ::= sorted_top.elt!;
toppingboxes.insert( #TOPPING(subframes[cur*4/bound], tp,
bind(compute_price) ));
end;
end;
-- EVENTS
unselect_all
-- Turns all topping buttons off.
is
loop toppingboxes.elt!.deselect end;
extras.set_text("none");
compute_price;
end;
compute_price(e:TK_EVENT_INFO) is compute_price end;
-- A hook for 'compute_price' without argument.
select_pizza(e:TK_EVENT_INFO)
-- Routine being called when Mouse is pressed in the
-- list of pizza specials. Looks whether there is a selection
-- (there shouldn't be more than one -- as the list is a browse list)
-- and selects the toppings of this pizza.
is
x: INT := 0;
y: INT := 0;
if pizzalist.curselection.size = 0 then return end;
e.mouse_coordinates(out x,out y);
select_pizza(pizzalist.index_at(x.flt,y.flt));
end;
-- ACTIONS:
compute_price
-- Will be called whenever something happens which changes the
-- value of the pizza and computes the new price.
is
newprice: FLT := PIZZA_DATA::baseprice;
loop
toppingbox ::= toppingboxes.elt!;
if toppingbox.is_selected then
newprice := newprice + toppingbox.price;
end
end;
price.configure
(TK_LABEL_CFG::std.text(#FMT("$<##.##>",newprice).str));
end;
select_pizza(newpizza:INT)
-- When a speical is selected, this function changes the topping
-- buttons to match the recipe.
is
loop
toppingbox ::= toppingboxes.elt!;
if PIZZA_DATA::has_topping(newpizza,toppingbox.name) then
toppingbox.select;
else
toppingbox.deselect;
end
end;
compute_price;
end;
end; -- class PIZZA_MAIN
class PIZZA_DATA
class PIZZA_DATA
-- This class stores all prices and selections of Sathers Pizza Blitz.
is
private shared specials: ARRAY{STR};
private shared special_count: INT;
-- List of all specials.
private shared pizzatoppings: ARRAY{ARRAY{STR}};
-- List of toppings on special number `i'.
private shared doubletoppings: ARRAY{STR} :=
| "Clams","Green Olives","Pastrami","Pesto Sauce",
"Marinated Chicken","Shrimp","Sun Dried Tomatoes" |;
-- List of toppings with double value.
private shared toppings: SET{STR};
-- List of all topping names.
init(out specialnames: ARRAY{STR},out toppingnames: SET{STR})
-- Sets the recepies for the speical pizzas which are available
-- from a specials list. The toppings mentioned in this list will
-- be used to generate the list of toppings.
is
toppings := #;
pizzatoppings := #(16);
specials := #(16);
special_count := 0;
addpizza( "Pizza with Sauche and Cheese", #ARRAY{STR}(0) );
addpizza( "The Mission Special",
|"Salami","Pepperoni","Mushrooms","Sausage"| );
addpizza( "Mr Pizza Man Special",
|"Salami","Pepperoni","Mushrooms","Onions","Bell Peppers",
"Sausage" | );
addpizza( "Vegetarian Special",
| "Mushrooms","Onions","Bell Peppers","Sliced Tomatos",
"Olives" | );
addpizza( "Meat Only Special",
| "Salami","Pepperoni","Linguica","Beef","Canadian Bacon",
"Sausage" | );
addpizza( "Aloha Special",
| "Ham","Canadian Bacon","Pineapple" | );
addpizza( "Fiesta Special",
| "Ground Beef","Onions","Linguica","Jalapenos",
"Mushrooms"| );
addpizza( "Ol' West Cattlemans's",
| "Salami","Pepperoni","Beef","Ham","Linguica",
"Mushrooms","Onions" | );
addpizza( "Pesto Special",
| "Pesto Sauce","Spinach","Onions","Feta Cheese" | );
addpizza( "Seafood Special",
| "Clams", "Garlic" | );
addpizza( "Zorba the Greek",
|"Salami","Pepperoni","Mushrooms","Onions","Bell Peppers",
"Sausage","Feta Cheese","Canadian Bacon" | );
addpizza( "Guadalajara Special",
|"Guadalajara Sauce","Green Olives","Beef","Onions",
"Jalapenos","Linguica","Ranchero Cheese"| );
addpizza( "Vegi Deluxe",
| "Pesto Sauce","Artichoke Hearts","Black Olives","Mushrooms",
"Garlic","Mozzarella" | );
addpizza( "Quatro Stagioni",
| "Ham","Artichoke Hearts","Black Olives","Mushrooms" | );
addpizza( "The Bird Special",
| "Marinated Chicken","Mushrooms" | );
addpizza( "Gurmet Vegetarian",
| "Pesto Sauce","Roasted Red Peppers","Pine Nuts",
"Zucchini","Broccoli","Eggplant" | );
specialnames := specials;
toppingnames := toppings;
end;
private addpizza( name:STR, thistoppings: ARRAY{STR} )
-- Function sued for initialzing. Adds a special with the name 'name'
-- and the list of toppings on that special.
is
specials[special_count] := name;
pizzatoppings[special_count] := thistoppings;
loop toppings.insert(thistoppings.elt!) end;
special_count := special_count + 1;
end;
has_topping(special_nr:INT,topping:STR): BOOL
-- Returns 'true' if the special number 'special_nr' has the given
-- topping.
is
return pizzatoppings[special_nr].has(topping)
end;
baseprice: FLT
-- Computes the base price for a pizza of the currently selected size.
is
s: STR := PIZZA_MAIN::size.query;
case s
when "12" then return 7.16
when "14" then return 8.52
when "16" then return 10.62
when "18" then return 12.1
else
raise "unknown pizza size " + s;
end;
end;
topping_factor(topping:STR): FLT
-- Computes the relative price for a topping.
is
if doubletoppings.has(topping) then return 2.0 end;
return 1.0;
end;
price(topping:STR): FLT
-- Computes the price for the given topping. Considers expensice toppings
-- and the pizza size.
is
val_factor: FLT := topping_factor(topping);
case PIZZA_MAIN::size.query
when "12" then return 0.95 * val_factor
when "14" then return 1.10 * val_factor
when "16" then return 1.30 * val_factor
when "18" then return 1.45 * val_factor
else
raise "unknown pizza size"
end
end;
end; -- PIZZA_VALUES