#include <gtk/gtk.h>

#include <gtkglext-1.0/gtk/gtkgl.h>

#include <GL/gl.h>
#include <GL/glu.h>

#include "zft.h"

#define MAIN_WINDOW_HEIGHT 800
#define MAIN_WINDOW_WIDTH 600

#define PRINT_SPOT printf("file: %s, line: %d\n", __FILE__, __LINE__)

typedef enum{SAVE_FLUX, SAVE_HIVES, SAVE_LANDSCAPE_OBJECTS, SAVE_DROIDS, SAVE_LEECHES, SAVE_EELS, SAVE_DRONES, SAVE_FLUXRINGS, SAVE_HEXFLUXFIELDS, SAVE_BATTERYRINGS, SAVE_TIERRINGS} SaveType;

/* declare main window */
GtkWidget* main_window;

static void
edit_state_changed(GtkWidget* widget,
		   gpointer data)
{
    /* update edit state using combo box state */
    zft_set_edit_state(gtk_combo_box_get_active(GTK_COMBO_BOX(widget)));

    /* if the edit state changed to landscape objects, make landscape object
       combo box sensitive*/
    if (zft_get_edit_state() == ADD_LANDSCAPE_OBJECT)
    {
	gtk_widget_set_sensitive(GTK_WIDGET(data), TRUE);
    }
    else
    {
	gtk_widget_set_sensitive(GTK_WIDGET(data), TRUE);
    }
}

/*!
  \brief Called by GUI when state of Landscape Object (LO) combo box changes
*/
static void
LO_state_changed(GtkWidget* widget,
		 gpointer data)
{
    zft_set_LO_state(gtk_combo_box_get_active(GTK_COMBO_BOX(widget)));
}

/*!
  \todo Default the file choosers to the logical folders.
*/
static void
create_heightmap_file(GtkWidget* widget,
		      gpointer data)
{
    GtkWidget* file_dialog;
    char*      heights_filename;
    char*      colours_filename;
    char*      detail_texture_filename;
    char*      output_filename;
    CLUalignedbox* box;

    gchar*     folder_name;

    printf("%s() : START\n", __FUNCTION__);

    /* get the heights filename from a dialog */
    file_dialog = gtk_file_chooser_dialog_new("Open Heights Image",
					      GTK_WINDOW(main_window),
					      GTK_FILE_CHOOSER_ACTION_SAVE,
					      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
					      GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
					      NULL);
    
    /* get currently displayed folder */
    folder_name = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(file_dialog));
    g_print("folder_name = %s\n", folder_name);

    /* set folder to images directory */
    //gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_dialog), "../data/images/");
    
    g_signal_connect_swapped (file_dialog,
			      "response", 
			      G_CALLBACK (gtk_widget_hide),
			      file_dialog);

    if (gtk_dialog_run(GTK_DIALOG(file_dialog)) == GTK_RESPONSE_ACCEPT)
    {    
	heights_filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_dialog));
	printf("%s() : heights_filename = %s\n", __FUNCTION__, heights_filename);
    }
    else
    {
	/* free the file dialog window */
	gtk_widget_destroy(file_dialog);
	return;
    }

    /* free the file dialog window */
    gtk_widget_destroy(file_dialog);
    

    /* get the colours filename from a dialog */
    file_dialog = gtk_file_chooser_dialog_new("Open Colours Image",
					      GTK_WINDOW(main_window),
					      GTK_FILE_CHOOSER_ACTION_SAVE,
					      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
					      GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
					      NULL);

    g_signal_connect_swapped (file_dialog,
			      "response", 
			      G_CALLBACK (gtk_widget_hide),
			      file_dialog);

    if (gtk_dialog_run(GTK_DIALOG(file_dialog)) == GTK_RESPONSE_ACCEPT)
    {    
	colours_filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_dialog));
	printf("%s() : colours_filename = %s\n", __FUNCTION__, colours_filename);
    }
    else
    {
	/* free the file dialog window */
	gtk_widget_destroy(file_dialog);
	return;
    }

    /* free the file dialog window */
    gtk_widget_destroy(file_dialog);

    
    /* get the detail texture filename from a dialog */
    file_dialog = gtk_file_chooser_dialog_new("Open Detail Texture Image",
					      GTK_WINDOW(main_window),
					      GTK_FILE_CHOOSER_ACTION_SAVE,
					      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
					      GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
					      NULL);

    g_signal_connect_swapped (file_dialog,
			      "response", 
			      G_CALLBACK (gtk_widget_hide),
			      file_dialog);

    if (gtk_dialog_run(GTK_DIALOG(file_dialog)) == GTK_RESPONSE_ACCEPT)
    {    
	detail_texture_filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_dialog));
	printf("%s() : detail_texture_filename = %s\n", __FUNCTION__, detail_texture_filename);
    }
    else
    {
	/* free the file dialog window */
	gtk_widget_destroy(file_dialog);
	return;
    }

    /* free the file dialog window */
    gtk_widget_destroy(file_dialog);


   
    /* get the output filename from a dialog */
    file_dialog = gtk_file_chooser_dialog_new("Select Output File",
					      GTK_WINDOW(main_window),
					      GTK_FILE_CHOOSER_ACTION_SAVE,
					      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
					      GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
					      NULL);

    g_signal_connect_swapped (file_dialog,
			      "response", 
			      G_CALLBACK (gtk_widget_hide),
			      file_dialog);

    if (gtk_dialog_run(GTK_DIALOG(file_dialog)) == GTK_RESPONSE_ACCEPT)
    {    
	output_filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_dialog));
	printf("%s() : output_filename = %s\n", __FUNCTION__, output_filename);
    }
    else
    {
	/* free the file dialog window */
	gtk_widget_destroy(file_dialog);
	return;
    }

    /* free the file dialog window */
    gtk_widget_destroy(file_dialog);

    /* create the heightmap box */
    box = cluNewAlignedBox();
    box->min.y = 0.0f;
    box->max.y = 64.0f;    

    /* now we have 4 filenames, we can ask zf_heightmap to create and save a
       heightmap file */
    zf_heightmap_write_file(heights_filename,
			    colours_filename,
			    detail_texture_filename,
			    output_filename,
			    box);

    /* free all the filenames we used */
    g_free(heights_filename);
    g_free(colours_filename);
    g_free(detail_texture_filename);
    g_free(output_filename);

    printf("%s() : END\n", __FUNCTION__);
}

/*!
  \todo Incomplete
*/
static void
create_level_file(GtkWidget* widget,
		  gpointer data)
{
    ZfLevel* level;
    char* output_filename = NULL;

    printf("%s() : START\n", __FUNCTION__);

    /* create a level struct */
    level = zf_level_new();

    /* spawn some file dialogs to assign correct files to each object type */
    
    /* get an output filename */
    

    /* then create the level file by calling a function from zf_level.c */
    zf_level_write_file(level, output_filename);

    printf("%s() : END\n", __FUNCTION__);
}

static void
save(GtkWidget* widget,
     gpointer *data)
{
    GtkWidget* file_dialog;

    printf("%s() : START\n", __FUNCTION__);

    /* create a file chooser dialog widget */
    file_dialog = gtk_file_chooser_dialog_new("Save File",
					      GTK_WINDOW(main_window),
					      GTK_FILE_CHOOSER_ACTION_SAVE,
					      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
					      GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
					      NULL);
    
    /* if a file is chosen by the user */
    if (gtk_dialog_run(GTK_DIALOG(file_dialog)) == GTK_RESPONSE_ACCEPT)
    {
	char* filename;
	
	/* get the chosen filename */
	filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_dialog));
	printf("filename = %s\n", filename);
	
	printf("data type = %d\n", (int)data);

	/* write it out */
	switch((int)data)
	{
	case SAVE_FLUX:
	    zf_flux_write(filename);
	    break;
	    
	case SAVE_HIVES:
	    zf_hive_write(filename);
	    break;
	    
	case SAVE_LANDSCAPE_OBJECTS:
	    zf_landscape_object_write(filename);
	    break;
	    
	case SAVE_DROIDS:
	    zf_droid_write(filename, zft_viewer_get_droid_list());
	    break;
	    
	case SAVE_LEECHES:
	    zf_leech_write(filename, zft_viewer_get_leech_list());
	    break;

	case SAVE_EELS:
	    zf_eel_segment_write(filename, zft_viewer_get_eel_list());
	    break;

	case SAVE_DRONES:
	    zf_drone_write(filename, zft_viewer_get_drone_list());
	    break;
    
	case SAVE_FLUXRINGS:
	    zf_flux_ring_write(filename, zft_viewer_get_fluxring_list());
	    break;

	case SAVE_HEXFLUXFIELDS:
	    zf_hexfluxfield_write(filename, zft_viewer_get_hexfluxfield_list());
	    break;

	case SAVE_BATTERYRINGS:
	    zf_battery_ring_write(filename, zft_viewer_get_batteryring_list());
	    break;

	case SAVE_TIERRINGS:
	    zf_tier_ring_write(filename, zft_viewer_get_tierring_list());
	    break;

	default:
	    printf("%s() : ERROR : unknown save type\n", __FUNCTION__);
	    break;
	}

	/* free the filename */
	g_free(filename);   
    }
    
    /* free the file dialog window */
    gtk_widget_destroy(file_dialog);
    
    

    /* zf_wasp_save(); */
    /*
    zf_hive_save();
    zf_turret_save();
    zf_laser_turret_save();
    zf_drone_save();
    zf_eel_segment_save();
    */

    printf("%s() : END\n", __FUNCTION__);
}

static void
new_level(GtkWidget* widget,
	  gpointer* data)
{
    printf("%s() : START\n", __FUNCTION__);

    

    printf("%s() : END\n", __FUNCTION__);
}     

static void
open_level(GtkWidget* widget,
	   gpointer *data)
{
    GtkWidget*     file_dialog;
    GtkFileFilter* file_filter;
    
    printf("%s() : START\n", __FUNCTION__);

    /* create a file chooser dialog widget */
    file_dialog = gtk_file_chooser_dialog_new("Open Level",
					      GTK_WINDOW(main_window),
					      GTK_FILE_CHOOSER_ACTION_SAVE,
					      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
					      GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
					      NULL);
    
    /* add a filter for *.zfl to the dialog */
    file_filter = gtk_file_filter_new();
    gtk_file_filter_set_name(file_filter, "*.zfl");
    gtk_file_filter_add_pattern(file_filter, "*.zfl");
    gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(file_dialog), file_filter);

    /* if a file is chosen by the user */
    if (gtk_dialog_run(GTK_DIALOG(file_dialog)) == GTK_RESPONSE_ACCEPT)
    {
	char* filename;
	ZfLevel* level;

	/* get the chosen filename */
	filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_dialog));

	/* free the file dialog window */
	gtk_widget_destroy(file_dialog);    
	
	/* print the filename */
	printf("filename = %s\n", filename);

	/* open the new level */
	printf("reading level file\n");
	level = zf_level_read_file(filename);

	printf("loading level\n");
	zf_level_load(level);

	printf("printing level\n");
	zf_level_print(level);

	zf_render_system_set_tool_mode(true);
	
	/* free the filename */
	g_free(filename);   
    }
    
    printf("%s() : END\n", __FUNCTION__);
}

int
main(int argc, char* argv[])
{
    /* declare main table */
    GtkWidget* main_table;
    
    /* declare menu */
    GtkWidget* menu_bar;
    
    GtkWidget* file_menu;
    GtkWidget* extras_menu;

    GtkWidget* file_item;
    GtkWidget* new_item;
    GtkWidget* open_level_item;
    GtkWidget* save_flux_item;
    GtkWidget* save_hives_item;
    GtkWidget* save_landscape_objects_item;
    GtkWidget* save_droids_item;
    GtkWidget* save_leeches_item;
    GtkWidget* save_eels_item;
    GtkWidget* save_drones_item;
    GtkWidget* save_fluxrings_item;
    GtkWidget* save_hexfluxfields_item;
    GtkWidget* save_batteryrings_item;
    GtkWidget* save_tierrings_item;
 
    GtkWidget* quit_item;

    GtkWidget* extras_item;
    GtkWidget* create_heightmap_file_item;
    GtkWidget* create_level_file_item;

    /* declare edit state combo box */
    GtkWidget* edit_state_vbox;
    GtkWidget* edit_state_label;
    GtkWidget* edit_state_combo;

    /* declare edit state combo box */
    GtkWidget* landscape_object_vbox;
    GtkWidget* landscape_object_label;
    GtkWidget* landscape_object_combo;
    
    /* declare viewers */
    GtkWidget* viewer_1;

    GtkWidget* render_toggle_vbox;
    GtkWidget* render_toggle_label;
    GtkWidget* heightmap_check;
    GtkWidget* flux_check;
    GtkWidget* hives_check;
    GtkWidget* trees_check;

    /* declare camera attributes */
    CLvertex camera_eye;
    CLvertex camera_center;
    CLvertex camera_up;
    
    /* declare zft toolbar */
    //GtkWidget* zft_toolbar;
    
    GtkWidget* status_bar;

    /* nickl - requiredto use glut primitives */
    glutInit(&argc, argv);
    
    /* initialise gtk */
    gtk_init(&argc, &argv);
    
    /* initialise gtk_gl_ext */
    gtk_gl_init (&argc, &argv);

    /* make clean quiet */
    clDisable(CL_VERBOSE);
    clioDisable(CLIO_VERBOSE);

    /* disable audio, no need for that in the tool */
    zf_audio_disable();
	    
    /* create main window and set its attributes */
    main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    
    gtk_window_set_title(GTK_WINDOW(main_window), "ZyberFlux Level Editing Tool 2.0");
    gtk_widget_set_usize(GTK_WIDGET(main_window), MAIN_WINDOW_HEIGHT, MAIN_WINDOW_WIDTH);
    
    /* create menu */
    menu_bar = gtk_menu_bar_new();
    file_menu = gtk_menu_new();
    extras_menu = gtk_menu_new();
    
    /* file menu */
    file_item = gtk_menu_item_new_with_label("File");
    new_item = gtk_menu_item_new_with_label("New");
    open_level_item = gtk_menu_item_new_with_label("Open Level");
    save_flux_item = gtk_menu_item_new_with_label("Save Flux");
    save_hives_item = gtk_menu_item_new_with_label("Save Hives");
    save_landscape_objects_item = gtk_menu_item_new_with_label("Save Landscape Objects");
    save_droids_item = gtk_menu_item_new_with_label("Save Droids");
    save_leeches_item = gtk_menu_item_new_with_label("Save Leeches");
    save_eels_item = gtk_menu_item_new_with_label("Save Eels");
    save_drones_item = gtk_menu_item_new_with_label("Save Drones");
    save_fluxrings_item = gtk_menu_item_new_with_label("Save Fluxrings");
    save_hexfluxfields_item = gtk_menu_item_new_with_label("Save HexFluxFields");
    save_batteryrings_item = gtk_menu_item_new_with_label("Save Batteryrings");
    save_tierrings_item = gtk_menu_item_new_with_label("Save Tierrings");
    quit_item = gtk_menu_item_new_with_label("Quit");
    
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(file_item), file_menu);	
    gtk_menu_bar_append(GTK_MENU_BAR(menu_bar), file_item);
    
    gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), new_item);
    gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), open_level_item);
    gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), save_flux_item);
    gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), save_hives_item);
    gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), save_landscape_objects_item);
    gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), save_droids_item);
    gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), save_leeches_item);
    gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), save_eels_item);
    gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), save_drones_item);
    gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), save_fluxrings_item);
    gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), save_hexfluxfields_item);
    gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), save_batteryrings_item);
    gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), save_tierrings_item);
    gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), quit_item);	
    
    /* extras menu */
    extras_item = gtk_menu_item_new_with_label("Extras");
    create_heightmap_file_item = gtk_menu_item_new_with_label("Create Heightmap File");
    create_level_file_item = gtk_menu_item_new_with_label("Create Level File");

    gtk_menu_item_set_submenu(GTK_MENU_ITEM(extras_item), extras_menu);	
    gtk_menu_bar_append(GTK_MENU_BAR(menu_bar), extras_item);

    gtk_menu_shell_append(GTK_MENU_SHELL(extras_menu), create_heightmap_file_item);
    gtk_menu_shell_append(GTK_MENU_SHELL(extras_menu), create_level_file_item);


    /* create main table and add to main window */
    main_table = gtk_table_new(7, 7, FALSE);
    gtk_table_set_homogeneous(GTK_TABLE(main_table), FALSE);
    gtk_container_add(GTK_CONTAINER(main_window), main_table);

    /* set camera attributes */
    camera_eye.x = 0;
    camera_eye.y = 300;
    camera_eye.z = 0;
    camera_center.x = camera_eye.x;
    camera_center.y = camera_eye.y - 1;
    camera_center.z = camera_eye.z;
    camera_up.x = 0;
    camera_up.y = 0;
    camera_up.z = -1;
    
    /* create combo box */
    edit_state_label = gtk_label_new("Edit State");
    edit_state_combo = gtk_combo_box_new_text();
    gtk_combo_box_append_text(GTK_COMBO_BOX(edit_state_combo), "None");
    gtk_combo_box_append_text(GTK_COMBO_BOX(edit_state_combo), "Flux Repeater");
    gtk_combo_box_append_text(GTK_COMBO_BOX(edit_state_combo), "Hex Flux Field");
    gtk_combo_box_append_text(GTK_COMBO_BOX(edit_state_combo), "Flux Ring");
    gtk_combo_box_append_text(GTK_COMBO_BOX(edit_state_combo), "Battery Ring");
    gtk_combo_box_append_text(GTK_COMBO_BOX(edit_state_combo), "Tier Ring");
    gtk_combo_box_append_text(GTK_COMBO_BOX(edit_state_combo), "Hive");
    gtk_combo_box_append_text(GTK_COMBO_BOX(edit_state_combo), "Landscape Object");
    gtk_combo_box_append_text(GTK_COMBO_BOX(edit_state_combo), "Turret");
    gtk_combo_box_append_text(GTK_COMBO_BOX(edit_state_combo), "Droid");
    gtk_combo_box_append_text(GTK_COMBO_BOX(edit_state_combo), "Eel");
    gtk_combo_box_append_text(GTK_COMBO_BOX(edit_state_combo), "Leech");
    gtk_combo_box_append_text(GTK_COMBO_BOX(edit_state_combo), "Drone");
    gtk_combo_box_append_text(GTK_COMBO_BOX(edit_state_combo), "Hud Message");
    gtk_combo_box_append_text(GTK_COMBO_BOX(edit_state_combo), "Remove Object");
    gtk_combo_box_set_active(GTK_COMBO_BOX(edit_state_combo), 0);

    /* create combo box */
    landscape_object_label = gtk_label_new("Landscape Object");
    landscape_object_combo = gtk_combo_box_new_text();
    gtk_combo_box_append_text(GTK_COMBO_BOX(landscape_object_combo), "Tree");
    gtk_combo_box_append_text(GTK_COMBO_BOX(landscape_object_combo), "Broken Dome");
    gtk_combo_box_append_text(GTK_COMBO_BOX(landscape_object_combo), "Broken Building");
    gtk_combo_box_set_active(GTK_COMBO_BOX(landscape_object_combo), 0);
    gtk_widget_set_sensitive(landscape_object_combo, FALSE);

    /* create viewers and attach to main table */
    viewer_1 = zft_viewer_new(camera_eye, camera_center, camera_up);
    
    /* create zft_toolbar */
    //zft_toolbar = zft_toolbar_new();

    /* create vbox */
    edit_state_vbox = gtk_vbox_new(FALSE, 1);
    landscape_object_vbox = gtk_vbox_new(FALSE, 1);
    render_toggle_vbox = gtk_vbutton_box_new();
    
    /* create check buttons for toggle vbox */
    render_toggle_label = gtk_label_new("Render Toggles");
    heightmap_check = gtk_check_button_new_with_label("Heightmap");
    flux_check      = gtk_check_button_new_with_label("Flux");
    hives_check     = gtk_check_button_new_with_label("Hives");
    trees_check     = gtk_check_button_new_with_label("Trees");

    /* set check buttons to active */
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(heightmap_check), TRUE);
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(flux_check), TRUE);
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hives_check), TRUE);
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(trees_check), TRUE);

    /* add edit state and label to vbox */
    gtk_container_add(GTK_CONTAINER(edit_state_vbox), edit_state_label);
    gtk_container_add(GTK_CONTAINER(edit_state_vbox), edit_state_combo);

    /* add edit state and label to vbox */
    gtk_container_add(GTK_CONTAINER(landscape_object_vbox), landscape_object_label);
    gtk_container_add(GTK_CONTAINER(landscape_object_vbox), landscape_object_combo);

    /* add check buttons to toggle vbox */
    gtk_container_add(GTK_CONTAINER(render_toggle_vbox), render_toggle_label);
    gtk_container_add(GTK_CONTAINER(render_toggle_vbox), heightmap_check);
    gtk_container_add(GTK_CONTAINER(render_toggle_vbox), flux_check);
    gtk_container_add(GTK_CONTAINER(render_toggle_vbox), hives_check);
    gtk_container_add(GTK_CONTAINER(render_toggle_vbox), trees_check);

    /* create status bar */
    status_bar = gtk_statusbar_new();
    gtk_statusbar_push(GTK_STATUSBAR(status_bar),
		       gtk_statusbar_get_context_id(GTK_STATUSBAR(status_bar), "default"),
		       "Ready");

    /* attach widgets to table */
    gtk_table_attach(GTK_TABLE(main_table), menu_bar, 0, 8, 0, 1,
		     GTK_FILL | GTK_EXPAND, GTK_SHRINK,
		     0, 0);

    /* add edit state combo box to main table */
    gtk_table_attach(GTK_TABLE(main_table), edit_state_vbox, 0, 1, 1, 2,
		     GTK_SHRINK, GTK_SHRINK,
		     0, 0);

    /* add landscape object combo box to main table */
    gtk_table_attach(GTK_TABLE(main_table), landscape_object_vbox, 0, 1, 2, 3,
		     GTK_SHRINK, GTK_SHRINK,
		     0, 0);

    gtk_table_attach(GTK_TABLE(main_table), render_toggle_vbox, 0, 1, 6, 7,
		     GTK_SHRINK, GTK_SHRINK,
		     0, 0);
    
    gtk_table_attach(GTK_TABLE(main_table), viewer_1, 1, 8, 1, 7,
		     GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND,
		     0, 0);
    
    gtk_table_attach(GTK_TABLE(main_table), status_bar, 0, 8, 7, 8,
		     GTK_FILL | GTK_EXPAND, GTK_SHRINK,
		     0, 0);

    /* connect destroy event to window */
    g_signal_connect(G_OBJECT(main_window), "destroy",
		     G_CALLBACK(gtk_main_quit), NULL);

    /* extras */
    g_signal_connect(G_OBJECT(create_heightmap_file_item), "activate",
		     G_CALLBACK(create_heightmap_file), NULL);
    g_signal_connect(G_OBJECT(create_level_file_item), "activate",
		     G_CALLBACK(create_level_file), NULL);

    g_signal_connect(G_OBJECT(new_item), "activate",
		     G_CALLBACK(new_level), NULL);

    /* connect load callback to load item of menu */
    g_signal_connect(G_OBJECT(open_level_item), "activate",
		     G_CALLBACK(open_level), NULL);
    
    /* connect save callback to save item of menu */
    g_signal_connect(G_OBJECT(save_flux_item), "activate",
		     G_CALLBACK(save), (gpointer*)SAVE_FLUX);
    g_signal_connect(G_OBJECT(save_hives_item), "activate",
		     G_CALLBACK(save), (gpointer*)SAVE_HIVES);
    g_signal_connect(G_OBJECT(save_landscape_objects_item), "activate",
		     G_CALLBACK(save), (gpointer*)SAVE_LANDSCAPE_OBJECTS);
    g_signal_connect(G_OBJECT(save_droids_item), "activate",
		     G_CALLBACK(save), (gpointer*)SAVE_DROIDS);
    g_signal_connect(G_OBJECT(save_leeches_item), "activate",
		     G_CALLBACK(save), (gpointer*)SAVE_LEECHES);
    g_signal_connect(G_OBJECT(save_eels_item), "activate",
		     G_CALLBACK(save), (gpointer*)SAVE_EELS);
    g_signal_connect(G_OBJECT(save_drones_item), "activate",
		     G_CALLBACK(save), (gpointer*)SAVE_DRONES);
    g_signal_connect(G_OBJECT(save_fluxrings_item), "activate",
		     G_CALLBACK(save), (gpointer*)SAVE_FLUXRINGS);
    g_signal_connect(G_OBJECT(save_hexfluxfields_item), "activate",
		     G_CALLBACK(save), (gpointer*)SAVE_HEXFLUXFIELDS);
    g_signal_connect(G_OBJECT(save_batteryrings_item), "activate",
		     G_CALLBACK(save), (gpointer*)SAVE_BATTERYRINGS);
    g_signal_connect(G_OBJECT(save_tierrings_item), "activate",
		     G_CALLBACK(save), (gpointer*)SAVE_TIERRINGS);

    /* connect destroy event to quit item of menu */
    g_signal_connect(G_OBJECT(quit_item), "activate",
		     G_CALLBACK(gtk_main_quit), NULL);

    /* edit state manu change callback */
    g_signal_connect(G_OBJECT(edit_state_combo), "changed",
		     G_CALLBACK(edit_state_changed), landscape_object_combo);

    /* landscape object menu change callback */
    g_signal_connect(G_OBJECT(landscape_object_combo), "changed",
		     G_CALLBACK(LO_state_changed), NULL);
    
    /* show main window and all child widgets */
    gtk_widget_show_all(main_window);
    
    /* start the gui */
    gtk_main();
    
    return 0;
}
