Clojure Assignment 2: GUIs
Fall 2011, David Matuszek

Purposes of this assignment

Three versions

Java
package temperature;

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

public class CelsiusConverter extends JFrame {
    private static final long serialVersionUID = 1L;
    JTextField tempText = new JTextField();
    JLabel celsiusLabel = new JLabel("Celsius");
    JButton convertButton = new JButton("Convert");
    JLabel fahrenheitLabel = new JLabel("Fahrenheit");

    public static void main(String[] args) {
    new CelsiusConverter().run();
    }
    
    private void run() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLayout(new GridLayout(2, 2, 3, 3));
    add(tempText);
    add(celsiusLabel);
    add(convertButton);
    add(fahrenheitLabel);
    setSize(300, 80);
    setVisible(true);
    
    convertButton.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
        double c = Double.parseDouble(tempText.getText());
        fahrenheitLabel.setText((1.8 * c + 32) + " Fahrenheit");
        }    
    });
    }
}
36 lines, 796 characters (not counting whitespace), 48 parentheses, 2 brackets, 10 braces

Clojure
;http://en.wikibooks.org/wiki/Clojure_Programming/Examples/Temperature_Converter_GUI
(import '(javax.swing JFrame JLabel JTextField JButton)
        '(java.awt.event ActionListener)
        '(java.awt GridLayout))
 
(let [frame (new JFrame "Celsius Converter")
      temp-text (new JTextField)
      celsius-label (new JLabel "Celsius")
      convert-button (new JButton "Convert")
      fahrenheit-label (new JLabel "Fahrenheit")]
    (. convert-button
        (addActionListener
           (proxy [ActionListener] []
                (actionPerformed [evt]
                    (let [c (Double/parseDouble (. temp-text (getText)))]
                      (. fahrenheit-label
                         (setText (str (+ 32 (* 1.8 c)) " Fahrenheit"))))))))
    (doto frame 
                (.setDefaultCloseOperation (JFrame/EXIT_ON_CLOSE))
                (.setLayout (new GridLayout 2 2 3 3))
                (.add temp-text)
                (.add celsius-label)
                (.add convert-button)
                (.add fahrenheit-label)
                (.setSize 300 80)
                (.setVisible true)))
26 lines, 747 characters (not counting whitespace), 68 parentheses, 10 brackets, 0 braces

REBOL
REBOL[Title: "Celsius to Fahrenheit"]
view layout [ across
    celsius: field 100x24 text "Celsius"
    return
    btn "Convert" 100x24 [
        f: 1.8 * (to-decimal celsius/text) + 32
        fahrenheit/text: append to-string f " Fahrenheit"
        show fahrenheit
    ]
    fahrenheit: info "Fahrenheit" 120x24
]
11 lines, 234 characters (not counting whitespace), 2 parentheses, 6 brackets, 0 braces

Assignment

Use Clojure macros to create a DSL (Domain Specific Language) for GUIs, somewhat like REBOL/View.

Macros are harder to write than functions, so use functions where appropriate. Use macros as necessary; for example, you will probably need to use a macro when implementing an ActionListener, because that is code that should only be executed under certain conditions.

You should implement enough of the DSL to use it to write a working "Celsius to Fahrenheit Converter," which you will turn in with the DSL code. Your design of the DSL should be extendable to create much more complicated GUIs (using menus, radio buttons, etc.), but the assignment only requires enough to get the temperature converter working.

How similar should your DSL be to REBOL/View? I have a movie at home that is best described as "based on the title of a real book!!!" That close. The important thing is that it's briefer and easier than straight Clojure.

Teams

Work in a team of two to four people. Not less than two, not more than four. I'm not assigning the teams, that's up to you. Choose a name for your team! Send me email this week to tell me the name of your team, and who is on it.

Next Monday, one member of each team should give a very brief (< 5 minute) presentation to the class, describing your initial design. Show what the code is going to look like. Be prepared to use the projector. You have to have some kind of a design by Monday; after that, feel free to discard it and start over. If by any chance there is any time left over, use it to talk to other teams whose design you like.

You can have a small amount of class time (maybe 15 minutes?) next Wednesday to discuss the project with your teammates.

Due date

You should have a presentation ready by Monday, October 24.
Turn in the completed project via Blackboard by 6am Wednesday, October 31.