///////////////////////////////////////////////////
//
//	Contour-tree based isosurfaces
//	version 3.0
//	copyright Hamish Carr
//	February, 2001
//
//	------------------------
//	IsosurfaceWindow.cpp
//	------------------------
//	
//	A simple window with an isosurface & controls
//	
//	Notes:
//	------
//
//
//	Change log:
//	-----------
//	Date:		Changes:
//	-----		--------
//	02/09/01		Initial version
//
///////////////////////////////////////////////////

#include "IsosurfaceWindow.h"												//	the GLUTWindow class

#define TEXT_HEIGHT 24
#define SLIDER_OVERHANG 10
#define SLIDER_SIZE 25
#define BUTTON_HEIGHT 40

#define ISO_PANE_WIDTH 720
#define ISO_PANE_HEIGHT ISO_PANE_WIDTH
#define LABELLED_ROTATOR_HEIGHT 125
#define LABELLED_ROTATOR_WIDTH 100
#define ZOOM_SLIDER_WIDTH (ISO_PANE_WIDTH-2*LABELLED_ROTATOR_WIDTH-120)
#define ZOOM_SLIDER_HEIGHT SLIDER_SIZE
#define ZOOM_FILLER_HEIGHT (LABELLED_ROTATOR_HEIGHT-2*SLIDER_SIZE)
#define BOX_BUTTON_ROW_HEIGHT 120
#define BOX_BUTTON_COLUMN_WIDTH 320

#define ISOVALUE_COLUMN_WIDTH 100
#define ISOVALUE_SLIDER_HEIGHT ISO_PANE_HEIGHT
#define ISOVALUE_FILLER_HEIGHT (INITIAL_HEIGHT-TEXT_HEIGHT-ISOVALUE_SLIDER_HEIGHT-2*BUTTON_HEIGHT)

#define CONTOUR_COLUMN_WIDTH 400
#define CONTOUR_PANE_HEIGHT (ISO_PANE_HEIGHT-2*SLIDER_OVERHANG)
#define CONTOUR_CHECK_ROW_HEIGHT 40
#define COLOUR_PANEL_HEIGHT 40
#define CONTOUR_FILLER_HEIGHT (INITIAL_HEIGHT-TEXT_HEIGHT-SLIDER_OVERHANG-CONTOUR_PANE_HEIGHT-SLIDER_OVERHANG-CONTOUR_CHECK_ROW_HEIGHT-TEXT_HEIGHT-COLOUR_PANEL_HEIGHT-3*BUTTON_HEIGHT)

#define COLLAPSE_PANE_WIDTH 400
#define COLLAPSE_COLUMN_WIDTH (COLLAPSE_PANE_WIDTH + 2*SLIDER_OVERHANG)
#define COLLAPSE_PANE_HEIGHT (ISO_PANE_HEIGHT-2*SLIDER_OVERHANG)
#define COLLAPSE_ROW_FILLER_WIDTH 43
#define COLLAPSE_FILLER_HEIGHT (INITIAL_HEIGHT-TEXT_HEIGHT-SLIDER_OVERHANG-COLLAPSE_PANE_HEIGHT-SLIDER_OVERHANG-SLIDER_SIZE-BUTTON_HEIGHT)

#define MEASURE_COLUMN_WIDTH 200
#define MEASURE_SLIDER_HEIGHT ISO_PANE_HEIGHT
#define MEASURE_GROUP_HEIGHT 184
#define MEASURE_FILLER_HEIGHT (INITIAL_HEIGHT-TEXT_HEIGHT-MEASURE_SLIDER_HEIGHT-MEASURE_GROUP_HEIGHT)

#define INITIAL_HEIGHT (TEXT_HEIGHT+ISO_PANE_HEIGHT+LABELLED_ROTATOR_HEIGHT+BOX_BUTTON_ROW_HEIGHT)
#define INITIAL_WIDTH (ISO_PANE_WIDTH + ISOVALUE_COLUMN_WIDTH + CONTOUR_COLUMN_WIDTH + COLLAPSE_COLUMN_WIDTH + MEASURE_COLUMN_WIDTH)

const char *priorityNames[4] = { "Height", "Volume", "Height * Vol", "Riemann HV"}; 
int priorityValues[] = { PRIORITY_HEIGHT, PRIORITY_VOLUME, PRIORITY_HYPERVOLUME, PRIORITY_APPROX_HYPERVOLUME};

IsosurfaceWindow::IsosurfaceWindow(int argc, char **argv, const char *windowName)
	: GLUTWindow(windowName, INITIAL_WIDTH, INITIAL_HEIGHT)				//	constructor : everything else should be in the
	{ // IsosurfaceWindow()													//	IsosurfacePane
	// first column (isosurface pane) grows both horizontally and vertically
	isosurfacePaneColumn = 	new GLUTVertPane("Isosurface Column", this, ISO_PANE_WIDTH, INITIAL_HEIGHT, true, true, ALIGN_HORIZONTAL_CENTRE);

		// within that, we initialize elements in turn
		isoPaneLabel = new GLUTStaticText(isosurfacePaneColumn, "Flexible Isosurface");
		
		// the main pane, which grows both horizontally and vertically, and is passed the argc/argv for initialization
		isosurfacePane = new IsosurfacePane("Isosurface Pane", isosurfacePaneColumn, ISO_PANE_WIDTH, ISO_PANE_HEIGHT, argc, argv, true, true);	

		// we have a wide panel to hold the arcballs - this should grow horizontally but not vertically
		arcBallRow = new GLUTHorizPane("Arcball Row", isosurfacePaneColumn, ISO_PANE_WIDTH, LABELLED_ROTATOR_HEIGHT, true, false, ALIGN_VERTICAL_CENTRE);

			// the column holding the rotation arcball
			rotationColumn = new GLUTVertPane("Rotation Column", arcBallRow, LABELLED_ROTATOR_WIDTH, LABELLED_ROTATOR_HEIGHT, false, false, ALIGN_HORIZONTAL_LEFT);
				// the arcball itself
				rotator = new GLUTArcBall("Rotator", rotationColumn, (isosurfacePane->rotMat));
				// the text label
				rotatorLabel = new GLUTStaticText(rotationColumn, "Rotation");
				
			// the column holding the lighting arcball
			lightingColumn = new GLUTVertPane("Lighting Column", arcBallRow, LABELLED_ROTATOR_WIDTH, LABELLED_ROTATOR_HEIGHT, false, false, ALIGN_HORIZONTAL_LEFT);
				// the arcball itself
				lightRotator = new GLUTArcBall("Light Rotator", lightingColumn, (isosurfacePane->lightMat));
				// the text label
				lightLabel = new GLUTStaticText(lightingColumn, "Lighting");
				
			// now set the isosurface pane to link with the arcballs
			isosurfacePane->SetArcBalls(rotator, lightRotator);	
				
			// then we have a pane with two sliders: this should grow horizontally but not vertically
			labelledSliderColumn = new GLUTVertPane("Zoom/ZScale Slider Column", arcBallRow, ZOOM_SLIDER_WIDTH+20, ZOOM_SLIDER_HEIGHT, true, false, ALIGN_HORIZONTAL_CENTRE);

				// inside this, we have two panes, one to hold each slider & a label: this should grow horizontally but not vertically
				zoomSliderRow = new GLUTHorizPane("Zoom Slider Row", labelledSliderColumn, ZOOM_SLIDER_WIDTH, ZOOM_SLIDER_HEIGHT, true, false, ALIGN_VERTICAL_CENTRE);
				zoomSlider = new GLUTHorizSlider("Zoom Slider", zoomSliderRow, -2.0, 2.0, ZOOM_SLIDER_WIDTH, 0.0, &(isosurfacePane->scale), NULL);
				zoomLabelPane = new GLUTHorizPane("Zoom Label Pane", zoomSliderRow, 85, ZOOM_SLIDER_HEIGHT, false, false);
				zoomLabel = new GLUTStaticText(zoomLabelPane, "Zoom");
			
				// inside this, we have two panes, one to hold each slider & a label: this should grow horizontally but not vertically
				zScaleSliderRow = new GLUTHorizPane("Z Scale Slider Row", labelledSliderColumn, ZOOM_SLIDER_WIDTH, ZOOM_SLIDER_HEIGHT, true, false, ALIGN_VERTICAL_CENTRE);
				zScaleSlider = new GLUTHorizSlider("Z Scale Slider", zScaleSliderRow, 0.1, 4.0, ZOOM_SLIDER_WIDTH, 0.90, &(isosurfacePane->zScale), NULL);
				zScaleLabelPane = new GLUTHorizPane("Z Scale Label Pane", zScaleSliderRow, 85, ZOOM_SLIDER_HEIGHT, false, false);
				zScaleLabel = new GLUTStaticText(zScaleLabelPane, "Z Scale");

				// and a stretchy pane to force them to the top
				sliderFiller = new GLUTPane("Slider Filler", labelledSliderColumn, ZOOM_SLIDER_WIDTH, ZOOM_FILLER_HEIGHT, true, false);

		// a row to hold boxes and buttons
		boxButtonRow = new GLUTHorizPane("Box Button Row", isosurfacePaneColumn, ISO_PANE_WIDTH, BOX_BUTTON_ROW_HEIGHT, true, false, ALIGN_VERTICAL_CENTRE);

			// inside, we put each column in a separate VPane: these should not stretch
			checkBoxColumn = new GLUTVertPane("Check Box Column", boxButtonRow, BOX_BUTTON_COLUMN_WIDTH, BOX_BUTTON_ROW_HEIGHT, false, false, ALIGN_HORIZONTAL_LEFT);
				
				// the check box for coloured contours: forces refresh by reporting change of isovalue
				colouredContourBox = new GLUTCheckBox(checkBoxColumn, "Coloured Contours", &(isosurfacePane->field->differentColouredContours), &(isosurfacePane->isoSliderChanged), true);
				// the check box for local max contours: forces refresh by reporting change of isovalue
				localContourBox = new GLUTCheckBox(checkBoxColumn, "Local Contours", &(isosurfacePane->useLocalContours), &(isosurfacePane->isoSliderChanged), false);
				// the check box for local min contours: forces refresh by reporting change of isovalue
				localMinContourBox = new GLUTCheckBox(checkBoxColumn, "Minima not Maxima", &(isosurfacePane->useLocalMinContours), &(isosurfacePane->isoSliderChanged), false);

			// a column for the delete buttons
			deleteColumn = new GLUTVertPane("Delete Column", boxButtonRow, BOX_BUTTON_COLUMN_WIDTH, BOX_BUTTON_ROW_HEIGHT, false, false, ALIGN_HORIZONTAL_LEFT);
			
				// the button to delete the selection
				deleteSelectionButton = new GLUTTextButton(deleteColumn, "Delete Selection", isosurfacePane, IsosurfacePane::Action_Delete_Selection);
				// the button to delete the complement
				deleteComplementButton = new GLUTTextButton(deleteColumn, "Delete Complement", isosurfacePane, IsosurfacePane::Action_Delete_Complement);
				// the button to restore the last delete if possible
				restoreDeletedButton = new GLUTTextButton(deleteColumn, "Restore Deleted", isosurfacePane, IsosurfacePane::Action_Restore_Deleted);

			// a blank stretchy pane
			boxButtonFillerColumn = new GLUTVertPane("Filler Column", boxButtonRow, 10, BOX_BUTTON_ROW_HEIGHT, true, false);
			
	// second vertical column:	the isovalue slider
	isovalueColumn = new GLUTVertPane("Isovalue Column", this, ISOVALUE_COLUMN_WIDTH, INITIAL_HEIGHT, false, true, ALIGN_HORIZONTAL_CENTRE);
	
		// the text label
		isovalueLabel = new GLUTStaticText(isovalueColumn, "Isovalue");
		// the slider
		isovalueSlider = new GLUTVertSlider("Isovalue Slider", isovalueColumn, 0.0, 1.0, ISOVALUE_SLIDER_HEIGHT, 0.90, &(isosurfacePane->isoValue), &(isosurfacePane->isoSliderChanged));
		// button to increment isovalue
		incrementButton = new GLUTTextButton(isovalueColumn, "++", isosurfacePane, IsosurfacePane::Action_Increment);
		// button to decrement isovalue
		decrementButton = new GLUTTextButton(isovalueColumn, "--", isosurfacePane, IsosurfacePane::Action_Decrement);
		// the filler box
		isovalueFiller = new GLUTPane("Isovalue Filler", isovalueColumn, ISOVALUE_COLUMN_WIDTH, ISOVALUE_FILLER_HEIGHT, false, false);
				
	//	third vertical column: contour tree pane plus checkboxes / buttons
	contourTreeColumn = new GLUTVertPane("Contour Tree Column", this, CONTOUR_COLUMN_WIDTH, INITIAL_HEIGHT, false, true, ALIGN_HORIZONTAL_CENTRE);

		// a label for the contour tree pane
		contourTreeLabel = new GLUTStaticText(contourTreeColumn, "Contour Tree");
		
		// a filler to match the slider overhang
		treeTopFiller = new GLUTPane("Tree Top Filler", contourTreeColumn, CONTOUR_COLUMN_WIDTH, SLIDER_OVERHANG, false, false);
		
		// the contour tree pane itself
		contourTreePane = new ContourTreePane("Contour Tree Pane", contourTreeColumn, CONTOUR_COLUMN_WIDTH, CONTOUR_PANE_HEIGHT, isosurfacePane->field, &(isosurfacePane->isoValue), &(isosurfacePane->isoSliderChanged), isosurfacePane, false, true);

		// a filler to match the slider overhang
		treeMidFiller = new GLUTPane("Tree Mid Filler", contourTreeColumn, CONTOUR_COLUMN_WIDTH, SLIDER_OVERHANG, false, false);
		
		// a horizontal pane to contain check boxes
		contourTreeCheckRow = new GLUTHorizPane("Tree Check Row", contourTreeColumn, CONTOUR_COLUMN_WIDTH, CONTOUR_CHECK_ROW_HEIGHT, false, false, ALIGN_VERTICAL_CENTRE);

			// check box to show the tree
			showTreeBox = new GLUTCheckBox(contourTreeCheckRow, "Show Tree", &(contourTreePane->showTree), NULL, false);
			// check box to colour the superarcs
			colourTreeBox = new GLUTCheckBox(contourTreeCheckRow, "Colour Tree", &(contourTreePane->useColouredTree), NULL, false);

		// a text label explaining colour selection
		colourPaneLabel = new GLUTStaticText(contourTreeColumn, "Superarc Colour");
		
		// the colour selection pane
		colourPane = new ColourSelectionPane("Colour Selector", contourTreeColumn, isosurfacePane, IsosurfacePane::Action_Select_Colour, &(isosurfacePane->selectionColour));

		// filler box
		contourTreeFiller = new GLUTPane("Tree Column Filler", contourTreeColumn, CONTOUR_COLUMN_WIDTH, CONTOUR_FILLER_HEIGHT, false, false);
	
		// button for dot layout
		dotLayoutButton = new GLUTTextButton(contourTreeColumn, "Dot Layout", isosurfacePane, IsosurfacePane::Action_Dot_Layout);
		// button to save layout to disk
		saveLayoutButton = new GLUTTextButton(contourTreeColumn, "Save Layout", isosurfacePane, IsosurfacePane::Action_Save_Layout);
		// button to load layout from disk
		loadLayoutButton = new GLUTTextButton(contourTreeColumn, "Load Layout", isosurfacePane, IsosurfacePane::Action_Load_Layout);

	//	fourth vertical column: log-collapse pane plus buttons
	collapseColumn = new GLUTVertPane("Collapse Column", this, COLLAPSE_COLUMN_WIDTH, INITIAL_HEIGHT, false, true, ALIGN_HORIZONTAL_CENTRE);
	
		// a label for the plot
		collapseLabel = new GLUTStaticText(collapseColumn, "Simplification");

		// a filler to match the slider overhang
		collapseTopFiller = new GLUTPane("Collapse Top Filler", collapseColumn, COLLAPSE_COLUMN_WIDTH, SLIDER_OVERHANG, false, false);
		
		// the row pane
		collapsePaneRow = new GLUTHorizPane("Collapse Pane Row", collapseColumn, COLLAPSE_COLUMN_WIDTH, COLLAPSE_PANE_HEIGHT, false, true, ALIGN_VERTICAL_CENTRE);

			// the left slider overhang filler
			leftCollapseFiller = new GLUTPane("Collapse Left Filler", collapsePaneRow, SLIDER_OVERHANG, COLLAPSE_PANE_HEIGHT, false, true);		

			// the collapse pane proper
			collapsePane = new LogCollapsePane("Collapse Pane", collapsePaneRow, COLLAPSE_COLUMN_WIDTH, COLLAPSE_PANE_HEIGHT, isosurfacePane->field, false, true);

			// the right slider overhang filler
			rightCollapseFiller = new GLUTPane("Collapse Left Filler", collapsePaneRow, SLIDER_OVERHANG, COLLAPSE_PANE_HEIGHT, false, true);		

		// a filler to match the slider overhang
		collapseMidFiller = new GLUTPane("Collapse Mid Filler", collapseColumn, COLLAPSE_COLUMN_WIDTH, SLIDER_OVERHANG, false, false);
		
		// the slider for tree size
		treeSizeSlider = new GLUTHorizSlider("Tree Size Slider", collapseColumn, 0.0, 1.0, COLLAPSE_COLUMN_WIDTH, 0.0, &(isosurfacePane->field->logTreeSize), &(isosurfacePane->updateFromTreeSize));

		// row for the collapse buttons
		collapseRow = new GLUTHorizPane("Collapse Row", collapseColumn, COLLAPSE_COLUMN_WIDTH, BUTTON_HEIGHT, false, false, ALIGN_VERTICAL_CENTRE);

			// filler pane
			fillerLeftmost = new GLUTPane("Filler Leftmost", collapseRow, COLLAPSE_ROW_FILLER_WIDTH, BUTTON_HEIGHT, false, false);
			// collapse button
			collapseButton = new GLUTTextButton(collapseRow, "--", isosurfacePane, IsosurfacePane::Action_Collapse);
			// filler pane
			fillerLeft = new GLUTPane("Filler Left", collapseRow, COLLAPSE_ROW_FILLER_WIDTH, BUTTON_HEIGHT, false, false);
			// static text label
			treeSizeLabel = new GLUTStaticText(collapseRow, "Tree Size");
			// filler pane
			fillerRight = new GLUTPane("Filler Right", collapseRow, COLLAPSE_ROW_FILLER_WIDTH, BUTTON_HEIGHT, false, false);
			// uncollapse button
			collapseButton = new GLUTTextButton(collapseRow, "++", isosurfacePane, IsosurfacePane::Action_Uncollapse);
			// filler pane
			fillerRightmost = new GLUTPane("Filler Rightmost", collapseRow, COLLAPSE_ROW_FILLER_WIDTH, BUTTON_HEIGHT, false, false);

		// filler box
		collapseFiller = new GLUTHorizPane("Collapse Filler", collapseColumn, COLLAPSE_COLUMN_WIDTH, COLLAPSE_FILLER_HEIGHT, false, false, ALIGN_VERTICAL_CENTRE);

	//	fifth vertical column: measure slider & radio group
	measureColumn = new GLUTVertPane("Measure Column", this, MEASURE_COLUMN_WIDTH, INITIAL_HEIGHT, false, true, ALIGN_HORIZONTAL_CENTRE);

		// label for measure slider
		measureLabel = new GLUTStaticText(measureColumn, "Measure");
		
		// measure slider
		measureSlider = new GLUTVertSlider("Measure Slider", measureColumn, 0.0, 1.0, MEASURE_SLIDER_HEIGHT, isosurfacePane->field->InitialLogPriorityBound(), &(isosurfacePane->field->logPriorityBound), &(isosurfacePane->updateFromPriorityBound));

		// and a filler pane
		measureFiller = new GLUTPane("Measure Filler", measureColumn, MEASURE_COLUMN_WIDTH, MEASURE_FILLER_HEIGHT, false, false);

		// and radio group to choose priority
		measureChooser = new GLUTRadioGroup("Measure Chooser", measureColumn, "", 4, priorityNames, priorityValues, PRIORITY_HEIGHT, &(isosurfacePane->collapsePriority), &(isosurfacePane->recollapse));

	// and call reshape to force the initial layout
	Reshape(INITIAL_WIDTH, INITIAL_HEIGHT);
	} // IsosurfaceWindow()
