[comp.windows.news] PizzaTool for TNT 2.0

hopkins@sun.com (Don Hopkins) (04/02/91)

Now that The NeWS Toolkit version 2.0 is a real shipping product, here
is "PizzaTool" for TNT! This is *not* an April fools joke -- PizzaTool
is fully functional!! (well, fully object oriented, at least...)  If
you want to order The NeWS Toolkit version 2.0 from Sun, the part
number is "TNT-2.0-4-4-21". If you want to order pizza with PizzaTool,
you're going to have to set up your own pizza server, and make
arrangements with your local pizza parlor -- Tony & Alba's takes
orders by fax, but they can't fax the pizza back to you!

	-Don

==Cut "pizzatool.6" here: 8X==============================================
.\" @(#) pizzatool.6 1.1 91/03/08 SMI;
.ds Ne \s-2Ne\h'-0.2n'WS\s+2
.TH PIZZATOOL 6 "8 March 1991" "OpenWindows 3.0"
.IX "pizzatool" "" "\fLpizzatool\fP \(em a graphical pizza menu user interface"
.SH NAME
pizzatool \- a graphical pizza menu user interface
.SH SYNOPSIS
.B /usr/openwin/demo/pizzatool
.SH DESCRIPTION
.I PizzaTool
is a \*(Ne and tnt application that lets you select a pizza by
choosing toppings from checkboxes and menus, and preview a drawing of 
your pizza in a round spinning window.

The main PizzaTool window has some buttons, menus, and text fields that you 
can use to configure your order. The "Pizza Parlor" menu selects between
various pizza servers. The "Topping..." "Preview..." and "Edit..." buttons 
pop up associated control panels. The "Order!" button sends your order to 
the pizza server. You need to fill in your name and address so they know 
who you are and where to deliver your pizza. 

The Topping panel has a "Preview..." button that pops up the pizza
preview panel, and an "Order!" button to send your order, like the
main PizzaTool window. There are settings to select how big a pizza
you want, and to choose a whole or a half pizza. There is an
abbreviated menu button for selecting popular pizza styles, and lots
and lots of checkboxes, for selecting individual toppings. The field
at the bottom of the panel displays the estimated cost of the
currently selected pizza.

Popping up the pizza Preview panel paints a picture of the particular pizza 
you've picked. The round pizza is magically suspended in the hollow frame 
(it's supposed to be that way), and you can resize the frame to get a closer 
look at the pizza. Pressing the
.I MENU
button over the pizza pops up a menu of popular pizza styles, and you can 
spin the pizza around with the
.I SELECT
button, to cook it. 

The Pizza Menu Editor panel is for use by authorized pizza parlor personell
only. It can be used to add, delete, rename, and edit pizza styles, and to
change all the prices. 

.SH SEE ALSO
.I The \*(Ne Toolkit Reference Manual
.LP
.I \*(Ne 2.1 Programmer's Guide
.LP
.I OPEN LOOK Graphical User Interface
.I Functional Specification
.SH NOTES
.I \*(Ne
is a registered trademark of Sun Microsystems, Inc.
.LP
.I OPEN LOOK
is a trademark of AT&T.
.SH BUGS
There is presently no way to pay off your tab.

==Cut "pizzatool" here: 8X==============================================
#!/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.7 91/04/02
%
% Copyright (c) 1991 by Sun Microsystems, Inc.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% User Interface Structure
%
% * 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
% *** stylelabel: ClassLabel
% *** stylescroll: ClassVScrollbar
%     /scroll @ stylelist
% *** stylelist: ClassScrollList
%     /EditStyle
% *** styletoppingslabel: ClassLabel
% *** styletoppingsscroll: ClassVScrollbar
%     /scroll @ styletoppingslist
% *** styletoppingslist: ClassScrollList
%     /EditTopping
% *** 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

systemdict /findpackage known {
  /NeWS 3 0 findpackage beginpackage
  /TNTCore 3 0 findpackage beginpackage
  /TNT 3 0 findpackage beginpackage

  /SLEEP { sleep } def
  /BUILDIMAGE { framebuffer /Colormap get buildimage } def
} {
  /SLEEP { aload pop 1000 mul exch add 60 div sleep } def
  /BUILDIMAGE { buildimage } def
} ifelse

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Globals

/FavoriteStyle (Cheese) def
/ServerEnabled? false def
/ConfigFile (.pizzatool.ps) def

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Utilities

/CheckedToppingNames { % - => [name ...]
  [ { /value self send {
        /item self send
      } forall
    } meatcheckboxes send
    { /value self send {
        /item self send
      } forall
    } vegetablecheckboxes send
  ]
} def

/CheckedToppings { % - => [topping ...]
  CheckedToppingNames {
    [ exch {
        findtopping
        dup null eq { pop } if
      } forall
    ]
  } ClassTopping send
} def

/MeatToppingNames { % - => [Topping ...]
  [ /Meat /typetoppings ClassTopping send {
      /name exch send
    } forall ]
} def

/VegetableToppingNames { % - => [Topping ...]
  [ /Vegetable /typetoppings ClassTopping send {
      /name exch send
    } forall ]
} def

/PizzaStyleNames { % - => [(name) ...]
  [ /styles ClassStyle send {
      /name exch send
    } forall ]
} def

/SelectedStyleName { % - => style
  { /value self send 0 get /item self send }
  stylelist send
} def

/SelectedStyle { % - => style
  SelectedStyleName
  /findstyle ClassStyle send
  dup null eq { pop /defaultstyle ClassStyle send } if
} def

/UpdateStyleToppingMenus { % - => -
  SelectedStyle
  [ /toppings 2 index send {
      { /foodtype self send /Meat eq { /foodnumber self send } if }
      exch send
    } forall
  ] /setvalue meattoppingmenu send

  [ /toppings 3 -1 roll send {
      { /foodtype self send /Vegetable eq { /foodnumber self send } if }
      exch send
    } forall
  ] /setvalue vegetabletoppingmenu send
} def

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

/ShowNotice { % name => -
  NoticeDict exch get begin
    Text Buttons
  end
  /setbuttons Notice send
  /settext Notice send
  gsave
    framebuffer setcanvas
    [ currentcursorlocation ] /open Notice send
  grestore
} def

/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
    /Text {
      [ (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

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Class Definitions

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ClassPizza

/ClassPizza ClassCanvas [
  /Toppings /Style /PizzaSize /Fraction /Price
  /Cheese /ExtraToppings /PaintLock
] classbegin
  /Transparent false def
  /Retained true def
  /Mapped true def
  /PaintProc null def
  /MatchBias .9 def
  /CrustColor .9 .6 .1 rgbcolor def
  /SauceColor 1 .1 .1 rgbcolor def

% class methods

  /NewInit {
    /NewInit super send
    /Toppings nullarray def
    /ExtraToppings nullarray def
    /Style /defaultstyle ClassStyle send def
    /PizzaSize 3 def
    /Fraction 1 def
    /Price 0 def
    /Cheese (Cheese) findtopping def
    /PaintLock createmonitor def
    /Sprinklers growabledict def
    /TempCanvas self newcanvas def
    TempCanvas begin
      /Mapped false def
      /Transparent false def
      /Retained true def
    end
  } def

  /destroy {
    SpinProcess null ne {
      SpinProcess killprocess
    } if
    /SpinProcess unpromote
  } def

  /toppings { % - => [topping ...]
    Toppings
  } def

  /addtopping { % topping => -
    Toppings 1 index arraycontains? { pop } {
      Toppings 1 index arrayappend
      /Toppings exch def
      /updateview self send
      /mapped? Parent send {
	  gsave
	    self setcanvas
	    /PaintSetup self send
	    /PaintClip self send
	    /StartSprinkle self send
	  grestore
      } { pop } ifelse
    } ifelse
  } def

  /removetopping { % topping => -
    Toppings exch arrayindex {
      Toppings exch arraydelete
      /settoppings self send
    } if
  } def

  /settoppings { % [topping ...] => -
    /Toppings exch def
    /preview self send
    /updateview self send
  } def

  /setstyle { % style => -
    /Style 1 index def
    /toppings exch send
    /settoppings self send
  } def

  /style { % - => style
    Style
  } def

  /pizzasize { % - => 0..3 (for 10", 14", 16", and 18")
    PizzaSize
  } def

  /setpizzasize { % 0..3 => -
    /PizzaSize exch def
    /preview Pizza send
    gsave
      Parent setcanvas
      /bbox PreviewWindow send /reshape PreviewWindow send
    grestore
    /updateview self send
  } def

  /fraction { % - => real
    Fraction
  } def

  /setfraction { % real => -
    /Fraction exch def
    gsave
      Parent setcanvas
      /bbox PreviewWindow send /reshape PreviewWindow send
    grestore
    /updateview self send
  } def

  /radius { % - => r
    {.5555 .7778 .8889 1} PizzaSize get
  } def

  /price { % - => price
    Price
  } def

  /ViewUpdateProc null def

  /updateview {
    ViewUpdateProc null ne {
      ViewUpdateProc waitprocess pop
    } if
    /ViewUpdateProc {
      /UpdateView self send
      /ViewUpdateProc unpromote
    } fork promote
  } def

  /UpdateView { % - => -
    PizzaSize {
      dup /value self send 0 get ne {
 	[exch] /setvalue self send
      } { pop } ifelse
    } pizzasizesettings send

    Fraction 1 eq { 0 } { 1 } ifelse {
      dup /value self send 0 get eq { pop } {
        [exch] /setvalue self send
      } ifelse
    } pizzafractionsettings send

    /id Style send {
      dup /value self send 0 get eq { pop } {
        [exch] /setvalue self send
      } ifelse
    } stylemenu send

    /name Style send {
      dup /value self send eq { pop } {
        /setvalue self send
      } ifelse
    } stylevalue send

    [ Toppings {
        { /foodtype self send /Meat eq {
	    /foodnumber self send
	  } if
        } exch send
      } forall
    ] /setvalue meatcheckboxes send

    [ Toppings {
        { /foodtype self send /Vegetable eq {
	  /foodnumber self send
	  } if
	} exch send
      } forall
    ] /setvalue vegetablecheckboxes send

    {(10") (14") (16") (18")} PizzaSize get
    Fraction 1 eq { (Whole Pie) } { (Half Pie) } ifelse
    /setfooter PreviewWindow send

    /updatecost self send
  } def

  /updatecost { % - => -
    10 dict begin
      /TheBest /defaultstyle ClassStyle send def
      /TheStyle null def
      /TheTopping null def
      /TheBestCost 99 def
      /TheBestExtras 0 def

      /styles ClassStyle send {
        /TheStyle exch def
	/TheToppings /toppings TheStyle send def
	true
	TheToppings {
	  Toppings exch arraycontains? not {
	    pop false exit
	  } if
	} forall
	{ /ExtraToppings [
	    Toppings {
	      TheToppings 1 index arraycontains? { pop } if
	    } forall
	  ] store

	  PizzaSize  ExtraToppings length  /extraprice TheStyle send
	  dup
	  % Bias towards predefined pizzas rather than economical pizzas
	  ExtraToppings length /extras TheStyle send sub 1 le {
	    MatchBias mul
	  } if

	  TheBestCost le {
	    /TheBestCost exch store
	    /TheBest TheStyle store
	    /TheBestExtras ExtraToppings length /extras TheBest send sub store
	  } { pop } ifelse
	} if
      } forall

      TheBestExtras dup 0 lt {
	neg dup 1 eq { () } { (s) } ifelse
	exch (Choose % more topping%!) sprintf
	0 exch
      } {
	dup 0 eq {
	  ()
	} {
	  dup dup 1 eq { () } { (s) } ifelse
	  exch (With % extra topping%.) sprintf
	} ifelse
      } ifelse
      /name TheBest send exch
      /setfooter ToppingWindow send
      pop

      TheBestCost
      Fraction mul
      100 mul floor 100 div
      /Price 1 index store
      dup 100 mul round cvi 100 mod
      exch floor cvi
      1 index 10 lt { (%.0%) } { (%.%) } ifelse

      sprintf dup /setvalue costfield send /setvalue totalfield send
      /name TheBest send
      dup /setvalue stylevalue send
      PizzaStyleNames exch arrayindex {
          [exch] /setvalue stylemenu send
      } if
      /Style TheBest store
    end
  } def

  /extratoppings { % - => [topping ...]
    ExtraToppings
  } def

  /prices { % - => [# # # #]
    { /prices self send
      /toppings self send length /extras self send add
    } Style send					% toppings [# # # #]
    10 dict begin
      Toppings length exch sub /i exch def
      i 0 gt {
	/FirstToppingPrices ClassStyle send { add } arrayop
	i 1 gt {
	  /AdditionalToppingPrices ClassStyle send {
	    i 1 sub mul add
	  } arrayop
	} if
      } if
    end
  } def

  /minsize { % - => w h
    16 16
  } def

  /preferredsize { % - => w h
    256 256
  } def

  /reshape { % x y w h => -
    2 copy /size self send 3 -1 roll eq 3 1 roll eq and {
      pop pop /move self send
    } {
      /reshape super send
      gsave
        self setcanvas
	clippath
	TempCanvas reshapecanvas
      grestore
    } ifelse
  } def

  /preview { % - => -
    /paint self send
    pause pause pause
  } def

  /reset {
    StopSpin StopPaint
  } def

  /StopPaint { % - => -
    PaintProc null ne {
      PaintProc killprocess
      /PaintProc unpromote
    } if
    [Sprinklers {pop} forall] {killprocess} forall
    Sprinklers cleanoutdict
  } def

  /PaintSetup {
    /size self send
    2 div exch 2 div exch
    2 copy translate
    min 3 sub
    /radius self send mul
    dup scale
  } def

  /PaintInit {
    /PaintSetup self send
    0 0 1.02 0 360 arc
    0 0 .895 0 360 arc
    CrustColor setcolor eofill
    0 0 .9 0 360 arc
    gsave SauceColor setcolor fill grestore
    /PaintClip self send
  } def

  /PaintClip {
    0 0 .9 0 360 arc
    clip newpath
%    1 /radius self send div dup scale
  } def

  /Paint { % - => -
    PaintLock {
      /reset self send
      /PaintProc {
	pause
	/PaintInit self send

	[1 0] SLEEP % Wait a second until things settle down ...

	/mapped? Parent send {
	  % Draw all the toppings at once! Weeee!
	  4 { Cheese /StartSprinkle self send } repeat
	  /toppings Pizza send {
	    /StartSprinkle self send
	  } forall

	  { 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
      PaintProc /ProcessName (Pizza Painter) put
    } monitor
  } def

  /StartSprinkle { % topping => -
    { {clear paint} exch send
      Sprinklers currentprocess undef
    } fork
    Sprinklers exch dup put pop
  } def

  /SpinPause 10 def
  /SpinAngle 7 def
  /SpinProcess null def

  /StartSpin { % - => -
    /StopSpin self send
    /SpinProcess {
      clear
      /SpinSetup self send
      { SpinPause { pause } repeat
	/Spin self send
      } loop
      SpinProcess currentprocess eq {
        /SpinProcess unpromote
      } if
    } fork promote
  } def

  /StopSpin { % - => -
    SpinProcess null ne {
      SpinProcess killprocess
      /SpinProcess unpromote
    } if
  } def

  % Clip out the crust.
  %
  /SpinSetup {
    self setcanvas
    matrix currentmatrix
    /size self send
    2 div exch 2 div exch
    2 copy translate
    min 3 sub
    /radius self send mul
    dup scale
    0 0 .9 0 360 arc
    clip newpath
    setmatrix
  } def

  /Spin {
    gsave
      TempCanvas setcanvas self imagecanvas
    grestore
    gsave
      /size self send
      2 div exch 2 div exch
      2 copy translate
      SpinAngle random add rotate
      neg exch neg exch translate
      TempCanvas imagecanvas
     grestore
  } def

  /Menuable? true def
  /Menu {stylemenu} def

  /Trackable? true def

  /TrackStart { % event => /Default true
    gsave
      /StopSpin self send
      /SpinSetup self send
      /size self send
      2 div exch 2 div exch
      translate
      dup begin YLocation XLocation end
      2 copy 0 eq exch 0 eq and { pop pop 0 } {
	atan
      } ifelse
      /Ang0 1 index def
      /Ang1 exch def
      /SpinAngle 0 def
    grestore
    /TrackMotion self send
    /Default true
  } def

  /TrackMotion { % event => -
    gsave
      /SpinSetup self send
      /size self send
      2 div exch 2 div exch
      2 copy translate
      3 -1 roll begin YLocation XLocation end
      2 copy 0 eq exch 0 eq and { pop pop 0 } {
	atan
      } ifelse
      /Ang1 exch def
      /SpinAngle Ang1 Ang0 sub def
      SpinAngle rotate
      neg exch neg exch translate
      self imagecanvas
      /Ang0 Ang1 def
    grestore
  } def

  /TrackStop { % event => -
    pop
    SpinAngle abs 1 ge {
      /StartSpin self send
    } if
  } def

  /Receptible? true def

  /HandleReception { % event selection => bool
    exch					% selection event
    /begintransfer 2 index send

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

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

  /RasterReception { % event canvas => bool
      exch pop
      gsave
        self setcanvas
	/SpinSetup self send
	clippath pathbbox points2rect 4 2 roll translate scale
	imagecanvas
      grestore
      true
  } def

classend def

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ClassTopping

/ClassTopping ClassObject [
  /FoodType /Name /Sprinkles /Init /Paint /ID /FoodNumber
] classbegin
  /TheToppings nullarray def
  /ToppingDict growabledict def
  /ToppingTypes growabledict def

  /findtopping {
    ToppingDict 1 index known {
      ToppingDict exch get
    } {
      pop null
    } ifelse
  } def

  /typetoppings { % foodtype => [topping ...]
    [ TheToppings {
        { /foodtype self send
          counttomark 1 add index eq { self } if
	} exch send
      } forall
    ] exch pop
  } def

  /toppings { % - => [topping ...]
    TheToppings
  } def

  /name { % - => string
    Name
  } def

  /foodtype { % - => name
    FoodType
  } def

  /id { % - => id
    ID
  } def

  /foodnumber { % - => n
    FoodNumber
  } def

  /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 {
      0  ToppingTypes FoodType 1 put
    } {
      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 { % - => -
    currentprocess /ProcessName
    Name (Pizza Topping Sprinkler: %) sprintf put
    gsave
      /Init load cvx exec
      /Paint load cvx
      Sprinkles Sprinkle
    grestore
  } def

  /Sprinkle { % proc shakes => -
    { gsave
	random 360 mul rotate
	random sqrt 0 translate
	random 360 mul rotate
	dup exec
	random .3 lt {
	    random 10 mul 1 add cvi { pause } repeat
	} if
      grestore
    } repeat
  } def

classend def

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ClassStyle

/ClassStyle ClassObject [
  /Name /Toppings /Prices /Extras /ID
] classbegin
  /TheStyles nullarray def
  /StyleDict growabledict def

  /Economical? false def

  /FirstToppingPrices [ 1.00 1.00 1.00 1.00 ] def
  /AdditionalToppingPrices [ 0.50 0.75 1.00 1.25 ] def

  /findstyle { % name => style|null
    StyleDict 1 index known {
      StyleDict exch get
    } {
      pop null
    } ifelse
  } def

  /defaultstyle { % - => style
    TheStyles 0 get
  } def

  /styles { % - => [style ...] 
    TheStyles
  } def

  /name { % - => string
    Name
  } def

  /setname { % name => -
    Name null ne {
      StyleDict Name undef
    } if
    /Name exch def
    StyleDict Name self put
    /value stylelist send
    PizzaStyleNames
    2 copy
    {setitemlist setvalue paint} stylemenu send
    {setitemlist setvalue validate locatechoice paint} stylelist send
    null null EditStyle
  } def

  /delete { % - => -
    StyleDict Name undef
    /TheStyles TheStyles id arraydelete store
    id 1 TheStyles length 1 sub {
      /setid TheStyles 2 index get send
    } for
    /value stylelist send 0 get
    /styles ClassStyle send length 1 sub min [exch]
    PizzaStyleNames
    2 copy
    {setitemlist setvalue paint} stylemenu send
    {setitemlist setvalue validate locatechoice paint} stylelist send
    null null EditStyle
  } def

  /toppings { % - => [topping ...]
    Toppings dup length array copy
  } def

  /settoppings { % [topping ...] => -
    /Toppings exch def
    SelectedStyleName
    /name self send eq {
      null null EditStyle
    } if
  } def

  /typetoppings { % foodtype => [topping ...]
    [ Toppings {
        { /foodtype self send
          counttomark 1 add index eq { self } if
	} exch send
      } forall
    ] exch pop
  } def

  /prices { % - => [# # # #]
    Prices
  } def

  /setprices { % [# # # #] => -
    /Prices exch def
    SelectedStyleName
    /name self send eq {
      /updatecost Pizza send
      /updateprices self send
    } if
  } def

  /updateprices {
    styleprice18field styleprice16field styleprice14field styleprice10field 
    /prices self send {
      dup 100 mul round cvi 100 mod
      exch floor cvi
      1 index 10 lt { (%.0%) } { (%.%) } ifelse
      sprintf /setvalue 3 -1 roll send
    } forall
  } def

  /extras { % - => number
    Extras
  } def

  /setextras { % number => -
    /Extras exch def
    SelectedStyleName
    /name self send eq {
      /updatecost Pizza send
    } if
  } def

  /extraprice { % size extras => price
    Prices 2 index get				% size extras price
    exch Extras sub 0 max exch			% size extras' price
    1 index 0 gt {
      FirstToppingPrices 3 index get add
      1 index 1 gt {
        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

  /id { % - => id
    ID
  } def

  /setid { % id => -
    /ID exch def
  } def

  /editstyle {
    [ID] /setvalue stylelist send
    null null EditStyle
  } def

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

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ClassProPanel

/ClassProPanel ClassPanel []
classbegin
  /minsize { % - => w h
    /minsize super send
    /minsize [ 3 index 3 index ] cvx promote
  } def

  /invalidate { % - => -
    /minsize unpromote
    /invalidate super send
  } def
classend def

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ClassPopupPizzaWindow

/ClassPopupPizzaWindow ClassPopupWindow []
classbegin
  /FooterGap 4 def

  /BBoxStart {
      true /inhibitfocus ClassFocus send
      /BBoxStart super send
  } def

  /BBoxStop {
      false /inhibitfocus ClassFocus send
      /BBoxStop super send
  } def

  /path { % x y w h => -
    /minsize self send xymax
    matrix currentmatrix 5 1 roll		% mat x y w h
    4 2 roll translate				% mat w h
    0 0 3 index 3 index rectpath
    WInset SInset
    4 2 roll
    WInset EInset add SInset NInset add xysub
    4 copy rectpath

    2 div exch 2 div exch
    2 copy WInset SInset xyadd translate
    min 3 sub dup neg scale
    { /radius self send 0 moveto
      0 0 /radius self send
      0 360 /fraction self send mul
      arc closepath
    } /Center /client self send pop send
    pop pop
%    0 0 translate % XXX: V3 bug "setmatrix" work-around
    setmatrix
  } def

  /reshape { % x y w h => -
    /invalidate self send
    gsave
      4 2 roll translate 0 0 4 2 roll path self
      eoreshapecanvas
    grestore
  } def

  /PaintBorder { % - => -
    currentlinewidth
    ForegroundColor setcolor BorderStroke 2 mul setlinewidth
    /bbox self send rectpath stroke
    setlinewidth
  } def

classend def

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Topping Definitions

/maketopping { % foodtype name sprinkles {init} {paint} => -
  /new ClassTopping send pop
} def

/findtopping { % name => topping|null
  /findtopping ClassTopping send
} def

% 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

/makestyle { % name toppings prices extras => -
  /new ClassStyle send pop
} def

/findstyle { % name => style|null
  /findstyle ClassStyle send
} def

(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 Componants

/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
{ /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 {
  /reset Pizza send
  /QuitFromUser super send
} /installmethod ToolWindow send

/ToppingPanel 
 /Calculated framebuffer /new ClassProPanel send
def

/minsize { /minsize super send 4 4 xyadd } /installmethod ToppingPanel send

/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
  /preview Pizza send
} /installmethod PreviewWindow send
/close {
  /close super send
  /preview Pizza send
} /installmethod PreviewWindow send

/Notice
  ToolWindow framebuffer /new ClassNotice send
def

/Paint { % Smoked Notice Hack
  gsave
    /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

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ToolPanel Componants

/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 -4 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 -4 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 -4 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 -4 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 -4 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
%  0 0 /preferredsize 3 index send exch pop 300 exch /reshape 5 index send
  [ /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 -4 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
%  /Centered /setjustification 2 index send
  userdict /settarget 2 index send
  [ /NorthWest { /NorthWest PARENT POSITION 10 -10 xyadd } ]
  /addclient EditPanel send

/stylelabel
  (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 /stylelabel POSITION 0 -5 xyadd } ]
  /addclient EditPanel send

/stylelist
  framebuffer /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
  framebuffer /new ClassScrollList send 2 copy def
  0 0 180 150 /reshape 5 index send
  /NonExclusive /setchoicemode 2 index send
  userdict /settarget 2 index send
  /EditTopping /setnotifier 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 -4 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
  /increment {
    /increment super send
    /executenotifier self send
  } /installmethod 3 index send
  /decrement {
    /decrement super send
    /executenotifier self send
  } /installmethod 3 index send
  [ /SouthWest { /SouthEast /styleextralabel POSITION 10 -4 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
  /PizzaSize 0 /setproperty 3 index send
  userdict /settarget 2 index send
  /SetStylePrice /setnotifier 2 index send
  [ /SouthWest { /SouthEast /styleprice10label POSITION 0 -4 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
  /PizzaSize 1 /setproperty 3 index send
  userdict /settarget 2 index send
  /SetStylePrice /setnotifier 2 index send
  [ /SouthWest { /SouthEast /styleprice14label POSITION 0 -4 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
  /PizzaSize 2 /setproperty 3 index send
  userdict /settarget 2 index send
  /SetStylePrice /setnotifier 2 index send
  [ /SouthWest { /SouthEast /styleprice16label POSITION 0 -4 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
  /PizzaSize 3 /setproperty 3 index send
  userdict /settarget 2 index send
  /SetStylePrice /setnotifier 2 index send
  [ /SouthWest { /SouthEast /styleprice18label POSITION 0 -4 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

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Notifiers

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

/ShowToppingWindow { % index winbuttons => -
  pop pop
  {pin totop open} ToppingWindow send
} def

/ShowEditWindow { % index winbuttons => -
  pop pop
  {pin totop open} EditWindow send
} def

/ShowPreviewWindow { % index winbuttons|orderbuttons => -
  pop pop
  {pin totop open} PreviewWindow send
} def

/SetDelivery { % [index bool] deliverymenu => -
  exch 0 get /item 3 -1 roll send 0 get
  dup /setvalue deliveryvalue send
  (Please Deliver) eq {
    /MaybeDeliver ShowNotice
  } if
} def

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

/SetPizzaSize { % [index bool] pizzasizesettings => -
  pop 0 get /setpizzasize Pizza send
} def

/SetPizzaFraction { % [index bool] pizzafractionsettings => -
  pop 0 get 0 eq { 1 } { .5 } ifelse
  /setfraction Pizza send
} def

/MenuSetStyle { % [index bool] stylemenu => -
  exch 0 get exch /item exch send 0 get
  /findstyle ClassStyle send
  dup null eq { pop } {
    /setstyle Pizza send
  } ifelse
} def

/SetCheckboxes { % [index bool] {meat,vegetable}checkboxes => -
  1 index 0 get		% [i b] cb i
  /item 3 -1 roll send	% [i b] item
  findtopping			% [i b] topping
  dup null eq { pop pop } {	% [i b] topping
    exch 1 get		% topping b
    { /addtopping } { /removetopping } ifelse
    Pizza send
  } ifelse
} def

/OrderPizza { % index {win,order}buttons => -
  pop pop
  { /value self send 0 get /item self send 0 get
  } pizzaparlormenu send
  { (Tony&Alba's) {
      /TAOrder ShowNotice
    }
    (Riscy's) (Sparcy's) {
      /SunOrder ShowNotice
    }
    (Demo Room) {
      /DemoOrder ShowNotice
    }
    /Default {
      /OtherOrder ShowNotice
    }
  } case
} def

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

/NewPizzaStyle { % index editstylemenu|stylenamefield => -
  /value stylenamefield send
  PizzaStyleNames 1 index arraycontains? {
    pop /StyleAlreadyDefined ShowNotice
    pop pop
  } {
    /toppings Pizza send
    /prices Pizza send
    0
    makestyle
    PizzaStyleNames
    dup length 1 sub [exch] exch
    2 copy {setitemlist setvalue paint} stylemenu send
    {setitemlist setvalue validate locatechoice paint} stylelist send
    EditStyle
  } ifelse
} def

/EditPizzaStyle { % index editstylemenu => -
  pop pop
  /YouAreEditing ShowNotice
} def

/RenamePizzaStyle { % index editstylemenu => -
  pop pop
  /value stylenamefield send
  PizzaStyleNames 1 index arraycontains? {
    SelectedStyleName eq
    { /RenameToSelf } { /StyleAlreadyDefined } ifelse
    ShowNotice
  } {
    SelectedStyle /setname exch send
  } ifelse
} def

/DeletePizzaStyle { % index editstylemenu => -
  pop pop
  /styles ClassStyle send length 1 eq {
    pop /DontDeleteTheLastStyle ShowNotice
  } {
    SelectedStyle dup null eq { pop } {
      /delete exch send
    } ifelse
  } ifelse
} def

/SavePizzaStyle { % index editstylemenu => -
  pop pop
  ConfigFile (w) { file } stopped {
    pop pop
    /NoSave ShowNotice
  } {
    { 20 dict begin
	/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

	{ namefield phonefield addressfield emailfield
	  instructionfield0 instructionfield1 instructionfield2
	  instructionfield3 instructionfield4 instructionfield5
	} {
	  dup load /value exch send	% name string
	  typedprint
	  (/setvalue % send\n) printf
	} forall

	{ pizzaparlormenu deliverymenu
	} {
	  dup load
	  { /value self send 0 get
	  } exch send
	  ([%]/setvalue % send\n) printf
	} forall

	/value pizzasizesettings send 0 get
	(%/setpizzasize Pizza send\n) printf

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

	{ /value self send 0 get /item self send 0 get
	} stylemenu send
	(/FavoriteStyle(%)def\n) printf

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

/RemoveSelected { % index edittoppingmenu => -
  pop pop
  10 dict begin
    /ss SelectedStyle def
    /currenttoppings /toppings ss send def
    /selectedtoppings
      { [ /value self send {
	    /item self send findtopping
	  } forall ]
      } styletoppingslist send
    def
    [ currenttoppings {
        selectedtoppings 1 index arraycontains? { pop } if
      } forall
    ] /settoppings ss send
  end
} def

/CopyCheckboxes { % index edittoppingmenu => -
  pop pop
  CheckedToppings /settoppings SelectedStyle send
} def

/UpdateToppings { % [index bool] {meat,vegetable}toppingmenu => -
  10 dict begin
    /menu exch def
    aload pop /bool exch def /i exch def
    SelectedStyle

    /toppings 1 index send
    i /item menu send 0 get findtopping
    bool {
      [exch] append
    } {
      2 copy arrayindex pop
      exch pop arraydelete
    } ifelse
    /settoppings 3 -1 roll send
  end
} def

/EditStyle { % [index] stylelist => -
  pop pop
  SelectedStyle
  [ /toppings 2 index send { /name exch send } forall ]
  {gt} quicksort
  /setitemlist styletoppingslist send  /paint styletoppingslist send
  /name 1 index send /setvalue stylenamefield send
  /extras 1 index send /setvalue styleextrafield send

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

/EditTopping { % [index] styletoppingslist => -
  pop pop
} def

/SetStyleExtraToppings { % number styleextrafield => -
  pop
  /setextras SelectedStyle send
} def

/SetStylePrice { % string styleprice{10,14,16,18}field => -
  { exch token } stopped { null true } {
    { exch pop
      dup type dup /integertype eq exch /realtype eq or
      { false } { pop true } ifelse
    }
    { null true } ifelse
  } ifelse
  { pop pop beep } {			% price field
    SelectedStyle			% field price style
    /PizzaSize /property		% field price style /PS /p
    5 -1 roll send			% price style i
    /prices 2 index send		% price style i [# # # #]
    dup 4 1 roll			% price [# # # #] style i [# # # #]
    exch 5 -1 roll put			% [# # # #] style
    /setprices exch send		%
  } ifelse
} def

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

/NoticeClose { % index noticebuttons => -
  /close Notice send
  pop pop
} def

/NoticeYesNo { % index noticebuttons => -
  /close Notice send
  pop 0 eq { SendOrder } if
} def

/SendOrder { % - => -
  ServerEnabled? {
    20 dict begin
      (/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

      { /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

      { (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

      { 10 14 16 18 }
      /value pizzasizesettings send 0 get get
      { (whole) (half of a) }
      /value pizzafractionsettings send 0 get get
      (One % % inch pie:\n) sprintf
      f exch writestring

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

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

      f (\n) writestring

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

/Guido null def
/YerTab
  1000 random 50000 mul floor 100 div add
def

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

/mgr /new ClassEventMgr send def
mgr /ProcessName (PizzaTool Manager) put

[ToolWindow ToppingWindow PreviewWindow EditWindow Notice] {
  mgr /activate 3 -1 roll send
} forall

[ToolWindow ToppingWindow PreviewWindow EditWindow] {
  /place exch send
} forall

ConfigFile LoadFile pop

FavoriteStyle /findstyle ClassStyle send
dup null eq {
  pop /defaultstyle ClassStyle send
} if
/editstyle exch send

/map ToolWindow send

newprocessgroup currentfile closefile
%EOF