#!/bin/sh
psh << '%EOF'
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% This file is a product of Sun Microsystems, Inc. and is provided for
% unrestricted use provided that this legend is included on all tape
% media and as a part of the software program in whole or part.  Users
% may copy or modify this file without charge, but are not authorized to
% license or distribute it to anyone else except as part of a product
% or program developed by the user.
%
% THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
% WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
% PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
%
% This file is provided with no support and without any obligation on the
% part of Sun Microsystems, Inc. to assist in its use, correction,
% modification or enhancement.
%
% SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
% INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
% OR ANY PART THEREOF.
%
% In no event will Sun Microsystems, Inc. be liable for any lost revenue
% or profits or other special, indirect and consequential damages, even
% if Sun has been advised of the possibility of such damages.
%
% Sun Microsystems, Inc.
% 2550 Garcia Avenue
% Mountain View, California  94043
%
%
% @(#)pizzatool 1.9 91/07/22
%
% Copyright (c) 1991 by Sun Microsystems, Inc.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% PizzaTool Source Code List of Ingredients
%
%   User Interface Structure Outline
%   Setup for OpenWindows 2.0 or 3.0
%   Class Definitions
%     ClassPizza ClassTopping ClassStyle
%     ClassProPanel ClassPopupPizzaWindow
%   Globals
%   Utilities
%   Notifiers
%     ToolPanel ToppingPanel EditPanel Notice
%   Notice Definitions
%   Topping Definitions
%   Style Definitions
%   Top Level User Interface Componants
%   ToolPanel Componants
%   ToppingPanel Componants
%   EditPanel Componants
%   Notice Componants
%   Initialization
%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% User Interface Structure Outline
%
% This is an outline of the user interface structure of pizzatool.
% The number of "*"'s before the name is an object's level of nesting.
% A top level window starts with "*", a panel inside that starts with "**",
% a button inside that starts with "***", and so on.
% The name of the object tells where it is defined in userdict.
% Following the name is a colon and a description of the object.
% The description consists of optional choice mode or layout names,
% and the object's class name.
% The next optional line (not prefixed by "*"'s) lists the names of any
% notifiers called by the object. Most object's targets are set to userdict,
% which is where the notifier and object names are defined. Notifier names
% may be followed by and "@" sign and the name of the target object, if
% not userdict.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% * ToolWindow: ClassBaseWindow
% ** ToolPanel: /Calculated ClassPanel
% *** addressmenubuttons: /Grid ClassMenuButtons
% **** pizzaparlormenu: /Exclusive /Grid ClassMenu
% *** winbuttons: /Grid ClassButtons
%     /ShowToppingWindow /ShowPreviewWindow /OrderPizza /ShowEditWindow
% *** namefieldlabel: ClassLabel
% *** namefield: ClassTextField
%     nullnotify
% *** phonefieldlabel: ClassLabel
% *** phonefield: ClassTextField
%     nullnotify
% *** addressfieldlabel: ClassLabel
% *** addressfield: ClassTextField
%     nullnotify
% *** deliverylabel: ClassLabel
% *** deliverymenubutton: /Grid ClassMenuButtons
% **** deliverymenu: /Exclusive /Grid ClassMenu
%      /SetDelivery
% *** deliveryvalue: ClassLabel
% *** totallabel: ClassLabel
% *** totalfield: ClassTextField
%     nullnotify
% *** emaillabel: ClassLabel
% *** emailfield: ClassTextField
% *** instructionslabel: ClassLabel
% *** instructionfield0..5: ClassTextField
%     nullnotify
%
% * ToppingWindow: ClassPopupWindow
% ** ToppingPanel: /Calculated ClassPanel
% *** orderbuttons: /Grid ClassButtons
%     /ShowPreviewWindow /ShowEditWindow /OrderPizza
% *** pizzasizelabel: ClassLabel
% *** pizzasizesettings: /Grid ClassSettings
%     /SetPizzaSize
% *** pizzafractionlabel: ClassLabel
% *** pizzafractionsettings: /Grid ClassSettings
%     /SetPizzaFraction
% *** stylelabel: ClassLabel
% *** stylemenubutton: /Grid ClassMenuButtons
% **** stylemenu: /Exclusive /Grid ClassMenu
%      /MenuSetStyle
% *** stylevalue: ClassLabel
% *** meatlabel: ClassLabel
% *** meatcheckboxes: /Grid ClassCheckBoxes
%     /SetCheckboxes
% *** vegetablelabel: ClassLabel
% *** vegetablecheckboxes: /Grid ClassCheckBoxes
%     /SetCheckboxes
% *** costlabel: ClassLabel
% *** costfield: ClassTextField
%     nullnotify
%
% * EditWindow: ClassPopupWindow
% ** EditPanel: /Calculated ClassPanel
% *** stylemenubuttons: /Grid ClassMenuButtons
% **** editstylemenu: /Grid ClassMenu
%      /NewPizzaStyle /EditPizzaStyle /RenamePizzaStyle
%      /DeletePizzaStyle /SavePizzaStyle
% **** edittoppingmenu: /Grid ClassMenu
%      /RemoveSelected /CopyCheckboxes
% ***** meattoppingmenu: /NonExclusive /Grid ClassMenu
%	/UpdateToppings
% ***** vegetabletoppingmenu: /NonExclusive /Grid ClassMenu
%	/UpdateToppings
% *** stylelistlabel: ClassLabel
% *** stylescroll: ClassVScrollbar
%     /scroll @ stylelist
% *** stylelist: ClassScrollList
%     /EditStyle
% *** styletoppingslabel: ClassLabel
% *** styletoppingsscroll: ClassVScrollbar
%     /scroll @ styletoppingslist
% *** styletoppingslist: ClassScrollList
% *** stylenamelabel: ClassLabel
% *** stylenamefield: ClassTextField
%     /NewPizzaStyle
% *** styleextralabel: ClassLabel
% *** styleextrafield: ClassNumericField
%     /SetStyleExtraToppings
% *** stylepriceslabel: ClassLabel
% *** styleprice10label: ClassLabel
% *** styleprice10field: ClassTextField
%     /SetStylePrice
% *** styleprice14label: ClassLabel
% *** styleprice14field: ClassTextField
%     /SetStylePrice
% *** styleprice16label: ClassLabel
% *** styleprice16field: ClassTextField
%     /SetStylePrice
% *** styleprice18label: ClassLabel
% *** styleprice18field: ClassTextField
%     /SetStylePrice
%
% * PreviewWindow: ClassPopupPizzaWindow
% ** Pizza: ClassPizza
%
% * Notice: ClassNotice
% ** oknoticebuttons: ClassButtons
%    /NoticeClose
% ** yesnonoticebuttons: ClassButtons
%    /NoticeYesNo
%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Setup for OpenWindows 2.0 or 3.0

/is_v2? systemdict /findpackage known not def

is_v2? {
  /SLEEP { aload pop 1000 mul exch add 60 div sleep } def
  /BUILDIMAGE { buildimage } def
} {
  /NeWS 3 0 findpackage beginpackage
  /TNTCore 3 0 findpackage beginpackage
  /TNT 3 0 findpackage beginpackage

  /SLEEP { sleep } def
  /BUILDIMAGE { framebuffer /Colormap get buildimage } def
} ifelse

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Class Definitions
%
% Three classes are used to model the virual pizza reality.
%
% An instance of ClassPizza is an actual canvas on the screen,
% that embodies the pizza itself.
%
% An instance of ClassTopping encapsulates all that is known about
% a pizza topping, including its nominal, visual, dietary, and other
% aesthetic properties.
%
% An instance of ClassStyle describes a vendor supplied pizza style,
% consisting of a unique product name, a list of pizza toppings
% included with the default configuration, as well as pricing and
% discounting information.  
% 
% Two other classes are used to sew together the underpinnings of this
% consentual hallucination.
%
% An instance of ClassProPanel is just a control panel, that promotes
% (caches) its minsize into the instance as a constant function the
% first time /minsize is calculated, so that future calls to /minsize
% are very fast.
%
% An instance of ClassPopupPizzaWindow is used to frame the pizza
% canvas (an instance of ClassPizza). It overrides the /path method of
% the ClassPopupWindow frame, so that the frame is shaped around the
% pizza. It asks the pizza for its size and shape, and cuts a positive
% round (or semicircular) hole for it to float in the center of the
% window frame.
%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ClassPizza
%
% An instance of ClassPizza is an actual canvas on the screen,
% that embodies the pizza itself.

/ClassPizza ClassCanvas [
  % Instance variables (initialized to null):
  /Toppings /Style /PizzaSize /Fraction /Price
  /Cheese /ExtraToppings /PizzaLock
] classbegin

% Class variables:

  % Canvas attributes.
  /Transparent false def
  /Retained true def
  /Mapped true def

  % Constant colors.
  /CrustColor .9 .6 .1 rgbcolor def
  /SauceColor 1 .1 .1 rgbcolor def

  % The supported pizza sizes.
  /PizzaSizes [10 14 16 18] def

  % The size of the pizza box:
  /PizzaBoxSize 19 def

  % The thickness of the crust.
  /CrustRadius .9 def

  % Processes that paint, spin, and update the view of this pizza.
  % These class variable are used as backstops for the names of
  % processes who are promoted into the instance when active.
  /PaintProcess null def
  /SpinProcess null def
  /UpdateProcess null def

  % Class variables used for spinning.
  /SpinPause 6 def
  /SpinAngle 7 def

% Class methods:

  % Initialize the pizza.
  %
  /NewInit { % - => -
    /NewInit super send
    /Toppings nullarray def
    /ExtraToppings nullarray def
    /Style /defaultstyle ClassStyle send def
    /PizzaSize PizzaSizes dup length 1 sub get def
    /Fraction 1 def
    /Price 0 def
    /Cheese (Cheese) findtopping def
    /PizzaLock createmonitor def
    /Sprinklers growabledict def
  } def

  % Clean up after the pizza.
  %
  /destroy { % - => -
    /StopSpin self send
    /StopPaint self send
    UpdateProcess null ne { % if:
      UpdateProcess killprocess
    } if
    /UpdateProcess unpromote
    /destroy super send
  } def

  % Return an array of the toppings on this pizza.
  %
  /toppings { % - => [topping ...]
    Toppings
  } def

  % Add a topping to the pizza.
  % If the topping isn't already on the pizza,
  % add it to the array of pizza toppings,
  % update the objects viewing the pizza,
  % and start sprinkling the new topping on the pizza
  % (if the parent pizza window is mapped on the screen).
  %
  /addtopping { % topping => -
    Toppings 1 index arraycontains? { pop } { % else:
      Toppings 1 index arrayappend
      /Toppings exch def
      /updateview self send
      /mapped? Parent send { % ifelse:
	/StartSprinkle self send
      } { pop } ifelse
    } ifelse
  } def

  % Remove a topping from the pizza.
  % If the topping is on the pizza,
  % remove it from the array of toppings,
  % and set the new list of pizza toppings.
  % Since we've already painted the topping on the pizza,
  % we have to call /settoppings,
  % which will start painting the pizza again from scratch.
  %
  /removetopping { % topping => -
    Toppings exch arrayindex { % if:		% index
      Toppings exch arraydelete			% toppings'
      /settoppings self send			%
    } if					%
  } def

  % Set the toppings of this pizza to be the toppings in the given array.
  % This causes the pizza to repaint,
  % and updates the objects viewing this pizza.
  %
  /settoppings { % [topping ...] => -
    /Toppings exch def
    /updateview self send
    /paint self send
  } def

  % Set the toppings of this pizza to be the toppings of the given style.
  % Ask the style for its list of standard toppings, and set this pizza's 
  % topping list.
  %
  /setstyle { % style => -
    /Style 1 index def
    /toppings exch send
    /settoppings self send
  } def

  % Return the style of this pizza.
  %
  /style { % - => style
    Style
  } def

  % Return the size of this pizza in inches.
  % Supported sizes are 10", 14", 16", and 18".
  %
  /pizzasize { % - => 10|14|16|18
    PizzaSize
  } def

  % Set the size of this pizza in inches.
  % Accepted sizes are 10", 14", 16", and 18",
  % or the corresponding indices, 0, 1, 2, and 3.
  %
  /setpizzasize { % 10|14|16|18|index => -
    /pizzasizeindex self send			% index
    PizzaSizes exch get				% size
    /PizzaSize exch def				%
    /ReshapeParent self send
    /updateview self send
    /paint self send
  } def

  % Translate a pizza size in inches to a pizza size index.
  % Accepted sizes are 10", 14", 16", and 18",
  % or the corresponding indices, 0, 1, 2, and 3.
  %
  /pizzasizeindex { % size|index => index
    PizzaSizes exch arrayindex not {		%
      PizzaSizes length 1 sub			% index
    } if	 				% index
  } def

  % Translate a pizza index into a size in inches.
  %
  /pizzaindexsize { % index => size
    PizzaSizes exch get
  } def

  % Return the fraction of this pizza, whole or half.
  % 1 is whole, .5 is half.
  %
  /fraction { % - => real
    Fraction
  } def

  % Set the fraction of this pizza to whole or half.
  % 1 is whole, .5 is half.
  %
  /setfraction { % real => -
    /Fraction exch def
    /ReshapeParent self send
    /updateview self send
  } def

  % Reshape the parent popup pizza window,
  % to reflect a change in the pizza's shape.
  % In all truth, the pizza canvas is rectangular!
  % It gets its round (or semi-circular) shape
  % from the shape of its parent canvas,
  % which is a hollow rectangular popup window frame
  % (just the window borders),
  % with a discontiguous pie floating in the center.
  %
  /ReshapeParent { % - => -
    gsave
      Parent setcanvas
      /bbox PreviewWindow send /reshape PreviewWindow send
    grestore
  } def

  % Return the radius of this pizza,
  % proportional to the unit square pizza box.
  %
  /radiusscale { % - => r
    PizzaSize PizzaBoxSize div
  } def

  % Return the most recently calculated price of this pizza.
  %
  /price { % - => price
    Price
  } def

  % Fork a process to update the objects viewing this pizza.
  % Fork off a process to do it in the background, but first wait 
  % for the previous one to finish running first if it's not null.
  %
  /updateview { % - => -
    UpdateProcess null ne { % if:
      UpdateProcess waitprocess pop
    } if
    /UpdateProcess { % fork:
      /UpdateView self send
      /UpdateProcess unpromote
    } fork promote
  } def

  % Update the objects viewing this pizza.
  % Tell the various objects viewing this pizza to update their values.
  %
  /UpdateView { % - => -

    % Tell pizzasizesettings to update its value if it's different 
    % than our current size.
    PizzaSize						% inches
    /pizzasizeindex self send				% index
    { % send to pizzasizesettings:
      dup /value self send 0 get ne {
 	[exch] /setvalue self send
      } { pop } ifelse
    } pizzasizesettings send

    % Tell pizzafractionsettings to update its value if it's different
    % than our current fraction.
    Fraction 1 eq { 0 } { 1 } ifelse			% index
    { % send to pizzafractionsettings:
      dup /value self send 0 get eq { pop } {
        [exch] /setvalue self send
      } ifelse
    } pizzafractionsettings send

    % Tell stylemenu to update its value if it's different than our
    % currently selected style.
    % The style's id is an item index appropriate for stylemenu.
    /id Style send
    { % send to stylemenu:
      dup /value self send 0 get eq { pop } {
        [exch] /setvalue self send
      } ifelse
    } stylemenu send

    % Tell the stylevalue label to update its value if it's different
    % than the currently selected style name.
    /name Style send
    { % send to stylevalue:
      dup /value self send eq { pop } {
        /setvalue self send
      } ifelse
    } stylevalue send

    % Tell the meatcheckboxes to update its value to be an array of the
    % food numbers (item indices) of each meat topping on this pizza.
    % The meat topping's food number is an item index appropriate for
    % meatcheckboxes.
    [ Toppings { % forall:			% ... topping
        { % send to topping:
	  /foodtype self send /Meat eq { % if:
	    /foodnumber self send		% ... index
	  } if
        } exch send
      } forall
    ] /setvalue meatcheckboxes send		%

    % Tell the vegetablecheckboxes to update its value to be an array 
    % of the food numbers (item indices) of each vegetable topping on
    % this pizza.
    % The vegetable topping's food number is an item index appropriate 
    % for vegetablecheckboxes.
    [ Toppings { % forall:			% ... topping
        { % send to topping:
	  /foodtype self send /Vegetable eq { % if:
	    /foodnumber self send		% ... index
	  } if
	} exch send
      } forall
    ] /setvalue vegetablecheckboxes send	%

    % Set the footer of the popup pizza preview window,
    % to reflect the pizza size and fraction.
    PizzaSize (%") sprintf
    Fraction 1 eq { (Whole Pie) } { (Half Pie) } ifelse
    /setfooter PreviewWindow send

    /updatecost self send
  } def

  % Calculate the cost of this pizza.
  %
  /updatecost { % - => -
    10 dict begin % localdict
      /TheBest /defaultstyle ClassStyle send def
      /TheStyle null def
      /TheTopping null def
      /TheBestCost 99 def
      /TheBestExtras 0 def

      % For each and every pizza style in the universe:
      /styles ClassStyle send { % forall:		% style
        /TheStyle exch def				%

	% Ask this style for its list of standard toppings.
	/TheToppings /toppings TheStyle send def

	% Is every topping from this style on our pizza?
	true						% true
	TheToppings { % forall:				% true topping
	  Toppings exch arraycontains? not { % if:	% true
	    % Oops, this topping's not on the pizza. No dice.
	    pop false exit				% false
	  } if						% true
	} forall					% true|false

	{ % if: all the toppings of the style were on our pizza:
							%
	  % Make an array of our pizza toppings that aren't in the style.
	  /ExtraToppings [
	    Toppings {					% ... topping
	      % Is this topping included in the style? Then toss it.
	      TheToppings 1 index arraycontains? {	% ... topping
	        pop					% ...
	      } if
	    } forall
	  ] store					%

	  % Figure out the cost of the pizza,
	  % were we to order it as this style,
	  % and remember the style as the best match if it pleases us.
	  % The definition of pleasing us is biased towards matching
	  % higher level complex pizza styles, rather than economical
	  % lower level pizzas with extra toppings.
	  % This is the kick-back to Tony&Alba's for all that free beer. 
	  PizzaSize /pizzasizeindex self send		% sizeindex
	  ExtraToppings length				% sizeindex extras
	  /extraprice TheStyle send			% $
	  dup						% $ $
	  ExtraToppings length				% $ extras
	  /extras TheStyle send sub			% $ $ extras'
	  1 le { .9 mul } if				% $ biased$
	  TheBestCost le { % ifelse:			% $
	    % Hey this is the best match so far, let's not forget it!
	    /TheBestCost exch store			%
	    /TheBest TheStyle store
	    /TheBestExtras
	      ExtraToppings length /extras TheBest send sub
	    store
	  } { pop } ifelse				%
	} if						%
      } forall						%

      % Set the window footers of the pizza topping panel.
      % The left footer displays the name of the pizza style,
      % and the right footer displays a message
      % telling the user to choose more toppings,
      % or the number of extra toppings,
      % or nothing at all.
      TheBestExtras dup 0 lt { % ifelse:		% extras
	neg dup 1 eq { () } { (s) } ifelse		% extras (plural?)
	exch (Choose % more topping%!) sprintf		% (message)
      } { % else:					% extras
	dup 0 ne { % ifelse:
	  dup 1 eq { () } { (s) } ifelse		% extras (plural?)
	  exch (With % extra topping%.) sprintf		% (message)
	} { % else:					% extras
	  pop nullstring				% ()
	} ifelse
      } ifelse						% (left footer)
      /name TheBest send exch				% (left) (right)
      /setfooter ToppingWindow send			%

      % Remember the price of this pizza in dollars rounded to cents,
      % and calculate its string value. 
      TheBestCost					% $
      Fraction mul
      100 mul round 100 div
      /Price 1 index store
      dup 100 mul round cvi 100 mod			% $ cents
      exch floor cvi					% cents dollars
      1 index 10 lt { (%.0%) } { (%.%) } ifelse		% cents dollars fmt
      sprintf						% (price)

      % Set the value of the costfield and totalfield labels to
      % the price string.
      dup /setvalue costfield send
      /setvalue totalfield send				%

      % Set the value of the stylevalue label to the name of the best style,
      % and set the stylemenu value to the index of that name in the list of
      % pizza styles. (The stylemenu is an exclusive settings menu.)
      /name TheBest send				% name
      dup /setvalue stylevalue send
      PizzaStyleNames exch arrayindex {			% index
          [exch] /setvalue stylemenu send		%
      } if						%

      % Remember the best match pizza style.
      /Style TheBest store

    end % localdict
  } def

  % Return the array of extra toppings above and beyond those provided
  % by the currently selected pizza style.
  %
  /extratoppings { % - => [topping ...]
    ExtraToppings
  } def

  % Calculate the prices for the four different whole sizes of
  % the currently selected pizza style. 
  %
  /prices { % - => [10" 14" 16" 18"]
    { % send to the current pizza style:
      /prices self send					% [$ $ $ $]
      /toppings self send length /extras self send add  % [$ $ $ $] toppings
    } Style send
    10 dict begin % localdict
      % i is the number of additional toppings
      Toppings length exch sub /i exch def		% [$ $ $ $]
      i 0 gt { % if:
	/FirstToppingPrices ClassStyle send		% [$ $ $ $] [$ $ $ $]
	{ add } arrayop					% [$ $ $ $]
	i 1 gt { % if:					% [$ $ $ $]
	  /AdditionalToppingPrices ClassStyle send	% [$ $ $ $] [$ $ $ $]
	  { i 1 sub mul add } arrayop			% [$ $ $ $]
	} if
      } if
    end % localdict
  } def

  % Return the minimum size of the pizza box.
  %
  /minsize { % - => w h
    16 16
  } def

  % Return the preferred pizza box size.
  %
  /preferredsize { % - => w h
    256 256
  } def

  % Reshape the pizza canvas, just moving if the size doesn't change.
  %
  /reshape { % x y w h => -
    2 copy /size self send 3 -1 roll eq 3 1 roll eq and { % ifelse:
      pop pop /move self send
    } { % else:
      /reshape super send
    } ifelse
  } def

  % Stop the pizza painting and spinning.
  %
  /reset { % - => -
    /StopSpin self send
    /StopPaint self send
  } def

  % Stop the pizza painting.
  % Kill the painting process if it exists. Massacre all the topping
  % sprinklers just to be mean, and clean up after them.
  %
  /StopPaint { % - => -
    PaintProcess null ne { % if:
      PaintProcess killprocess
      /PaintProcess unpromote
    } if
    /StopSprinklers self send
  } def

  % Setup the graphics state for painting on the pizza.
  %
  /PaintSetup { % - => -
    self setcanvas
    /size self send
    2 div exch 2 div exch		% w/2 h/2
    % Translate to the center. Centered pizza constraint.
    2 copy translate
    % Maintain a 1:1 aspect ratio. Round pizza constraint.
    min					% radius
    % Adjust the scale for the pizza size.
    /radiusscale self send mul
    % Scale to the unit pizza coordinate system.
    dup scale
  } def

  % Paint the pizza crust and fill it with sauce.
  %
  /PaintNewPizza { % - => -
    gsave
      /PaintSetup self send
      0 0 1.02 0 360 arc
      0 0 CrustRadius .005 sub 0 360 arc
      CrustColor setcolor eofill
      0 0 CrustRadius 0 360 arc
      SauceColor setcolor fill
    grestore
  } def

  % Clip out the crust in preparation for toppings painting.
  %
  /ClipCrust { % - => -
    newpath
    0 0 CrustRadius 0 360 arc
    clip newpath
  } def

  % Paint the pizza, forking off a processes to paint every topping.
  %
  /Paint { % - => -
    PizzaLock { % monitor:
      /reset self send
      /PaintProcess { % fork:
	pause
	/PaintNewPizza self send

	% Wait a second until things settle down ...
	% If /paint is called again within the next second,
	% this process will be killed and a new paint process
	% will sleep for a second.
	[1 0] SLEEP

	% If our parent window frame isn't opened,
	% then it's hiding and we shouldn't draw the toppings.
	/opened? Parent send { % if:
	  % Draw all the toppings at once! Weeee!
	  4 { % Lots of cheese, repeat:
	    Cheese /StartSprinkle self send
	  } repeat
	  /toppings Pizza send { % forall:
	    /StartSprinkle self send
	  } forall

	  % Wait around for all the sprinklers to finish.
	  { % loop:
	    Sprinklers length 0 eq { exit } if
	    % push one of the sprinklers, doesn't matter which.
	    Sprinklers { pop exit } forall
	    waitprocess pop
	  } loop
	} if
	/StopPaint self send
      } fork def
      PaintProcess /ProcessName (Pizza Painter) put
    } monitor
  } def

  % Fork a process to sprinkle a topping on the pizza in the background.
  %
  /StartSprinkle { % topping => -
    { % fork:
      gsave
	/PaintSetup self send
	/ClipCrust self send
	{ % send to topping:
	  clear /paint self send
	} exch send
	Sprinklers currentprocess undef
      grestore
    } fork
    Sprinklers exch dup put pop
  } def

  % Kill all the processes sprinkling toppings.
  %
  /StopSprinklers { % - => -
    [Sprinklers {pop} forall] {killprocess} forall
    Sprinklers cleanoutdict
  } def

  % Start spinning the pizza, to cook it.
  %
  /StartSpin { % - => -
    /StopSpin self send
    /SpinProcess { % fork:
      clear
      /PaintSetup self send
      /ClipCrust self send
      initmatrix
      { % loop:
        SpinPause { pause } repeat
	/Spin self send
      } loop
      SpinProcess currentprocess eq { % if:
        /SpinProcess unpromote
      } if
    } fork promote
  } def

  % Stop spinning the pizza, before eating it.
  %
  /StopSpin { % - => -
    SpinProcess null ne { % if:
      SpinProcess killprocess
      /SpinProcess unpromote
    } if
  } def

  % Spin the pizza around a bit.
  %
  /Spin { % - => -
    gsave
      /size self send				% w h
      2 div exch 2 div exch			% w/2 h/2
      2 copy translate
      SpinAngle random add rotate
      neg exch neg exch translate		%
      self imagecanvas
     grestore
  } def

% Menu support:

  % Class variable to enable menu service.
  /Menuable? true def

  % Popup the stylemenu on the pizza.
  %
  /Menu { % - => menu
    stylemenu
  }  def

% Tracking support:

  % Class variable to enable track service.
  /Trackable? true def

  % Handle mouse button down on the pizza.
  % 
  /TrackStart { % event => /Default true
    gsave
      /StopSpin self send
      /PaintSetup self send
      /ClipCrust self send
      % Translate to the pizza center.
      initmatrix
      /size self send					% event w h
      2 div exch 2 div exch				% event w/2 h/2
      translate						% event
      % Figure out the angle towards the cursor.
      dup begin YLocation XLocation end			% event y x
      2 copy 0 eq exch 0 eq and				% event y x both-0?
      { pop pop 0 } { atan } ifelse			% event direction
      /Ang0 1 index def
      /Ang1 exch def					% event
      /SpinAngle 0 def
    grestore
    /TrackMotion self send				%
    /Default true					% /Default true
  } def

  % Handle mouse motion after pressing down on the pizza.
  % Spin the pizza by hand!
  %
  /TrackMotion { % event => -
    gsave
      /PaintSetup self send
      /ClipCrust self send
      % Translate to the pizza center
      initmatrix
      /size self send					% event w h
      2 div exch 2 div exch				% event w/2 h/2
      2 copy translate
      % Figure out the angle towards the cursor.
      3 -1 roll begin YLocation XLocation end		% w/2 h/2 y x
      2 copy 0 eq exch 0 eq and				% w/2 h/2 y x both-0?
      { pop pop 0 } { atan } ifelse			% w/2 h/2 direction
      /Ang1 exch def					% w/2 h/2
      /SpinAngle Ang1 Ang0 sub def
      /Ang0 Ang1 def
      % Rotate as much as the cursor direction has changed.
      SpinAngle rotate
      % Copy the pizza canvas to itself, rotated.
      neg exch neg exch translate			%
      self imagecanvas
    grestore
  } def

  % Handle mouse button up.
  % If the pizza was spinning, then keep it spinning!
  % It it was still, then leave it still.
  %
  /TrackStop { % event => -
    pop							%
    % If the pizza was was moving when the button was released,
    % then start the motor.
    SpinAngle abs 1 ge { % if:
      /StartSpin self send
    } if
  } def

% Selection support:

  % Class variable to enable reception service.
  /Receptible? true def
  /Keyable? true def

  % Deal the a selection dropped or pasted into this pizza.
  %
  /HandleReception { % event selection => bool
    exch					% selection event
    //is_v2? not { self } if
    /begintransfer 3 index send			% selection event

    /Raster /query 3 index send { % ifelse:	% selection event canvas
      /RasterReception self send		% selection bool
    } { % else:					% selection event
      /Canvas /query 3 index send { % ifelse:	% selection event canvas
	/RasterReception self send		% selection bool
      } { % else:				% selection event
	pop false				% selection bool
      } ifelse
    } ifelse					% selection bool

    dup /endtransfer 4 -1 roll			% bool bool /endt selection
    send					% bool
  } def

  % A raster (canvas) was dropped or pasted into this pizza.
  %
  /RasterReception { % event canvas => bool
    exch pop					% canvas
    dup type /canvastype ne { pop false beep } {
      gsave
	/PaintSetup self send
	/ClipCrust self send
	% Translate and scale the unit square to the place where we
	% want the image to land.
	initmatrix
	clippath pathbbox points2rect		% canvas x y w h
	4 2 roll translate scale		% canvas

	% Now scale by the inverse size of the source canvas's default
	% coordinate system, to make sure *its* unit square ends
	% up mapped to the unit square we are at right now.
	gsave
	  dup setcanvas
	  dup false getbbox			% canvas x y w h
	  4 2 roll pop pop			% canvas w h
	  1 exch div exch 1 exch div exch	% canvas 1/w 1/h
	grestore
	scale					% canvas
	imagecanvas				%
        true					% true
      grestore
    } ifelse					% bool
  } def

classend def

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ClassTopping
%
% An instance of ClassTopping encapsulates all that is known about
% a pizza topping, including its nominal, visual, dietary, and other
% aesthetic properties.

/ClassTopping ClassObject [
  % Instance variables (initialized to null):
  /FoodType /Name /Sprinkles /Init /Paint /ID /FoodNumber
] classbegin

% Class variables:

  % An array of all pizza toppings, shared in the class.
  /TheToppings nullarray def

  % The pizza topping registry, shared in the class.
  /ToppingDict growabledict def

  % A dictionary for counting the number of types of each topping.
  /ToppingTypes growabledict def

  % Given the name of a topping, return the topping itself,
  % or null if no such topping exists.
  %
  /findtopping { % name => topping|null
    ToppingDict 1 index known { % ifelse:
      ToppingDict exch get
    } { % else:
      pop null
    } ifelse
  } def

  % Given the name of a topping food type, return an array of every
  % pizza topping of that type (/Meat, /Vegetable, etc) that exists. 
  %
  /typetoppings { % foodtype => [topping ...]
    [ TheToppings { % forall:			% ... topping
        { % send to topping:
	  /foodtype self send			% ... type
          counttomark 1 add index		% ... type foodtype
	  eq { self } if			% ... topping
	} exch send
      } forall
    ]						% foodtype [topping ...]
    exch pop					% [topping ...]
  } def

  % Return the array of all defined pizza toppings.
  %
  /toppings { % - => [topping ...]
    TheToppings
  } def

  % Return the name of this topping.
  %
  /name { % - => string
    Name
  } def

  % Return the type of food this topping is.
  %
  /foodtype { % - => name
    FoodType
  } def

  % Return the unique id of this topping.
  %
  /id { % - => id
    ID
  } def

  % Return magic food number of this topping, which is the index of
  % this topping in the menu of toppings with the same food type.
  %
  /foodnumber { % - => n
    FoodNumber
  } def

  % Initialize this topping.
  %
  /NewInit { % foodtype name sprinkles {init} {paint} => -
    /NewInit super send
    /Paint exch def
    /Init exch def
    /Sprinkles exch def
    /Name exch def
    /FoodType exch def
    ToppingTypes FoodType known not { % ifelse:
      0  ToppingTypes FoodType 1 put
    } { % else:
      ToppingTypes FoodType get
      ToppingTypes FoodType 2 index 1 add put
    } ifelse
    /FoodNumber exch def
    /ID TheToppings length def
    /TheToppings [ TheToppings aload pop self ] store
    ToppingDict Name self put
  } def

  % Paint this topping on the pizza.
  % Assumes the graphics state is set up appropriatly,
  % and that the current process exists just to paint this topping.
  %
  /paint { % - => -
    currentprocess /ProcessName
    Name (Pizza Topping Sprinkler: %) sprintf put
    gsave
      /Init load cvx exec
      /Paint load cvx
      Sprinkles Sprinkle
    grestore
  } def

  % Sprinkle this topping all over a pizza.
  %
  /Sprinkle { % proc sprinkles => -
    { gsave
	random 360 mul rotate
	random sqrt 0 translate
	random 360 mul rotate
	dup exec
	random .3 lt { % if:
	    random 10 mul 1 add cvi { pause } repeat
	} if
      grestore
    } repeat
  } def

classend def

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ClassStyle
%
% An instance of ClassStyle describes a vendor supplied pizza style,
% consisting of a unique product name, a list of pizza toppings
% included with the default configuration, as well as pricing and
% discounting information.  

/ClassStyle ClassObject [
  % Instance variables (initialized to null):
  /Name /Toppings /Prices /Extras /ID
] classbegin

% Class variables:

  % An array of all pizza styles, shared in the class.
  /TheStyles nullarray def

  % The pizza style registry, shared in the class.
  /StyleDict growabledict def

  % The cost of the first and additional toppings, 
  % for all four different pizza sizes.
  % Pizza size:			  10"  14"  16"  18"
  /FirstToppingPrices		[ 1.00 1.00 1.00 1.00 ] def
  /AdditionalToppingPrices	[ 0.50 0.75 1.00 1.25 ] def

  % Given the name of a style, return the style itself,
  % or null if no such style exists.
  %
  /findstyle { % name => style|null
    StyleDict 1 index known { % ifelse:
      StyleDict exch get
    } { % else:
      pop null
    } ifelse
  } def

  % Return the default pizza style.
  %
  /defaultstyle { % - => style
    TheStyles 0 get
  } def

  % Return the array of all defined pizza styles.
  %
  /styles { % - => [style ...] 
    TheStyles
  } def

  % Return the name of this pizza style.
  %
  /name { % - => string
    Name
  } def

  % Rename this pizza style.
  % Updates the objects viewing the pizza style names.
  %
  /setname { % name => -
    Name null ne {
      StyleDict Name undef
    } if
    /Name exch def
    StyleDict Name self put
    /value stylelist send			% [index]
    PizzaStyleNames				% [index] [names]
    2 copy					% [index] [names] [index] [names]
    { % send to stylemenu:
      /setitemlist self send			% [index] [names] [index]
      /setvalue self send			% [index] [names]
      /paint self send
    } stylemenu send
    { % send to stylelist:
      /setitemlist self send			% [index]
      /setvalue self send			%
      /validate self send
      /locatechoice self send
      /paint self send
    } stylelist send
    null null EditStyle
  } def

  % Delete this pizza style.
  % Renumber the id's of the subsequent pizza styles.
  % Updates the objects viewing the pizza style names.
  %
  /delete { % - => -
    StyleDict Name undef
    /TheStyles TheStyles /id self send arraydelete store
    /id self send  1  TheStyles length 1 sub { % for:
      /setid TheStyles 2 index get send
    } for
    /value stylelist send			% [index]
    0 get					% index
    /styles ClassStyle send			% index [styles]
    length 1 sub min				% min(index,#styles-1)
    [exch]					% [index]
    PizzaStyleNames				% [index] [names]
    2 copy					% [index] [names] [index] [names]
    { % send to stylemenu:
      /setitemlist self send			% [index] [names] [index]
      /setvalue self send			% [index] [names]
      /paint self send
    } stylemenu send
    { % send to stylelist:
      /setitemlist self send			% [index]
      /setvalue self send			%
      /validate self send
      /locatechoice self send
      /paint self send
    } stylelist send
    null null EditStyle
  } def

  % Return an array, the list of toppings that comprise this pizza style.
  %
  /toppings { % - => [topping ...]
    Toppings dup length array copy
  } def

  % Set this list of toppings that comprose this pizza style.
  % Update the objects viewing the selected style if this style is it.
  %
  /settoppings { % [topping ...] => -
    /Toppings exch def
    SelectedStyleName
    /name self send eq { % if:
      null null EditStyle
    } if
  } def

  % Given the name of a topping food type, return an array of every
  % pizza topping of that type included with this particular style.
  %
  /typetoppings { % foodtype => [topping ...]
    [ Toppings { % forall:			% ... topping
        { % send to topping:
	  /foodtype self send			% ... type
          counttomark 1 add index		% ... type foodtype
	  eq { self } if			% ... topping
	} exch send
      } forall
    ]						% foodtype [topping ...]
    exch pop					% [topping ...]
  } def

  % Return an array of prices for this pizza style at four different sizes.
  %
  /prices { % - => [10" 14" 16" 18"]
    Prices
  } def

  % Set the prices for this pizza style at four different sizes.
  % Update the objects viewing the selected style prices if this
  % style is it.
  %
  /setprices { % [10" 14" 16" 18"] => -
    /Prices exch def
    SelectedStyleName
    /name self send eq { % if:
      /updatecost Pizza send
      /updateprices self send
    } if
  } def

  % Update the objects viewing this style's prices.
  %
  /updateprices { % - => -
    styleprice18field styleprice16field styleprice14field styleprice10field 
    /prices self send { % forall:
      dup 100 mul round cvi 100 mod
      exch floor cvi
      1 index 10 lt { (%.0%) } { (%.%) } ifelse
      sprintf /setvalue 3 -1 roll send
    } forall
  } def

  % Return the number of extra toppings you may add for free to
  % this pizza style.
  %
  /extras { % - => number
    Extras
  } def

  % Set the number of extra toppings you may add for free to
  % this pizza style.
  %
  /setextras { % number => -
    /Extras exch def
    SelectedStyleName
    /name self send eq { % if:
      /updatecost Pizza send
    } if
  } def

  % Calculate the price of this pizza, given a size index and 
  % the number of extra toppings.
  %
  /extraprice { % sizeindex extras => price
    Prices 2 index get				% size extras price
    exch Extras sub 0 max exch			% size extras' price
    1 index 0 gt { % if:
      FirstToppingPrices 3 index get add
      1 index 1 gt { % if:
        AdditionalToppingPrices 3 index get	% size extras' price ATP
	2 index 1 sub mul add			% size extras' price
      } if
    } if
    3 1 roll pop pop				% price
  } def

  % Return the unique id of this pizza style.
  % Used as an item index into objects that have a list of pizza styles.
  %
  /id { % - => id
    ID
  } def

  % Set the id of this pizza style.
  %
  /setid { % id => -
    /ID exch def
  } def

  % Edit this pizza style.
  % Set the value of the style editor's stylelist to the id of this pizza style
  % (corresponding to the item whose label is the name of this pizza style),
  % and update the objects viewing the currently edited style.
  %
  /editstyle { % - => -
    [ /id self send ] /setvalue stylelist send
    null null EditStyle
  } def

  % Initialize this pizza style.
  %
  /NewInit { % name toppings prices extras => -
    /NewInit super send
    /Extras exch def
    /Prices exch def
    [ exch { % forall toppings:
        dup type /stringtype eq { % if:
	  /findtopping ClassTopping send
	  dup null eq { pop } if
	} if
      } forall
    ] /Toppings exch def
    /Name exch def
    StyleDict Name self put
    TheStyles length /setid self send
    /TheStyles [ TheStyles aload pop self ] store
  } def

classend def

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ClassProPanel
%
% An instance of ClassProPanel is just a control panel, that promotes
% (caches) its minsize into the instance as a constant function the
% first time /minsize is calculated, so that future calls to /minsize
% are very fast.

/ClassProPanel ClassPanel []
classbegin

% Methods:

  % Calculate the minsize, and promote it.
  % Fluff the panel up a bit, while we're at it.
  %
  /minsize { % - => w h
    /minsize super send
    % Add in a little extra space.
    4 4 xyadd
    /minsize [ 3 index 3 index ] cvx promote
  } def

  % Unpromote the cached /minsize when the panel is invalidated, so it
  % will be recalculated next time it's needed. 
  %
  /invalidate { % - => -
    /minsize unpromote
    /invalidate super send
  } def

classend def

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ClassPopupPizzaWindow
%
% An instance of ClassPopupPizzaWindow is used to frame the pizza
% canvas (an instance of ClassPizza). It overrides the /path method of
% the ClassPopupWindow frame, so that the frame is shaped around the
% pizza. It asks the pizza for its size and shape, and cuts a positive
% round (or semicircular) hole for it to float in the center of the
% window frame.

/ClassPopupPizzaWindow ClassPopupWindow []
classbegin

% Class variables:

  % Override default footer gap.
  /FooterGap 4 def

% Methods:

  % The popup pizza window path includes the window borders and the
  % round (or semi-circular) pie floating in the middle, but excludes
  % everything between.
  %
  /path { % x y w h => -
    matrix currentmatrix 5 1 roll		% mat x y w h
      /minsize self send xymax
      4 2 roll translate			% mat w h
      0 0 3 index 3 index rectpath
      WInset SInset translate			% mat w h
      EInset WInset add				% mat w h ewinsets
      NInset SInset add				% mat w h ewinsets nsinsets
      xysub					% mat insidew insideh
      0 0 3 index 3 index rectpath

      2 div exch 2 div exch			% mat centerx centery

      2 copy translate
      min dup neg scale				% mat

      { % send to Center client (the Pizza):
	/radiusscale self send 0 moveto
	0 0 /radiusscale self send
	0 360 /fraction self send mul
	arc closepath
      }						% mat {msg}
      /Center /client self send			%       ... client true | false
      /WhatPizza? assert			% mat {msg} client
      send					% mat
    setmatrix					%
  } def

  % Reshape the window canvas with the even/odd rule.
  %
  /reshape { % x y w h => -
    /invalidate self send
    gsave
      4 2 roll translate			% w h
      0 0 4 2 roll				% 0 0 w h
      /path self send				%
      self eoreshapecanvas
    grestore
  } def

  % Override the border painting method to just stroke the pizza box.
  %
  /PaintBorder { % - => -
    currentlinewidth
    ForegroundColor setcolor BorderStroke 2 mul setlinewidth
    /bbox self send rectpath stroke
    setlinewidth
  } def

classend def

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Globals
%
% Global variables defined in userdict.

% Where persistant pizza parameters are placed.
/ConfigFile (.pizzatool.ps) def

% The default startup style. Saved in config file.
/FavoriteStyle (Cheese) def

% Don't enable this unless you know what you're doing!!
/ServerEnabled? false def

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Utilities
%
% These utilities are defined in userdict, 
% where they can be shared by all objects and notifiers.
% The user interface object names and notifiers are also defined in userdict.
% Many objects have their notification target set to userdict,
% which will cause the notifier to be executed with userdict on the
% top of the dictionary stack, not in the context of any object. 
% The notifier is usually the name of a handler defined in userdict,
% so it works out fine. 
% In several cases, an object's target is set to another object, 
% so the notifier is sent to that object, and executed with userdict
% on the dictionary stack below the object's send context, so all 
% the other object names and utilities are accessable.
%

% Return an array of the selected pizza topping names.
% Ask both sets of topping checkboxes to take their value,
% an array of selected item indices,
% and look up the corresponding item labels,
% which are the selected topping names.
% Collect them all into an array of topping names.
%
/CheckedToppingNames { % - => [ name ...]
  [ { % send to meatcheckboxes:
      /value self send {			% ... index
        /item self send				% ... label
      } forall
    } meatcheckboxes send
    { % send to vegetablecheckboxes:
      /value self send {			% ... index
        /item self send				% ... label
      } forall
    } vegetablecheckboxes send
  ]						% [ name ... ]
} def

% Return an array of all toppings that are checked.
% Take an array of names of checked toppings, and ask ClassTopping
% to find each of those toppings, given the name, and
% collect each one it could find into an array.
%
/CheckedToppings { % - => [topping ...]
  CheckedToppingNames				% [ name ... ]
  { % send to ClassTopping:
    [ exch {					% ... name
        findtopping				% ... topping|null
        dup null eq { pop } if			% ... topping
      } forall
    ]						% [ topping ... ]
  } ClassTopping send
} def

% Return an array of the names of all meat toppings. 
% Ask ClassTopping for all the toppings of type /Meat,
% then ask each of those for its name, and stuff them all 
% into an array. 
%
/MeatToppingNames { % - => [meatname ...]
  [ /Meat /typetoppings ClassTopping send	% mark [meattopping ...]
    { /name exch send } forall			% mark meatname ...
  ]						% [meatname ...]
} def

% Return an array of the names of all vegetable toppings. 
% Same as MeatToppingNames, but of type /Vegetable.
%
/VegetableToppingNames { % - => [vegname ...]
  [ /Vegetable /typetoppings ClassTopping send	% mark [vegtopping ...]
    { /name exch send } forall			% mark vegname ...
  ]						% [vegname ...]
} def

% Return an array of names of pizza styles.
% Ask ClassStyle for an array of styles,
% and ask each of them for its name,
% putting them all into an array.
%
/PizzaStyleNames { % - => [(name) ...]
  [ /styles ClassStyle send			% mark [style ...]
    { /name exch send } forall			% mark stylename ...
  ]						% [stylename ...]
} def

% Return the name of the selected pizza style.
% Ask the scrolling list stylelist to take its value,
% which is an array containing one item index,
% and convert the index into an item label,
% which is the selected style name.
%
/SelectedStyleName { % - => stylename
  { % send to stylelist:
    /value self send				% [index]
    0 get					% index
    /item self send				% stylename
  } stylelist send
} def

% Return the selected style, or the default if not found.
% Ask ClassStyle to find the style whose name is the selected style.
% If it couldn't find it, ask ClassStyle for the default style.
%
/SelectedStyle { % - => style
  SelectedStyleName				% stylename
  /findstyle ClassStyle send			% style|null
  dup null eq {					% null
    pop /defaultstyle ClassStyle send		% style
  } if						% style
} def

% Update the value of the topping menus.
% This is called to update the menus of pizza topping names, 
% to reflect the pizza style selected for editing.
% Ask the selected style for the array of pizza toppings it includes.
% Ask each of those meat toppings for its magic food number
% (an item index), collect them all into an array,
% and set the value of meattoppingmenu (which is a settings menu
% of meat topping names, and whose value is an array of item indices).
% Do the same for the vegetable pizza toppings and vegetabletoppingmenu.
%
/UpdateStyleToppingMenus { % - => -
  /toppings SelectedStyle send			% toppings
  [ 1 index					% toppings mark toppings
    { % forall toppings:
      { % Send to each topping:
        /foodtype self send /Meat eq {
	  /foodnumber self send			% ... index
	} if
      } exch send
    } forall
  ] /setvalue meattoppingmenu send		% toppings
  [ exch					% mark toppings
    { % forall toppings:
      { % Send to each topping:
        /foodtype self send /Vegetable eq {
	  /foodnumber self send			% ... index
	} if
      } exch send
    } forall
  ] /setvalue vegetabletoppingmenu send		%
} def

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Notifiers
%
% These notifiers are defined in userdict.
% Each notifier takes two arguments: a value and an object.
% User interface componants whose notifiers are defined in userdict
% have their target set to userdict, so the notifier is executed
% by sending its name to userdict. The effect of sending to userdict
% is that the name is looked up and executed in a "classless"
% send context with userdict on the top of the dict stack.
%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ToolPanel Notifiers

% Pop up the topping selection window.
%
/ShowToppingWindow { % index winbuttons => -
  pop pop
  { % send to ToppingWindow:
    /pin self send
    /totop self send
    /open self send
  } ToppingWindow send
} def

% Pop up the style editor window.
%
/ShowEditWindow { % index winbuttons => -
  pop pop
  { % send to EditWindow:
    /pin self send
    /totop self send
    /open self send
  } EditWindow send
} def

% Pop up the pizza preview window.
%
/ShowPreviewWindow { % index winbuttons|orderbuttons => -
  pop pop
  { % send to PreviewWindow:
    /pin self send
    /totop self send
    /open self send
  } PreviewWindow send
} def

% Set the delivery mode. Give a warning message if necessary.
%
/SetDelivery { % [index bool] deliverymenu => -
  exch 0 get				% deliverymenu index
  /item 3 -1 roll send			% [(label)]
  0 get					% label
  dup /setvalue deliveryvalue send
  (Please Deliver) eq {			%
    /MaybeDeliver ShowNotice
  } if					%
} def

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ToppingPanel Notifiers

% Set the pizza size. 
% Index 0 is 10". 1 is 14". 2 is 16". 3 is 18".
%
/SetPizzaSize { % [index bool] pizzasizesettings => -
  pop 0 get				% index
  { % send to Pizza:
    /pizzaindexsize self send		% inches
    /setpizzasize self send		%
  } Pizza send
} def

% Set the pizza fraction.
% Index 0 is 1 for whole, 1 is .5 for half.
%
/SetPizzaFraction { % [index bool] pizzafractionsettings => -
  pop 0 get				% index
  0 eq { 1 } { .5 } ifelse		% 1|.5
  /setfraction Pizza send		%
} def

% Set the pizza style.
%
/MenuSetStyle { % [index bool] stylemenu => -
  exch 0 get exch			% index stylemenu
  /item exch send			% [(label)]
  0 get					% (label)
  /findstyle ClassStyle send		% style|null
  dup null eq { pop } {			% style
    /setstyle Pizza send		%
  } ifelse				%
} def

% Update the pizza when the topping check boxes change.
%
/SetCheckboxes { % [index bool] {meat,vegetable}checkboxes => -
  1 index 0 get				% [index bool] checkboxes index
  /item 3 -1 roll send			% [index bool] (label)
  findtopping				% [index bool] topping|null
  dup null eq { pop pop } {		% [index bool] topping
    exch 1 get				% topping bool
    { /addtopping }
    { /removetopping } ifelse		% topping /method
    Pizza send				%
  } ifelse				%
} def

% Order the currently selected pizza.
% (Well, just pop up an appropriate notice.
% The notice's "yes" button actually makes it happen.)
%
/OrderPizza { % index {win,order}buttons => -
  pop pop
  { % send to pizzaparlormenu:
    /value self send			% [index]
    0 get				% index
    /item self send			% [(label)]
    0 get				% (label)
  } pizzaparlormenu send
  { % case (on the menu label):		%
    (Tony&Alba's) {
      /TAOrder ShowNotice
    }
    (Riscy's) (Sparcy's) {
      /SunOrder ShowNotice
    }
    (Demo Room) {
      /DemoOrder ShowNotice
    }
    /Default {
      /OtherOrder ShowNotice
    }
  } case				%
} def

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% EditPanel Notifiers

% Define a new pizza style.
% Make sure the name is unique.
% Create a new style with the new name and current pizza configuration.
% Update the style menu and scrolling list of styles,
% so the new style is included and selected.
%
/NewPizzaStyle { % index editstylemenu|stylenamefield => -
  /value stylenamefield send		% index obj (name)
  PizzaStyleNames 1 index arraycontains? {
    pop /StyleAlreadyDefined ShowNotice	% i o
    pop pop				%
  } {
    /toppings Pizza send		% i o (name) toppings
    /prices Pizza send			% i o (name) toppings prices
    0					% i o (name) toppings prices extras
    makestyle				% i o
    PizzaStyleNames			% i o [names]
    dup length 1 sub			% i o [names] #names-1
    [exch] exch				% i o [index] [names]
    2 copy				% i o [index] [names] [index] [names]
    { % send to stylemenu:
      /setitemlist self send		% i o [index] [names] [index]
      /setvalue self send		% i o [index] [names]
      /paint self send
    } stylemenu send
    { % send to stylelist:
      /setitemlist self send		% i o [index]
      /setvalue self send		% i o
      /validate self send
      /locatechoice self send
      /paint self send
    } stylelist send
    EditStyle				%
  } ifelse
} def

% Edit the pizza style.
% Every program needs an edit menu item,
% even if it doesn't do anything useful.
% This one certainly doesn't.
%
/EditPizzaStyle { % index editstylemenu => -
  pop pop
  /YouAreEditing ShowNotice
} def

% Rename the pizza style currently selected for editing.
% Make sure it's a unique name.
% Tell the style to take care of renaming itself.
%
/RenamePizzaStyle { % index editstylemenu => -
  pop pop
  /value stylenamefield send
  PizzaStyleNames 1 index arraycontains? {
    SelectedStyleName eq
    { /RenameToSelf } { /StyleAlreadyDefined } ifelse
    ShowNotice
  } {
    SelectedStyle /setname exch send
  } ifelse
} def

% Delete the pizza style currently selected for editing.
% Make sure it's not the last one.
% Tell the style to delete itself.
%
/DeletePizzaStyle { % index editstylemenu => -
  pop pop
  /styles ClassStyle send length 1 eq {
    /DontDeleteTheLastStyle ShowNotice
  } {
    SelectedStyle dup null eq { pop } {
      /delete exch send
    } ifelse
  } ifelse
} def

% Save the current pizzatool configuration.
% This doesn't save everything yet (Like user defined styles).
%
/SavePizzaStyle { % index editstylemenu => -
  pop pop
  ConfigFile (w) { file } stopped { % if stopped:
  						% (filename) (w)
    pop pop					%
    /NoSave ShowNotice
  } { % else:
						% file
    { % fork:
      20 dict begin % localdict
	/f exch def				%
	% NOTE: *Always* be careful about defining /Stdout into a variable.
	% Convert it to a literal, first. Because /Stdout is an executable
	% file object (currentprocess /Stdout get xcheck => true), when you
	% refer to the variable by name, the file will be *executed*! This
	% leads to totally bizarre bugs.
	/cf currentprocess /Stdout get cvlit def
	currentprocess /Stdout f put

	f (% TNT PizzaTool configuration file\n)
	writestring

	{ % for all of these executable names:
	  namefield phonefield addressfield emailfield
	  instructionfield0 instructionfield1 instructionfield2
	  instructionfield3 instructionfield4 instructionfield5
	} { % forall of those executable names:
	  dup load				% name textfield
	  /value exch send			% name string
	  typedprint				% name
	  (/setvalue % send\n) printf		%
	} forall

	{ % for all of these executable names:
	  pizzaparlormenu deliverymenu
	} { % for all of those executable names:
	  dup load				% name menu
	  /value exch send			% name [index]
	  0 get					% name index
	  ([%]/setvalue % send\n) printf	%
	} forall

	/value pizzasizesettings send		% [index]
	0 get					% index
	/pizzaindexsize Pizza send		% size
	(%/setpizzasize Pizza send\n) printf	%

	/value pizzafractionsettings send	% [index]
	0 get					% index
	{ 1 .5 } exch get			% 1|.5
	(%/setfraction Pizza send\n) printf	%

	{ % send to stylemenu:
	  /value self send			% [index]
	  0 get					% index
	  /item self send			% [(label)]
	  0 get					% (label)
	} stylemenu send
	(/FavoriteStyle(%)def\n) printf		%

	currentprocess /Stdout cf put
	f closefile
      end % localdict
      /DidSave ShowNotice
    } fork					% file process
    /ProcessName (Save Pizza Style) put		% file
    pop						%
  } ifelse
} def

% Remove the toppings selected in the scrolling list
% from the style currently selected for editing.
%
/RemoveSelected { % index edittoppingmenu => -
  pop pop					%
  10 dict begin % localdict
    /ss SelectedStyle def
    /currenttoppings /toppings ss send def
    /selectedtoppings
      { % send to styletoppingslist:
        [ /value self send { % forall value indices:
	    /item self send			% /st mark ... (label)
	    findtopping				% /st mark ... topping|null
	    dup null eq {pop} if		% /st mark ... topping
	  } forall
	]					% /st [topping ...]
      } styletoppingslist send
    def						%
    [ currenttoppings { % forall toppings:
        % Filter out toppings that are in the array of selected toppings.
        selectedtoppings 1 index arraycontains? { pop } if
      } forall					% mark ... topping
    ]						% [topping ...]
    /settoppings ss send			%
  end % localdict
} def

% Copy the toppings selected on the checkboxes
% to the style currently selected for editing.
%
/CopyCheckboxes { % index edittoppingmenu => -
  pop pop					%
  CheckedToppings				% [topping ... ]
  /settoppings SelectedStyle send		%
} def

% Update the toppings on the style currently selected for editing,
% when the nonexclusive meat or vegetable topping menus are changed.
%
/UpdateToppings { % [index bool] {meat,vegetable}toppingmenu => -
  10 dict begin % localdict
    /menu exch def				% [index bool]
    aload pop /bool exch def /i exch def	%
    SelectedStyle				% style

    /toppings 1 index send			% style toppings
    i /item menu send				% style toppings [(label)]
    0 get					% style toppings (label)
    findtopping					% style toppings topping|null
    dup null eq {				% style toppings null
      pop pop pop				%
    } {						% style toppings topping
      bool {
	[exch] append				% style toppings++
      } {					% style toppings topping
	2 copy arrayindex {			% style toppings topping index
	  exch pop				% style toppings index
	  arraydelete				% style toppings--
	} {					% style toppings topping
	  pop					% style toppings
	} ifelse
      } ifelse
      /settoppings 3 -1 roll send		%
    } ifelse					%
  end % localdict
} def

% Select a pizza style to edit from the scrolling list.
%
/EditStyle { % [index] stylelist => -
  pop pop					%
  SelectedStyle					% style
  [ /toppings 2 index send			% style mark [toppings]
    { % forall toppings:			% style mark ... topping
      /name exch send				% style mark ... name
    } forall
  ]						% style [names]
  {gt} quicksort				% style [sorted-names]
  /setitemlist styletoppingslist send		% style
  /paint styletoppingslist send
  /name 1 index send				% style name
  /setvalue stylenamefield send			% style
  /extras 1 index send				% style extras
  /setvalue styleextrafield send		% style

  /updateprices 1 index send
  UpdateStyleToppingMenus
  /setstyle Pizza send				%
} def

% Set the number of extra toppings you get for free
% on the style currently selected for editing.
% This is a numeric field notifier.
%
/SetStyleExtraToppings { % number styleextrafield => -
  pop
  /setextras SelectedStyle send
} def

% Set the price of a particular pizza size,
% of the style currently selected for editing.
% This notifier is shared by four text fields,
% one for each price.
% Each text field has a property called /PizzaSizeIndex,
% that is the index (0 to 3) of the pizza size whose price
% the numeric field effects.
%
/SetStylePrice { % string styleprice{10,14,16,18}field => -
  exch					% field string
  { token } stopped { % if stopped:
    null true				% field null true
  } { % else:				% field string token true
    { % if good token:			% field string token
      exch pop				% field token
      dup type dup /integertype eq	% field token token int?
      exch /realtype eq or		% field token int|real?
      { % if numeric:
        false				% field number false
      } { % else bogus:
        pop null true			% field null true
      } ifelse				% field number|null bool
    } { % else bad token:		% field
      null true				% field null true
    } ifelse
  } ifelse				% field number|null bool
  { % if bogus input:			% field null
    pop pop beep			%
  } { % else:				% field price
    99.99 min 0 max
    SelectedStyle			% field price style
    /PizzaSizeIndex /property 5 -1 roll	% price style /PSI /p field
    send				% price style i
    /prices 2 index send		% price style i [$ $ $ $]
    dup 4 1 roll			% price [$ $ $ $] style i [$ $ $ $]
    exch 5 -1 roll			% [$ $ $ $] style [$ $ $ $] i price
    put					% [$ $ $ $] style
    /setprices exch send		%
  } ifelse				%
} def

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Notice Notifiers

% Notifier for notice buttons that doesn't do anything
% but close the notice.
%
/NoticeClose { % index noticebuttons => -
  /close Notice send
  pop pop
} def

% Notifier for notice buttons that closes the notice
% and orders a pizza of "Yes" was pressed.
%
/NoticeYesNo { % index noticebuttons => -
  /close Notice send
  pop 0 eq { SendOrder } if
} def

% Guido is in charge of extracting payments from dead-beats.
%
/Guido null def

% Give dead-beats something to worry about.
% If Guido can extract such a payment then all the better!
%
/YerTab 1000 random 50000 mul floor 100 div add def

% Order the pizza. 
%
/SendOrder { % - => -
  ServerEnabled? { % ifelse:
    20 dict begin % localdict
      (/usr/ucb/mail -s 'Pizza Order' 'pizza-server@poit.eng.sun.com')
      sprintf
      /value emailfield send
      dup length 0 eq { pop } { exch (% %) sprintf } ifelse

      pipe /f exch def pop

      { % send to pizzaparlromenu:
        /value self send 0 get /item self send 0 get
      } pizzaparlormenu send
      (To pizza parlor:\t%\n) sprintf
      f exch writestring
      /value namefield send
      (Food order from:\t%\n) sprintf
      f exch writestring
      /value phonefield send
      (\t  Phone:\t%\n) sprintf
      f exch writestring
      /value addressfield send
      (\tAddress:\t%\n\n) sprintf
      f exch writestring

      { % an in-line array of strings:
        (We will eat the food there.\n\n)
	(This order is to go.\n\n)
	(This order is "Take & Bake".\n\n)
	(Please deliver to the above address.\n\n) }
      /value deliverymenu send 0 get get
      f exch writestring

      /pizzasize Pizza send
      /fraction Pizza send
      1 eq { (whole) } { (half of a) } ifelse
      (One % % inch pie:\n) sprintf
      f exch writestring

      /style Pizza send /name exch send (\t%\n) sprintf
      f exch writestring
      /extratoppings Pizza send { % forall toppings:
	/name exch send (\tAdd %\n) sprintf
	f exch writestring
      } forall

      f (\n\n) writestring
      [ instructionfield0 instructionfield1 instructionfield2
	instructionfield3 instructionfield4 instructionfield5
      ] { forall instruction fields:
	/value exch send
	f exch writestring
	f (\n) writestring
      } forall

      f (\n) writestring

      f closefile
    end % localdict
  } { % else:
    /YerTab YerTab /price Pizza send add store
    Guido null ne { Guido killprocess } if
    /Guido { % fork:
      currentprocess /ProcessName (Guido) put
      [ 2 10 random mul cvi add 0] SLEEP
      beep beep beep /PayUp ShowNotice
      /Guido null store
    } fork store
  } ifelse
} def

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Notice Definitions

% Show a named popup notice dialog.
% The name should be defined in NoticeDict,
% and its value should be a dictionary.
% The dictionary should contain /Text, an array of strings,
% and /Buttons, a function returning an instance of ClassButtons.
% The notice is opened up, forcing the user to press a button.
% The whole application is frozen while the notice is up.
% The button notifier should close the notice. 
%
/ShowNotice { % name => -
  /mapped? Notice send {
    /close Notice send
  } if
  NoticeDict exch get begin
    Text Buttons
  end
  /setbuttons Notice send
  /settext Notice send
  gsave
    framebuffer setcanvas
    [ currentcursorlocation ] /open Notice send
  grestore
} def

% This is a dictionary of popup notice dialog description
% dictionaries (for what that's worth).
% Each dictionary contains Text, an array of strings,
% and Buttons, a function returning an instance of ClassButtons.
% These popup notices might be data based and object oriented,
% but they're still annoying. 
%
/NoticeDict dictbegin

  /TAOrder dictbegin
    /Text [
      (Do you really want to order a)
      (pizza from Tony and Alba's?)
      (This will cost real money and)
      (make you want to drink beer.)
    ] def
    /Buttons { yesnonoticebuttons } def
  dictend def

  /SunOrder dictbegin
    /Text [
      (Are you sure you want Sun)
      (to pay for this pizza?)
    ] def
    /Buttons { yesnonoticebuttons } def
  dictend def

  /DemoOrder dictbegin
    /Text [
      (Do you really want to order a pizza)
      (from the demo room??!)
      (This will most likely just confuse people,)
      (and they probably won't cook you a pizza.)
    ] def
    /Buttons { yesnonoticebuttons } def
  dictend def

  /OtherOrder dictbegin
    /Text [
      (Are you sure you want)
      (to order a pizza?)
    ] def
    /Buttons { yesnonoticebuttons } def
  dictend def

  /YouAreEditing dictbegin
    /Text [
      (You *are* editing the pizza menu!)
      (So be careful!)
    ] def
    /Buttons { oknoticebuttons } def
  dictend def

  /NoSave dictbegin
    /Text [
      (This is a demo version of PizzaTool,)
      (so the Save function is discomboobelated.)
    ] def
    /Buttons { oknoticebuttons } def
  dictend def

  /DidSave dictbegin
    /Text [
      (The PizzaTool configuration)
      (has been successfully saved.)
    ] def
    /Buttons { oknoticebuttons } def
  dictend def

  /DontDeleteTheLastStyle dictbegin
    /Text [
      (It's not nice to delete all the pizza styles.)
    ] def
    /Buttons { oknoticebuttons } def
  dictend def

  /UnknownStyleName dictbegin
    /Text [
      (That pizza style name is not known.)
      (You can select New from the style menu to define a new style,)
      (or Rename to change the name of the currently selected style.)
    ] def
    /Buttons { oknoticebuttons } def
  dictend def

  /StyleAlreadyDefined dictbegin
    /Text [
      (That pizza style name is already being used.)
      (Type in a new name and try again.)
    ] def
    /Buttons { oknoticebuttons } def
  dictend def

  /RenameToSelf dictbegin
    /Text [
      (Silly! Type in a *different* name,)
      (if you want to rename the pizza style!)
    ] def
    /Buttons { oknoticebuttons } def
  dictend def

  /MaybeDeliver dictbegin
    /Text [
      (They probably won't deliver unless you make it)
      (worth their while by ording *lots* of pizza!)
    ] def
    /Buttons { oknoticebuttons } def
  dictend def

  /PayUp dictbegin
    % Dynamic popup notice text!
    /Text { % - => [string ...]
      [ (Yer pizza is being held hostage,)
        (until ya pay's off yer tab, chump!)
	(Yer tab's presently:)
        YerTab
        dup 100 mul round cvi 100 mod
        exch floor cvi
        1 index 10 lt { ($%.0%) } { ($%.%) } ifelse
        sprintf
      ]
    } def
    /Buttons { oknoticebuttons } def
  dictend def

dictend def

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Topping Definitions
%
% This code and data defines the pizza toppings.
% Each topping definition consists of a type (/Dairy, /Meat, /Vegetable),
% a name (a string), the number of toppings to sprinkle on the pizza,
% a painting initialization procedure,
% and a procedure to paint the topping after initialization.

% Make a new topping instance.
%
/maketopping { % foodtype name sprinkles {init} {paint} => -
  /new ClassTopping send pop
} def

% Find a named topping instance, returning null if not found.
%
/findtopping { % name => topping|null
  /findtopping ClassTopping send
} def

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Pizza Toppings

% TODO: Order all of these toppings to see what they really look like!

/Dairy (Cheese) 150 {
  1 1 0 setrgbcolor
  .018 setlinewidth
} {
  0 0
  random .1 mul .1 add
  0  random 100 mul 30 add
  arc
  stroke
} maketopping

/Meat (Anchovies) 50 {
  .2 .8 .2 setrgbcolor
} {
  .1 .08 scale
  .2 .5 moveto
  0 .5 .4 -90 90 arc
  .2 .5 lineto closepath
  1.2 .5 scale
  1 1 lineto
  .75 1 .5 20 340 arc  1 1 lineto closepath
  fill
} maketopping

/Meat (Beef) 150 {
  .65 .1 .1 setrgbcolor
} {
  random .1 mul random .1 mul moveto
  8 {
    random .1 mul random .1 mul lineto
  } repeat
  fill
} maketopping

/Meat (Clams) 150 {
  .9 .9 2 setrgbcolor
  /ZapfDingbats findfont .2 scalefont setfont
} {
  0 0 moveto (\173) show
} maketopping

/Meat (Coppa) 150 {
  .55 .3 .2 setrgbcolor
} {
  random .1 mul random .1 mul moveto
  5 {
    random .1 mul random .1 mul lineto
  } repeat
  fill
} maketopping

/Meat (Ham) 150 {
  .7 .7 .2 setrgbcolor
} {
  0 0 .07 .03 rectpath fill 
} maketopping

/Meat (Italian sausage) 150 {
  .7 .1 .2 setrgbcolor
} {
  random .1 mul random .1 mul moveto
  10 {
    random .1 mul random .1 mul lineto
  } repeat
  fill
} maketopping

/Meat (Linguica) 150 {
  .8 .1 .6 setrgbcolor
} {
  random .1 mul random .1 mul moveto
  6 {
    random .1 mul random .1 mul lineto
  } repeat
  fill
} maketopping

/Meat (Pancetta) 150 {
  .8 .1 .1 setrgbcolor
} {
  random .1 mul random .1 mul moveto
  7 {
    random .1 mul random .1 mul lineto
  } repeat
  fill
} maketopping

/Meat (Pepperoni) 100 {
  .7 .1 .2 setrgbcolor
} {
  0 0 .05 0 360 arc fill
} maketopping

/Meat (Prosciutto) 150 {
  .9 .6 .1 setrgbcolor
} {
  random .1 mul random .1 mul moveto
  10 {
    random .1 mul random .1 mul lineto
  } repeat
  fill
} maketopping

/Meat (Salamete) 150 {
  .9 .2 .5 setrgbcolor
} {
  random .1 mul random .1 mul moveto
  8 {
    random .1 mul random .1 mul lineto
  } repeat
  fill
} maketopping

/Meat (Salami) 150 {
  .9 .2 .1 setrgbcolor
} {
  random .1 mul random .1 mul moveto
  5 {
    random .1 mul random .1 mul lineto
  } repeat
  fill
} maketopping

/Meat (Shrimp) 150 {
  1 .5 .5 setrgbcolor
  .02 setlinewidth
} {
  0 .05 moveto
  .1 0 moveto
  0 0 .1 0 50 arc
  stroke
} maketopping

/Meat (Turkey) 150 {
  .8 .8 .1 setrgbcolor
} {
  0 0 .07 .03 rectpath fill
} maketopping

/Vegetable (Artichoke hearts) 150 {
  0 .7 0 setrgbcolor
} {
  0 0 moveto
  0 0 .07 0 100 arc
  fill
} maketopping

/Vegetable (Bell peppers) 150 {
  .2 .7 0 setrgbcolor
  .02 setlinewidth
} {
  0 0
  .2
  0 40 arc
  stroke
} maketopping

/Vegetable (Fresh garlic) 150 {
  .5 .4 .3 setrgbcolor
} {
  random .1 mul random .1 mul moveto
  5 {
    random .1 mul random .1 mul lineto
  } repeat
  fill
} maketopping

/Vegetable (Jalapenos) 150 {
  .2 .9 0 setrgbcolor
} {
  0 0 .05 0 360 arc closepath
  1 1.6 scale
  -.025 0 .02 0 360 arc closepath
  .025 0 .02 0 360 arc closepath
  eofill
} maketopping

/Vegetable (Mushrooms) 150 {
  .4 .5 .4 setrgbcolor
} {
  0 .01 .07 20 150 arc
  0 -.01 .04 140 30 arcn
  closepath
  fill
  -.02 -.05 moveto
  -.01 .05 lineto
  .01 .05 lineto
  .02 -.05 lineto
  closepath
  fill
} maketopping

/Vegetable (Olives) 150 {
  0 .2 .1 setrgbcolor
} {
  0 0 .03 0 360 arc closepath
  0 0 .01 0 360 arc closepath
  eofill
} maketopping

/Vegetable (Onions) 150 {
  .9 .9 .8 setrgbcolor
  .012 setlinewidth
} {
  0 0
  random .1 mul .05 add
  0  random 50 mul 30 add
  arc
  stroke
} maketopping

/Vegetable (Pesto) 150 {
  .2 .9 .3 setrgbcolor
} {
  random .1 mul random .1 mul moveto
  5 {
    random .1 mul random .1 mul lineto
  } repeat
  fill
} maketopping

/Vegetable (Pineapple) 150 {
  .9 .8 0 setrgbcolor
} {
  0 0 moveto
  0 0 .07 0 60 arc
  fill
} maketopping

/Vegetable (Pine nuts) 150 {
  .9 .8 .6 setrgbcolor
} {
  0 0 moveto
  0 0 .04 0 40 arc
  fill
} maketopping

% (Well, Provolone is Dairy, actually, but it works better this way.
/Vegetable (Provolone) 72 {
  1 1 .5 setrgbcolor
  .018 setlinewidth
} {
  0 0
  random .1 mul .1 add
  0  random 100 mul 30 add
  arc
  stroke
} maketopping

/Vegetable (Sicilian Olives) 150 {
  0 .7 .3 setrgbcolor
} {
  0 0 .03 0 360 arc closepath
  0 0 .01 0 360 arc closepath
  eofill
} maketopping

/Vegetable (Tomatoes) 150 {
  .8 0 0 setrgbcolor
} {
  1.2 1.2 scale
  0 0 .05 0 360 arc closepath
  1 1.6 scale
  5 {
    360 random mul rotate
    -.025 0 .02 0 360 arc closepath
  } repeat
  eofill
} maketopping

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Style Definitions
%
% This data defines the pizza styles.
% Each style definition consists of a name (a string),
% an array of topping names,
% an array of pizza prices (corresponding to [10" 14" 16" 18"]),
% and the number of extra toppings you can add to the style for free.

% Make a new style instance.
%
/makestyle { % name toppings prices extras => -
  /new ClassStyle send pop
} def

% Find a named pizza style, returning null if not found.
%
/findstyle { % name => style|null
  /findstyle ClassStyle send
} def

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Pizza Styles

(Cheese)
  [ ]
  [ 7.00 10.00 11.00 14.00 ]
  0 makestyle

(Ala Gilroy)
  [ (Fresh garlic) (Jalapenos) ]
  [ 9.00 12.00 14.00 17.00 ]
  1 makestyle

(All Meat Combo)
  [ (Beef) (Ham) (Italian sausage) (Linguica)
    (Pepperoni) (Salami) ]
  [ 9.00 12.00 14.00 17.00 ]
  0 makestyle

(Garlic, Clam, & Tomato)
  [ (Clams) (Fresh garlic) (Tomatoes) ]
  [ 9.00 12.00 14.00 17.00 ]
  0 makestyle

(Keep Fit Special)
  [ (Artichoke hearts) (Bell peppers) (Fresh garlic)
    (Mushrooms) (Olives) (Onions) (Tomatoes) ]
  [ 9.00 12.00 14.00 17.00 ]
  0 makestyle

(Pesto Pizza Special)
  [ (Fresh garlic) (Pesto) (Pine nuts) (Tomatoes) ]
  [ 9.00 12.00 14.00 17.00 ]
  0 makestyle

(Tony's Gourmet)
  [ (Coppa) (Pancetta) (Prosciutto) (Salamete)
    (Fresh garlic) (Provolone) (Sicilian Olives) ]
  [ 10.00 15.00 17.00 19.00 ]
  0 makestyle

(Tony's Special)
  [ (Beef) (Italian sausage) (Linguica) (Pepperoni)
    (Salami) (Bell peppers) (Mushrooms) (Onions) ]
  [ 9.00 12.00 14.00 17.00 ]
  0 makestyle

(Vegetarian Delight)
  [ (Artichoke hearts) (Bell peppers) (Fresh garlic)
    (Mushrooms) (Olives) (Onions) (Pine nuts) (Tomatoes) ]
  [ 9.00 12.00 14.00 17.00 ]
  0 makestyle

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Top Level User Interface Componants
%
% First we create and initialize the top level window frames,
% and the clients that go directly inside them.

/ToolPanel
  /Calculated framebuffer /new ClassProPanel send
def

/ToolWindow
  ToolPanel framebuffer /new ClassBaseWindow send 
def

  (Pizza Tool) /setlabel ToolWindow send
  /Reshape? false /setattribute ToolWindow send

  /toolicon
    64 64 1 [64 0 0 -64 0 64] {<
      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF83CE66FFFFFFFFFF9F8E4EFFFFF
      FFFFF9F4E1CFFFFFFFFFF064F3CFFFFFFFFFF3E0E1FFFFFFFFFFF3CCC99FFFFF
      FFFFF3CC999FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
      5555555005555555AAAAAA8FF8AAAAAA5555547FFF155555AAAAA9FFFFCAAAAA
      5555573446F55555AAAAAF56ED7AAAAA55555F34CD7D5555AAAABF77723EAAAA
      55557F74CBBF5555AAAAFFFFFFFFAAAA5554FFFFFFFF9555AAA9FFFFFFFFCAAA
      5555FFFFFFFFD555AAABFFFFFFFFEAAA5FFFFFFFFFFFFFFDBFFFFFFFFF11FFBA
      503FFFF18799FF3DB4849107C79871425C924933D799248DBC924920839930C2
      5C924D49939924F5B8464C60100060025FFFFCFFFFFFFFFDBFFFF0FFFFFFFFFA
      5557FFC77FEFF555AAABFF6A942FEAAA5553F95DF0EFE555AAABFFFFFFFFEAAA
      5555FFFFFFFFD555AAA9FFFFFFFFCAAA5554FFFFFFFF9555AAAAFD62AB3FAAAA
      55557B26B05F5555AAAABBB0D75EAAAA55555FFFFFFD5555AAAAAFFFFFFAAAAA
      555557FFFFF55555AAAAA9F7FBCAAAAA5555547EDF155555AAAAAA8FF8AAAAAA
      FFFFFFF007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF83CE66FFFFF
      FFFFF9F8E4EFFFFFFFFFF9F4E1CFFFFFFFFFF064F3CFFFFFFFFFF3E0E1FFFFFF
      FFFFF3CCC99FFFFFFFFFF3CC999FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
    >} buildimage
  def

  % executable array display item:
  { /size eq { 64 64 } {
      gsave
	64 64 scale
	.9 0 0 rgbcolor setcolor
	1 1 1 rgbcolor setbackcolor
	//toolicon imagecanvas
      grestore
    } ifelse
  } /seticonimage ToolWindow send

  /QuitFromUser { % ctl => -
    /reset Pizza send
    /QuitFromUser super send
  } /installmethod ToolWindow send

/ToppingPanel 
  /Calculated framebuffer /new ClassProPanel send
def

/ToppingWindow
  ToppingPanel framebuffer /new ClassPopupWindow send 
def

  (Pizza Topping Panel) /setlabel ToppingWindow send
  /Footer? true /setattribute ToppingWindow send
  /Reshape? false /setattribute ToppingWindow send
  /pin ToppingWindow send
  ToppingWindow /addsubwindow ToolWindow send

/EditPanel
  /Calculated framebuffer /new ClassProPanel send
def

/EditWindow
  EditPanel framebuffer /new ClassPopupWindow send
def

  (Pizza Menu Editor) /setlabel EditWindow send
  /Reshape? false /setattribute EditWindow send
  /pin EditWindow send
  EditWindow /addsubwindow ToolWindow send

/Pizza
  framebuffer /new ClassPizza send
def

/PreviewWindow
  Pizza framebuffer /new ClassPopupPizzaWindow send
def

  /pin PreviewWindow send
  (Popup Pizza Preview) /setlabel PreviewWindow send
  /Footer? true /setattribute PreviewWindow send
  PreviewWindow /addsubwindow ToolWindow send

  /open { % - => -
    /open super send
    /paint Pizza send
  } /installmethod PreviewWindow send

  /close { % - => -
    /close super send
    /paint Pizza send
  } /installmethod PreviewWindow send

/Notice
  ToolWindow framebuffer /new ClassNotice send
def

  framebuffer /Color get { % if:
    /Paint { % - => -
      gsave % Smokey Notice Hack
	/path1 self send clip newpath
	1 ApexName GetColor setcolor currentgray
	[ exch /mul load ] cvx settransfer
	currentcanvas imagecanvas
	initclip
	/path2 self send clip newpath
	2 ApexName GetColor setcolor currentgray
	[ exch /mul load ] cvx settransfer
	currentcanvas imagecanvas
      grestore
    } /installmethod /ClassNoticeTail ClassNotice send send
  } if

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ToolPanel Componants
%
% The ToolPanel uses the calculated layout protocol. A calculated
% panel's /addclient method takes as arguments a client name, a client
% object, and a calculated layout specification.  In these examples,
% the name of the object defined in userdict is the same as its client
% name in the panel. However, the name given to /addclient need not
% bear any relationship to the client being added.  The names to
% identify objects in the calculated layout specifications are the
% names given to /addclient, NOT the names under which the clients are
% defined in other dictionaries.

/pizzaparlormenu
  /Grid framebuffer /new ClassMenu send 2 copy def
  [ (Tony&Alba's)
    (Sparcy's)
    (Riscy's)
    (Demo Room)
    (Student Union)
  ] /setitemlist 2 index send
  /Exclusive /setchoicemode 2 index send
  [0] /setvalue 2 index send
  0 /setdefault 2 index send
  pop pop

/addressmenubuttons
  /Grid framebuffer /new ClassMenuButtons send 2 copy def
  [ [ (Pizza Parlor) pizzaparlormenu ]
  ] /setitemlist 2 index send
  [ /NorthWest { /NorthWest PARENT POSITION 10 -10 xyadd } ]
  /addclient ToolPanel send

/winbuttons
  /Grid framebuffer /new ClassButtons send 2 copy def
  [ [ (Topping...) /ShowToppingWindow ]
    [ (Preview...) /ShowPreviewWindow ]
    [ (Edit...) /ShowEditWindow ]
    [ (Order!) /OrderPizza ]
  ] /setitemlist 2 index send
  userdict /settarget 2 index send
  10 0 /setgaps 3 index send
  [ /SouthWest { /SouthEast /addressmenubuttons POSITION 10 0 xyadd } ]
  /addclient ToolPanel send

/namefieldlabel
  (Name:) framebuffer /new ClassLabel send 2 copy def
  [ /NorthWest { 30 /SouthWest /addressmenubuttons POSITION
		 exch pop -15 add } ]
  /addclient ToolPanel send

/namefield
  framebuffer /new ClassTextField send 2 copy def
  0 0 /preferredsize 3 index send exch pop 200 exch /reshape 5 index send
  [ /SouthWest { /SouthEast /namefieldlabel POSITION 10 -2 xyadd } ]
  /addclient ToolPanel send

/phonefieldlabel
  (Phone:) framebuffer /new ClassLabel send 2 copy def
  [ /NorthEast { /SouthEast /namefieldlabel POSITION 0 -10 xyadd } ]
  /addclient ToolPanel send

/phonefield
  framebuffer /new ClassTextField send 2 copy def
  0 0 /preferredsize 3 index send exch pop 200 exch /reshape 5 index send
  [ /SouthWest { /SouthEast /phonefieldlabel POSITION 10 -2 xyadd } ]
  /addclient ToolPanel send

/addressfieldlabel
  (Address:) framebuffer /new ClassLabel send 2 copy def
  [ /NorthEast { /SouthEast /phonefieldlabel POSITION 0 -10 xyadd } ]
  /addclient ToolPanel send

/addressfield
  framebuffer /new ClassTextField send 2 copy def
  0 0 /preferredsize 3 index send exch pop 400 exch /reshape 5 index send
  [ /SouthWest { /SouthEast /addressfieldlabel POSITION 10 -2 xyadd } ]
  /addclient ToolPanel send

/deliverymenu
  /Grid framebuffer /new ClassMenu send 2 copy def
  /Exclusive /setchoicemode 2 index send
  [ (Eat at T&A) (Pick Up) (Take & Bake) (Please Deliver)
  ] /setitemlist 2 index send
  0 /setdefault 2 index send
  [0] /setvalue 2 index send
  userdict /settarget 2 index send
  /SetDelivery /setnotifier 2 index send
  pop pop

/deliverylabel
  (Delivery:) framebuffer /new ClassLabel send 2 copy def
  [ /NorthEast { /SouthEast /addressfieldlabel POSITION 0 -15 xyadd } ]
  /addclient ToolPanel send

/deliverymenubutton
  /Grid framebuffer /new ClassMenuButtons send 2 copy def
  [ [ () deliverymenu ] ] /setitemlist 2 index send
  0 true /setabbreviated 3 index send
  [ /SouthWest { /SouthEast /deliverylabel POSITION 10 0 xyadd } ]
  /addclient ToolPanel send

/deliveryvalue
  (Eat at T&A        ) framebuffer /new ClassLabel send 2 copy def
  [ /SouthWest { /SouthEast /deliverymenubutton POSITION 10 0 xyadd } ]
  /addclient ToolPanel send

/totallabel
  (Total estimated cost: $) framebuffer /new ClassLabel send 2 copy def
  [ /NorthWest { 10 /SouthWest /deliverylabel POSITION exch pop -15 add } ]
  /addclient ToolPanel send

/totalfield
  framebuffer /new ClassTextField send 2 copy def
  0 0 /preferredsize 3 index send exch pop 80 exch /reshape 5 index send
  true /setreadonly 2 index send
  [ /SouthWest { /SouthEast /totallabel POSITION 0 -2 xyadd } ]
  /addclient ToolPanel send

/emaillabel
  (Email copy to:   ) framebuffer /new ClassLabel send 2 copy def
  [ /NorthEast { /SouthEast /totallabel POSITION 0 -10 xyadd } ]
  /addclient ToolPanel send

/emailfield
  framebuffer /new ClassTextField send 2 copy def
  0 0 /preferredsize 3 index send exch pop 200 exch /reshape 5 index send
  [ /SouthWest { /SouthEast /emaillabel POSITION 0 -2 xyadd } ]
  /addclient ToolPanel send

/instructionslabel
  (Additional Instructions:) framebuffer /new ClassLabel send 2 copy def
  [ /NorthWest { 10 /SouthWest /emaillabel POSITION exch pop -15 add } ]
  /addclient ToolPanel send

  phonefield /setnextfocus namefield send
  addressfield /setnextfocus phonefield send
  emailfield /setnextfocus addressfield send
  emailfield

% /instructionfield[0-5]
  0 1 5 {  % This should be a jot canvas, but we're just server side for now.
    (instructionfield%) sprintf cvn
      framebuffer /new ClassTextField send 2 copy def
      0 0 /preferredsize 3 index send exch pop 500 exch /reshape 5 index send
      dup /setnextfocus 5 -1 roll send
      dup 3 1 roll
      [ /NorthWest { /SouthWest PREVIOUS POSITION 0 -5 xyadd } ]
      /addclient ToolPanel send
  } for

  namefield /setnextfocus 3 -1 roll send

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ToppingPanel Componants

/orderbuttons
  /Grid framebuffer /new ClassButtons send 2 copy def
  [ [ (Preview...) /ShowPreviewWindow ]
    [ (Order!) /OrderPizza ]
  ] /setitemlist 2 index send
  userdict /settarget 2 index send
  10 0 /setgaps 3 index send
  [ /NorthWest { /NorthWest PARENT POSITION 10 -10 xyadd } ]
  /addclient ToppingPanel send

/pizzasizelabel
  (Pizza Size:) framebuffer /new ClassLabel send 2 copy def
  [ /NorthWest { /SouthWest /orderbuttons POSITION  0 -20 xyadd } ]
  /addclient ToppingPanel send

/pizzasizesettings
  /Grid framebuffer /new ClassSettings send 2 copy def
  [ (10") (14") (16") (18") ] /setitemlist 2 index send
  userdict /settarget 2 index send
  /SetPizzaSize /setnotifier 2 index send
  [3] /setvalue 2 index send
  [ /SouthWest { /SouthEast /pizzasizelabel POSITION 10 -6 xyadd } ]
  /addclient ToppingPanel send

/pizzafractionlabel
  (Fraction:) framebuffer /new ClassLabel send 2 copy def
  [ /SouthWest { /SouthEast /pizzasizesettings POSITION 20 6 xyadd } ]
  /addclient ToppingPanel send

/pizzafractionsettings
  /Grid framebuffer /new ClassSettings send 2 copy def
  [ (Whole) (Half) ] /setitemlist 2 index send
  userdict /settarget 2 index send
  /SetPizzaFraction /setnotifier 2 index send
  [ /SouthWest { /SouthEast /pizzafractionlabel POSITION 10 -6 xyadd } ]
  /addclient ToppingPanel send

/stylelabel
  (Style:) framebuffer /new ClassLabel send 2 copy def
  [ /NorthWest { /SouthWest /pizzasizelabel POSITION 0 -20 xyadd } ]
  /addclient ToppingPanel send

/stylemenu
  /Grid framebuffer /new ClassMenu send 2 copy def
  /Exclusive /setchoicemode 2 index send
  PizzaStyleNames /setitemlist 2 index send
  userdict /settarget 2 index send
  /MenuSetStyle /setnotifier 2 index send
  [0] /setvalue 2 index send
  0 /setdefault 2 index send
  true /setpinnable 2 index send
  (Pizza Style) /setpinnedlabel 2 index send
  (Pizza Style) /setlabel 2 index send
  pop pop

/stylemenubutton
  /Grid framebuffer /new ClassMenuButtons send 2 copy def
  [ [ () stylemenu ] ] /setitemlist 2 index send
  0 true /setabbreviated 3 index send
  [ /SouthWest { /SouthEast /stylelabel POSITION 10 0 xyadd } ]
  /addclient ToppingPanel send

/stylevalue
  (Cheese) framebuffer /new ClassLabel send 2 copy def
  [ /SouthWest { /SouthEast /stylemenubutton POSITION 10 0 xyadd } ]
  /addclient ToppingPanel send

/meatlabel
  (Meats:) framebuffer /new ClassLabel send 2 copy def
  [ /NorthWest { /SouthWest /stylelabel POSITION 10 -15 xyadd } ]
  /addclient ToppingPanel send

/meatcheckboxes
  /Grid framebuffer /new ClassCheckBoxes send 2 copy def
  MeatToppingNames /setitemlist 2 index send
  [ true 5 3 ] /setlayoutparameters 2 index send
  userdict /settarget 2 index send
  /SetCheckboxes /setnotifier 2 index send
  [ /NorthWest { /SouthWest /meatlabel POSITION 10 -10 xyadd } ]
  /addclient ToppingPanel send

/vegetablelabel
  (Vegetables:) framebuffer /new ClassLabel send 2 copy def
  [ /NorthWest { /SouthWest /meatcheckboxes POSITION -10 -15 xyadd } ]
  /addclient ToppingPanel send

/vegetablecheckboxes
  /Grid framebuffer /new ClassCheckBoxes send 2 copy def
  VegetableToppingNames /setitemlist 2 index send
  [ true 5 3 ] /setlayoutparameters 2 index send
  userdict /settarget 2 index send
  /SetCheckboxes /setnotifier 2 index send
  [ /NorthWest { /SouthWest /vegetablelabel POSITION 10 -10 xyadd } ]
  /addclient ToppingPanel send

/costlabel
  (Estimated cost: $) framebuffer /new ClassLabel send 2 copy def
  [ /NorthWest { /SouthWest /vegetablecheckboxes POSITION -15 -20 xyadd } ]
  /addclient ToppingPanel send

/costfield
  framebuffer /new ClassTextField send 2 copy def
  0 0 /preferredsize 3 index send exch pop 80 exch /reshape 5 index send
  true /setreadonly 2 index send
  [ /SouthWest { /SouthEast /costlabel POSITION 0 -2 xyadd } ]
  /addclient ToppingPanel send

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% EditPanel Componants

/editstylemenu
  /Grid framebuffer /new ClassMenu send 2 copy def
  [ [ (New) /NewPizzaStyle ]
    [ (Edit) /EditPizzaStyle ]
    [ (Rename  ) /RenamePizzaStyle ]
    [ (Delete) /DeletePizzaStyle ]
    [ (Save) /SavePizzaStyle ]
  ] /setitemlist 2 index send
  true /setpinnable 2 index send
  (Style) /setpinnedlabel 2 index send
  0 /setdefault 2 index send
  pop pop

/meattoppingmenu
  /Grid framebuffer /new ClassMenu send 2 copy def
  /NonExclusive /setchoicemode 2 index send
  true /setpinnable 2 index send
  (Meat Toppings) /setpinnedlabel 2 index send
  MeatToppingNames /setitemlist 2 index send
  userdict /settarget 2 index send
  /UpdateToppings /setnotifier 2 index send
  [ true 5 3 ] /setlayoutparameters 2 index send
  pop pop

/vegetabletoppingmenu
  /Grid framebuffer /new ClassMenu send 2 copy def
  /NonExclusive /setchoicemode 2 index send
  true /setpinnable 2 index send
  (Vegetable Toppings) /setpinnedlabel 2 index send
  VegetableToppingNames /setitemlist 2 index send
  userdict /settarget 2 index send
  /UpdateToppings /setnotifier 2 index send
  [ true 5 3 ] /setlayoutparameters 2 index send
  pop pop

/edittoppingmenu
  /Grid framebuffer /new ClassMenu send 2 copy def
  [ [ (Copy Checkboxes) /CopyCheckboxes ]
    [ (Remove Selected) /RemoveSelected ]
    [ (Meats) meattoppingmenu ]
    [ (Vegetables) vegetabletoppingmenu ]
  ] /setitemlist 2 index send
  true /setpinnable 2 index send
  (Toppings) /setpinnedlabel 2 index send
  pop pop

/stylemenubuttons
  /Grid framebuffer /new ClassMenuButtons send 2 copy def
  [ [ (Style) editstylemenu ]
    [ (Toppings) edittoppingmenu ]
  ] /setitemlist 2 index send
  10 0 /setgaps 3 index send
  userdict /settarget 2 index send
  [ /NorthWest { /NorthWest PARENT POSITION 10 -10 xyadd } ]
  /addclient EditPanel send

/stylelistlabel
  (Available Pizza Styles:) framebuffer /new ClassLabel send 2 copy def
  [ /NorthWest { /SouthWest /stylemenubuttons POSITION 0 -10 xyadd } ]
  /addclient EditPanel send

/stylescroll
  framebuffer /new ClassVScrollbar send 2 copy def
  /scroll /setnotifier 2 index send
  /scroll /setpreviewer 2 index send
  0 0 /preferredsize stylescroll send pop 150 /reshape 5 index send
  [ /NorthWest { /SouthWest /stylelistlabel POSITION 0 -5 xyadd } ]
  /addclient EditPanel send

/stylelist
  EditPanel /new ClassScrollList send 2 copy def
  0 0 180 150 /reshape 5 index send
  PizzaStyleNames /setitemlist 2 index send
  /Exclusive /setchoicemode 2 index send
  [0] /setvalue 2 index send
  userdict /settarget 2 index send
  /EditStyle /setnotifier 2 index send
  dup /settarget stylescroll send
  stylescroll /setscrollbar 2 index send
  [ /SouthWest { /SouthEast /stylescroll POSITION 2 0 xyadd } ]
  /addclient EditPanel send

/styletoppingslabel
  (Toppings:) framebuffer /new ClassLabel send 2 copy def
  [ /SouthWest { /NorthEast /stylelist POSITION 10 5 xyadd } ]
  /addclient EditPanel send

/styletoppingsscroll
  framebuffer /new ClassVScrollbar send 2 copy def
  /scroll /setnotifier 2 index send
  /scroll /setpreviewer 2 index send
  0 0 /preferredsize styletoppingsscroll send pop 150 /reshape 5 index send
  [ /NorthWest { /SouthWest /styletoppingslabel POSITION 0 -5 xyadd } ]
  /addclient EditPanel send

/styletoppingslist
  EditPanel /new ClassScrollList send 2 copy def
  0 0 180 150 /reshape 5 index send
  /NonExclusive /setchoicemode 2 index send
  styletoppingsscroll /setscrollbar 2 index send
  dup /settarget styletoppingsscroll send
  [ /SouthWest { /SouthEast /styletoppingsscroll POSITION 2 0 xyadd } ]
  /addclient EditPanel send

/stylenamelabel
  (Style:) framebuffer /new ClassLabel send 2 copy def
  [ /NorthWest { /SouthWest /stylescroll POSITION 0 -10 xyadd } ]
  /addclient EditPanel send

/stylenamefield
  framebuffer /new ClassTextField send 2 copy def
  0 0 /preferredsize 3 index send exch pop 140 exch /reshape 5 index send
  (Cheese) /setvalue 2 index send
  userdict /settarget 2 index send
  /NewPizzaStyle /setnotifier 2 index send
  [ /SouthWest { /SouthEast /stylenamelabel POSITION 10 -2 xyadd } ]
  /addclient EditPanel send

/styleextralabel
  (Extra toppings:) framebuffer /new ClassLabel send 2 copy def
  [ /NorthWest { /SouthWest /styletoppingsscroll POSITION 0 -10 xyadd } ]
  /addclient EditPanel send

/styleextrafield
  framebuffer /new ClassNumericField send 2 copy def
  0 /setvalue styleextrafield send
  0 9 /setrange styleextrafield send
  4 /setminimumvisible 2 index send
  userdict /settarget 2 index send
  /SetStyleExtraToppings /setnotifier 2 index send
  [ /SouthWest { /SouthEast /styleextralabel POSITION 10 -2 xyadd } ]
  /addclient EditPanel send

  styleextrafield /setnextfocus stylenamefield send

/stylepriceslabel
  (Prices:) framebuffer /new ClassLabel send 2 copy def
  [ /NorthWest { /SouthWest /stylenamelabel POSITION 0 -10 xyadd } ]
  /addclient EditPanel send

/styleprice10label
  (10" $) framebuffer /new ClassLabel send 2 copy def
  [ /SouthWest { /SouthEast /stylepriceslabel POSITION 15 0 xyadd } ]
  /addclient EditPanel send

/styleprice10field
  framebuffer /new ClassTextField send 2 copy def
  0 0 /preferredsize 3 index send exch pop 40 exch /reshape 5 index send
  /PizzaSizeIndex 0 /setproperty 3 index send
  userdict /settarget 2 index send
  /SetStylePrice /setnotifier 2 index send
  [ /SouthWest { /SouthEast /styleprice10label POSITION 0 -2 xyadd} ]
  /addclient EditPanel send

  styleprice10field /setnextfocus styleextrafield send

/styleprice14label
  (14" $) framebuffer /new ClassLabel send 2 copy def
  [ /SouthWest { /SouthEast /styleprice10field POSITION 15 2 xyadd } ]
  /addclient EditPanel send

/styleprice14field
  framebuffer /new ClassTextField send 2 copy def
  0 0 /preferredsize 3 index send exch pop 40 exch /reshape 5 index send
  /PizzaSizeIndex 1 /setproperty 3 index send
  userdict /settarget 2 index send
  /SetStylePrice /setnotifier 2 index send
  [ /SouthWest { /SouthEast /styleprice14label POSITION 0 -2 xyadd } ]
  /addclient EditPanel send

  styleprice14field /setnextfocus styleprice10field send

/styleprice16label
  (16" $) framebuffer /new ClassLabel send 2 copy def
  [ /SouthWest { /SouthEast /styleprice14field POSITION 15 2 xyadd } ]
  /addclient EditPanel send

/styleprice16field
  framebuffer /new ClassTextField send 2 copy def
  0 0 /preferredsize 3 index send exch pop 40 exch /reshape 5 index send
  /PizzaSizeIndex 2 /setproperty 3 index send
  userdict /settarget 2 index send
  /SetStylePrice /setnotifier 2 index send
  [ /SouthWest { /SouthEast /styleprice16label POSITION 0 -2 xyadd } ]
  /addclient EditPanel send

  styleprice16field /setnextfocus styleprice14field send

/styleprice18label
  (18" $) framebuffer /new ClassLabel send 2 copy def
  [ /SouthWest { /SouthEast /styleprice16field POSITION 15 2 xyadd } ]
  /addclient EditPanel send

/styleprice18field
  framebuffer /new ClassTextField send 2 copy def
  0 0 /preferredsize 3 index send exch pop 40 exch /reshape 5 index send
  /PizzaSizeIndex 3 /setproperty 3 index send
  userdict /settarget 2 index send
  /SetStylePrice /setnotifier 2 index send
  [ /SouthWest { /SouthEast /styleprice18label POSITION 0 -2 xyadd } ]
  /addclient EditPanel send

  styleprice18field /setnextfocus styleprice16field send
  stylenamefield /setnextfocus styleprice18field send

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Notice Componants

/oknoticebuttons
  /Spaced framebuffer /new ClassButtons send 2 copy def
  [ (OK) ] /setitemlist 2 index send
  0 /setdefault 2 index send
  userdict /settarget 2 index send
  /NoticeClose /setnotifier 2 index send
  pop pop

/yesnonoticebuttons
  /Spaced framebuffer /new ClassButtons send 2 copy def
  [ (Yes) (No) ] /setitemlist 2 index send
  0 /setdefault 2 index send
  10 0 /setgaps 3 index send
  userdict /settarget 2 index send
  /NoticeYesNo /setnotifier 2 index send
  pop pop

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Initialization

% Create a new event manager to take care of this monstrosity.
/mgr /new ClassEventMgr send def
mgr /ProcessName (PizzaTool Manager) put

% Activate all the windows.
[ToolWindow ToppingWindow PreviewWindow EditWindow Notice] {
  mgr /activate 3 -1 roll send
} forall

% Place all the windows.
[ToolWindow ToppingWindow PreviewWindow EditWindow] {
  /place exch send
} forall

% Try to load the configuration file.
ConfigFile LoadFile pop

% Set the favorite style, or the default if not found.
FavoriteStyle /findstyle ClassStyle send
dup null eq {
  pop /defaultstyle ClassStyle send
} if
/editstyle exch send

% Get the show on the road.
/map ToolWindow send

newprocessgroup currentfile closefile
%EOF