Swinger06.java

package com.bozoid.cis370.hw06;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*; // for Border
import java.text.*; // for NumberFormat
import java.io.File;


/**
CISC370-011 homework #6 (partial implementation)

Two requirements are missing in this version:

    A text field with a document filter.

    A text field with a custom formatter.

@author Walt Leipold
*/
public class Swinger06
{
    public static void main(String argv[])
    {
        Frame06 f = new Frame06();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(500,600);
        f.show();
    }
}


class Frame06 extends JFrame
{
    public Frame06()
    {
        int i;
        Container cp = getContentPane();
        setTitle("Design-a-clown");

        // Add a scrolling text area at the bottom of the frame.
        log = new JTextArea(16,40);
        JScrollPane scrollPane = new JScrollPane(log);
        cp.add(scrollPane,BorderLayout.SOUTH);

        // Create the menu bar.
        JMenuBar mbar = new JMenuBar();
        setJMenuBar(mbar);

        // Create the required 'File' menu.
        JMenu fileMenu = new JMenu("File");
        JMenuItem exitItem = new JMenuItem("Exit");
        exitItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e)
                {  System.exit(0);  }
            });
        fileMenu.add(exitItem);
        mbar.add(fileMenu);

        // Create a 'Height' menu for the radio button menu items.
        JMenu heightMenu = new JMenu("Height");
        mbar.add(heightMenu);
        heightGroup = new ButtonGroup();
        heightItems = new JRadioButtonMenuItem[heightStrings.length];
        for (i=0; i<heightStrings.length; i++) {
            Action act = 
                new HeightAction(heightStrings[i]);
            heightItems[i] = new JRadioButtonMenuItem(act);
            heightMenu.add(heightItems[i]);
            heightGroup.add(heightItems[i]);
            if (i == 0)
                heightItems[i].setSelected(true);
            }

        // Create a 'Routines' menu to select comedy routines.
        JMenu routinesMenu = new JMenu("Routines");
        mbar.add(routinesMenu);
        routineItems = new JCheckBoxMenuItem[routines.length];
        for (i=0; i<routines.length; i++) {
            routineItems[i] = 
                new JCheckBoxMenuItem(routines[i]);
            routinesMenu.add(routineItems[i]);
            RoutineAction ract = 
                new RoutineAction(routines[i]);
            routineItems[i].addActionListener(ract);
            }

        // Add a pane for the parameter controls.
        Box paramPane = Box.createVerticalBox();
        cp.add(paramPane,BorderLayout.CENTER);
        //paramPane.setLayout(new FlowLayout());

        // Add a radio button group to select the clown's name.
        JPanel namePane = new JPanel();
        Border b1 = BorderFactory.createEtchedBorder();
        Border b2 = BorderFactory.createTitledBorder(b1,"Name");
        namePane.setBorder(b2);
        nameGroup = new ButtonGroup();
        nameButtons = new JRadioButton[clownNames.length];
        for (i=0; i<clownNames.length; i++) {
            nameButtons[i] =
                new JRadioButton(clownNames[i],i==0);
            namePane.add(nameButtons[i]);
            nameGroup.add(nameButtons[i]);
            nameButtons[i].addActionListener(
                new NameAction(clownNames[i]));
            }

        // Add some check boxes.
        JPanel featurePane = new JPanel();
        Border b3 = BorderFactory.createEtchedBorder();
        Border b4 = BorderFactory.createTitledBorder(b3,"Features");
        featurePane.setBorder(b4);
        featureBoxes = new JCheckBox[featureNames.length];
        for (i=0; i<featureNames.length; i++) {
            featureBoxes[i] = new JCheckBox(featureNames[i]);
            featureBoxes[i].addActionListener(
                new FeatureAction(featureNames[i]));
            featurePane.add(featureBoxes[i]);
            }

        // Add a combo box to pick the circus.
        JPanel circusPane = new JPanel();
        JLabel circusLabel = new JLabel("Circus:");
        circusBox = new JComboBox();
        Border b5 = BorderFactory.createEtchedBorder();
        circusPane.setBorder(b5);
        for (i=0; i<circusNames.length; i++) {
            circusBox.addItem(circusNames[i]);
            }
        circusBox.addActionListener(new CircusAction());
        circusPane.add(circusLabel);
        circusPane.add(circusBox);

        // Add a couple of buttons.
        JPanel buttonPane = new JPanel();
        JButton bu1 = new JButton("Make clown");
        buttonPane.add(bu1);
        bu1.addActionListener(new AbstractAction() {
            public void actionPerformed(ActionEvent e)
                { logMsg(describeClown()); }
            });
        JButton bu2 = new JButton("Restore defaults");
        buttonPane.add(bu2);
        bu2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e)
                {  resetDefaults();  }
            });
        JButton bu3 = new JButton("Read file...");
        buttonPane.add(bu3);
        bu3.addActionListener(new FileAction(this));

        paramPane.add(namePane);
        paramPane.add(featurePane);
        paramPane.add(circusPane);
        paramPane.add(buttonPane);
    }

    private void resetDefaults()
    {
        for (int i=0; i<featureBoxes.length; i++)
            featureBoxes[i].setSelected(false);
        for (int i=0; i<routineItems.length; i++)
            routineItems[i].setSelected(false);
        nameButtons[0].setSelected(true);
        heightItems[0].setSelected(true);
    }

    private String describeClown()
    {
        String indent = "    ";

        // Note: Uses *VERY* inefficient string concatenation!
        String s1 = "Name: " + curName;
        String s2 = "Height: " + curHeight;
        String s3 = "Circus: " + 
            (String)(circusBox.getSelectedItem());

        String s4 = "Features: ";
        String s5 = "";
        for (int i=0; i<featureBoxes.length; i++) {
            if (featureBoxes[i].isSelected())
                s5 = s5 + "\n" + indent + indent + featureNames[i];
            }
        if (s5.equals(""))
            s5 = "\n" + indent + indent + "<none>";

        String s6 = "Routines:";
        String s7 = "";
        for (int i=0; i<routineItems.length; i++) {
            if (routineItems[i].isSelected())
                s7 = s7 + "\n" + indent + indent + routines[i];
            }
        if (s7.equals(""))
            s7 = "\n" + indent + indent + "<none>";

        String s8 = "Configuration file: <none>";
        if (configFile != null)
            s8 = "Configuration file: " + configFile;

        return "\n" +
            "Clown design:\n" +
            indent + s1 + "\n" +
            indent + s2 + "\n" +
            indent + s3 + "\n" +
            indent + s4 + s5 + "\n" +
            indent + s6 + s7 + "\n" +
            indent + s8;
    }

    private void logMsg(String msg)
    {
        log.append(msg + "\n");
    }

    private String openFile(JFrame frame)
    {
        String s = null;

        JFileChooser chooser = new JFileChooser();
        chooser.setCurrentDirectory(new File("."));
        chooser.setFileFilter(new ClownFilter());
        chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        if (chooser.showOpenDialog(frame) ==
                JFileChooser.APPROVE_OPTION) {
            s = chooser.getSelectedFile().toString();
            }
        return s;
    }

    class HeightAction extends AbstractAction
    {
        public HeightAction(String height)
        {
            super(height);
            this.height = height;
        }
        public void actionPerformed(ActionEvent e)
        {
            curHeight = height;
            logMsg("Chose height " + height + ".");
        }
        private String height;
    }

    class NameAction extends AbstractAction
    {
        public NameAction(String name)
        {
            super(name);
            this.name = name;
        }
        public void actionPerformed(ActionEvent e)
        {
            curName = name;
            logMsg("Chose name '" + name + "'.");
        }
        private String name;
    }

    class RoutineAction extends AbstractAction
    {
        public RoutineAction(String routine)
        {
            super(routine);
            this.routine = routine;
        }
        public void actionPerformed(ActionEvent e)
        {
            JCheckBoxMenuItem mi = (JCheckBoxMenuItem)(e.getSource());
            if (mi.isSelected())
                logMsg("Selected routine '" + routine + "'.");
            else
                logMsg("Unselected routine '" + routine + "'.");
        }
        private String routine;
    }

    class FeatureAction extends AbstractAction
    {
        public FeatureAction(String feature)
        {
            super(feature);
            this.feature = feature;
        }
        public void actionPerformed(ActionEvent e)
        {
            JCheckBox cb = (JCheckBox)(e.getSource());
            if (cb.isSelected())
                logMsg("Selected feature '" + feature + "'.");
            else
                logMsg("Unselected feature '" + feature + "'.");
        }
        private String feature;
    }

    class CircusAction extends AbstractAction
    {
        public void actionPerformed(ActionEvent e)
        {
            JComboBox cb = (JComboBox)(e.getSource());
            logMsg("Selected circus '" + cb.getSelectedItem() + "'.");
        }
    }

    class FileAction extends AbstractAction
    {
        public FileAction(JFrame frame)
        {
            super("fileOpenCommand");
            this.frame = frame;
        }
        public void actionPerformed(ActionEvent e)
        {
            String s = openFile(frame);
            if (s != null) {
                configFile = s;
                logMsg("File selected: '" + s + "'.");
                }
        }
        private JFrame frame;
    }

    // Clown heights (for the 'Height' menu).
    String heightStrings[] = { "5'", "5' 6\"", "6'", "6' 6\"" };
    double heightValues[] = { 5.0, 5.5, 6.0, 6.5 };
    // Clown attributes (for the checkboxes).
    String featureNames[] = {
        "Large feet", "Red ball nose", "Orange hair" };
    JCheckBox featureBoxes[];
    // Clown names (for the radio buttons).
    String clownNames[] = {
        "Bozo", "Happy", "Homey", "Walt" };
    // Humor routines this clown knows.
    String routines[] = {
        "Who's on first?", "Fire drill", "Pie in face" };
    // The combo box for choosing the circus name.
    String[] circusNames = {
        "Barnum 'n' Bailey", "Ringling Bros.", "Monty Python's" };
    JComboBox circusBox;
    // A text area in which we 'create' the clown.
    JTextArea log = null;

    JRadioButton[] nameButtons;
    JCheckBoxMenuItem[] routineItems;
    JRadioButtonMenuItem[] heightItems;

    String curHeight = heightStrings[0];
    String curName = clownNames[0];
    ButtonGroup nameGroup,heightGroup;
    String configFile = "";
}


/**
Accept only an HTML, Java, or text file.
*/
class ClownFilter extends javax.swing.filechooser.FileFilter
{
    static String[] extensions = {
        ".txt",
        ".java",
        ".html",
        };
    public boolean accept(File f)
    {
        if (f.isDirectory())
            return true;
        for (int i=0; i<extensions.length; i++)
            if (f.getName().toLowerCase().endsWith(extensions[i]))
                return true;
        return false;
    }

    public String getDescription()
    {
        return "Clown description file";
    }
}


/*

=-=-=-=-=-= 
Items included:

Two check boxes. --> Three check boxes, to select the clown's
features (large feet, red nose, and orange hair).

One group of four radio buttons with a labelled border. --> Allow
the user to select the name for the clown.

Three checkbox menu items. --> Allow user to select clown's
comedy routines.

Two buttons. --> Allow the user to create a clown (as text in the
text area), or to reset the defaults for the clown controls.

One combo box. --> Allow the user to choose a circus.

A group of four radio button menu items. --> Allow the user to
select a height for his clown.

A text area with scrollbars. --> The clown is 'constructed' in
this text area.

As many JLabels as are necessary to make the function of the
other components clear.

One button must display a "Save as..." dialog which allows the user
to select only files with the extensions ".java", ".html", and ".txt".

=-=-=-=-=-=
Items missing:

A text field with a document filter.

A text field with a custom formatter.

*/