/* page.cpp */

#include <iostream>
#include <iterator>
#include <stdio.h>
#include "vamosworld.h"
#include "controls.h"
#include "mouse.h"
#include "utility.h"
#include "gui/widget.h"
#include "gui/page.h"
#include "gui/gui.h"
#include "gui/button.h"
#include "gui/calibrate.h"
#include "gui/controlgrab.h"
#include "gui/image.h"
#include "gui/label.h"
#include "gui/multi_image.h"
#include "gui/slider.h"
#include "gui/spinning_car.h"
#include "gui/textbox.h"
#include "gui/toggle.h"
#include "gui/wheel.h"

using namespace VGUI;

extern bool verbose_output;


Page::Page()
{
	cout << "OOPS! tried to create a page without a filename. Not attempting load/init." << endl;
}

Page::Page( string filename )
{
	path = filename;
	menu_file.Load( path );
	menu_file.SuppressError( !verbose_output );
	num_widgets = 0;
	default_obj = cur_obj = cancel_obj = cur_tab = 0;
	has_changes = is_dialog = l_pressed = r_pressed = false;
	name = tab_text = "";
	clicked_obj = 10000;
	Init();
}

Page::~Page()
{
	menu_file.Clear();
	for( unsigned int i = 0; i < page_objects.size(); i++ )
	{
		delete page_objects[i];
	}
	page_objects.clear();
}

void Page::Init()
{
	string background_filename;
	Widget* wgt;
	Button* btn;
	Image* img;
	MultiImage* mimg;
	Label* lbl;
	Slider* sld;
	Toggle* tgl;
	Wheel<int>* iwhl;
	Wheel2<int, int>* iiwhl;
	Wheel<float>* fwhl;
	Wheel<string>* swhl;
	SpinningCar* scar;
	TextBox* tbox;
	ControlGrab* cgrb;
	Calibrate* cal;
//	TextBox* tbx;
//	ListBox* lbx;
	int n_wgts;

	if( verbose_output ) cout << endl << "Menu file: " << path << endl << "=================================" << endl;

	// get the page's name
	if( menu_file.GetParam( ".name", name ) )
	{
		if( verbose_output ) cout << "Name: " << name << endl;
	}
	else
	{
		if( verbose_output ) cout << "Name not found. Page is nameless..." << endl;
	}

	// get the number of widgets
	if( !menu_file.GetParam( ".widgets", n_wgts ) )
	{
		if( verbose_output ) cout << "could not find number of widgets, assuming 10" << endl;
		num_widgets = 10;
	}
	else
	{
		num_widgets = n_wgts;
		if( verbose_output ) cout << "Number of widgets in this file: " << num_widgets << endl;
	}

	// load the background image for this page
	if( !menu_file.GetParam( ".background", background_filename ) )
	{
		if( verbose_output ) cout << "cound not find background image for this page, default to gui/box.png" << endl;
		background_filename = "box.png";
	}
	else
	{
		if( verbose_output ) cout << "Background image: " << background_filename << endl;
	}
	background.Load( settings.GetSkinPath() + "/textures/" + background_filename, false );

	// does this page have a tab text?
	if( !menu_file.GetParam( ".tab_text", tab_text ) )
	{
		if( verbose_output ) cout << "cound not find tab text, assuming none." << endl;
		tab_text = "";
	}
	else
	{
		if( verbose_output ) cout << "tab text: " << tab_text << endl;
	}

	// is this page a dialog?
	if( !menu_file.GetParam( ".dialog", is_dialog ) )
	{
		if( verbose_output ) cout << "dialog setting not found, default to false." << endl;
		is_dialog = false;
	}
	else
	{
		if( verbose_output ) cout << "Dialog: " << is_dialog << endl;
	}

	int n_tabs = 0;
	// is this page tabbed?
	if( !menu_file.GetParam( ".tabs", n_tabs ) )
	{
		if( verbose_output ) cout << "number of tabs not found, default to 0." << endl;
		num_tabs = 0;
	}
	else
	{
		num_tabs = n_tabs;
		if( verbose_output ) cout << "Tabs: " << num_tabs << endl;

		tab_active.Load( "gui/widgets/tab_active.png", false );
		tab_inactive.Load( "gui/widgets/tab_inactive.png", false );
		tab_page_background.Load( "gui/widgets/tab_page_background.png", false );
		char tab_txt[20];
		string tab_str, tab_name;

		for( unsigned int j = 0; j < num_tabs; j++ )
		{
			sprintf( tab_txt, "tab-%02d", j );
			tab_str = tab_txt;
			if( !menu_file.GetParam( "." + tab_str, tab_name ) )
			{
				if( verbose_output ) cout << "Could not find " << tab_str << ", skipping." << endl;
			}
			else
			{
				// TODO: the path "/lists/new-menus/" should not be hard-coded
				tabs.push_back( new Page( settings.GetFullDataPath( "lists/new-menus/" + tab_name ) ) );
				if( verbose_output ) cout << "Added tab: " << tab_name << endl;
			}
		}
	}

	for( unsigned int n = 0; n < num_widgets; n++ )
	{
		char w[20];
		sprintf( w, "widget-%02d", n );
		string wgt_id = w;
		string wgt_type, wgt_name, wgt_text, wgt_center_double, wgt_width_txt, wgt_height_txt, wgt_setting, wgt_tip, wgt_hook;
		string value_source = "manual";
		float x_val = 0.5;
		float y_val = 0.5;
		float wgt_color[3] = {1.0, 1.0, 1.0};
		Location wgt_center;
		bool wgt_enabled, wgt_selected, wgt_default, wgt_cancel;
		int wgt_font_size;
		wgt = new Widget();

		// get the widget's name
		if( menu_file.GetParam( wgt_id + ".name", wgt_name ) )
		{
			wgt->SetName( wgt_name );
			if( verbose_output ) cout << wgt_id << ": name: " << wgt_name << endl;
		}
		else
		{
			if( verbose_output ) cout << wgt_id << ": name not found. Can't use this widget, skipping." << endl;
			break;
		}

		// get the widget's type
		if( menu_file.GetParam( wgt_id + ".type", wgt_type ) )
		{
			wgt->SetType( wgt_type );
			if( verbose_output ) cout << wgt_id << ": type: " << wgt_type << endl;

			// set the widget's text
			if( !menu_file.GetParam( wgt_id + ".text", wgt_text ) )
			{
				if( verbose_output ) cout << wgt_id << ": text not found, using [empty]." << endl;
				wgt_text = "";
			}
			else
			{
				wgt_text = _(wgt_text);
				if( verbose_output ) cout << wgt_id << ": text: " << wgt_text << endl;
			}
			wgt->SetText( wgt_text );

			// set the widget's font size
			if( !menu_file.GetParam( wgt_id + ".fontsize", wgt_font_size ) )
			{
				if( verbose_output ) cout << wgt_id << ": font size not found, using 5." << endl;
				wgt_font_size = 5;
			}
			else
			{
				if( verbose_output ) cout << wgt_id << ": fontsize: " << wgt_font_size << endl;
			}
			wgt->SetFontSize( wgt_font_size );

			// set the widget's text color
			if( !menu_file.GetParam( wgt_id + ".color", wgt_color ) )
			{
				if( verbose_output ) cout << wgt_id << ": color not found, using white." << endl;
				wgt_color[0] = 1.0;
				wgt_color[1] = 1.0;
				wgt_color[2] = 1.0;
			}
			else
			{
				if( verbose_output ) cout << wgt_id << ": color: " << wgt_color[0] << "," << wgt_color[1] << "," << wgt_color[2] << endl;
			}
			wgt->SetColor( wgt_color[0], wgt_color[1], wgt_color[2] );

			// set the widget's location
			if( menu_file.GetParam( wgt_id + ".center", wgt_center_double ) )
			{
				if( EOF == sscanf( wgt_center_double.c_str(), "%f, %f", &x_val, &y_val ) )
				{
					if( verbose_output ) cout << wgt_id << ": center location could not be read, using \"0.5, 0.5\"." << endl;
				}
				else
				{
					if( verbose_output ) cout << wgt_id << ": location: " << x_val << ", " << y_val << endl;
				}
			}
			else
			{
				if( verbose_output ) cout << wgt_id << ": center location not found, using \"0.5, 0.5\"." << endl;
			}
			wgt_center = Location( x_val, y_val );
			wgt->SetCenter( wgt_center );

			// get the widget's width
			if( menu_file.GetParam( wgt_id + ".width", wgt_width_txt ) )
			{
				float width_val;
				if( wgt_width_txt == "auto" )
				{
					if( verbose_output ) cout << wgt_id << ": width: " << wgt_width_txt << endl;
					wgt->SetWidthAuto( true );
				}
				else
				{
					if( EOF == sscanf( wgt_width_txt.c_str(), "%f", &width_val ) )	
					{
						if( verbose_output ) cout << wgt_id << ": width could not be read, default to auto." << endl;
						wgt->SetWidthAuto( true );
					}
					else
					{
						if( verbose_output ) cout << wgt_id << ": width: " << width_val << endl;
						wgt->SetRelWidth( width_val );
						wgt->SetWidthAuto( false );
					}
				}
			}
			else
			{
				if( verbose_output ) cout << wgt_id << ": width not found, default to auto." << endl;
				wgt->SetWidthAuto( true );
			}

			// get the widget's height
			if( menu_file.GetParam( wgt_id + ".height", wgt_height_txt ) )
			{
				float height_val;
				if( wgt_height_txt == "auto" )
				{
					if( verbose_output ) cout << wgt_id << ": height: " << wgt_height_txt << endl;
					wgt->SetHeightAuto( true );
				}
				else
				{
					if( EOF == sscanf( wgt_height_txt.c_str(), "%f", &height_val ) )	
					{
						if( verbose_output ) cout << wgt_id << ": height could not be read, default to auto." << endl;
						wgt->SetHeightAuto( true );
					}
					else
					{
						if( verbose_output ) cout << wgt_id << ": height: " << height_val << endl;
						wgt->SetRelHeight( height_val );
						wgt->SetHeightAuto( false );
					}
				}
			}
			else
			{
				if( verbose_output ) cout << wgt_id << ": height not found, default to auto." << endl;
				wgt->SetHeightAuto( true );
			}

			// is widget enabled?
			if( !menu_file.GetParam( wgt_id + ".enabled", wgt_enabled ) )
			{
				if( verbose_output ) cout << wgt_id << ": enabled status unknown, default to on." << endl;
				wgt_enabled = true;
			}
			else
			{
				if( verbose_output ) cout << wgt_id << ": enabled: " << wgt_enabled << endl;
			}
			wgt->SetEnabled( wgt_enabled );

			// is widget selected?
			if( !menu_file.GetParam( wgt_id + ".selected", wgt_selected ) )
			{
				if( verbose_output ) cout << wgt_id << ": selected status unknown, default to off." << endl;
				wgt_selected = false;
			}
			else
			{
				if( verbose_output ) cout << wgt_id << ": selected: " << wgt_selected << endl;
			}
			wgt->SetSelected( wgt_selected );
			if( wgt_selected )
				default_obj = cur_obj = n;

			// is widget default?
			if( !menu_file.GetParam( wgt_id + ".default", wgt_default ) )
			{
				if( verbose_output ) cout << wgt_id << ": default status unknown, default to off." << endl;
				wgt_default = false;
			}
			else
			{
				if( verbose_output ) cout << wgt_id << ": default: " << wgt_default << endl;
			}
			wgt->SetDefault( wgt_default );

			// is widget cancel?
			if( !menu_file.GetParam( wgt_id + ".cancel", wgt_cancel ) )
			{
				if( verbose_output ) cout << wgt_id << ": cancel status unknown, default to off." << endl;
				wgt_cancel = false;
			}
			else
			{
				if( verbose_output ) cout << wgt_id << ": cancel: " << wgt_cancel << endl;
			}
			wgt->SetCancel( wgt_cancel );

			// get the tip for this widget
			if( !menu_file.GetParam( wgt_id + ".tip", wgt_tip ) )
			{
				if( verbose_output ) cout << wgt_id << ": tip not found, default to [empty]." << endl;
				wgt_tip = "";
			}
			else
			{
				wgt_tip = _(wgt_tip);
				if( verbose_output ) cout << wgt_id << ": tip: " << wgt_tip << endl;
			}
			wgt->SetTip( wgt_tip );

			if( !menu_file.GetParam( wgt_id + ".values", value_source ) )
			{
				if( verbose_output ) cout << wgt_id << ": value source not found, default to manual." << endl;
				value_source = "manual";
			}
			else
			{
				if( verbose_output ) cout << wgt_id << ": value source: " << value_source << endl;
			}

			// set type-specific things
			if( wgt_type == "button" )
			{
				btn = new Button( wgt );
				string action = "Main";

				if( !menu_file.GetParam( wgt_id + ".action", action ) )
				{
					if( verbose_output ) cout << wgt_id << ": button action not found, default to Main." << endl;
				}
				else
				{
					if( verbose_output ) cout << wgt_id << ": button action: " << action << endl;
				}
				btn->SetAction( action );

				page_objects.push_back( btn );
			}
			else if( wgt_type == "slider" )
			{
				sld = new Slider( wgt );
				float slider_val = -1.0;

				// see what setting this slider is hooked to
				if( !menu_file.GetParam( wgt_id + ".setting", wgt_setting ) )
				{
					if( verbose_output ) cout << wgt_id << ": setting not found. This slider will not affect anything." << endl;
				}
				else
				{
					if( !settings.Get( wgt_setting, slider_val ) )
					{
						if( verbose_output ) cout << wgt_id << ": setting " << wgt_setting << " unknown. This slider will not affect anything." << endl;
					}
					else
					{
						if( verbose_output ) cout << wgt_id << ": slider hooked to " << wgt_setting << ", got value: " << slider_val << endl;
					}
				}
				sld->SetSetting( wgt_setting );

				size_t pos = wgt_setting.find( ".", 0 );
				string cat = wgt_setting.substr( 0, pos );
				wgt_setting.erase( 0, pos + 1 );
				string name = wgt_setting;
				OPTION<float> option = settings.GetFloatOption( cat, name );
				//float min = option.GetMinValue();
				//float max = option.GetMaxValue();
				if( value_source == "options" )
				{
					sld->SetText( _(option.GetTitle()) );
					sld->SetTip( _(option.GetDesc()) );
					if( slider_val == -1.0 )
					{
						sld->SetValue( option.GetDefaultValue() );
						sld->SetDefaultValue( option.GetDefaultValue() );
					}
					else
					{
						sld->SetValue( slider_val );
						sld->SetDefaultValue( slider_val );
					}
				}
				else if( value_source == "manual" )
				{
					if( !menu_file.GetParam( wgt_id + ".sliderval", slider_val ) )
					{
						// there is no default slider value so use the value from settings
						if( slider_val == -1.0 ) slider_val = 0.0;
					}
					else
					{
						if( verbose_output ) cout << wgt_id << ": slider value: " << slider_val << endl;
					}
					sld->SetValue( slider_val );
					sld->SetDefaultValue( slider_val );
				}

				page_objects.push_back( sld );
			}
			else if( wgt_type == "toggle" )
			{
				tgl = new Toggle( wgt );
				bool tog = false;
				bool found_val = false;
				string tog_true, tog_false;
				float tog_spacing = 0.3;

				// see what setting this toggle is hooked to
				if( !menu_file.GetParam( wgt_id + ".setting", wgt_setting ) )
				{
					if( verbose_output ) cout << wgt_id << ": setting not found. This toggle will not affect anything." << endl;
				}
				else
				{
					if( !settings.Get( wgt_setting, tog ) )
					{
						if( verbose_output ) cout << wgt_id << ": setting unknown. This toggle will not affect anything." << endl;
					}
					else
					{
						if( verbose_output ) cout << wgt_id << ": toggle hooked to " << wgt_setting << ", got value: " << tog << endl;
						found_val = true;
					}
				}
				tgl->SetSetting( wgt_setting );

				size_t pos = wgt_setting.find( ".", 0 );
				string cat = wgt_setting.substr( 0, pos );
				wgt_setting.erase( 0, pos + 1 );
				string name = wgt_setting;
				OPTION<bool> option = settings.GetBoolOption( cat, name );
				if( value_source == "options" )
				{
					tgl->SetText( _(option.GetTitle()) );
					tgl->SetTip( _(option.GetDesc()) );
					tgl->SetTrueText( _(option.GetTrueValue()) );
					tgl->SetFalseText( _(option.GetFalseValue()) );
					tgl->SetValue( tog );
					tgl->SetDefaultValue( tog );
				}
				else if( value_source == "manual" )
				{
					if( !menu_file.GetParam( wgt_id + ".toggleval", tog ) )
					{
						// there is no default toggle value so use the value from settings
					}
					else
					{
						if( verbose_output ) cout << wgt_id << ": toggle value: " << tog << endl;
					}
					tgl->SetValue( tog );
					tgl->SetDefaultValue( tog );

					// get custom true/false text
					if( !menu_file.GetParam( wgt_id + ".true", tog_true ) )
					{
						if( verbose_output ) cout << wgt_id << ": toggle true text not found, default: On" << endl;
						tog_true = "On";
					}
					else
					{
						if( verbose_output ) cout << wgt_id << ": toggle true text: " << tog_true << endl;
					}
					tgl->SetTrueText( tog_true );
					if( !menu_file.GetParam( wgt_id + ".false", tog_false ) )
					{
						if( verbose_output ) cout << wgt_id << ": toggle false text not found, default: Off" << endl;
						tog_false = "Off";
					}
					else
					{
						if( verbose_output ) cout << wgt_id << ": toggle false text: " << tog_false << endl;
					}
					tgl->SetFalseText( tog_false );
				}

				// get the spacing between the toggle text and wheel
				if( !menu_file.GetParam( wgt_id + ".spacing", tog_spacing ) )
				{
					if( verbose_output ) cout << wgt_id << ": spacing not found, using default 0.3." << endl;
					tog_spacing = 0.3;
				}
				else
				{
					if( verbose_output ) cout << wgt_id << ": toggle spacing: " << tog_spacing << endl;
				}
				tgl->SetSpacing( tog_spacing );

				page_objects.push_back( tgl );
			}
			else if( wgt_type == "floatwheel" )
			{
				fwhl = new Wheel<float>( wgt );
				vector<string> whl_list;
				vector<float> val_list;
				float whl_val_c = 0.0, whl_val = 0.0, whl_spacing = 0.3;
				int whl_opts;

				// see what setting this wheel is hooked to
				if( !menu_file.GetParam( wgt_id + ".setting", wgt_setting ) )
				{
					if( verbose_output ) cout << wgt_id << ": setting not found. This wheel will not affect anything." << endl;
				}
				else
				{
					if( !settings.Get( wgt_setting, whl_val ) )
					{
						if( verbose_output ) cout << wgt_id << ": setting unknown. This wheel will not affect anything." << endl;
					}
					else
					{
						if( verbose_output ) cout << wgt_id << ": wheel hooked to " << wgt_setting << ", got value: " << whl_val << endl;
					}
				}
				fwhl->SetSetting( wgt_setting );

				size_t pos = wgt_setting.find( ".", 0 );
				string cat = wgt_setting.substr( 0, pos );
				wgt_setting.erase( 0, pos + 1 );
				string name = wgt_setting;
				OPTION<float> option = settings.GetFloatOption( cat, name );
				if( value_source == "options" )
				{
					fwhl->SetText( _(option.GetTitle()) );
					fwhl->SetTip( _(option.GetDesc()) );
					fwhl->SetOptionList( option.GetOptionList() );
					fwhl->SetValueList( option.GetValueList() );
				}
				else if( value_source == "manual" )
				{
					// get the number of options for the wheel
					if( !menu_file.GetParam( wgt_id + ".opts", whl_opts ) )
					{
						if( verbose_output ) cout << wgt_id << ": unknown number of wheel options." << endl;
					}
					else
					{
						if( verbose_output ) cout << wgt_id << ": reading " << whl_opts << " wheel options." << endl;
						for( int i = 0; i < whl_opts; i++ )
						{
							char optx[10];
							char valx[10];
							string stmp;
							float ftmp;
							sprintf( optx, ".opt%02d", i );
							sprintf( valx, ".val%02d", i );
							if( !menu_file.GetParam( wgt_id + optx, stmp ) )
							{
								if( verbose_output ) cout << wgt_id << ": option number " << i << " not found, aborting." << endl;
								break;
							}
							else
							{
								if( !menu_file.GetParam( wgt_id + valx, ftmp ) )
								{
									if( verbose_output ) cout << wgt_id << ": value number " << i << " not found, using 0.0." << endl;
									ftmp = 0.0;
								}
								else
								{
									if( verbose_output ) cout << wgt_id << ": float wheel option " << stmp << " (" << i << ") found, value: " << ftmp << endl;
								}
								whl_list.push_back( stmp );
								val_list.push_back( ftmp );
							}
						}
					}
					fwhl->SetOptionList( whl_list );
					fwhl->SetValueList( val_list );
				}

				if( !menu_file.GetParam( wgt_id + ".wheelval", whl_val_c ) )
				{
					// there is no default wheel value so use the value from settings
					whl_val_c = whl_val;
				}
				else
				{
					if( verbose_output ) cout << wgt_id << ": wheel value: " << whl_val_c << endl;
				}
				fwhl->SetValue( whl_val );
				fwhl->SetDefaultValue( whl_val );

				// get the spacing between the wheel text and wheel
				if( !menu_file.GetParam( wgt_id + ".spacing", whl_spacing ) )
				{
					if( verbose_output ) cout << wgt_id << ": spacing not found, using default 0.3." << endl;
					whl_spacing = 0.3;
				}
				else
				{
					if( verbose_output ) cout << wgt_id << ": wheel spacing: " << whl_spacing << endl;
				}
				fwhl->SetSpacing( whl_spacing );

				page_objects.push_back( fwhl );
			}
			else if( wgt_type == "stringwheel" )
			{
				swhl = new Wheel<string>( wgt );
				vector<string> whl_list;
				vector<string> val_list;
				string whl_val = "";
				float whl_spacing;
				int whl_opts;

				// see what setting this wheel is hooked to
				if( !menu_file.GetParam( wgt_id + ".setting", wgt_setting ) )
				{
					if( verbose_output ) cout << wgt_id << ": setting not found. This wheel will not affect anything." << endl;
				}
				else
				{
					if( !settings.Get( wgt_setting, whl_val ) )
					{
						if( verbose_output ) cout << wgt_id << ": setting unknown. This wheel will not affect anything." << endl;
					}
					else
					{
						if( verbose_output ) cout << wgt_id << ": wheel hooked to " << wgt_setting << ", got value: " << whl_val << endl;
					}
				}
				swhl->SetSetting( wgt_setting );

				size_t pos = wgt_setting.find( ".", 0 );
				string cat = wgt_setting.substr( 0, pos );
				wgt_setting.erase( 0, pos + 1 );
				string name = wgt_setting;
				OPTION<string> option = settings.GetStringOption( cat, name );
				if( value_source == "options" )
				{
					swhl->SetText( _(option.GetTitle()) );
					swhl->SetTip( _(option.GetDesc()) );
					swhl->SetOptionList( option.GetOptionList() );
					swhl->SetValueList( option.GetValueList() );
				}
				else if( value_source == "manual" )
				{
					// get the number of options for the wheel
					if( !menu_file.GetParam( wgt_id + ".opts", whl_opts ) )
					{
						if( verbose_output ) cout << wgt_id << ": unknown number of wheel options." << endl;
					}
					else
					{
						if( verbose_output ) cout << wgt_id << ": reading " << whl_opts << " wheel options." << endl;
						for( int i = 0; i < whl_opts; i++ )
						{
							char optx[10];
							char valx[10];
							string stmp;
							string ttmp;
							sprintf( optx, ".opt%02d", i );
							sprintf( valx, ".val%02d", i );
							if( !menu_file.GetParam( wgt_id + optx, stmp ) )
							{
								if( verbose_output ) cout << wgt_id << ": option number " << i << " not found, aborting." << endl;
								break;
							}
							else
							{
								if( !menu_file.GetParam( wgt_id + valx, ttmp ) )
								{
									if( verbose_output ) cout << wgt_id << ": value number " << i << " not found, using [empty]." << endl;
									ttmp = "";
								}
								else
								{
									if( verbose_output ) cout << wgt_id << ": string wheel option " << stmp << " (" << i << ") found, value: " << ttmp << endl;
								}
								whl_list.push_back( stmp );
								val_list.push_back( ttmp );
							}
						}
					}
					swhl->SetOptionList( whl_list );
					swhl->SetValueList( val_list );
				}

				if( !menu_file.GetParam( wgt_id + ".wheelval", whl_val ) )
				{
					// there is no default wheel value so use the value from settings
				}
				else
				{
					if( verbose_output ) cout << wgt_id << ": wheel value: " << whl_val << endl;
				}
				swhl->SetValue( whl_val );
				swhl->SetDefaultValue( whl_val );

				// see if this wheel is hooked to another widget (multi-image)
				if( !menu_file.GetParam( wgt_id + ".hook", wgt_hook ) )
				{
					if( verbose_output ) cout << wgt_id << ": wheel hook not found. no hook." << endl;
				}
				else
				{
					if( verbose_output ) cout << wgt_id << ": wheel hooked to widget: " << wgt_hook << endl;
				}
				swhl->SetHook( wgt_hook );

				// get the spacing between the wheel text and wheel
				if( !menu_file.GetParam( wgt_id + ".spacing", whl_spacing ) )
				{
					if( verbose_output ) cout << wgt_id << ": spacing not found, using default 0.3." << endl;
					whl_spacing = 0.3;
				}
				else
				{
					if( verbose_output ) cout << wgt_id << ": wheel spacing: " << whl_spacing << endl;
				}
				swhl->SetSpacing( whl_spacing );

				page_objects.push_back( swhl );
			}
			else if( wgt_type == "intwheel" )
			{
				iwhl = new Wheel<int>( wgt );
				vector<string> whl_list;
				vector<int> val_list;
				int whl_val = 0;
				float whl_spacing;
				int whl_opts;

				// see what setting this wheel is hooked to
				if( !menu_file.GetParam( wgt_id + ".setting", wgt_setting ) )
				{
					if( verbose_output ) cout << wgt_id << ": setting not found. This wheel will not affect anything." << endl;
				}
				else
				{
					if( !settings.Get( wgt_setting, whl_val ) )
					{
						if( verbose_output ) cout << wgt_id << ": setting unknown. This wheel will not affect anything." << endl;
					}
					else
					{
						if( verbose_output ) cout << wgt_id << ": wheel hooked to " << wgt_setting << ", got value: " << whl_val << endl;
					}
				}
				iwhl->SetSetting( wgt_setting );

				size_t pos = wgt_setting.find( ".", 0 );
				string cat = wgt_setting.substr( 0, pos );
				wgt_setting.erase( 0, pos + 1 );
				string name = wgt_setting;
				OPTION<int> option = settings.GetIntOption( cat, name );
				if( value_source == "options" )
				{
					iwhl->SetText( _(option.GetTitle()) );
					iwhl->SetTip( _(option.GetDesc()) );
					iwhl->SetOptionList( option.GetOptionList() );
					iwhl->SetValueList( option.GetValueList() );
				}
				else if( value_source == "manual" )
				{
					// get the number of options for the wheel
					if( !menu_file.GetParam( wgt_id + ".opts", whl_opts ) )
					{
						if( verbose_output ) cout << wgt_id << ": unknown number of wheel options." << endl;
					}
					else
					{
						if( verbose_output ) cout << wgt_id << ": reading " << whl_opts << " wheel options." << endl;
						for( int i = 0; i < whl_opts; i++ )
						{
							char optx[10];
							char valx[10];
							string stmp;
							int ttmp;
							sprintf( optx, ".opt%02d", i );
							sprintf( valx, ".val%02d", i );
							if( !menu_file.GetParam( wgt_id + optx, stmp ) )
							{
								if( verbose_output ) cout << wgt_id << ": option number " << i << " not found, aborting." << endl;
								break;
							}
							else
							{
								if( !menu_file.GetParam( wgt_id + valx, ttmp ) )
								{
									if( verbose_output ) cout << wgt_id << ": value number " << i << " not found, using 0." << endl;
									ttmp = 0;
								}
								else
								{
									if( verbose_output ) cout << wgt_id << ": int wheel option " << stmp << " (" << i << ") found, value: " << ttmp << endl;
								}
								whl_list.push_back( stmp );
								val_list.push_back( ttmp );
							}
						}
					}
					iwhl->SetOptionList( whl_list );
					iwhl->SetValueList( val_list );
				}

				if( !menu_file.GetParam( wgt_id + ".wheelval", whl_val ) )
				{
					// there is no default wheel value so use the value from settings
				}
				else
				{
					if( verbose_output ) cout << wgt_id << ": wheel value: " << whl_val << endl;
				}
				iwhl->SetValue( whl_val );
				iwhl->SetDefaultValue( whl_val );

				bool whl_saved;
				if( !menu_file.GetParam( wgt_id + ".saved", whl_saved ) )
				{
					// blah
					whl_saved = true;
				}
				else
				{
					if( verbose_output ) cout << wgt_id << ": wheel saved: " << whl_saved << endl;
				}
				iwhl->SetSaved( whl_saved );

				// see if this wheel is hooked to another widget (multi-image)
				if( !menu_file.GetParam( wgt_id + ".hook", wgt_hook ) )
				{
					if( verbose_output ) cout << wgt_id << ": wheel hook not found. no hook." << endl;
				}
				else
				{
					if( verbose_output ) cout << wgt_id << ": wheel hooked to widget: " << wgt_hook << endl;
				}
				iwhl->SetHook( wgt_hook );

				// get the spacing between the wheel text and wheel
				if( !menu_file.GetParam( wgt_id + ".spacing", whl_spacing ) )
				{
					if( verbose_output ) cout << wgt_id << ": spacing not found, using default 0.3." << endl;
					whl_spacing = 0.3;
				}
				else
				{
					if( verbose_output ) cout << wgt_id << ": wheel spacing: " << whl_spacing << endl;
				}
				iwhl->SetSpacing( whl_spacing );

				page_objects.push_back( iwhl );
			}
			else if( wgt_type == "intintwheel" )
			{
				iiwhl = new Wheel2<int, int>( wgt );
				string whl_setting_1, whl_setting_2;
				vector<string> whl_list;
				vector<int> val_list_1;
				vector<int> val_list_2;
				int whl_val_1 = 0;
				int whl_val_2 = 0;
				float whl_spacing;
				int whl_opts;

				// see what setting this wheel's first value is hooked to
				if( !menu_file.GetParam( wgt_id + ".setting1", whl_setting_1 ) )
				{
					if( verbose_output ) cout << wgt_id << ": setting1 not found. This wheel will not affect anything." << endl;
				}
				else
				{
					if( !settings.Get( whl_setting_1, whl_val_1 ) )
					{
						if( verbose_output ) cout << wgt_id << ": setting1 unknown. This wheel will not affect anything." << endl;
					}
					else
					{
						if( verbose_output ) cout << wgt_id << ": wheel setting1 hooked to " << whl_setting_1 << ", got value: " << whl_val_1 << endl;
					}
				}
				iiwhl->SetSetting1( whl_setting_1 );

				// see what setting this wheel's second value is hooked to
				if( !menu_file.GetParam( wgt_id + ".setting2", whl_setting_2 ) )
				{
					if( verbose_output ) cout << wgt_id << ": setting2 not found. This wheel will not affect anything." << endl;
				}
				else
				{
					if( !settings.Get( whl_setting_2, whl_val_2 ) )
					{
						if( verbose_output ) cout << wgt_id << ": setting2 unknown. This wheel will not affect anything." << endl;
					}
					else
					{
						if( verbose_output ) cout << wgt_id << ": wheel setting2 hooked to " << whl_setting_2 << ", got value: " << whl_val_2 << endl;
					}
				}
				iiwhl->SetSetting2( whl_setting_2 );

				size_t pos = whl_setting_1.find( ".", 0 );
				string cat = whl_setting_1.substr( 0, pos );
				whl_setting_1.erase( 0, pos + 1 );
				string name = whl_setting_1;
				OPTION<int> option_1 = settings.GetIntOption( cat, name );
				pos = whl_setting_2.find( ".", 0 );
				cat = whl_setting_2.substr( 0, pos );
				whl_setting_2.erase( 0, pos + 1 );
				name = whl_setting_2;
				OPTION<int> option_2 = settings.GetIntOption( cat, name );
				if( value_source == "options" )
				{
					iiwhl->SetText( _(option_1.GetTitle()) );
					iiwhl->SetTip( _(option_1.GetDesc()) );
					iiwhl->SetOptionList( option_1.GetOptionList() );
					iiwhl->SetValueList1( option_1.GetValueList() );
					iiwhl->SetValueList2( option_2.GetValueList() );
				}
				else if( value_source == "manual" )
				{
					// get the number of options for the wheel
					if( !menu_file.GetParam( wgt_id + ".opts", whl_opts ) )
					{
						if( verbose_output ) cout << wgt_id << ": unknown number of wheel options." << endl;
					}
					else
					{
						if( verbose_output ) cout << wgt_id << ": reading " << whl_opts << " wheel options." << endl;
						for( int i = 0; i < whl_opts; i++ )
						{
							char optx[10];
							char valx[10];
							string stmp;
							int ttmp1, ttmp2;
							sprintf( optx, ".opt%02d", i );
							sprintf( valx, ".val%02d", i );
							if( !menu_file.GetParam( wgt_id + optx, stmp ) )
							{
								if( verbose_output ) cout << wgt_id << ": option number " << i << " not found, aborting." << endl;
								break;
							}
							else
							{
								if( !menu_file.GetParam( wgt_id + valx + "-a", ttmp1 ) )
								{
									if( verbose_output ) cout << wgt_id << ": value number " << i << "-a not found, using 0." << endl;
									ttmp1 = 0;
								}
								else
								{
									if( verbose_output ) cout << wgt_id << ": int int wheel option " << stmp << " (" << i << ") found, value: " << ttmp1 << endl;
								}
	
								if( !menu_file.GetParam( wgt_id + valx + "-b", ttmp2 ) )
								{
									if( verbose_output ) cout << wgt_id << ": value number " << i << "-b not found, using 0." << endl;
									ttmp2 = 0;
								}
								else
								{
									if( verbose_output ) cout << wgt_id << ": int int wheel option " << stmp << " (" << i << ") found, value: " << ttmp2 << endl;
								}
								whl_list.push_back( stmp );
								val_list_1.push_back( ttmp1 );
								val_list_2.push_back( ttmp2 );
							}
						}
					}
					iiwhl->SetOptionList( whl_list );
					iiwhl->SetValueList1( val_list_1 );
					iiwhl->SetValueList2( val_list_2 );
				}

				if( !menu_file.GetParam( wgt_id + ".wheelval", whl_val_1 ) )
				{
					// there is no default wheel value so use the value from settings
					if( verbose_output ) cout << wgt_id << ": using previously found wheel value " << whl_val_1 << endl;
				}
				else
				{
					if( verbose_output ) cout << wgt_id << ": wheel value: " << whl_val_1 << endl;
				}
				iiwhl->SetValue1( whl_val_1 );
				iiwhl->SetDefaultValue1( whl_val_1 );

				// get the spacing between the wheel text and wheel
				if( !menu_file.GetParam( wgt_id + ".spacing", whl_spacing ) )
				{
					if( verbose_output ) cout << wgt_id << ": spacing not found, using default 0.3." << endl;
					whl_spacing = 0.3;
				}
				else
				{
					if( verbose_output ) cout << wgt_id << ": wheel spacing: " << whl_spacing << endl;
				}
				iiwhl->SetSpacing( whl_spacing );

				page_objects.push_back( iiwhl );
			}
			else if( wgt_type == "label" )
			{
				lbl = new Label( wgt );
				page_objects.push_back( lbl );
			}
			else if( wgt_type == "calibrate" )
			{
				cal = new Calibrate( wgt );
				page_objects.push_back( cal );
			}
			else if( wgt_type == "image" )
			{
				string img_file = "";
				img = new Image( wgt );

				// get the image's filename
				if( !menu_file.GetParam( wgt_id + ".filename", img_file ) )
				{
					if( verbose_output ) cout << wgt_id << ": filename not found, using [empty]." << endl;
				}
				else
				{
					if( verbose_output ) cout << wgt_id << ": image filename: " << img_file << endl;
				}
				img->SetFilename( settings.GetSkinPath() + "/textures/" + img_file );

				page_objects.push_back( img );
			}
			else if( wgt_type == "textbox" )
			{
				string tbox_val = "", tbox_accepts = "";
				tbox = new TextBox( wgt );
				float tbox_spacing = 0.3;

				// see what setting this text box is hooked to
				if( !menu_file.GetParam( wgt_id + ".setting", wgt_setting ) )
				{
					if( verbose_output ) cout << wgt_id << ": setting not found. This text box will not have a default value." << endl;
				}
				else
				{
					if( verbose_output ) cout << wgt_id << ": setting found: " << wgt_setting << endl;
					if( !settings.Get( wgt_setting, tbox_val ) )
					{
						if( verbose_output ) cout << wgt_id << ": setting unknown. This text box will not affect anything." << endl;
					}
					else
					{
						if( verbose_output ) cout << wgt_id << ": text box hooked to " << wgt_setting << ", got value: " << tbox_val << endl;
					}
				}
				tbox->SetSetting( wgt_setting );

				size_t pos = wgt_setting.find( ".", 0 );
				string cat = wgt_setting.substr( 0, pos );
				wgt_setting.erase( 0, pos + 1 );
				string name = wgt_setting;
				OPTION<string> option = settings.GetStringOption( cat, name );
				if( value_source == "options" )
				{
					tbox->SetText( _(option.GetTitle()) );
					tbox->SetTip( _(option.GetDesc()) );
					tbox->SetAccepts( option.GetAccepts() );
				}
				else if( value_source == "manual" )
				{
					// get the character list this textbox accepts
					if( !menu_file.GetParam( wgt_id + ".accepts", tbox_accepts ) )
					{
						if( verbose_output ) cout << wgt_id << ": accepts list not found - assuming numbers only." << endl;
						tbox_accepts = "1234567890";
					}
					else
					{
						if( verbose_output ) cout << wgt_id << ": textbox accepts: " << tbox_accepts << endl;
					}
					tbox->SetAccepts( tbox_accepts );
				}

				// get the text box's value
				if( !menu_file.GetParam( wgt_id + ".value", tbox_val ) )
				{
					if( verbose_output ) cout << wgt_id << ": filename not found, using value from settings." << endl;
				}
				else
				{
					if( verbose_output ) cout << wgt_id << ": value: " << tbox_val << endl;
				}
				tbox->SetValue( tbox_val );

				// get the spacing between the text box text and text box
				if( !menu_file.GetParam( wgt_id + ".spacing", tbox_spacing ) )
				{
					if( verbose_output ) cout << wgt_id << ": spacing not found, using default 0.3." << endl;
					tbox_spacing = 0.3;
				}
				else
				{
					if( verbose_output ) cout << wgt_id << ": text box spacing: " << tbox_spacing << endl;
				}
				tbox->SetSpacing( tbox_spacing );

				page_objects.push_back( tbox );
			}
			else if( wgt_type == "controlgrab" )
			{
				cgrb = new ControlGrab( wgt );
				bool cgrb_analog = false;
				float cgrb_spacing = 0.3;

				// see what setting this control grab is hooked to
				if( !menu_file.GetParam( wgt_id + ".setting", wgt_setting ) )
				{
					if( verbose_output ) cout << wgt_id << ": setting not found. This control grab will not have a default value." << endl;
				}
				else
				{
					if( verbose_output ) cout << wgt_id << ": setting found: " << wgt_setting << endl;
				}
				cgrb->SetSetting( wgt_setting );

				// see if this is an analog or digital action
				if( !menu_file.GetParam( wgt_id + ".analog", cgrb_analog ) )
				{
					if( verbose_output ) cout << wgt_id << ": analog not found. assuming false." << endl;
					cgrb_analog = false;
				}
				else
				{
					if( verbose_output ) cout << wgt_id << ":analog found, value: " << cgrb_analog << endl;
				}
				cgrb->SetAnalog( cgrb_analog );

				// get the spacing between the control grab text and control grab
				if( !menu_file.GetParam( wgt_id + ".spacing", cgrb_spacing ) )
				{
					if( verbose_output ) cout << wgt_id << ": spacing not found, using default 0.3." << endl;
					cgrb_spacing = 0.3;
				}
				else
				{
					if( verbose_output ) cout << wgt_id << ": control grab spacing: " << cgrb_spacing << endl;
				}
				cgrb->SetSpacing( cgrb_spacing );

				page_objects.push_back( cgrb );
			}
			else if( wgt_type == "spinningcar" )
			{
				vector<string> car_file_list;
				vector<string> car_val_list;
				string car_val = "";
				int car_opts = 0;
				scar = new SpinningCar( wgt );
				float scar_pos[3];

				// see what setting this spinning car is hooked to
				if( !menu_file.GetParam( wgt_id + ".setting", wgt_setting ) )
				{
					if( verbose_output ) cout << wgt_id << ": setting not found. This spinning car will not have a default value." << endl;
				}
				else
				{
					if( verbose_output ) cout << wgt_id << ": setting found: " << wgt_setting << endl;
					if( !settings.Get( wgt_setting, car_val ) )
					{
						if( verbose_output ) cout << wgt_id << ": setting unknown. This spinning car will not affect anything." << endl;
					}
					else
					{
						if( verbose_output ) cout << wgt_id << ": spinning car hooked to " << wgt_setting << ", got value: " << car_val << endl;
					}
				}
				scar->SetSetting( wgt_setting );

				size_t pos = wgt_setting.find( ".", 0 );
				string cat = wgt_setting.substr( 0, pos );
				wgt_setting.erase( 0, pos + 1 );
				string name = wgt_setting;
				OPTION<string> option = settings.GetStringOption( cat, name );
				if( value_source == "options" )
				{
					car_val_list = option.GetOptionList();
					car_file_list = option.GetValueList();
					scar->SetText( _(option.GetTitle()) );
					scar->SetTip( _(option.GetDesc()) );
					scar->SetValueList( car_val_list );
					scar->SetFilenameList( car_file_list );
				}
				else if( value_source == "manual" )
				{
					// get the spinning car's filename
					// get the number of options for the spinning car
					if( !menu_file.GetParam( wgt_id + ".opts", car_opts ) )
					{
						if( verbose_output ) cout << wgt_id << ": unknown number of spinning car options." << endl;
					}
					else
					{
						if( verbose_output ) cout << wgt_id << ": reading " << car_opts << " spinning car options." << endl;
						for( int i = 0; i < car_opts; i++ )
						{
							char optx[10];
							char valx[10];
							string stmp;
							string ttmp;
							sprintf( optx, ".opt%02d", i );
							sprintf( valx, ".val%02d", i );
							if( !menu_file.GetParam( wgt_id + optx, stmp ) )
							{
								if( verbose_output ) cout << wgt_id << ": filename number " << i << " not found, aborting." << endl;
								break;
							}
							else
							{
								if( !menu_file.GetParam( wgt_id + valx, ttmp ) )
								{
									if( verbose_output ) cout << wgt_id << ": value number " << i << " not found, using [empty]." << endl;
									ttmp = "";
								}
								else
								{
									if( verbose_output ) cout << wgt_id << ": spinning car filename " << stmp << " (" << i << ") found, value: " << ttmp << endl;
								}
								car_file_list.push_back( stmp );
								car_val_list.push_back( ttmp );
							}
						}
					}
					scar->SetValueList( car_val_list );
					scar->SetFilenameList( car_file_list );
					if( verbose_output ) cout << wgt_id << ":setting spinning car value: " << car_val << endl;
				}
				scar->SetValue( car_val );

				// get the carpos
				if( !menu_file.GetParam( wgt_id + ".carpos", scar_pos ) )
				{
					if( verbose_output ) cout << wgt_id << ": car position not found. Using 0,0,0." << endl;
					scar_pos[0] = scar_pos[1] = scar_pos[2] = 0.0;
				}
				else
				{
					if( verbose_output ) cout << wgt_id << ": car position: " << scar_pos[0] << "," << scar_pos[1] << "," << scar_pos[2] << endl;
				}
				scar->SetCarPos( scar_pos );

				page_objects.push_back( scar );
			}
			else if( wgt_type == "multi-image" )
			{
				vector<string> img_file_list;
				vector<string> val_list;
				string mimg_val = "";
				int mimg_opts = 0;
				mimg = new MultiImage( wgt );

				// see what setting this multi image is hooked to
				if( !menu_file.GetParam( wgt_id + ".setting", wgt_setting ) )
				{
					if( verbose_output ) cout << wgt_id << ": setting not found. This multi image will not have a default value." << endl;
				}
				else
				{
					if( verbose_output ) cout << wgt_id << ": setting found: " << wgt_setting << endl;
					if( !settings.Get( wgt_setting, mimg_val ) )
					{
						if( verbose_output ) cout << wgt_id << ": setting unknown. This wheel will not affect anything." << endl;
					}
					else
					{
						if( verbose_output ) cout << wgt_id << ": wheel hooked to " << wgt_setting << ", got value: " << mimg_val << endl;
					}
				}
				mimg->SetSetting( wgt_setting );

				size_t pos = wgt_setting.find( ".", 0 );
				string cat = wgt_setting.substr( 0, pos );
				wgt_setting.erase( 0, pos + 1 );
				string name = wgt_setting;
				OPTION<string> option = settings.GetStringOption( cat, name );
				if( value_source == "options" )
				{
					mimg->SetText( _(option.GetTitle()) );
					mimg->SetTip( _(option.GetDesc()) );
					mimg->SetValueList( option.GetOptionList() );
					mimg->SetFilenameList( option.GetValueList() );
				}
				else if( value_source == "manual" )
				{
					// get the number of options for the multi image
					if( !menu_file.GetParam( wgt_id + ".opts", mimg_opts ) )
					{
						if( verbose_output ) cout << wgt_id << ": unknown number of MultiImage options." << endl;
					}
					else
					{
						if( verbose_output ) cout << wgt_id << ": reading " << mimg_opts << " MultiImage options." << endl;
						for( int i = 0; i < mimg_opts; i++ )
						{
							char optx[10];
							char valx[10];
							string stmp;
							string ttmp;
							sprintf( optx, ".opt%02d", i );
							sprintf( valx, ".val%02d", i );
							if( !menu_file.GetParam( wgt_id + optx, stmp ) )
							{
								if( verbose_output ) cout << wgt_id << ": filename number " << i << " not found, aborting." << endl;
								break;
							}
							else
							{
								if( !menu_file.GetParam( wgt_id + valx, ttmp ) )
								{
									if( verbose_output ) cout << wgt_id << ": value number " << i << " not found, using [empty]." << endl;
									ttmp = "";
								}
								else
								{
									if( verbose_output ) cout << wgt_id << ": multi image filename " << stmp << " (" << i << ") found, value: " << ttmp << endl;
								}
								img_file_list.push_back( stmp );
								val_list.push_back( ttmp );
							}
						}
					}
					mimg->SetValueList( val_list );
					mimg->SetFilenameList( img_file_list );
					if( verbose_output ) cout << wgt_id << ":setting multi image value: " << mimg_val << endl;
				}
				mimg->SetValue( mimg_val );

				page_objects.push_back( mimg );
			}
			else
			{
				if( verbose_output ) cout << wgt_id << ": type unknown. Using type label." << endl;
				lbl = new Label( wgt );
				page_objects.push_back( lbl );
			}
		}
		else
		{
			if( verbose_output ) cout << wgt_id << ": type not found. Can't use this widget, skipping." << endl;
			break;
		}

		delete wgt;
	}
}

void Page::DeInit()
{
}

void Page::Draw()
{
	Draw( 1.0 );
}

void Page::Draw( float opacity )
{
	if( tab_text == "" )
	{
		// draw background image
		utility.Draw2D( 0.0, 0.0, 1.0, 1.0, &background, 0.0, 0, opacity );
	}

	if( num_tabs > 0 )
	{
		string tab_text;
		float tab_width, tab_text_opacity;
		TEXTURE_HANDLE * tab_img;
		float half_tabwindow_width = 0.3;
		float half_tabwindow_height = 0.35;
		float tab_x = 0.5 - half_tabwindow_width;
		float tab_y = 0.5 - half_tabwindow_height;

		utility.Draw2D( tab_x + 0.000868,
		                tab_y + (0.02777*2.0) - 0.001157,
		                tab_x + 0.6,
		                tab_y + 0.6,
		                &tab_page_background, 0.0, 0, 0.9 );

		for( unsigned int t = 0; t < num_tabs; t++ )
		{
			tab_text = tabs[t]->GetTabText();
			tab_width = font.Width( tab_text.c_str(), 1, 7 );
			tab_img = t == cur_tab ? &tab_active : &tab_inactive;
			tab_text_opacity = t == cur_tab ? 1.0 : 0.6;
			utility.DrawButton( tab_x + (0.02777*2.0),
			                    tab_y,
			                    tab_x + (0.02777) + tab_width,
			                    tab_y + (0.02777*2.0),
			                    (0.02777*2.0), tab_img, opacity * 0.9 );
			font.Print( tab_x + 0.02777, tab_y - (0.02777/2.0), tab_text.c_str(), 1, 7, 1.0, 1.0, 1.0, opacity * tab_text_opacity );
			tab_x += (0.02777*2.0) + tab_width + (0.02777);
		}

		tabs[cur_tab]->Draw( opacity );
	}

	// draw objects on this page
	for( unsigned int i = 0; i < page_objects.size(); i++ )
	{
		page_objects[i]->Draw( opacity );
	}
}

void Page::UpWidget()
{
	page_objects[cur_obj]->SetSelected( false );

	if( cur_obj == 0 )
		cur_obj = num_widgets - 1;
	else
		cur_obj--;

	while( !page_objects[cur_obj]->GetEnabled() )
	{
		if( cur_obj == 0 )
			cur_obj = num_widgets - 1;
		else
			cur_obj--;
	}

	page_objects[cur_obj]->SetSelected( true );

	if( page_objects[cur_obj]->GetType() == "controlgrab" )
	{
		page_objects[cur_obj]->SelectIcon( 0 );
	}
}

void Page::DownWidget()
{
	page_objects[cur_obj]->SetSelected( false );

	cur_obj++;
	if( cur_obj == num_widgets )
		cur_obj = 0;

	while( !page_objects[cur_obj]->GetEnabled() )
	{
		cur_obj++;
		if( cur_obj == num_widgets )
			cur_obj = 0;
	}

	page_objects[cur_obj]->SetSelected( true );

	if( page_objects[cur_obj]->GetType() == "controlgrab" )
	{
		page_objects[cur_obj]->SelectIcon( 0 );
	}
}

void Page::LeftWidgetPress()
{
	ReleaseWidgets();

	string type = page_objects[cur_obj]->GetType();

	if( ( type == "slider" ) ||
	    ( type == "floatwheel" ) ||
	    ( type == "stringwheel" ) ||
	    ( type == "intwheel" ) ||
	    ( type == "intintwheel" ) ||
	    ( type == "spinningcar" ) ||
	    ( type == "controlgrab" ) ||
	    ( type == "textbox" ) )
	{
		l_pressed = true;
		clicked_obj = cur_obj;
		page_objects[clicked_obj]->DecValuePress();
		if( ( type == "intwheel" ) || ( type == "stringwheel" ) )
		{
			string hook = page_objects[clicked_obj]->GetHook();
			if( hook != "" )
			{
				for( unsigned int i = 0; i < page_objects.size(); i++ )
				{
					string aname = page_objects[i]->GetName();
					if( aname == hook )
					{
						page_objects[i]->HookDecValuePress();
						break;
					}
				}
			}
		}
	}
	else if( type == "toggle" )
	{
		l_pressed = true;
		clicked_obj = cur_obj;
		page_objects[clicked_obj]->Press();
	}
	else
	{
		UpWidget();
	}
}

void Page::RightWidgetPress()
{
	ReleaseWidgets();

	string type = page_objects[cur_obj]->GetType();

	if( ( type == "slider" ) ||
	    ( type == "floatwheel" ) ||
	    ( type == "stringwheel" ) ||
	    ( type == "intwheel" ) ||
	    ( type == "intintwheel" ) ||
	    ( type == "spinningcar" ) ||
	    ( type == "controlgrab" ) ||
	    ( type == "textbox" ) )
	{
		r_pressed = true;
		clicked_obj = cur_obj;
		page_objects[clicked_obj]->IncValuePress();
		if( ( type == "intwheel" ) || ( type == "stringwheel" ) )
		{
			string hook = page_objects[clicked_obj]->GetHook();
			if( hook != "" )
			{
				for( unsigned int i = 0; i < page_objects.size(); i++ )
				{
					string aname = page_objects[i]->GetName();
					if( aname == hook )
					{
						page_objects[i]->HookIncValuePress();
						break;
					}
				}
			}
		}
	}
	else if( type == "toggle" )
	{
		r_pressed = true;
		clicked_obj = cur_obj;
		page_objects[clicked_obj]->Press();
	}
	else
	{
		DownWidget();
	}
}

void Page::LeftWidgetRelease()
{
	string type = "";
	if( clicked_obj == 10000 )
		return;

	if( clicked_obj == cur_obj )
	{
		type = page_objects[clicked_obj]->GetType();
		if( ( type == "slider" ) ||
		    ( type == "floatwheel" ) ||
		    ( type == "stringwheel" ) ||
		    ( type == "intwheel" ) ||
		    ( type == "intintwheel" ) ||
		    ( type == "spinningcar" ) ||
		    ( type == "controlgrab" ) ||
		    ( type == "textbox" ) )
		{
			page_objects[clicked_obj]->DecValueRelease();
			has_changes = true;

			if( ( type == "intwheel" ) || ( type == "stringwheel" ) )
			{
				string hook = page_objects[clicked_obj]->GetHook();
				if( hook != "" )
				{
					for( unsigned int i = 0; i < page_objects.size(); i++ )
					{
						string aname = page_objects[i]->GetName();
						if( aname == hook )
						{
							page_objects[i]->HookDecValueRelease();
							break;
						}
					}
				}
			}
		}
		else if( type == "toggle" )
		{
			page_objects[clicked_obj]->SetValue( true );
			has_changes = true;
		}
	}

	ReleaseWidgets();
}

void Page::RightWidgetRelease()
{
	string type = "";
	if( clicked_obj == 10000 )
		return;

	if( clicked_obj == cur_obj )
	{
		type = page_objects[clicked_obj]->GetType();
		if( ( type == "slider" ) ||
		    ( type == "floatwheel" ) ||
		    ( type == "stringwheel" ) ||
		    ( type == "intwheel" ) ||
		    ( type == "intintwheel" ) ||
		    ( type == "spinningcar" ) ||
		    ( type == "controlgrab" ) ||
		    ( type == "textbox" ) )
		{
			page_objects[clicked_obj]->IncValueRelease();
			has_changes = true;

			if( ( type == "intwheel" ) || ( type == "stringwheel" ) )
			{
				string hook = page_objects[clicked_obj]->GetHook();
				if( hook != "" )
				{
					for( unsigned int i = 0; i < page_objects.size(); i++ )
					{
						string aname = page_objects[i]->GetName();
						if( aname == hook )
						{
							page_objects[i]->HookIncValueRelease();
							break;
						}
					}
				}
			}
		}
		else if( type == "toggle" )
		{
			page_objects[clicked_obj]->SetValue( false );
			has_changes = true;
		}
	}

	ReleaseWidgets();
}

void Page::ReleaseWidgets()
{
	string type = "";
	r_pressed = l_pressed = false;
	for( unsigned int i = 0; i < page_objects.size(); i++ )
	{
		type = page_objects[i]->GetType();

		if( ( type == "slider" ) ||
		    ( type == "floatwheel" ) ||
		    ( type == "stringwheel" ) ||
		    ( type == "intwheel" ) ||
		    ( type == "intintwheel" ) ||
		    ( type == "toggle" ) ||
		    ( type == "multi-image" ) ||
		    ( type == "spinningcar" ) ||
		    ( type == "textbox" ) ||
		    ( type == "controlgrab" ) )
		{
			page_objects[i]->Release();

			if( type == "stringwheel" )
			{
				string hook = page_objects[i]->GetHook();
				if( hook != "" )
				{
					for( unsigned int j = 0; j < page_objects.size(); j++ )
					{
						string aname = page_objects[j]->GetName();
						if( aname == hook )
						{
							page_objects[j]->HookRelease();
							break;
						}
					}
				}
			}
		}

	}

	clicked_obj = 10000;	
}

void Page::BackspacePress()
{
	string type = page_objects[cur_obj]->GetType();
	if( type == "textbox" )
	{
		page_objects[cur_obj]->BackspacePress();
	}
}

void Page::DeletePress()
{
	string type = page_objects[cur_obj]->GetType();
	if( type == "textbox" )
	{
		page_objects[cur_obj]->DeletePress();
	}
}

void Page::BackspaceRelease()
{
	string type = page_objects[cur_obj]->GetType();
	if( type == "textbox" )
	{
		has_changes = true;
		page_objects[cur_obj]->BackspaceRelease();
	}
}

void Page::DeleteRelease()
{
	string type = page_objects[cur_obj]->GetType();
	if( type == "textbox" )
	{
		has_changes = true;
		page_objects[cur_obj]->DeleteRelease();
	}
}

string Page::ExecWidget()
{
	string type = page_objects[cur_obj]->GetType();
	string action = "";

	if( type == "button" )
	{
		action = page_objects[cur_obj]->GetAction();
	}
	else if( type == "toggle" )
	{
		page_objects[cur_obj]->TogValue();
		has_changes = true;
	}
	else if( type == "controlgrab" )
	{
		has_changes = true;
		if( page_objects[cur_obj]->GetAdding() )
		{
			action = "Lock";
		}
	}

	if( page_objects[cur_obj]->GetDefault() )
	{
		SaveSettings();
		has_changes = false;

		if( name == "DisplayOptions" || name == "InGameDisplayOptions" )
		{
			action = "ReloadDisplay";
		}
		else if( name == "MouseOptions" || name == "InGameMouseOptions" )
		{
			action = "UpdateMouse";
			//mouse.UpdateSettings();
		}
		else if( name == "JoystickOptions" || name == "InGameJoystickOptions" )
		{
			action = "UpdateJoystick";
			//gamecontrols.UpdateSettings();
		}
		else if( name == "JoystickCalibrate" || name == "InGameJoystickCalibrate" )
		{
			action = "UpdateCalibrations";
		}
		else if( name == "ControlsOptions" || name == "InGameControlsOptions" )
		{
			action = "UpdateControls";
			//gamecontrols.UpdateSettings();
			//world.UpdateSettings();
		}
		else if( name == "SoundOptions" || name == "InGameSoundOptions" )
		{
			action = "UpdateSound";
			//sound.UpdateSettings();
			//world.UpdateSettings();
		}

		cur_obj = default_obj;
	}
	else if( page_objects[cur_obj]->GetCancel() )
	{
		has_changes = false;
		//ClearSettings();
	}

	return action;
}

void Page::CancelPress()
{
	for( unsigned int i = 0; i < page_objects.size(); i++ )
	{
		if( page_objects[i]->GetCancel() )
		{
			page_objects[cur_obj]->SetSelected( false );
			cancel_obj = cur_obj = i;
			page_objects[cur_obj]->SetSelected( true );
			page_objects[i]->Press();
			break;
		}
	}
}

string Page::CancelRelease()
{
	string action = "";

	for( unsigned int i = 0; i < page_objects.size(); i++ )
	{
		if( page_objects[i]->GetCancel() && ( i == cancel_obj ) )
		{
			page_objects[i]->Release();
			action = page_objects[i]->GetAction();
			//ClearSettings();
			cancel_obj = 0;
			break;
		}
	}

	return action;
}

void Page::KeyPress()
{
	string type = page_objects[cur_obj]->GetType();

	if( ( type == "toggle" ) || ( type == "button" ) || ( type == "controlgrab" ) )
	{
		has_changes = true;
		clicked_obj = cur_obj;
		page_objects[cur_obj]->Press();
	}
}

string Page::KeyRelease()
{
	string type = "";
	if( clicked_obj != 10000 ) type = page_objects[clicked_obj]->GetType();
	else return "";

	string action = "";

	if( ( type == "toggle" ) || ( type == "button" ) || ( type == "controlgrab" ) )
	{
		has_changes = true;
		page_objects[clicked_obj]->Release();
		if( cur_obj == clicked_obj )
		{
			action = ExecWidget();
		}
	}

	return action;
}

void Page::Type( SDLKey key )
{
	if( page_objects[cur_obj]->GetType() == "textbox" )
	{
		has_changes = true;
		page_objects[cur_obj]->EnterText( key );
	}
}

void Page::SaveSettings()
{
	string type;

	if( !has_changes )
		return;

	for( unsigned int i = 0; i < page_objects.size(); i++ )
	{
		type = page_objects[i]->GetType();

		if( ( type == "toggle" ) ||
		    ( type == "slider" ) ||
		    ( type == "floatwheel" ) ||
		    ( type == "stringwheel" ) ||
		    ( type == "intwheel" ) ||
		    ( type == "intintwheel" ) ||
		    ( type == "controlgrab" ) ||
		    ( type == "spinningcar" ) ||
		    ( type == "calibrate" ) )
		{
			if( page_objects[i]->GetSaved() )
				page_objects[i]->Save();
		}
	}

	SelectDefault();

	has_changes = false;
	
	for( unsigned int i = 0; i < tabs.size(); i++ )
	{
		tabs[i]->SaveSettings();
	}
}

void Page::ClearSettings()
{
	if( !has_changes )
	{
		string type;
		for( unsigned int i = 0; i < page_objects.size(); i++ )
		{
			type = page_objects[i]->GetType();
	
			if( ( type == "toggle" ) ||
			    ( type == "slider" ) ||
			    ( type == "floatwheel" ) ||
			    ( type == "stringwheel" ) ||
			    ( type == "intwheel" ) ||
			    ( type == "intintwheel" ) ||
			    ( type == "multi-image" ) ||
			    ( type == "controlgrab" ) ||
			    ( type == "spinningcar" ) ||
			    ( type == "calibrate" ) )
			{
				page_objects[i]->ResetValue();
			}
		}
	}

	for( unsigned int i = 0; i < tabs.size(); i++ )
	{
		tabs[i]->ClearSettings();
	}
}

void Page::MouseSelect( float x, float y )
{
	if( clicked_obj != 10000 && !( l_pressed || r_pressed ) )
	{
		if( page_objects[clicked_obj]->GetType() == "slider" )
		{
			has_changes = true;
			page_objects[clicked_obj]->MousePress( x, y );
		}
	}

	for( unsigned int i = 0; i < page_objects.size(); i++ )
	{
		if( page_objects[i]->MouseOver( x, y ) )
		{
			if( page_objects[i]->GetEnabled() )
			{
				page_objects[cur_obj]->SetSelected( false );
				page_objects[i]->SetSelected( true );
				cur_obj = i;
			}
		}
	}

	if( num_tabs > 0 )
	{
		tabs[cur_tab]->MouseSelect( x, y );
	}
}

bool Page::MouseOver( float x, float y )
{
	if( page_objects[cur_obj]->MouseOver( x, y ) )
	{
		if( page_objects[cur_obj]->GetEnabled() )
		{
			return true;
		}
	}

	if( num_tabs > 0 )
	{
		float half_tabwindow_width = 0.3;
		float half_tabwindow_height = 0.35;
		float tab_x = 0.5 - half_tabwindow_width;
		float tab_y = 0.5 - half_tabwindow_height;

		if( ( x >= ( tab_x + 0.000868 ) ) &&
		    ( y >= ( tab_y + (0.02777*2.0) - 0.001157 ) ) &&
		    ( x <= ( tab_x + 0.6 ) ) &&
		    ( y <= ( tab_y + 0.6 ) ) )
		{
			return tabs[cur_tab]->MouseOver( x, y );
		}
	}

	return false;
}

string Page::MousePressWidget( float x, float y )
{
	if( num_tabs > 0 )
	{
		float half_tabwindow_width = 0.3;
		float half_tabwindow_height = 0.35;
		float tab_x = 0.5 - half_tabwindow_width;
		float tab_y = 0.5 - half_tabwindow_height;

		if( ( x >= ( tab_x + 0.000868 ) ) &&
		    ( y >= ( tab_y + (0.02777*2.0) - 0.001157 ) ) &&
		    ( x <= ( tab_x + 0.6 ) ) &&
		    ( y <= ( tab_y + 0.6 ) ) )
		{
			string action = tabs[cur_tab]->MousePressWidget( x, y );
			cout << "asldkfjhsladkf" << endl;
			return "";
		}
	}
	else 
	{
		string action = page_objects[cur_obj]->MousePress( x, y );
		string type = page_objects[cur_obj]->GetType();
		if( ( type == "stringwheel" ) || ( type == "intwheel" ) )
		{
			string hook = page_objects[cur_obj]->GetHook();
			if( hook != "" )
			{
				for( unsigned int i = 0; i < page_objects.size(); i++ )
				{
					string name = page_objects[i]->GetName();
					if( name == hook )
					{
						if( action == hook + "L" )
						{
							page_objects[i]->HookDecValuePress();
						}
						else if( action == hook + "R" )
						{
							page_objects[i]->HookIncValuePress();
						}
					}
				}
			}
		}
		clicked_obj = cur_obj;
	}

	return "";
}

string Page::MouseReleaseWidget( float x, float y )
{
	if( num_tabs > 0 )
	{
		float half_tabwindow_width = 0.3;
		float half_tabwindow_height = 0.35;
		float tab_x = 0.5 - half_tabwindow_width;
		float tab_y = 0.5 - half_tabwindow_height;

		if( ( x >= ( tab_x + 0.000868 ) ) &&
		    ( y >= ( tab_y + (0.02777*2.0) - 0.001157 ) ) &&
		    ( x <= ( tab_x + 0.6 ) ) &&
		    ( y <= ( tab_y + 0.6 ) ) )
		{
			string action = tabs[cur_tab]->MouseReleaseWidget( x, y );
			cout << "halloooo" << endl;
			return "";
		}
	}
	else
	{
		string action = "";
		if( clicked_obj != 10000 )
		{
			action = page_objects[clicked_obj]->MouseRelease( x, y );
			has_changes = true;
		}

		if( clicked_obj == cur_obj )
		{
			string type = page_objects[cur_obj]->GetType();
			if( ( type == "stringwheel" ) || ( type == "intwheel" ) )
			{
				string hook = page_objects[cur_obj]->GetHook();
				if( hook != "" )
				{
					for( unsigned int i = 0; i < page_objects.size(); i++ )
					{
						string name = page_objects[i]->GetName();
						if( name == hook )
						{
							if( action == hook + "L" )
							{
								page_objects[i]->HookDecValueRelease();
							}
							else if( action == hook + "R" )
							{
								page_objects[i]->HookIncValueRelease();
							}
						}
					}
				}
			}

			if( page_objects[clicked_obj]->MouseOver( x, y ) && ( ( type == "button" ) || ( type == "toggle" ) || ( type == "controlgrab" ) ) )
			{
				return ExecWidget();
			}
		}

		clicked_obj = 10000;
	}

	return "";
}

void Page::StartGame()
{
	if( ( name == "PracticeGame" ) || ( name == "NetworkGame" ) )
	{
		for( unsigned int i = 0; i < page_objects.size(); i++ )
		{
			if( page_objects[i]->GetName() == "SpinningCar" )
			{
				page_objects[i]->ClearCar();
			}
		}
	}
}

void Page::ControlGrabKey( SDLKey key )
{
	if( page_objects[cur_obj]->GetType() == "controlgrab" )
	{
		page_objects[cur_obj]->GrabKey( key );
	}
}

void Page::ControlGrabMouseMove( string direction )
{
	if( page_objects[cur_obj]->GetType() == "controlgrab" )
	{
		page_objects[cur_obj]->GrabMouseMovement( direction );
	}
}

void Page::ControlGrabMouseButton( int button_idx )
{
	if( page_objects[cur_obj]->GetType() == "controlgrab" )
	{
		page_objects[cur_obj]->GrabMouseButton( button_idx );
	}
}

void Page::ControlGrabJoyButton( Uint8 joy_idx, Uint8 joy_btn )
{
	if( page_objects[cur_obj]->GetType() == "controlgrab" )
	{
		page_objects[cur_obj]->GrabJoyButton( joy_idx, joy_btn );
	}
}

void Page::ControlGrabJoyMove( Uint8 joy_idx, Uint8 joy_axis, bool joy_positive, float joy_value )
{
	string type = page_objects[cur_obj]->GetType() ;
	if( type == "controlgrab" )
	{
		page_objects[cur_obj]->GrabJoyMove( joy_idx, joy_axis, joy_positive, joy_value );
	}
	else
	{
		vector<Widget*>::iterator objs_iter;
		for( objs_iter = page_objects.begin(); objs_iter != page_objects.end(); ++objs_iter )
		{
			if( (*objs_iter)->GetType() == "calibrate" )
			{
				(*objs_iter)->GrabJoyMove( joy_idx, joy_axis, joy_positive, joy_value );
			}
		}
	}
}


/*
TabbedPage::TabbedPage( Page* pg )
{
	// Create a page from the passed in page, fill with tabs
}

TabbedPage::~TabbedPage()
{
	// destroy all tabbed pages
	for( unsigned int i = 0; i < tabs.size(); i++ )
	{
		delete tabs[i];
	}
}

void TabbedPage::SaveSettings()
{
	// save settings on all tabbed pages
	for( unsigned int i = 0; i < tabs.size(); i++ )
	{
		tabs[i]->SaveSettings();
	}
}

void TabbedPage::ClearSettings()
{`
	// clear settings on all tabbed pages
	for( unsigned int i = 0; i < tabs.size(); i++ )
	{
		tabs[i]->ClearSettings();
	}
}

void TabbedPage::SelectDefault()
{
	// select defaults on all tabbed pages
	for( unsigned int i = 0; i < tabs.size(); i++ )
	{
		tabs[i]->SelectDefault();
	}
}
*/
