/*******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.opengl.examples;


import org.eclipse.swt.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.opengl.*;
import org.eclipse.swt.widgets.*;

class AreaTab extends OpenGLTab {
	abstract class Shape {
		abstract void draw();
	}
	class State {
		private String name;
		private int index;
		/**
		 * Constructor.
		 * 
		 * @param name the display name of this state
		 * @param index the display list index corresponding to this state
		 */
		State (String name, int index) {
			super();
			this.index = index;
			this.name = name;
		}
		void display() {
			GL.glCallList(index);
		}
		void dispose() {
			GL.glDeleteLists(index, 1);
		}
		String getName() {
			return name;
		}
	}

	private State[] states;
	private State currentState;
	private float xPos = 0.0f, yPos = 0.0f, zPos = -30.0f;
	private float xRot = 90.0f, yRot = 0.0f, zRot = 0.0f;
	private int quadratic, disk;

	/**
	 * @see OpenGLTab#createControls(Composite)
	 */
	void createControls(Composite composite) {
		Group movementGroup = new Group(composite, SWT.NONE);
		movementGroup.setText("Translation");
		movementGroup.setLayout(new GridLayout(2, false));

		new Label(movementGroup, SWT.NONE).setText("X:");
		final Slider xMove = new Slider(movementGroup, SWT.NONE);
		xMove.setIncrement(1);
		xMove.setMaximum(22);
		xMove.setMinimum(0);
		xMove.setThumb(2);
		xMove.setPageIncrement(2);
		xMove.setSelection(10);
		xMove.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event e) {
				xPos = xMove.getSelection() - 10;
			}
		});

		new Label(movementGroup, SWT.NONE).setText("Y:");
		final Slider yMove = new Slider(movementGroup, SWT.NONE);
		yMove.setIncrement(1);
		yMove.setMaximum(22);
		yMove.setMinimum(0);
		yMove.setThumb(2);
		yMove.setPageIncrement(2);
		yMove.setSelection(10);
		yMove.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event e) {
				yPos = yMove.getSelection() - 10;
			}
		});

		new Label(movementGroup, SWT.NONE).setText("Z:");
		final Slider zMove = new Slider(movementGroup, SWT.NONE);
		zMove.setIncrement(1);
		zMove.setMaximum(22);
		zMove.setMinimum(0);
		zMove.setThumb(2);
		zMove.setPageIncrement(2);
		zMove.setSelection(10);
		zMove.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event e) {
				zPos = zMove.getSelection() - 40;
			}
		});

		Group rotationGroup = new Group(composite, SWT.NONE);
		rotationGroup.setText("Rotation");
		rotationGroup.setLayout(new GridLayout(2, false));

		new Label(rotationGroup, SWT.NONE).setText("X:");
		final Slider xRotation = new Slider(rotationGroup, SWT.NONE);
		xRotation.setIncrement(10);
		xRotation.setMaximum(362);
		xRotation.setMinimum(0);
		xRotation.setThumb(2);
		xRotation.setPageIncrement(20);
		xRotation.setSelection(90);
		xRotation.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event e) {
				xRot = xRotation.getSelection();
			}
		});

		new Label(rotationGroup, SWT.NONE).setText("Y:");
		final Slider yRotation = new Slider(rotationGroup, SWT.NONE);
		yRotation.setIncrement(10);
		yRotation.setMaximum(362);
		yRotation.setMinimum(0);
		yRotation.setThumb(2);
		yRotation.setPageIncrement(20);
		yRotation.setSelection(0);
		yRotation.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event e) {
				yRot = yRotation.getSelection();
			}
		});

		new Label(rotationGroup, SWT.NONE).setText("Z:");
		final Slider zRotation = new Slider(rotationGroup, SWT.NONE);
		zRotation.setIncrement(10);
		zRotation.setMaximum(362);
		zRotation.setMinimum(0);
		zRotation.setThumb(2);
		zRotation.setPageIncrement(20);
		zRotation.setSelection(0);
		zRotation.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event e) {
				zRot = zRotation.getSelection();
			}
		});

		Composite optionsGroup = new Composite(composite, SWT.NONE);
		GridLayout layout = new GridLayout(2, false);
		layout.marginWidth = 0;
		optionsGroup.setLayout(layout);

		new Label(optionsGroup, SWT.NONE).setText("Shape:");

		final Combo statesCombo = new Combo(optionsGroup, SWT.READ_ONLY);
		for (int i = 0; i < states.length; i++) {
			statesCombo.add(states[i].getName());
		}
		statesCombo.select(0);
		statesCombo.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event e) {
				currentState = states[statesCombo.getSelectionIndex()];
			}
		});

		final Button lightsButton = new Button(composite, SWT.CHECK);
		lightsButton.setText("Lights");
		lightsButton.setSelection(true);
		lightsButton.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event e) {
				if (lightsButton.getSelection()) {
					GL.glEnable(GL.GL_LIGHTING);
				} else {
					GL.glDisable(GL.GL_LIGHTING);
				}
			}
		});
	}

	/**
	 * @see OpenGLTab#dispose()
	 */
	void dispose() {
		super.dispose();
		GLU.gluDeleteQuadric(quadratic);
		GLU.gluDeleteQuadric(disk);
		if (states != null) {
			for (int i = 0; i < states.length; i++) {
				states [i].dispose();
			}
		}
	}

	/**
	 * Draws the logical AND of two shapes.
	 *
	 * @param a shape A
	 * @param b shape B
	 */
	void drawAandB(Shape a, Shape b) {
		// draw parts of B that are inside A
		drawAinsideB(a, b, GL.GL_BACK, GL.GL_NOTEQUAL);
		// we do not want the following to show up
		GL.glColorMask(false, false, false, false);
		// turn on depth testing
		GL.glEnable(GL.GL_DEPTH_TEST);
		GL.glDepthFunc(GL.GL_ALWAYS);
		// render the front face of B
		b.draw();
		// reset the depth function
		GL.glDepthFunc(GL.GL_LESS);
		// draw parts of A that are inside B
		drawAinsideB(b, a, GL.GL_BACK, GL.GL_NOTEQUAL);
	}

	/**
	 * Draws the contents of one shape that appear within another.
	 *
	 * @param a the shape to draw
	 * @param b the constraining shape
	 * @param face
	 * @param test
	 */
	void drawAinsideB(Shape a, Shape b, int face, int test) {
		// turn off the color buffer
		GL.glColorMask(false, false, false, false);
		// clear the stencil buffer
		GL.glClearStencil(0);
		GL.glEnable(GL.GL_DEPTH_TEST);
		// set to proper Culling
		GL.glCullFace(face);
		// render shape A
		a.draw();
		// set depth mask
		GL.glDepthMask(false);
		// enable stencil test
		GL.glEnable(GL.GL_STENCIL_TEST);
		GL.glStencilFunc(GL.GL_ALWAYS, 0, 0);
		// set the stencil buffer to increment if the depth test passes
		GL.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_INCR);
		// turn on back face culling
		GL.glCullFace(GL.GL_BACK);
		// render B
		b.draw();
		// set the stencil buffer to decrement if the depth test passes
		GL.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_DECR);
		// cull the front face
		GL.glCullFace(GL.GL_FRONT);
		// render B again
		b.draw();
		// set depth mask
		GL.glDepthMask(true);
		GL.glColorMask(true, true, true, true);
		// set the stencil buffer
		GL.glStencilFunc(test, 0, 1);
		// turn off depth testing
		GL.glDisable(GL.GL_DEPTH_TEST);
		// set to proper culling
		GL.glCullFace(face);
		// render A
		a.draw();
		// disable stencil test
		GL.glDisable(GL.GL_STENCIL_TEST);
	}

	/**
	 * Draws the logical OR of two shapes.
	 *
	 * @param a shape A
	 * @param b shape B
	 */
	void drawAorB(Shape a, Shape b) {
		GL.glEnable(GL.GL_DEPTH_TEST);
		a.draw();
		b.draw();
		GL.glDisable(GL.GL_DEPTH_TEST);
	}

	/**
	 * Draws one shape subtracted from another.
	 *
	 * @param a the base shape
	 * @param b the shape to subtract
	 */
	void drawAsubB(Shape a, Shape b) {
		// draw back parts of B inside A
		drawAinsideB(b, a, GL.GL_FRONT, GL.GL_NOTEQUAL);
		// we do not want the following to show up
		GL.glColorMask(false, false, false, false);
		GL.glEnable(GL.GL_DEPTH_TEST);
		// change the depth test to GL_ALWAYS
		GL.glDepthFunc(GL.GL_ALWAYS);
		// render the front face of B
		a.draw();
		// reset the depth function
		GL.glDepthFunc(GL.GL_LESS);
		// draw front parts of A outside B
		drawAinsideB(a, b, GL.GL_BACK, GL.GL_EQUAL);
	}

	/**
	 * Draws the specifed shape.
	 * 
	 * @param shape the shape to draw
	 */
	void drawShape(Shape shape) {
		GL.glEnable(GL.GL_DEPTH_TEST);
		shape.draw();
		GL.glDisable(GL.GL_DEPTH_TEST);
	}

	/**
	 * @see OpenGLTab#getTabText()
	 */
	String getTabText() {
		return "Area";
	}
	
	/**
	 * @see OpenGLTab#init()
	 */
	void init() {
		if (!hasStencilSupport()) return;
		
		GL.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
		float[] lightPos = { 0.0f, 5.0f, -10.0f, 1.0f };
		GL.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, lightPos);
		quadratic = GLU.gluNewQuadric();
		disk = GLU.gluNewQuadric();
	
		GL.glEnable(GL.GL_CULL_FACE);
		GL.glEnable(GL.GL_LIST_MODE);
		GL.glEnable(GL.GL_LIGHT0);
		GL.glEnable(GL.GL_LIGHTING);
		GL.glLightModeli(GL.GL_LIGHT_MODEL_TWO_SIDE, GL.GL_TRUE);

		final float[] sphereMaterial = { 0.0f, 1.0f, 0.0f, 1.0f };
		final float[] cylinderMaterial = { 1.0f, 0.0f, 0.0f, 1.0f };

		Shape sphere = new Shape() {
			public void draw() {
				GL.glMaterialfv(
					GL.GL_FRONT_AND_BACK,
					GL.GL_AMBIENT_AND_DIFFUSE,
					sphereMaterial);
				GL.glColor3f(0.0f, 1.0f, 0.0f);
				GLU.gluSphere(quadratic, 3, 32, 32);
			}
		};
		Shape cylinder = new Shape() {
			public void draw() {
				GL.glMaterialfv(
					GL.GL_FRONT_AND_BACK,
					GL.GL_AMBIENT_AND_DIFFUSE,
					cylinderMaterial);
				GL.glColor3f(1.0f, 0.0f, 0.0f);
				GLU.gluQuadricOrientation(disk, GLU.GLU_INSIDE);
				GL.glPushMatrix();
				GL.glTranslatef(1.0f, 1.0f, 0.0f);
				GLU.gluDisk(disk, 0, 3, 32, 32);
				GLU.gluCylinder(quadratic, 3, 3, 6, 32, 32);
				GL.glPushMatrix();
				GL.glTranslatef(0.0f, 0.0f, 6.0f);
				GLU.gluQuadricOrientation(disk, GLU.GLU_OUTSIDE);
				GLU.gluDisk(disk, 0, 3, 32, 32);
				GL.glPopMatrix();
				GL.glPopMatrix();
			}
		};

		// create the display lists and states
		states = new State[6];
		int index = 1;
		
		GL.glNewList(index, GL.GL_COMPILE);
		drawShape(cylinder);
		GL.glEndList();
		states[0] = new State("Cylinder",index++);

		GL.glNewList(index, GL.GL_COMPILE);
		drawShape(sphere);
		GL.glEndList();
		states[1] = new State("Sphere",index++);

		GL.glNewList(index, GL.GL_COMPILE);
		drawAorB(cylinder, sphere);
		GL.glEndList();
		states[2] = new State("Cylinder OR Sphere",index++);

		GL.glNewList(index, GL.GL_COMPILE);
		drawAandB(cylinder, sphere);
		GL.glEndList();
		states[3] = new State("Cylinder AND Sphere",index++);

		GL.glNewList(index, GL.GL_COMPILE);
		drawAsubB(cylinder, sphere);
		GL.glEndList();
		states[4] = new State("Cylinder SUB Sphere",index++);
		
		GL.glNewList(index, GL.GL_COMPILE);
		drawAsubB(sphere, cylinder);
		GL.glEndList();
		states[5] = new State("Sphere SUB Cylinder",index++);

		currentState = states[0];
	}
	
	/**
	 * @see OpenGLTab#isStencilSupportNeeded
	 */
	boolean isStencilSupportNeeded() {
		return true;
	}

	/**
	 * @see OpenGLTab#renderScene()
	 */
	void renderScene() {
		GL.glClear(
			GL.GL_COLOR_BUFFER_BIT
				| GL.GL_DEPTH_BUFFER_BIT
				| GL.GL_STENCIL_BUFFER_BIT);

		GL.glLoadIdentity();
		GL.glTranslatef(xPos, yPos, zPos);
		GL.glRotatef(xRot, 1.0f, 0.0f, 0.0f);
		GL.glRotatef(yRot, 0.0f, 1.0f, 0.0f);
		GL.glRotatef(zRot, 0.0f, 0.0f, 1.0f);

		currentState.display();
	}
}
