Graphical User Interfaces

There are three phases of constructing a Graphical User Interface (or GUI).
  1. Creating the components and setting their properties.
  2. Determining how the components should be arranged on the page
  3. Associating actions to the various components, i.e., specifying what should happen when a button is pressed, a choice or menu selected, or the enter key pushed in a textfield. The main types of actions are

We will consider each of these in turn:

Creating the components

Buttons

  (button "TEXT" (color 200   150   300) (HelveticaBold 32) (action (lambda(e) ...)))
You can also use one of a small set of predefined color names:
white black red green blue yellow pink orange magenta cyan lightGray darkGray
The color procedure is used to specify a color given the amount of red/green/blue light to be used. The font is specified by giving a font name (one of Helvetica, TimesRoman, Courier) and a font style (one of Bold, Italic, Plain) followed by a whole number specifying the point size. Note that the font name/style has to be one word, and the capitilization is important.

Labels

Labels are created in the same way as button, except that actions are not allowed in a label.

Choices

A choice is a component that allows you to select from among multiple alternatives:
(choice "first" "second" "third" ... "last" 
        (color 255 255 0) (TimesRomanItalic 12) (action (lambda(e) ... )))
The color and font specification are the same as above, and we will discuss actions later.

Textfield

A textfield is a component that a user can type into.
(textfield "initial text" 30 (color 200 200 255) (CourierPlain 18) (action (lambda(e) ... )))
The first two arguments to the textfield procedure have to be the initial text and the size of the textfield (in this case, 30 columns). The color, font, and action are the same as above.

Textarea

A textarea is a multi-line textfield that the user can type text into. The first two arguments are the numbers of rows and columns, respectively, to be displayed. You can also, optionally, add the initial text, color, and font. Actions are not allowed on textareas.
(textarea 10 50 "initial text" (color 255 255 0) (TimesRomanPlain 18))

Windows and Menus

Windows are specified by giving a title string, an optional menu, and an optional component or layout. When you create a window, you then have to "pack" it and "show" it to make it appear. Packing makes the window just the right size to fit all the components it contains. You can also "resize" the window, it you want it to be a particular size:
(define win (window "test" (button "Hello World" (HelveticaBold 60))))
(.pack win) (.show win)
;; or  (.resize win 300 600) (.show win)
Menus are specified using three procedures: menubar, menu, and menuitem. There can only be one menubar, which must contains one or more menus. Each menu can contain either menuitems or menus. Menuitems can have actions.
(define win 
  (window "test" yellow (HelveticaBold 18)
    (menubar
       (menu "File" 
         (menuitem "quit" (action (lambda(e) (.hide win)))))
       (menu "Fun"
         (menu "Knock Knock"
            (menu "who's there"
              (menu "Ida"
                (menu "Ida who?"
                  (menuitem "I dunno, do you?"))))
            (menu "Si??"
              (menu "Me llamo Aida"
                (menu "Aida quien"
                   (menuitem "Ai de mi!"))))))
       (menu "Help"
          (menuitem "about")
          (menuitem "release notes")))
    (button "Hello World" (HelveticaBold 60))))
(.pack win) (.show win)


Layout

JLIB provides several alternatives for arranging a collection C1, ... Cn of components (or groups of components):

(row C1 C2 ... Cn)  -- arrange the horizontally
(col C1 C2 ... Cn)  -- arrange them vertically
(table R C C1 .... Cn) -- arrange in R rows and C cols
(grid  R C C1 .... Cn) -- arrange in R rows and C cols, 
                          with all cells the same size
(border
  (north C1)
  (south C2)
  (east  C3)
  (west  C4)
  (center C5))
In addition, you can add font or colors to any of the layouts, and for row and column you can also specify what should happen when the row/col is expanded:
  Stretching parameters for rows/cols:
    'none
    'horizontal
    'vertical
    'both

  Placement parameters for rows/cols:
    'north 'south 'east 'west 'center
    'northeast 'northwest ....


Actions

There are several different types of actions which we discuss below:

Reading and Writing on GUIs

Actions always have the form
  (action (lambda(e) ......))
The two most important actions we will use in this class are the following:
  (readexpr COMP)  -- this reads the symbol or number on the component
  (writeexpr COMP VAL) -- this writes the value on the component
For example, to read a restaurant bill on (t "a") and write the tip on (t "b") we would use the following:
   (writeexpr (t "b") (* 0.15 (readexpr (t "a"))))

Operating on windows

  (.show win)  -- make the window visible
  (.hide win)  -- make the window temporarily invisible
  (.resize win width height) -- change the size of the window
  (.pack win)  -- make the window just the right size to hold everything in it

Arithmetic Operations

Scheme provides access to all the arithmetic operators, but as with all scheme functions, the operators have to appear first within a parenthesized expression, e.g.
  (* 365 24 60 60)
  (/ 100 7.0)
  (Math.sqrt (+ (* 3 3) (* 4 4)))
  (Math.sin (* 2 3.1415926))
  (Math.pow 2 10)                   ;; raise 2 to the 10th power
  (Math.round 2.6)                  ;; round to the nearest integer
  (Math.random)                     ;; return a random decimal between 0 and 1
  (Math.round (* 365 (Math.random))) ;; return a random number between 0 and 365

Comparison Operations

Comparison operators are used in if statements
  (< a b)            ;; returns true if a<b, otherwise returns false
  (= a b)            ;; returns true if a=b
  (<= a b)           ;; returns true if a is less than or equal to b
  (or A B C D)       ;; returns true if any one of A,B,C,D is true
  (and A B C D)      ;; returns true if all of A,B,C,D are true

Conditional Statements

  (if TEST THEN ELSE)
This statement first evaluates the TEST.
** If the test is true, then it evaluates the THEN expression.
** If the test is false, it evaluates the ELSE expression.
Another useful conditional expression is the "case"
  (case VAL
    (("a") DO-something)
    (("b") DO-somethingelse)
    (("c") DO-yetanotherthing)
    ...
    (else DO-somedefaultthing))
The values "a", "b", etc. can be either quoted string as shown, or numbers.

Finally, the last conditional expression is the "cond" operator which is useful, when you want to have many tests:

   (cond
      (Test1 action1)
      (Test2 action2)
       ...
      (else default-action)
    )

giving names to values

There are several ways of giving names to values in Scheme The define statement is the simplest
  (define NAME VALUE)       ,e.g. (define pi 3.1415926) 
Another useful method is the "let" statement
  (let (
     (name1 value1)
     (name2 value2)
     ...
     (namex valuex)
       )
     action1
     action2
     ...
     actionz
   )