//*****************************************************************************************
// Truevision - a 3d modeler for gnome and povray
//
// viewmanager.cc
//
// Vincent LE PRINCE <vincentleprince@users.sourceforge.net>
// Copyright (C) 2000-2005 Vincent LE PRINCE
// This file is part of the TRUEVISION Package

//   This program is free software; you can redistribute it and/or modify
//   it under the terms of the GNU General Public License as published by
//   the Free Software Foundation; either version 2 of the License, or
//   (at your option) any later version.
//
//   This program is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU General Public License for more details.
//
//   You should have received a copy of the GNU General Public License
//   along with this program; if not, write to the Free Software
//   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
//*******************************************************************************************
#include "include/viewmanager.h"
#include "include/objectlist.h"
#include "include/preferences.h"
#include "include/tvio.h"


//***********************************************
// X Win pointers
//***********************************************
GdkCursorType Pointeurs[MAX_PMODE] = {
	GDK_HAND1,
	GDK_TOP_LEFT_ARROW,
	GDK_SIZING,
	GDK_EXCHANGE,
	GDK_FLEUR,	
	GDK_TCROSS,
	};


//***********************************************
// Constructor
//***********************************************
ViewManager::ViewManager( app_objs *appref, GtkWidget *parent, GtkUIManager *ui_manager  )
{
	// Initialisation
	app_ref = appref;
	appref->vmanager = this;
	PREF_DEF
	pointeur = NULL;
	pointer_mode = TV_PMODE_TRACKBALL;
	freezed = true;
	pmode_in_change = false;

	// Get GtkActions for each pointer mode
	pointer_actions[0] = gtk_ui_manager_get_action( ui_manager, "/MainToolbar/Trackball" );
	pointer_actions[1] = gtk_ui_manager_get_action( ui_manager, "/MainToolbar/Select" );
	pointer_actions[2] = gtk_ui_manager_get_action( ui_manager, "/MainToolbar/Scale" );
	pointer_actions[3] = gtk_ui_manager_get_action( ui_manager, "/MainToolbar/Rotate" );
	pointer_actions[4] = gtk_ui_manager_get_action( ui_manager, "/MainToolbar/Move" );

	// Boxes for gl widgets
	GtkWidget *box = gtk_hbox_new( TRUE, 2 );
	vbox1 = gtk_vbox_new( FALSE, 1 );
	vbox2 = gtk_vbox_new( FALSE, 1 );
	gtk_box_pack_start( GTK_BOX(box), vbox1, TRUE, TRUE, 0 );
	gtk_box_pack_start( GTK_BOX(box), vbox2, TRUE, TRUE, 0 );
	gtk_paned_add1( GTK_PANED(parent), box );
	GtkWidget *boxes[4] = { vbox1, vbox1, vbox2, vbox2 };


		// Create views
	for ( int i = 0 ; i < 4 ; i++ ) {
		switch ( pref->view_modes[i]->value() ) {
			case  TV_VIEW_3D:
				views[i] = new glview3d( app_ref,  boxes[i], NULL, NULL );
				break;
		
			case  TV_VIEW_CAMERA:
				views[i] = new glcamview( app_ref, boxes[i], NULL, NULL );
				break;
	
			case   TV_VIEW_TOP:
			case   TV_VIEW_FRONT:
			case   TV_VIEW_RIGHT:
				views[i] = new glview2d( app_ref, (ViewType)(pref->view_modes[i]->value()), boxes[i], NULL, NULL );
			 break;
		}
	}
	freezed = false;
}




//**************************************************
// Set pointer mode
//**************************************************

// GtkAction callback
void ViewManager::sign_pmode_change( GtkAction *action )
{
	if ( pmode_in_change ) 
		return;
	for ( int i = 0 ; i < 5 ; i++ ) {
		if ( action == pointer_actions[i] )
			//cout << "\nwe have action callback N°" << i; cout.flush();
			set_pointer_mode( (PointerMode)i );
	}
}

// Set current pointer mode 
// Modify active GtkAction
void ViewManager::set_pointer_mode( PointerMode pmode )
{
	if ( pmode != -1 ) 
		pointer_mode = pmode;
	if ( pointeur != NULL ) 
		gdk_cursor_destroy( pointeur );
	pointeur = gdk_cursor_new( Pointeurs[pointer_mode] );

	for ( int i = 0 ; i < 4 ; i++ )
		gdk_window_set_cursor( views[i]->shared()->window, pointeur );

	// Change Active GtkAction
	pmode_in_change = true;
	for ( int i = 0 ; i < MAX_PMODE-1 ; i++ )
		gtk_toggle_action_set_active( GTK_TOGGLE_ACTION( pointer_actions[i] ), pointer_mode == i ? TRUE : FALSE );
	pmode_in_change = false;
	

	OBJLIST_DEF
	if ( objlist->get_current_param() != NULL ) {
		objlist->get_current_param()->ungrab_pointer();
		objlist->clear_current_param();
	}
}

// Set Pointer mode as custom
// i.e pointer is owned by an ObjParam
void ViewManager::set_custom_pointer_mode( GdkCursorType cursor )
{
	pointer_mode = TV_PMODE_CUSTOM;
	if ( pointeur != NULL ) 
		gdk_cursor_destroy( pointeur );
	pointeur = gdk_cursor_new( cursor );

	for ( int i = 0 ; i < 4 ; i++ )
		gdk_window_set_cursor( views[i]->shared()->window, pointeur );

	// Unactivate all GtkAction relatives to pointer mode
	pmode_in_change = true;
	for ( int i = 0 ; i < MAX_PMODE-1 ; i++ )
		gtk_toggle_action_set_active( GTK_TOGGLE_ACTION( pointer_actions[i] ), FALSE );
	pmode_in_change = false;

OBJLIST_DEF
if ( objlist->get_current_param() != NULL ) 
	{
	objlist->get_current_param()->ungrab_pointer();
	objlist->clear_current_param();
	}
}

// Restore 'normal' cursor for each gl preview
void ViewManager::unset_cursor()
{
	for ( int i = 0 ; i < 4 ; i++ )
		gdk_window_set_cursor( views[i]->shared()->window, NULL );
}


//**************************************************
// Preferences Changed
//**************************************************
void ViewManager::pref_changed()
{
	for ( int i = 0 ; i < 4 ; i++ )
		views[i]->pref_changed();
}


//**************************************************
// Hide / Unhide Sisters
//
// Hide all preview except one
//**************************************************
void ViewManager::hide_sisters( glview *view, GtkWidget *container )
{
	for ( int i = 0 ; i < 4 ; i ++ )
		if ( views[i] != view ) 
			views[i]->Hide();
	if ( container == vbox1 ) 
		gtk_widget_hide( vbox2 );
	else  
		gtk_widget_hide( vbox1 );
}

void ViewManager::unhide_sisters()
{
	for ( int i = 0 ; i < 4 ; i ++ )
		views[i]->Show();
	gtk_widget_show( vbox1 );
	gtk_widget_show( vbox2 );
}


//**************************************************
// Change view
// 
//Create a new view of specified type and replace oldone
//**************************************************
void ViewManager::change_view( glview *oldone, ViewType type, GtkWidget *box, GtkWidget *area_frame, GtkWidget *tbar_frame, bool maximized )
{
	register int i = 0;
	while ( views[i++] == oldone );

	int newone=0;
	for ( i = 0 ; i < 4 ; i ++ )
		if ( views[i] == oldone ) { 
			newone = i; 
			break; 
			}

	delete oldone;
	switch ( type ) {
		case TV_VIEW_3D:
			views[newone] = new glview3d( app_ref, box, area_frame, tbar_frame );
			break;
	
		case TV_VIEW_CAMERA:
			views[newone] = new glcamview( app_ref, box, area_frame, tbar_frame );
			break;
		
		case TV_VIEW_TOP:
		case TV_VIEW_RIGHT:
		case TV_VIEW_FRONT:
			views[newone] = new glview2d( app_ref, type, box, area_frame, tbar_frame );
			break;
	}
	if ( maximized ) 
		views[newone]->MaximizeRestore();
}


//*******************************************************************
// Save & Load
//
// In truevision scene file
//******************************************************************
void ViewManager::save( ofstream & file )
{
	file << " \nVIEWS{\n";
	for ( int i = 0 ; i < 4 ; i ++ )
		views[i]->save( file );
	file << "\n}";
}

void ViewManager::clear()
{
	PREF_DEF
	for ( int i = 0 ; i < 4 ; i ++ )
		views[i]->clear( (ViewType)(pref->view_modes[i]->value()) );
	refresh();
}


bool ViewManager::load( ifstream & file, char *ltag )
{
	if ( strcmp( ltag, "VIEWS" ) ) 
		return false;
	int i = 0;
	char * tag = NULL;
	do {
		tag = tvio_get_next_tag( file );
		if ( tag == NULL || i > 4 ) 
			break;

    	if ( ! strcmp( tag, "GLVIEW2D" ) ) {
    		if ( views[i]->get_type() == TV_VIEW_3D || views[i]->get_type() == TV_VIEW_CAMERA )  views[i]->change_type( TV_VIEW_FRONT );
    			views[i]->load( file, tag );
    		i++;
    		continue;
    	}

	    if ( ! strcmp( tag, "GLVIEW3D" )  ) {
    		if ( views[i]->get_type() != TV_VIEW_3D )  views[i]->change_type( TV_VIEW_3D );
    			views[i]->load( file, tag );
    		i++;
    		continue;
    	}

    	if ( ! strcmp( tag, "GLCAMVIEW" )  ) {
    		if ( views[i]->get_type() != TV_VIEW_CAMERA )  views[i]->change_type( TV_VIEW_CAMERA );
    			views[i]->load( file, tag );
    		i++;
    		continue;
    	}
			
		tvio_skip_section(file );
	} while ( tag != NULL );
	refresh();
	return true;
}
