/*
 *  =======================================================================
 *  DemoCompositeShape.java : This applet displays two overlapping shapes :
 *  a general path diamond shape and an ellipse. At the top of the applet
 *  is a control panel where you can select use a radio button to select a
 *  specific constructive area geometry (CAG) operation.
 * 
 *  Adapted from : Pantham S., Pure JFC Swing, 1999.
 *  Modified by : Mark Austin                                   March, 2001
 *  =======================================================================
 */

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

public class DemoCompositeShape extends JApplet {
    DemoCompositeShapeCanvas canvas;
    JRadioButton addButton, subtractButton, intersectButton,
                 exclusiveORButton, resetButton;

    public void init() {

        // 1. Get the content pane

        Container container = getContentPane();

        // 2. Create a display panel with titled border

        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout(2, 2));
        TitledBorder border = new TitledBorder(
            "Select an Operation to Study Its Effect");
        panel.setBorder(border);

        // 3. Create radio buttons

        resetButton = new JRadioButton("Reset", true);

        addButton = new JRadioButton("Add");
        subtractButton = new JRadioButton("Subtract");
        intersectButton = new JRadioButton("Intersect");
        exclusiveORButton = new JRadioButton("ExclusiveOR");

        // Group the radio button for mutual exclusion

        ButtonGroup group = new ButtonGroup();
        group.add(resetButton);
        group.add(addButton); group.add(subtractButton);
        group.add(intersectButton); group.add(exclusiveORButton);
        group.add(resetButton);

        // Register action listeners to the radio buttons

        resetButton.addActionListener(new ActionEventHandler());
        addButton.addActionListener(new ActionEventHandler());
        subtractButton.addActionListener(new ActionEventHandler());
        intersectButton.addActionListener(new ActionEventHandler());
        exclusiveORButton.addActionListener(new ActionEventHandler());

        // Add the CAG operation buttons to the control panel

        panel.add(addButton);
        panel.add(subtractButton);
        panel.add(intersectButton);
        panel.add(exclusiveORButton);

        // 4. Add the panel to the applet and reset button separately
        // to the applet.

        container.add(panel, BorderLayout.NORTH);
        container.add(resetButton, BorderLayout.SOUTH);

        // 5. Add the drawing canvas to the applet

        canvas = new DemoCompositeShapeCanvas();
        container.add(canvas);
    }

    // 6. Definition of the 'DemoCompositeShapeCanvas' class

    class DemoCompositeShapeCanvas extends Canvas {
        GeneralPath gp;
        Ellipse2D ellipse;
        Area area1, area2;
        boolean drawFlag = true;
        boolean fillFlag = false;

        // 7. Constructor

        public DemoCompositeShapeCanvas() {

            setBackground(Color.white);
        
            int w = getWidth(); int h = getHeight();

            // Create area objects from the general path
            // and ellipse objects

            gp = new GeneralPath();
            gp.moveTo(w/8, h/2);
            gp.lineTo(w/2, h/4); gp.lineTo(7*w/8, h/2);
            gp.lineTo(w/2, 3*h/4);
            gp.closePath();
            area1 = new Area(gp);   // General path area object

            ellipse = new Ellipse2D.Double(w/4, h/4, w/2, h/2);

            area2 = new Area(ellipse); // Ellipse area object
        }

        // 8. The Overriding paint method

        public void paint(Graphics g) {

            // Create the graphics context object

            Graphics2D g2D = (Graphics2D) g;

            // Assign a slightly wider stroke

            g2D.setStroke(new BasicStroke(2.0f));

            // This is executed when the paint() method is called
            // initally, or when the reset button is selected.

            if (drawFlag) {
                g2D.draw(area1);
                g2D.draw(area2);
            }

            // The manipulated area object is redrawn in fill style.

            if (fillFlag) 
                g2D.fill(area1);
        }
    }

    // 9. Event handler for events from radio buttons

    class ActionEventHandler implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            JRadioButton temp = (JRadioButton) e.getSource();

            // For the add button

            if (temp.equals(addButton)) {
                canvas.area1 = new Area(canvas.gp);
                canvas.area1.add(canvas.area2);
                canvas.drawFlag = false;
                canvas.fillFlag = true;
                canvas.repaint();
            }
            // For the subtract button

            else if (temp.equals(subtractButton)) {
                canvas.area1 = new Area(canvas.gp);
                canvas.area1.subtract(canvas.area2);
                canvas.drawFlag = false;
                canvas.fillFlag = true;
                canvas.repaint();
            }
            // For the intersect button

            else if (temp.equals(intersectButton)) {
                canvas.area1 = new Area(canvas.gp);
                canvas.area1.intersect(canvas.area2);
                canvas.drawFlag = false;
                canvas.fillFlag = true;
                canvas.repaint();
            }

            // For the exclusiveOR button

            else if (temp.equals(exclusiveORButton)) {
                canvas.area1 = new Area(canvas.gp);
                canvas.area1.exclusiveOr(canvas.area2);
                canvas.drawFlag = false;
                canvas.fillFlag = true;
                canvas.repaint();
            }
            // For the Reset button

            else if (temp.equals(resetButton)) {
                if (canvas.drawFlag == false) {
                    canvas.area1 = new Area(canvas.gp);
                    canvas.drawFlag = true;
                    canvas.fillFlag = false;
                    canvas.repaint();
                }
            }
        }
    }
}
