package vgp.tutor.pick;

import java.awt.Color;

import jv.geom.PgElementSet;
import jv.geom.PgPolygon;
import jv.object.PsDebug;
import jv.project.PjProject;
import jv.project.PvPickEvent;
import jv.vecmath.PdVector;

import jvx.curve.PgTube;

/**
 * Project demonstrates the mechanism to pick points on surfaces and handle the callback.
 * 
 * @see			jv.project.PvPickEvent
 * @author		Konrad Polthier
 * @version		10.06.99, 1.01 revised (kp).<br>
 *					10.06.99, 1.00 created (kp)
 */
public class PjPickEvent extends PjProject {
	// Some of the necessary steps to handle pick events are done by
	// the super class PjProject, so if a class does not extend PjProject,
	// there will be more necessary steps to receive pick events: 
	// - The class has to implement the interface PvPickListenerIf.
	// - Registration in the display as PickListener has to be done.
	protected	boolean				m_bShowTorus;
	protected	boolean				m_bShowTube;
	protected	PgElementSet		m_torus;
	protected	PgTube				m_tube;
	protected	PgPolygon			m_knot;

	/** Constructor. */
	public PjPickEvent() {
		// First the constructor of the super class PjProject is called. PjProject
		// implements PvPickListenerIf, so all necessary methods to receive pick
		// events are already implemented (most of these methods don't do anything but
		// exist to fulfill the interface PvPickListenerIf); PjProject also registers in the
		// display as PickListener, so this class PjPichEvent does not need to do this.
		// If not the super class would already implement the PvPickListetnerIf, this 
		// class PjhPickEvent would have to implement the interface and register in the display
		// as PickListener.
		super("Pick Event");
		m_torus = new PgElementSet(3);
		m_torus.setName("Torus");
		m_knot = new PgPolygon(3);
		m_knot.setName("Curve on Surface");
		m_tube = new PgTube(3);
		m_tube.setName("Tube around Curve");
		m_tube.setEnabledArrowPanel(false);
		m_tube.setPolygon(m_knot);

		if (getClass() == PjPickEvent.class) {
			init();
		}
	}
	/** Initialization. */
	public void init() {
		super.init();
		m_bShowTorus	= true;
		m_bShowTube		= true;

		m_torus.showElements(false);
		m_torus.computeTorus(10, 10, 2., 1.);
		m_torus.makeQuadrBnd(10, 10);
		m_torus.close();
		m_knot.init();
		m_knot.setGlobalEdgeColor(Color.blue);

		m_tube.setDefThickness(0.2);
		m_tube.init();
		m_tube.setPolygon(m_knot);
		m_tube.generateTube();
	}
	
	/**
	 * Method is invoked during loading of a project in JavaView.
	 */
	public void start() {
		if (PsDebug.NOTIFY) PsDebug.notify("PjPickEvent.start: ");
		addGeometry(m_torus);
		addGeometry(m_knot);
		addGeometry(m_tube);
		selectGeometry(m_torus);
		super.start();
	}
	/**
	 * Update the class whenever a child has changed.
	 * Method is usually invoked from the children.
	 */
	public boolean update(Object event) {
		if (PsDebug.NOTIFY) PsDebug.notify("PjPickEvent.update: called");
		if (event == m_tube) {
			if (PsDebug.NOTIFY) PsDebug.notify("PjPickEvent.update: called with event==m_tube");
			return super.update(null);
		} else if (event == m_knot) {
			if (PsDebug.NOTIFY) PsDebug.notify("PjPickEvent.update: called with event==m_knot");
			return m_tube.update(m_knot);
		}
		return super.update(event);
	}
	/**
	 *  Receive an "Initial Pick" event. This is one of the methods required by 
	 *  PvPickListenerIf; it is already implemented by the super class PjProject
	 *  (without doing anything but fulfilling the interface). Here this method
	 *  is overwritten to have some reaction on the initial pick event.
	 *  This method will usually be called by a display in all registered pick
	 *  listeners, when an initial pick is done. 
	 *  Initial pick events may be invoked by clicking on the geometry with either
	 *  the display's major mode set to jv.project.PvDisplayIf.MODE_INITIAL_PICK
	 *  or with "i" key pressed. 
	 */
	public void pickInitial(PvPickEvent pos) {
		if (PsDebug.NOTIFY) PsDebug.notify("PjPickEvent.pickInitial: called");
		int num = m_knot.getNumVertices();
		if (num > 0) {
			PdVector prev = m_knot.getVertex(num-1);
			if (PdVector.sqrDist(prev, pos.getVertex()) < m_torus.getDiameter()/100.)
				return;
		}
		m_knot.addVertex(pos.getVertex());
		m_knot.update(m_knot);
	}
}

