import java.awt.*;
import java.awt.event.*;
import java.awt.event.ActionListener;
import java.awt.geom.*;

import javax.swing.*;

/**
 * @author Remi Forax
 *
 */
public class AreaExample extends JComponent {

  static abstract class CAGOp {
    public CAGOp(String name) {
      this.name=name;
    }
    public abstract void apply(Area area,Area anotherArea);
    public String toString() {
      return name;
    }
    private final String name;
  }

  protected void paintComponent(Graphics graphics) {
    super.paintComponent(graphics);

    Graphics2D g= (Graphics2D)graphics;

    g.clearRect(0, 0, getWidth(), getHeight());

    g.setRenderingHint(
      RenderingHints.KEY_ANTIALIASING,
      RenderingHints.VALUE_ANTIALIAS_ON);
    
    Area area=(Area)first.clone();
    op.apply(area, second);
    
    g.setColor(Color.ORANGE);
    g.fill(area);
    
    g.setColor(Color.BLACK);
    g.setStroke(stroke);
    g.draw(area);
  }
  
  public void setOp(CAGOp op) {
    this.op=op;
    paintImmediately(0,0, getWidth(), getHeight());
  }
  
  private CAGOp op;
  
  private static final BasicStroke stroke=new BasicStroke(7.5f);
  private static final Area first=new Area(new Ellipse2D.Float(50,50,100,100));
  private static final Area second=new Area(new Rectangle(100,100,100,100));

  public static void main(String[] args) {

    JFrame frame= new JFrame("AreaExample");
    final AreaExample component= new AreaExample();
    
    CAGOp[] ops=new CAGOp[] {
      new CAGOp("add") {
        public void apply(Area area, Area anotherArea) {
          area.add(anotherArea);
        }
      },
      new CAGOp("exclusiveOr") {
        public void apply(Area area, Area anotherArea) {
          area.exclusiveOr(anotherArea);
        }
      },
      new CAGOp("intersect") {
        public void apply(Area area, Area anotherArea) {
          area.intersect(anotherArea);
        }
      },
      new CAGOp("subtract") {
        public void apply(Area area, Area anotherArea) {
          area.subtract(anotherArea);
        }
      }
    };
    component.setOp(ops[0]);
    
    final JComboBox comboBox=new JComboBox(ops);
    comboBox.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        component.setOp((CAGOp)comboBox.getSelectedItem());
      }
    });
    
    frame.getContentPane().add(comboBox,BorderLayout.NORTH);
    frame.getContentPane().add(component);
    frame.setSize(400,300);
    frame.show();
  }
}
