celestia/src/celestia/gtkmain.cpp

2297 lines
67 KiB
C++

// gtkmain.cpp
//
// Copyright (C) 2000, Chris Laurel <claurel@shatters.net>
//
// GTk front end for Celestia.
//
// 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.
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <time.h>
#include <unistd.h>
#include <celengine/gl.h>
#include <celengine/glext.h>
#include <celengine/celestia.h>
#include <celengine/starbrowser.h>
#ifndef DEBUG
# define G_DISABLE_ASSERT
#endif
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <gdk/gdkkeysyms.h>
#include <gtkgl/gtkglarea.h>
#include <gnome.h>
#include "celmath/vecmath.h"
#include "celmath/quaternion.h"
#include "celmath/mathlib.h"
#include "celengine/astro.h"
#include "celutil/util.h"
#include "celutil/filetype.h"
#include "celutil/debug.h"
#include "imagecapture.h"
#include "celestiacore.h"
#include "celengine/simulation.h"
#include <libgnomeui/gnome-init.h>
char AppName[] = "Celestia";
static CelestiaCore* appCore = NULL;
static Renderer* appRenderer = NULL;
static Simulation* appSim = NULL;
// Mouse motion tracking
static int lastX = 0;
static int lastY = 0;
typedef struct _checkFunc CheckFunc;
typedef int (*Callback)(int);
struct _checkFunc
{
GtkCheckMenuItem *widget;
char *path;
Callback func;
int active;
int funcdata;
};
static GtkWidget* mainWindow = NULL;
static GtkWidget* mainMenu = NULL;
static GtkWidget* mainBox = NULL;
static GtkWidget* oglArea = NULL;
int oglAttributeList[] =
{
GDK_GL_RGBA,
GDK_GL_RED_SIZE, 1,
GDK_GL_GREEN_SIZE, 1,
GDK_GL_BLUE_SIZE, 1,
GDK_GL_DEPTH_SIZE, 1,
GDK_GL_DOUBLEBUFFER,
GDK_GL_NONE,
};
static GtkItemFactory* menuItemFactory = NULL;
static int verbose;
#if 0
static void SetRenderFlag(int flag, bool state)
{
appRenderer->setRenderFlags((appRenderer->getRenderFlags() & ~flag) |
(state ? flag : 0));
}
static void SetLabelFlag(int flag, bool state)
{
appRenderer->setLabelMode((appRenderer->getLabelMode() & ~flag) |
(state ? flag : 0));
}
#endif
enum
{
Menu_ShowGalaxies = 2001,
Menu_ShowOrbits = 2002,
Menu_ShowConstellations = 2003,
Menu_ShowAtmospheres = 2004,
Menu_PlanetLabels = 2005,
Menu_ShowClouds = 2005,
Menu_ShowCelestialSphere = 2006,
Menu_ShowNightSideMaps = 2007,
Menu_MajorPlanetLabels = 2008,
Menu_MinorPlanetLabels = 2009,
Menu_StarLabels = 2010,
Menu_GalaxyLabels = 2011,
Menu_ConstellationLabels = 2012,
Menu_PixelShaders = 2013,
Menu_VertexShaders = 2014,
Menu_ShowLocTime = 2015,
};
static void menuSelectSol()
{
appCore->charEntered('H');
}
static void menuCenter()
{
appCore->charEntered('C');
}
static void menuGoto()
{
appCore->charEntered('G');
}
static void menuSync()
{
appCore->charEntered('Y');
}
static void menuTrack()
{
appCore->charEntered('T');
}
static void menuFollow()
{
appCore->charEntered('F');
}
static void menuFaster()
{
appCore->charEntered('L');
}
static void menuSlower()
{
appCore->charEntered('K');
}
static void menuPause()
{
appCore->charEntered(' ');
}
static void menuRealTime()
{
appCore->charEntered('\\');
}
static void menuReverse()
{
appCore->charEntered('J');
}
static gint menuShowGalaxies(GtkWidget* w, gpointer data)
{
// bool on = (GTK_CHECK_MENU_ITEM(w)->active == 1);
// SetRenderFlag(Renderer::ShowGalaxies, on);
appCore->charEntered('U');
return TRUE;
}
static gint menuShowOrbits(GtkWidget* w, gpointer data)
{
// bool on = (GTK_CHECK_MENU_ITEM(w)->active == 1);
// SetRenderFlag(Renderer::ShowOrbits, on);
appCore->charEntered('O');
return TRUE;
}
static gint menuShowClouds(GtkWidget* w, gpointer data)
{
// bool on = (GTK_CHECK_MENU_ITEM(w)->active == 1);
// SetRenderFlag(Renderer::ShowCloudMaps, on);
appCore->charEntered('I');
return TRUE;
}
static gint menuShowAtmospheres(GtkWidget* w, gpointer data)
{
// bool on = (GTK_CHECK_MENU_ITEM(w)->active == 1);
// SetRenderFlag(Renderer::ShowAtmospheres, on);
appCore->charEntered('\001'); //Ctrl+A
return TRUE;
}
static gint menuPixelShaders(GtkWidget* w, gpointer data)
{
// bool on = (GTK_CHECK_MENU_ITEM(w)->active == 1);
// SetRenderFlag(Renderer::ShowNightSideMaps, on);
appCore->charEntered('\020'); //Ctrl+P
return TRUE;
}
static gint menuVertexShaders(GtkWidget* w, gpointer data)
{
// bool on = (GTK_CHECK_MENU_ITEM(w)->active == 1);
// SetRenderFlag(Renderer::ShowNightSideMaps, on);
appCore->charEntered('\026'); //Ctrl+V
return TRUE;
}
static gint menuShowNightSideMaps(GtkWidget* w, gpointer data)
{
// bool on = (GTK_CHECK_MENU_ITEM(w)->active == 1);
// SetRenderFlag(Renderer::ShowNightSideMaps, on);
appCore->charEntered('\014'); //Ctrl+L
return TRUE;
}
static gint menuShowCelestialSphere(GtkWidget* w, gpointer data)
{
// bool on = (GTK_CHECK_MENU_ITEM(w)->active == 1);
// SetRenderFlag(Renderer::ShowCelestialSphere, on);
appCore->charEntered(';');
return TRUE;
}
static gint menuShowConstellations(GtkWidget* w, gpointer data)
{
// bool on = (GTK_CHECK_MENU_ITEM(w)->active == 1);
// SetRenderFlag(Renderer::ShowDiagrams, on);
appCore->charEntered('/');
return TRUE;
}
static gint menuShowLocTime(GtkWidget* w, gpointer data)
{
bool on = (GTK_CHECK_MENU_ITEM(w)->active != FALSE);
if (on)
{
appCore->setTimeZoneBias(-timezone);
appCore->setTimeZoneName(tzname[daylight?0:1]);
}
else
{
appCore->setTimeZoneBias(0);
appCore->setTimeZoneName("UTC");
}
return TRUE;
}
static gint menuStarLabels(GtkWidget* w, gpointer data)
{
// bool on = (GTK_CHECK_MENU_ITEM(w)->active == 1);
// SetLabelFlag(Renderer::StarLabels, on);
appCore->charEntered('B');
return TRUE;
}
static gint menuGalaxyLabels(GtkWidget* w, gpointer data)
{
// bool on = (GTK_CHECK_MENU_ITEM(w)->active == 1);
// SetLabelFlag(Renderer::StarLabels, on);
appCore->charEntered('E');
return TRUE;
}
static gint menuConstellationLabels(GtkWidget* w, gpointer data)
{
// bool on = (GTK_CHECK_MENU_ITEM(w)->active == 1);
// SetLabelFlag(Renderer::ConstellationLabels, on);
appCore->charEntered('=');
return TRUE;
}
static gint menuMajorPlanetLabels(GtkWidget* w, gpointer data)
{
// bool on = (GTK_CHECK_MENU_ITEM(w)->active == 1);
// SetLabelFlag(Renderer::MajorPlanetLabels, on);
appCore->charEntered('N');
return TRUE;
}
static gint menuMinorPlanetLabels(GtkWidget* w, gpointer data)
{
// bool on = (GTK_CHECK_MENU_ITEM(w)->active == 1);
// SetLabelFlag(Renderer::MinorPlanetLabels, on);
appCore->charEntered('M');
return TRUE;
}
static void menuMoreStars()
{
appCore->charEntered(']');
}
static void menuLessStars()
{
appCore->charEntered('[');
}
static void menuNoAmbient()
{
appCore->getRenderer()->setAmbientLightLevel(0.0f);
}
static void menuLowAmbient()
{
appCore->getRenderer()->setAmbientLightLevel(0.02f);
}
static void menuMedAmbient()
{
appCore->getRenderer()->setAmbientLightLevel(0.1f);
}
static void menuHiAmbient()
{
appCore->getRenderer()->setAmbientLightLevel(0.25f);
}
static void menuShowInfo()
{
appCore->charEntered('V');
}
static void menuRunDemo()
{
appCore->charEntered('D');
}
static void menuAbout()
{
const gchar* authors[] = {
"Chris Laurel <claurel@shatters.net>",
"Deon Ramsey <dramsey@sourceforge.net>",
"Clint Weisbrod <cweisbrod@adelphia.net>",
NULL
};
const gchar* logo = gnome_pixmap_file("gnome-hello-logo.png");
static GtkWidget* about;
if (about != NULL)
{
// Try to de-iconify and raise the dialog.
gdk_window_show(about->window);
gdk_window_raise(about->window);
}
else
{
about = gnome_about_new("Celestia",
VERSION,
"(c) 2001-2002 Chris Laurel",
authors,
"3D Space Simulation",
logo);
if (about == NULL)
return;
gtk_window_set_modal(GTK_WINDOW(about), TRUE);
gnome_dialog_set_parent((GnomeDialog*) about, GTK_WINDOW(mainWindow));
gtk_widget_show(about);
}
}
static GtkWidget* fileSelector = NULL;
static string* captureFilename = NULL;
void storeCaptureFilename(GtkFileSelection* selector, gpointer)
{
char *tmp;
tmp=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileSelector));
if(!tmp || !(*tmp)) // Don't change the captureFilename and exit if empty
return;
*captureFilename = tmp; // remember it for next time
// Get the dimensions of the current viewport
int viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
bool success = false;
ContentType type = DetermineFileType(*captureFilename);
if (type == Content_Unknown)
{
GtkWidget* errBox = gnome_message_box_new("Unable to determine image file type from name, please use a name ending in '.jpg' or '.png'.",
GNOME_MESSAGE_BOX_ERROR,
GNOME_STOCK_BUTTON_OK,
NULL);
gtk_widget_show(errBox);
return;
}
else if (type == Content_JPEG)
{
success = CaptureGLBufferToJPEG(*captureFilename,
viewport[0], viewport[1],
viewport[2], viewport[3]);
}
else if (type == Content_PNG)
{
success = CaptureGLBufferToPNG(string(*captureFilename),
viewport[0], viewport[1],
viewport[2], viewport[3]);
}
else
{
GtkWidget* errBox = gnome_message_box_new("Sorry, currently screen capturing to JPEG or PNG files only is supported, please use a name ending in '.jpg' or '.png'.",
GNOME_MESSAGE_BOX_ERROR,
GNOME_STOCK_BUTTON_OK,
NULL);
gtk_widget_show(errBox);
return;
}
if (!success)
{
GtkWidget* errBox = gnome_message_box_new("Error writing captured image.",
GNOME_MESSAGE_BOX_ERROR,
GNOME_STOCK_BUTTON_OK,
NULL);
gtk_widget_show(errBox);
}
}
static void menuCaptureImage()
{
fileSelector = gtk_file_selection_new("Select capture file.");
gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fileSelector)->ok_button),
"clicked",
GTK_SIGNAL_FUNC(storeCaptureFilename),
NULL);
gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(fileSelector)->ok_button),
"clicked",
GTK_SIGNAL_FUNC(gtk_widget_destroy),
GTK_OBJECT(fileSelector));
gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(fileSelector)->cancel_button),
"clicked",
GTK_SIGNAL_FUNC(gtk_widget_destroy),
GTK_OBJECT(fileSelector));
gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileSelector), captureFilename->c_str());
gtk_file_selection_show_fileop_buttons(GTK_FILE_SELECTION(fileSelector));
gtk_widget_show(fileSelector);
}
static void menuSelectObject()
{
GtkWidget* dialog = gnome_dialog_new("Find Object",
GNOME_STOCK_BUTTON_OK,
GNOME_STOCK_BUTTON_CANCEL,
NULL);
if (dialog == NULL)
return;
GtkWidget* label = gtk_label_new("Enter object name:");
if (label == NULL)
return;
gtk_box_pack_start(GTK_BOX(GNOME_DIALOG (dialog)->vbox),
label,
TRUE,
TRUE,
0);
GtkWidget* entry = gtk_entry_new();
if (entry == NULL)
return;
gtk_box_pack_start(GTK_BOX(GNOME_DIALOG (dialog)->vbox),
entry,
TRUE,
TRUE,
0);
gtk_widget_show(label);
gtk_widget_show(entry);
gnome_dialog_close_hides(GNOME_DIALOG(dialog), true);
// gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
gnome_dialog_set_parent((GnomeDialog*) dialog, GTK_WINDOW(mainWindow));
gnome_dialog_set_default((GnomeDialog*) dialog, GNOME_YES);
gint whichButton = gnome_dialog_run(GNOME_DIALOG(dialog));
if (whichButton == 0)
{
gchar* name = gtk_entry_get_text(GTK_ENTRY(entry));
if (name != NULL)
{
Selection sel = appCore->getSimulation()->findObject(name);
if (!sel.empty())
appCore->getSimulation()->setSelection(sel);
}
}
gnome_dialog_close(GNOME_DIALOG(dialog));
}
class GotoObjectDialog
{
public:
GotoObjectDialog();
~GotoObjectDialog();
bool init();
GtkWidget* dialog;
GtkWidget* nameEntry;
GtkWidget* latEntry;
GtkWidget* longEntry;
GtkWidget* distEntry;
};
static bool GetEntryFloat(GtkWidget* w, float& f)
{
GtkEntry* entry = GTK_ENTRY(w);
bool tmp;
if (entry == NULL)
return false;
gchar* text = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
f = 0.0;
if (text == NULL)
return false;
tmp=sscanf(text, " %f", &f) == 1;
g_free(text);
return tmp;
}
static gint GotoObject(GtkWidget* w, gpointer data)
{
GotoObjectDialog* gotoObjectDlg = reinterpret_cast<GotoObjectDialog*>(data);
if (gotoObjectDlg == NULL)
return FALSE;
gchar* objectName = gtk_entry_get_text(GTK_ENTRY(gotoObjectDlg->nameEntry));
if (objectName != NULL)
{
Selection sel = appSim->findObjectFromPath(objectName);
if (!sel.empty())
{
appSim->setSelection(sel);
appSim->follow();
float distance = (float) (sel.radius() * 5.0f);
if (GetEntryFloat(gotoObjectDlg->distEntry, distance))
{
distance += (float) sel.radius();
}
distance = astro::kilometersToLightYears(distance);
float longitude, latitude;
if (GetEntryFloat(gotoObjectDlg->latEntry, latitude) &&
GetEntryFloat(gotoObjectDlg->longEntry, longitude))
{
appSim->gotoSelectionLongLat(5.0,
distance,
degToRad(longitude),
degToRad(latitude),
Vec3f(0, 1, 0));
}
else
{
appSim->gotoSelection(5.0,
distance,
Vec3f(0, 1, 0),
astro::ObserverLocal);
}
}
}
return TRUE;
}
GotoObjectDialog::GotoObjectDialog() :
dialog(NULL),
nameEntry(NULL),
latEntry(NULL),
longEntry(NULL),
distEntry(NULL)
{
}
GotoObjectDialog::~GotoObjectDialog()
{
}
bool GotoObjectDialog::init()
{
dialog = gnome_dialog_new("Goto Object",
GNOME_STOCK_BUTTON_CANCEL,
NULL);
nameEntry = gtk_entry_new();
latEntry = gtk_entry_new();
longEntry = gtk_entry_new();
distEntry = gtk_entry_new();
if (dialog == NULL ||
nameEntry == NULL ||
latEntry == NULL ||
longEntry == NULL ||
distEntry == NULL)
{
// Potential memory leak here . . .
return false;
}
GtkWidget* hbox = NULL;
GtkWidget* label = NULL;
// Object name label and entry
hbox = gtk_hbox_new(FALSE, 6);
if (hbox == NULL)
return false;
label = gtk_label_new("Object name:");
if (label == NULL)
return false;
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(hbox), nameEntry, FALSE, TRUE, 0);
gtk_widget_show(label);
gtk_widget_show(nameEntry);
gtk_box_pack_start(GTK_BOX (GNOME_DIALOG (dialog)->vbox),
hbox, FALSE, TRUE, 0);
gtk_widget_show(hbox);
// Latitude and longitude
hbox = gtk_hbox_new(FALSE, 6);
if (hbox == NULL)
return false;
label = gtk_label_new("Latitude:");
if (label == NULL)
return false;
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(hbox), latEntry, FALSE, TRUE, 0);
gtk_widget_show(label);
gtk_widget_show(latEntry);
label = gtk_label_new("Longitude:");
if (label == NULL)
return false;
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(hbox), longEntry, FALSE, TRUE, 0);
gtk_widget_show(label);
gtk_widget_show(longEntry);
gtk_box_pack_start(GTK_BOX (GNOME_DIALOG (dialog)->vbox),
hbox, FALSE, TRUE, 0);
gtk_widget_show(hbox);
// Distance
hbox = gtk_hbox_new(FALSE, 6);
if (hbox == NULL)
return false;
label = gtk_label_new("Distance:");
if (label == NULL)
return false;
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(hbox), distEntry, FALSE, TRUE, 0);
gtk_widget_show(label);
gtk_widget_show(distEntry);
gtk_box_pack_start(GTK_BOX (GNOME_DIALOG (dialog)->vbox),
hbox, FALSE, TRUE, 0);
gtk_widget_show(hbox);
// Goto button
GtkWidget* gotoButton = gtk_button_new_with_label(" Go To ");
if (gotoButton == NULL)
return false;
gtk_widget_show(gotoButton);
gtk_box_pack_start(GTK_BOX (GNOME_DIALOG (dialog)->vbox),
gotoButton, FALSE, TRUE, 0);
gtk_signal_connect(GTK_OBJECT(gotoButton),
"pressed",
GTK_SIGNAL_FUNC(GotoObject),
this);
gnome_dialog_set_parent((GnomeDialog*) dialog, GTK_WINDOW(mainWindow));
gnome_dialog_set_default((GnomeDialog*) dialog, GNOME_NO);
gnome_dialog_run_and_close(GNOME_DIALOG(dialog));
return true;
}
static void menuGotoObject()
{
GotoObjectDialog* gotoObjectDlg = new GotoObjectDialog();
gotoObjectDlg->init();
}
static Destination* selectedDest = NULL;
static gint TourGuideSelect(GtkWidget* w, gpointer data)
{
// bool on = (GTK_CHECK_MENU_ITEM(w)->active == 1);
// SetRenderFlag(Renderer::ShowGalaxies, on);
// appCore->charEntered('U');
GtkMenu* menu = GTK_MENU(w);
if (menu == NULL)
return FALSE;
GtkWidget* item = gtk_menu_get_active(GTK_MENU(menu));
if (item == NULL)
return FALSE;
GList* list = gtk_container_children(GTK_CONTAINER(menu));
int itemIndex = g_list_index(list, item);
const DestinationList* destinations = appCore->getDestinations();
if (destinations != NULL &&
itemIndex >= 0 && itemIndex < (int) destinations->size())
{
selectedDest = (*destinations)[itemIndex];
}
GtkLabel* descLabel = GTK_LABEL(data);
if (descLabel != NULL && selectedDest != NULL)
{
gtk_label_set_text(descLabel, selectedDest->description.c_str());
}
return TRUE;
}
static gint TourGuideGoto(GtkWidget* w, gpointer data)
{
if (selectedDest != NULL && appSim != NULL)
{
Selection sel = appSim->findObjectFromPath(selectedDest->target);
if (!sel.empty())
{
appSim->follow();
appSim->setSelection(sel);
if (selectedDest->distance <= 0)
{
// Use the default distance
appSim->gotoSelection(5.0,
Vec3f(0, 1, 0),
astro::ObserverLocal);
}
else
{
appSim->gotoSelection(5.0,
selectedDest->distance,
Vec3f(0, 1, 0),
astro::ObserverLocal);
}
}
}
return TRUE;
}
static void menuTourGuide()
{
GtkWidget* dialog = gnome_dialog_new("Tour Guide...",
GNOME_STOCK_BUTTON_OK,
NULL);
if (dialog == NULL)
return;
GtkWidget* hbox = gtk_hbox_new(FALSE, 6);
if (hbox == NULL)
return;
GtkWidget* label = gtk_label_new("Select your destination:");
if (label == NULL)
return;
gtk_box_pack_start(GTK_BOX(hbox),
label,
FALSE,
TRUE,
0);
GtkWidget* menubox = gtk_option_menu_new();
if (menubox == NULL)
return;
gtk_box_pack_start(GTK_BOX(hbox),
menubox,
FALSE,
TRUE,
0);
GtkWidget* gotoButton = gtk_button_new_with_label(" Go To ");
if (gotoButton == NULL)
return;
gtk_box_pack_start(GTK_BOX(hbox),
gotoButton,
TRUE,
FALSE,
0);
gtk_box_pack_start(GTK_BOX (GNOME_DIALOG (dialog)->vbox),
hbox,
FALSE,
TRUE,
0);
gtk_widget_show(hbox);
GtkWidget* descLabel = gtk_label_new("");
if (descLabel == NULL)
return;
gtk_label_set_line_wrap(GTK_LABEL(descLabel), TRUE);
gtk_label_set_justify(GTK_LABEL(descLabel), GTK_JUSTIFY_FILL);
gtk_box_pack_start(GTK_BOX (GNOME_DIALOG (dialog)->vbox),
descLabel,
TRUE,
TRUE,
0);
GtkWidget* menu = gtk_menu_new();
const DestinationList* destinations = appCore->getDestinations();
if (destinations != NULL)
{
for (DestinationList::const_iterator iter = destinations->begin();
iter != destinations->end(); iter++)
{
Destination* dest = *iter;
if (dest != NULL)
{
GtkWidget* item = gtk_menu_item_new_with_label(dest->name.c_str());
gtk_menu_append(GTK_MENU(menu), item);
gtk_widget_show(item);
}
}
}
gtk_signal_connect(GTK_OBJECT(menu),
"selection-done",
GTK_SIGNAL_FUNC(TourGuideSelect),
GTK_OBJECT(descLabel));
gtk_signal_connect(GTK_OBJECT(gotoButton),
"pressed",
GTK_SIGNAL_FUNC(TourGuideGoto),
NULL);
gtk_option_menu_set_menu(GTK_OPTION_MENU(menubox), menu);
gtk_widget_set_usize(dialog, 400, 300);
gtk_widget_show(label);
gtk_widget_show(menubox);
gtk_widget_show(descLabel);
gtk_widget_show(gotoButton);
// gtk_widget_set_usize(descLabel, 250, 150);
gnome_dialog_set_parent((GnomeDialog*) dialog, GTK_WINDOW(mainWindow));
gnome_dialog_set_default((GnomeDialog*) dialog, GNOME_YES);
gnome_dialog_run_and_close(GNOME_DIALOG(dialog));
// gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
// gtk_widget_show(dialog);
}
char *readFromFile(char *fname)
{
ifstream textFile(fname, ios::in);
string s("");
if (!textFile.is_open())
{
s="Unable to open file '";
s+= fname ;
s+= "', probably due to improper installation !\n";
}
char c;
while(textFile.get(c))
{
if (c=='\t')
s+=" "; // 8 spaces
else if (c=='\014') // Ctrl+L (form feed)
s+="\n\n\n\n";
else
s+=c;
}
return g_strdup(s.c_str());
}
static void textInfoDialog(GtkWidget** dialog, const char *txt, const char *title)
{
/* I would use a gnome_message_box dialog for this, except they don't seem
to notice that the texts are so big that they create huge windows, and
would work better with a scrolled window. Deon */
if (*dialog != NULL)
{
// Try to de-iconify and raise the dialog.
gdk_window_show((*dialog)->window);
gdk_window_raise((*dialog)->window);
gnome_dialog_run_and_close(GNOME_DIALOG(*dialog));
}
else
{
*dialog = gnome_dialog_new(title,
GNOME_STOCK_BUTTON_OK,
NULL);
if (*dialog == NULL)
{
DPRINTF(0, "Unable to open '%s' dialog!\n",title);
return;
}
GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (*dialog)->vbox), scrolled_window, TRUE, TRUE, 0);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_widget_show (scrolled_window);
GtkWidget *text = gtk_text_new (NULL, NULL);
gtk_text_set_editable (GTK_TEXT (text), FALSE);
gtk_text_set_word_wrap (GTK_TEXT (text), FALSE);
gtk_text_set_line_wrap (GTK_TEXT (text), FALSE);
gtk_container_add (GTK_CONTAINER (scrolled_window), text);
gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, txt, -1);
gtk_widget_show (text);
gtk_widget_set_usize(*dialog, 500, 400); //Absolute Size, urghhh
gnome_dialog_set_parent((GnomeDialog*) *dialog, GTK_WINDOW(mainWindow));
gnome_dialog_set_default((GnomeDialog*) *dialog, GNOME_YES);
gnome_dialog_close_hides((GnomeDialog*) *dialog, TRUE);
gtk_window_set_modal(GTK_WINDOW(*dialog), FALSE);
gnome_dialog_run_and_close(GNOME_DIALOG(*dialog));
}
}
static GtkWidget* controldialog=NULL;
static void menuControls()
{
char *txt=readFromFile("controls.txt");
textInfoDialog(&controldialog,txt,"Mouse and Keyboard Controls");
g_free(txt);
}
static GtkWidget* licdialog=NULL;
static void menuLicense()
{
char *txt=readFromFile("COPYING");
textInfoDialog(&licdialog,txt,"Celestia License");
g_free(txt);
}
static GtkWidget* ogldialog=NULL;
static void menuOpenGL()
{
// Code grabbed from winmain.gtk
char* vendor = (char*) glGetString(GL_VENDOR);
char* render = (char*) glGetString(GL_RENDERER);
char* version = (char*) glGetString(GL_VERSION);
char* ext = (char*) glGetString(GL_EXTENSIONS);
string s;
s = "Vendor : ";
if (vendor != NULL)
s += vendor;
s += "\n";
s += "Renderer : ";
if (render != NULL)
s += render;
s += "\n";
s += "Version : ";
if (version != NULL)
s += version;
s += "\n";
char buf[100];
GLint simTextures = 1;
if (ExtensionSupported("GL_ARB_multitexture"))
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &simTextures);
sprintf(buf, "Max simultaneous textures: %d\n",
simTextures);
s += buf;
GLint maxTextureSize = 0;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
sprintf(buf, "Max texture size: %d\n\n",
maxTextureSize);
s += buf;
s += "Supported Extensions:\n ";
if (ext != NULL)
{
string extString(ext);
unsigned int pos = extString.find(' ', 0);
while (pos != string::npos)
{
extString.replace(pos, 1, "\n ");
pos = extString.find(' ', pos+5);
}
s += extString;
}
textInfoDialog(&ogldialog,s.c_str(),"Open GL Info");
}
static char *sstitles[]=
{
"Name",
"Type"
};
static char *cstitles[]=
{
" Name ",
" Distance(LY) ",
" App. Mag ",
" Abs. Mag ",
" Type "
};
static char *radioLabels[]=
{
"Nearest",
"Brightest(App)",
"Brightest(Abs)",
"With Planets"
};
static const char *tmp[5];
static GtkWidget *ctree=NULL;
static GtkWidget *clist=NULL;
void addPlanetarySystemToTree(const PlanetarySystem* sys, GtkCTreeNode *parent, int lev)
{
GtkCTreeNode *child;
for (int i = 0; i < sys->getSystemSize(); i++)
{
Body* world = sys->getBody(i);
tmp[0] = g_strdup(world->getName().c_str());
if (lev == 2)
{
if (world->getRadius() >= 1000.0)
tmp[1]="Planet";
else
tmp[1]="Planetoid";
}
else
{
if (world->getRadius() > 0.1)
tmp[1]="Moon";
else
tmp[1]="Satellite";
}
const PlanetarySystem* satellites = world->getSatellites();
child=gtk_ctree_insert_node(GTK_CTREE(ctree), parent, NULL,
(char**) tmp , 0 , NULL, NULL, NULL, NULL,
(satellites ? FALSE : TRUE), TRUE);
gtk_ctree_node_set_row_data(GTK_CTREE(ctree), child, world);
gtk_ctree_collapse (GTK_CTREE(ctree), child);
g_free((char*) tmp[0]);
if (satellites != NULL)
addPlanetarySystemToTree(satellites, child, lev + 1);
}
}
static const Star *nearestStar;
static Selection browserSel;
static gint listSelect(GtkCList *list, gint row, gint column, gpointer dummy, gpointer dumm2)
{
Star *selStar =(Star *)gtk_clist_get_row_data(list,row);
if (selStar)
{
browserSel.select(selStar);
return TRUE;
}
return FALSE;
}
static gint treeSelect(GtkCTree *tree, GtkCTreeNode *node, gint column, gpointer dummy)
{
Body *body;
if (column < 0)
{
/* This will happen when the tree attempts to autoselect a node
as it is just being switched to, but is still empty */
return FALSE;
}
if ((body=(Body *)gtk_ctree_node_get_row_data(tree,node)))
{
if (body == (Body *) nearestStar)
browserSel.select((Star *) nearestStar);
else
browserSel.select(body);
return TRUE;
}
DPRINTF(0, "Unable to find body for this node.\n");
return FALSE;
}
static gint selectBrowsed()
{
if (!browserSel.empty())
{
appSim->setSelection(browserSel);
return TRUE;
}
return FALSE;
}
static gint centerBrowsed()
{
if (!selectBrowsed())
return FALSE;
appCore->charEntered('C');
return TRUE;
}
static gint gotoBrowsed()
{
if (!selectBrowsed())
return FALSE;
appCore->charEntered('G');
return TRUE;
}
static gint buttonMake(GtkWidget *hbox, char *txt, GtkSignalFunc func, gpointer data)
{
GtkWidget* button = gtk_button_new_with_label(txt);
if (button == NULL)
{
DPRINTF(0, "Unable to get GTK Elements.\n");
return 1;
}
gtk_widget_show(button);
gtk_box_pack_start(GTK_BOX (hbox),
button, TRUE, TRUE, 0);
gtk_signal_connect(GTK_OBJECT(button),
"pressed",
func,
data);
return 0;
}
static StarBrowser sbrowser;
unsigned int currentLength=0;
static void addStars()
{
StarDatabase* stardb = appSim->getUniverse()->getStarCatalog();
sbrowser.refresh();
vector<const Star*> *stars = sbrowser.listStars(100);
gtk_clist_freeze(GTK_CLIST(clist));
for (unsigned int i = 0; i < currentLength; i++)
gtk_clist_remove(GTK_CLIST(clist), 0);
currentLength=(*stars).size();
browserSel.select((Star *)(*stars)[0]);
UniversalCoord ucPos = appSim->getObserver().getPosition();
for (unsigned int i = 0; i < currentLength; i++)
{
char buf[20];
const Star *star=(*stars)[i];
tmp[0] = g_strdup((stardb->getStarName(*star)).c_str());
sprintf(buf, " %.3f ", ucPos.distanceTo(star->getPosition()));
tmp[1] = g_strdup(buf);
Vec3f r = star->getPosition() - ucPos;
sprintf(buf, " %.2f ", astro::absToAppMag(star->getAbsoluteMagnitude(),r.length()));
tmp[2] = g_strdup(buf);
sprintf(buf, " %.2f ", star->getAbsoluteMagnitude());
tmp[3] = g_strdup(buf);
star->getStellarClass().str(buf, sizeof buf);
tmp[4] = g_strdup(buf);
gint row = gtk_clist_append(GTK_CLIST(clist), (char**) tmp);
gtk_clist_set_row_data(GTK_CLIST(clist), row, (gpointer) star);
for (unsigned int j = 0; j < 5; j++)
g_free((void*) tmp[j]);
}
gtk_clist_thaw(GTK_CLIST(clist));
delete stars;
}
static int radioClicked(GtkButton *button, int pred)
{
if (!sbrowser.setPredicate(pred))
return FALSE;
addStars();
return TRUE;
}
static int refreshBrowser()
{
addStars();
return TRUE;
}
static void loadNearestStarSystem()
{
const SolarSystem* solarSys = appSim->getNearestSolarSystem();
StarDatabase *stardb=appSim->getUniverse()->getStarCatalog();
g_assert(stardb);
gtk_clist_freeze(GTK_CLIST(ctree));
gtk_ctree_post_recursive(GTK_CTREE(ctree),NULL,(GtkCTreeFunc)gtk_ctree_remove_node,NULL);
if (solarSys != NULL)
nearestStar=solarSys->getStar();
else
nearestStar=sbrowser.nearestStar();
tmp[0] = const_cast<char*>(stardb->getStarName(*nearestStar).c_str());
char buf[30];
sprintf(buf, "%s Star", (nearestStar->getStellarClass().str().c_str()));
tmp[1] = buf;
GtkCTreeNode *top = gtk_ctree_insert_node (GTK_CTREE(ctree), NULL, NULL,
(char**) tmp , 0 , NULL, NULL,
NULL, NULL, FALSE, TRUE);
gtk_ctree_node_set_row_data(GTK_CTREE(ctree), top, (gpointer)nearestStar);
if (solarSys != NULL)
{
const PlanetarySystem* planets = solarSys->getPlanets();
if (planets != NULL)
addPlanetarySystemToTree(planets, top, 2);
}
gtk_clist_thaw((GTK_CLIST(ctree)));
}
static const Star *tmpSel=NULL;
int nbookSwitch(GtkNotebook *nbook, gpointer dummy, gint page, gpointer dummy2)
{
if (page == 1) // Page switch to the Solar System Browser
{
sbrowser.refresh();
loadNearestStarSystem();
tmpSel=browserSel.star;
browserSel.star=(Star *)nearestStar;
browserSel.body=NULL;
}
else
browserSel.select((Star *)tmpSel);
return(TRUE);
}
static void menuBrowser()
{
GtkWidget *browser= gnome_dialog_new("Celestial Browser",
GNOME_STOCK_BUTTON_OK,
NULL);
browserSel.select((Star *)NULL);
if (browser == NULL)
{
DPRINTF(0, "Unable to open celestial browser dialog!\n");
return;
}
GtkWidget *nbook = gtk_notebook_new();
GtkWidget *label = gtk_label_new("Stars");
GtkWidget *vbox = gtk_vbox_new(FALSE, 3);
GtkWidget *hbox = gtk_hbox_new(FALSE, 3);
GtkWidget *scrolled_win;
if ((nbook==NULL) || (label==NULL) || (vbox==NULL) || (hbox==NULL))
{
DPRINTF(0, "Unable to get GTK Elements.\n");
return;
}
// Star System Browser
gtk_notebook_append_page(GTK_NOTEBOOK(nbook), vbox, label);
gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (nbook), vbox,
TRUE, FALSE, GTK_PACK_START);
gtk_widget_show (label);
scrolled_win = gtk_scrolled_window_new (NULL, NULL);
clist = gtk_clist_new_with_titles(5, cstitles);
gtk_clist_column_titles_passive (GTK_CLIST(clist));
gtk_clist_set_auto_sort (GTK_CLIST(clist), FALSE);
gtk_clist_set_reorderable (GTK_CLIST(clist), FALSE);
GtkWidget *align=gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
if ((align==NULL) || (clist==NULL) || (scrolled_win==NULL))
{
DPRINTF(0, "Unable to get GTK Elements.\n");
return;
}
gtk_clist_set_column_justification(GTK_CLIST(clist), 0, GTK_JUSTIFY_LEFT);
gtk_clist_set_column_auto_resize(GTK_CLIST(clist), 0, TRUE);
gtk_clist_set_column_justification(GTK_CLIST(clist), 1, GTK_JUSTIFY_RIGHT);
gtk_clist_set_column_auto_resize(GTK_CLIST(clist), 1, TRUE);
gtk_clist_set_column_justification(GTK_CLIST(clist), 2, GTK_JUSTIFY_RIGHT);
gtk_clist_set_column_auto_resize(GTK_CLIST(clist), 2, TRUE);
gtk_clist_set_column_justification(GTK_CLIST(clist), 3, GTK_JUSTIFY_RIGHT);
gtk_clist_set_column_auto_resize(GTK_CLIST(clist), 3, TRUE);
gtk_clist_set_column_justification(GTK_CLIST(clist), 4, GTK_JUSTIFY_LEFT);
gtk_clist_set_column_auto_resize(GTK_CLIST(clist), 4, FALSE);
gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 5);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_ALWAYS);
gtk_container_add (GTK_CONTAINER (scrolled_win), GTK_WIDGET (clist));
gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_BROWSE);
gtk_clist_set_shadow_type (GTK_CLIST(clist), GTK_SHADOW_IN);
gtk_container_add(GTK_CONTAINER(align),GTK_WIDGET(hbox));
sbrowser.setSimulation(appSim);
addStars();
tmpSel=browserSel.star;
gtk_signal_connect(GTK_OBJECT(clist), "select-row",
GTK_SIGNAL_FUNC(listSelect), NULL);
gtk_clist_select_row(GTK_CLIST(clist), 0, 0);
GSList *group=NULL;
gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, TRUE, 5);
for(unsigned int i=0;i<4;i++)
{
GtkWidget *button=gtk_radio_button_new_with_label(group, radioLabels[i]);
if (button==NULL)
{
DPRINTF(0, "Unable to get GTK Elements.\n");
return;
}
group=gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),(i==0)?1:0);
gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
gtk_widget_show (button);
gtk_signal_connect(GTK_OBJECT(button), "pressed",
GTK_SIGNAL_FUNC(radioClicked), (gpointer)i );
}
if (buttonMake(hbox, " Refresh ", (GtkSignalFunc)refreshBrowser, NULL))
return;
gtk_widget_show (clist);
gtk_widget_show (align);
gtk_widget_show (hbox);
gtk_widget_show (scrolled_win);
gtk_widget_show (label);
gtk_widget_show (vbox);
// Solar System Browser
label = gtk_label_new("Solar System");
vbox = gtk_vbox_new(TRUE, 3);
scrolled_win = gtk_scrolled_window_new (NULL, NULL);
if ((label==NULL) || (vbox==NULL) || (scrolled_win==NULL))
{
DPRINTF(0, "Unable to get GTK Elements.\n");
return;
}
gtk_notebook_append_page(GTK_NOTEBOOK(nbook), vbox, label);
gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (nbook), vbox,
TRUE, FALSE, GTK_PACK_START);
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(nbook), TRUE);
gtk_notebook_set_scrollable(GTK_NOTEBOOK(nbook), FALSE);
gtk_notebook_set_tab_pos (GTK_NOTEBOOK (nbook), GTK_POS_TOP);
gtk_container_set_border_width (GTK_CONTAINER (nbook), 10);
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (browser)->vbox), nbook, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 5);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_ALWAYS);
gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
gtk_widget_show (scrolled_win);
ctree = GTK_WIDGET (gtk_ctree_new_with_titles (2, 0, sstitles));
gtk_clist_column_titles_passive (GTK_CLIST(ctree));
gtk_clist_set_auto_sort (GTK_CLIST(ctree), FALSE);
gtk_clist_set_reorderable (GTK_CLIST(ctree), FALSE);
gtk_container_add (GTK_CONTAINER (scrolled_win), GTK_WIDGET (ctree));
gtk_clist_set_column_auto_resize (GTK_CLIST (ctree), 0, TRUE);
gtk_clist_set_column_width (GTK_CLIST (ctree), 1, 200);
gtk_clist_set_selection_mode (GTK_CLIST (ctree), GTK_SELECTION_BROWSE);
gtk_ctree_set_line_style (GTK_CTREE(ctree), GTK_CTREE_LINES_SOLID);
gtk_ctree_set_expander_style (GTK_CTREE(ctree), GTK_CTREE_EXPANDER_SQUARE);
gtk_widget_show (vbox);
loadNearestStarSystem();
gtk_signal_connect(GTK_OBJECT(ctree), "tree-select-row",
GTK_SIGNAL_FUNC(treeSelect), NULL);
gtk_signal_connect(GTK_OBJECT(nbook), "switch-page",
GTK_SIGNAL_FUNC(nbookSwitch), NULL);
gtk_widget_show (ctree);
gtk_widget_show (nbook);
// Common Buttons
hbox = gtk_hbox_new(FALSE, 3);
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (browser)->vbox), hbox, FALSE, FALSE, 0);
if (buttonMake(hbox, " Select ", (GtkSignalFunc)selectBrowsed, NULL))
return;
if (buttonMake(hbox, " Center ", (GtkSignalFunc)centerBrowsed, NULL))
return;
if (buttonMake(hbox, " Go To ", (GtkSignalFunc)gotoBrowsed, NULL))
return;
gtk_widget_show (hbox);
gtk_widget_set_usize(browser, 500, 400); // Absolute Size, urghhh
gnome_dialog_set_parent((GnomeDialog*) browser, GTK_WINDOW(mainWindow));
gnome_dialog_set_default((GnomeDialog*) browser, GNOME_YES);
gnome_dialog_close_hides((GnomeDialog*) browser, FALSE);
gtk_window_set_modal(GTK_WINDOW(browser), FALSE);
gnome_dialog_run_and_close(GNOME_DIALOG(browser));
clist=NULL;
ctree=NULL;
browserSel.select((Star *)NULL);
}
static gint intAdjChanged(GtkAdjustment* adj, int *val)
{
if (val)
{
*val=(int)adj->value;
return TRUE;
}
return FALSE;
}
char *timeOptions[]=
{
"UTC",
NULL,
NULL
};
char *monthOptions[]=
{
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
NULL
};
static int tzone;
static int *monthLoc=NULL;
static gint zonechosen(GtkMenuItem *item, int zone)
{
tzone=zone;
return TRUE;
}
static gint monthchosen(GtkMenuItem *item, int month)
{
if (monthLoc)
*monthLoc=month;
return TRUE;
}
static void chooseOption(GtkWidget *hbox, char *str, char *choices[], int *val, char *sep, GtkSignalFunc chosen)
{
GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
GtkWidget *label = gtk_label_new(str);
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
GtkWidget *optmenu = gtk_option_menu_new ();
GtkWidget *menu = gtk_menu_new ();
GSList *group=NULL;
for(unsigned int i=0; choices[i]; i++)
{
GtkWidget *menu_item = gtk_radio_menu_item_new_with_label (group, choices[i]);
gtk_signal_connect (GTK_OBJECT (menu_item), "activate", chosen, (gpointer) (i+1));
group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menu_item));
gtk_menu_append (GTK_MENU (menu), menu_item);
if ((((int)i+1))==*val)
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), TRUE);
gtk_widget_show (menu_item);
}
gtk_option_menu_set_menu (GTK_OPTION_MENU (optmenu), menu);
gtk_option_menu_set_history (GTK_OPTION_MENU (optmenu), (*val-1));
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (vbox), optmenu, FALSE, TRUE, 7);
gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 2);
gtk_widget_show (label);
gtk_widget_show (optmenu);
gtk_widget_show (vbox);
}
static void intSpin(GtkWidget *hbox, char *str, int min, int max, int *val, char *sep)
{
GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
GtkWidget *label = gtk_label_new(str);
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
GtkAdjustment *adj = (GtkAdjustment *) gtk_adjustment_new ((float)*val, (float) min, (float) max,
1.0, 5.0, 0.0);
GtkWidget *spinner = gtk_spin_button_new (adj, 1.0, 0);
gtk_spin_button_set_numeric(GTK_SPIN_BUTTON (spinner), TRUE);
gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner),
GTK_SHADOW_IN);
gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON (spinner),TRUE);
gtk_entry_set_max_length(GTK_ENTRY (spinner), ((max<99)?2:4) );
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
if ((sep) && (*sep))
{
gtk_widget_show (label);
GtkWidget *hbox2 = gtk_hbox_new(FALSE, 3);
label = gtk_label_new(sep);
gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5);
gtk_box_pack_start (GTK_BOX (hbox2), spinner, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (vbox), hbox2, TRUE, TRUE, 7);
gtk_widget_show (label);
gtk_widget_show (hbox2);
}
else
{
gtk_box_pack_start (GTK_BOX (vbox), spinner, TRUE, TRUE, 7);
}
gtk_widget_show (label);
gtk_widget_show (spinner);
gtk_widget_show (vbox);
gtk_signal_connect(GTK_OBJECT(adj), "value-changed",
GTK_SIGNAL_FUNC(intAdjChanged), val);
}
static void menuSetTime()
{
int second;
GtkWidget *stimedialog = gnome_dialog_new("Set Time",
GNOME_STOCK_BUTTON_OK,
"Set Current Time",
GNOME_STOCK_BUTTON_CANCEL,
NULL);
tzone=1;
if (appCore->getTimeZoneBias())
tzone=2;
if (stimedialog == NULL)
{
DPRINTF(0, "Unable to open 'Set Time' dialog!\n");
return;
}
GtkWidget *hbox = gtk_hbox_new(FALSE, 6);
GtkWidget *frame = gtk_frame_new("Time");
GtkWidget *align=gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
if ((hbox == NULL) || (frame == NULL) || (align == NULL))
{
DPRINTF(0, "Unable to get GTK Elements.\n");
return;
}
astro::Date date(appSim->getTime() +
astro::secondsToJulianDate(appCore->getTimeZoneBias()));
monthLoc = &date.month;
gtk_widget_show(align);
gtk_widget_show(frame);
gtk_container_add(GTK_CONTAINER(align),GTK_WIDGET(hbox));
gtk_container_add(GTK_CONTAINER(frame),GTK_WIDGET(align));
gtk_container_set_border_width (GTK_CONTAINER (frame), 7);
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (stimedialog)->vbox), frame, FALSE, FALSE, 0);
intSpin(hbox, "Hour", 1, 24, &date.hour, ":");
intSpin(hbox, "Minute", 1, 60, &date.minute, ":");
second=(int)date.seconds;
intSpin(hbox, "Second", 1, 60, &second, " ");
chooseOption(hbox, "Timzone", timeOptions, &tzone, NULL, GTK_SIGNAL_FUNC(zonechosen));
gtk_widget_show_all(hbox);
hbox = gtk_hbox_new(FALSE, 6);
frame = gtk_frame_new("Date");
align=gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
gtk_container_set_border_width (GTK_CONTAINER (frame), 7);
if ((hbox == NULL) || (frame == NULL) || (align == NULL))
{
DPRINTF(0, "Unable to get GTK Elements.\n");
return;
}
chooseOption(hbox,"Month", monthOptions, &date.month, " ", GTK_SIGNAL_FUNC(monthchosen));
intSpin(hbox,"Day", 1, 31, &date.day, ",");
intSpin(hbox,"Year", -9999, 9999, &date.year, " "); /* (Hopefully,
noone will need to go beyond these :-) */
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (stimedialog)->vbox), frame, FALSE, FALSE, 0);
gtk_container_add(GTK_CONTAINER(align),GTK_WIDGET(hbox));
gtk_container_add(GTK_CONTAINER(frame),GTK_WIDGET(align));
gtk_widget_show(align);
gtk_widget_show(frame);
gtk_widget_show_all(hbox);
gnome_dialog_set_parent((GnomeDialog*) stimedialog, GTK_WINDOW(mainWindow));
gnome_dialog_set_default((GnomeDialog*) stimedialog, GNOME_YES);
gnome_dialog_close_hides((GnomeDialog*) stimedialog, FALSE);
gtk_window_set_modal(GTK_WINDOW(stimedialog), FALSE);
gint button=gnome_dialog_run_and_close(GNOME_DIALOG(stimedialog));
monthLoc=NULL;
if (button==1) // Set current time and exit.
{
time_t curtime=time(NULL);
appSim->setTime((double) curtime / 86400.0 + (double) astro::Date(1970, 1, 1));
appSim->update(0.0);
}
else if (button==0) // Set entered time and exit
{
appSim->setTime((double) date - ((tzone==1) ? 0 : astro::secondsToJulianDate(appCore->getTimeZoneBias())));
appSim->update(0.0);
}
}
static GtkItemFactoryEntry menuItems[] =
{
{ "/_File", NULL, NULL, 0, "<Branch>" },
{ "/File/Capture Image...", "F10", menuCaptureImage,0, NULL },
{ "/File/Quit", "<control>Q", gtk_main_quit, 0, NULL },
{ "/_Navigation", NULL, NULL, 0, "<Branch>" },
{ "/Navigation/Select Sol", "H", menuSelectSol, 0, NULL },
{ "/Navigation/Tour Guide", NULL, menuTourGuide, 0, NULL },
{ "/Navigation/Select Object...", NULL, menuSelectObject, 0, NULL },
{ "/Navigation/Goto Object...", NULL, menuGotoObject,0, NULL },
{ "/Navigation/sep1", NULL, NULL, 0, "<Separator>" },
{ "/Navigation/Center Selection", "C", menuCenter, 0, NULL },
{ "/Navigation/Goto Selection", "G", menuGoto, 0, NULL },
{ "/Navigation/Follow Selection", "F", menuFollow, 0, NULL },
{ "/Navigation/Sync Orbit", "Y", menuSync, 0, NULL },
{ "/Navigation/Track Selection", "T", menuTrack, 0, NULL },
{ "/Navigation/sep2", NULL, NULL, 0, "<Separator>" },
{ "/Navigation/Celestial Browser", NULL,menuBrowser, 0, NULL },
{ "/_Time", NULL, NULL, 0, "<Branch>" },
{ "/Time/10x Faster", "L", menuFaster, 0, NULL },
{ "/Time/10x Slower", "K", menuSlower, 0, NULL },
{ "/Time/Pause", "space", menuPause, 0, NULL },
{ "/Time/Real Time", "backslash", menuRealTime, 0, NULL },
{ "/Time/Reverse", "J", menuReverse, 0, NULL },
{ "/Time/Set Time", NULL, menuSetTime, 0, NULL },
{ "/Time/sep1", NULL, NULL, 0, "<Separator>" },
{ "/Time/Show Local Time", "I", NULL, Menu_ShowLocTime, "<ToggleItem>" },
{ "/_Render", NULL, NULL, 0, "<Branch>" },
{ "/Render/Show Galaxies", "U", NULL, Menu_ShowGalaxies, "<ToggleItem>" },
{ "/Render/Show Atmospheres", "<control>A",NULL, Menu_ShowAtmospheres, "<ToggleItem>" },
{ "/Render/Show Clouds", "I", NULL, Menu_ShowClouds, "<ToggleItem>" },
{ "/Render/Show Orbits", "O", NULL, Menu_ShowOrbits, "<ToggleItem>" },
{ "/Render/Show Constellations", "slash",NULL, Menu_ShowConstellations, "<ToggleItem>" },
{ "/Render/Show Coordinate Sphere", "semicolon",NULL, Menu_ShowCelestialSphere, "<ToggleItem>" },
{ "/Render/Show Night Side Lights", "<control>L",NULL, Menu_ShowNightSideMaps, "<ToggleItem>" },
{ "/Render/sep1", NULL, NULL, 0, "<Separator>" },
{ "/Render/More Stars Visible", "bracketleft", menuMoreStars, 0, NULL },
{ "/Render/Fewer Stars Visible", "bracketright", menuLessStars, 0, NULL },
{ "/Render/sep2", NULL, NULL, 0, "<Separator>" },
{ "/Render/Label Major Planets", "N", NULL, Menu_MajorPlanetLabels, "<ToggleItem>" },
{ "/Render/Label Minor Planets", "M", NULL, Menu_MinorPlanetLabels, "<ToggleItem>" },
{ "/Render/Label Stars", "B", NULL, Menu_StarLabels, "<ToggleItem>" },
{ "/Render/Label Galaxies", "E", NULL, Menu_GalaxyLabels, "<ToggleItem>" },
{ "/Render/Label Constellations", "equal",NULL, Menu_ConstellationLabels, "<ToggleItem>" },
{ "/Render/Show Info Text", "V", menuShowInfo, 0, NULL },
{ "/Render/sep3", NULL, NULL, 0, "<Separator>" },
{ "/Render/_Ambient", NULL, NULL, 0, "<Branch>" },
{ "/Render/Ambient/None", NULL, menuNoAmbient, 0, NULL },
{ "/Render/Ambient/Low", NULL, menuLowAmbient,0, NULL },
{ "/Render/Ambient/Medium", NULL, menuMedAmbient,0, NULL },
{ "/Render/Ambient/High", NULL, menuHiAmbient, 0, NULL },
{ "/_Help", NULL, NULL, 0, "<LastBranch>" },
{ "/Help/Run Demo", "D", menuRunDemo, 0, NULL },
{ "/Help/sep1", NULL, NULL, 0, "<Separator>" },
{ "/Help/Controls", NULL, menuControls, 0, NULL },
{ "/Help/OpenGL Info", NULL, menuOpenGL, 0, NULL },
{ "/Help/License", NULL, menuLicense, 0, NULL },
{ "/Help/sep2", NULL, NULL, 0, "<Separator>" },
{ "/Help/About", NULL, menuAbout, 0, NULL },
};
static GtkItemFactoryEntry optMenuItems[] =
{
{ "/Render/Use Pixel Shaders", "<control>P", NULL, Menu_PixelShaders, "<ToggleItem>" },
{ "/Render/Use Vertex Shaders", "<control>V", NULL, Menu_PixelShaders, "<ToggleItem>" },
};
int checkLocalTime(int dummy)
{
return(appCore->getTimeZoneBias()!=0);
}
int checkPixelShaders(int dummy)
{
return(appRenderer->getFragmentShaderEnabled());
}
int checkVertexShaders(int dummy)
{
return(appRenderer->getVertexShaderEnabled());
}
int checkShowGalaxies(int dummy)
{
return((appRenderer->getRenderFlags() & Renderer::ShowGalaxies) == Renderer::ShowGalaxies);
}
int checkRenderFlag(int flag)
{
return((appRenderer->getRenderFlags() & flag) == flag);
}
int checkLabelFlag(int flag)
{
return((appRenderer->getLabelMode() & flag) == flag);
}
static CheckFunc checks[] =
{
{ NULL, "/Time/Show Local Time", checkLocalTime, 1, 0 },
{ NULL, "/Render/Use Pixel Shaders", checkPixelShaders, 0, 0 },
{ NULL, "/Render/Use Vertex Shaders", checkVertexShaders, 0, 0 },
{ NULL, "/Render/Show Galaxies", checkRenderFlag, 1, Renderer::ShowGalaxies },
{ NULL, "/Render/Show Atmospheres", checkRenderFlag, 1, Renderer::ShowAtmospheres },
{ NULL, "/Render/Show Clouds", checkRenderFlag, 1, Renderer::ShowCloudMaps },
{ NULL, "/Render/Show Orbits", checkRenderFlag, 1, Renderer::ShowOrbits },
{ NULL, "/Render/Show Constellations", checkRenderFlag, 1, Renderer::ShowDiagrams },
{ NULL, "/Render/Show Coordinate Sphere",checkRenderFlag, 1, Renderer::ShowCelestialSphere },
{ NULL, "/Render/Show Night Side Lights",checkRenderFlag, 1, Renderer::ShowNightMaps },
{ NULL, "/Render/Label Major Planets", checkLabelFlag, 1, Renderer::MajorPlanetLabels },
{ NULL, "/Render/Label Minor Planets", checkLabelFlag, 1, Renderer::MinorPlanetLabels },
{ NULL, "/Render/Label Stars", checkLabelFlag, 1, Renderer::StarLabels },
{ NULL, "/Render/Label Galaxies", checkLabelFlag, 1, Renderer::GalaxyLabels },
{ NULL, "/Render/Label Constellations", checkRenderFlag, 1, Renderer::ConstellationLabels },
};
void setupCheckItem(GtkItemFactory* factory, int action, GtkSignalFunc func)
{
GtkWidget* w = gtk_item_factory_get_widget_by_action(factory, action);
if (w != NULL)
{
gtk_signal_connect(GTK_OBJECT(w), "toggled",
GTK_SIGNAL_FUNC(func),
NULL);
}
}
void createMainMenu(GtkWidget* window, GtkWidget** menubar)
{
gint nItems = sizeof(menuItems) / sizeof(menuItems[0]);
GtkAccelGroup* accelGroup = gtk_accel_group_new();
menuItemFactory = gtk_item_factory_new(GTK_TYPE_MENU_BAR,
"<main>",
accelGroup);
gtk_accel_group_attach (accelGroup, GTK_OBJECT (window));
gtk_item_factory_create_items(menuItemFactory, nItems, menuItems, NULL);
appRenderer=appCore->getRenderer();
g_assert(appRenderer);
appSim = appCore->getSimulation();
g_assert(appSim);
if (appRenderer->fragmentShaderSupported())
{
gtk_item_factory_create_item(menuItemFactory, &optMenuItems[0], NULL, 1);
checks[1].active=1;
}
if (appRenderer->vertexShaderSupported())
{
gtk_item_factory_create_item(menuItemFactory, &optMenuItems[1], NULL, 1);
checks[2].active=1;
}
if (menubar != NULL)
*menubar = gtk_item_factory_get_widget(menuItemFactory, "<main>");
setupCheckItem(menuItemFactory, Menu_ShowGalaxies,
GTK_SIGNAL_FUNC(menuShowGalaxies));
setupCheckItem(menuItemFactory, Menu_ShowConstellations,
GTK_SIGNAL_FUNC(menuShowConstellations));
setupCheckItem(menuItemFactory, Menu_ShowAtmospheres,
GTK_SIGNAL_FUNC(menuShowAtmospheres));
setupCheckItem(menuItemFactory, Menu_ShowClouds,
GTK_SIGNAL_FUNC(menuShowClouds));
setupCheckItem(menuItemFactory, Menu_ShowNightSideMaps,
GTK_SIGNAL_FUNC(menuShowNightSideMaps));
setupCheckItem(menuItemFactory, Menu_ShowOrbits,
GTK_SIGNAL_FUNC(menuShowOrbits));
setupCheckItem(menuItemFactory, Menu_MajorPlanetLabels,
GTK_SIGNAL_FUNC(menuMajorPlanetLabels));
setupCheckItem(menuItemFactory, Menu_MinorPlanetLabels,
GTK_SIGNAL_FUNC(menuMinorPlanetLabels));
setupCheckItem(menuItemFactory, Menu_StarLabels,
GTK_SIGNAL_FUNC(menuStarLabels));
setupCheckItem(menuItemFactory, Menu_GalaxyLabels,
GTK_SIGNAL_FUNC(menuGalaxyLabels));
setupCheckItem(menuItemFactory, Menu_ConstellationLabels,
GTK_SIGNAL_FUNC(menuConstellationLabels));
setupCheckItem(menuItemFactory, Menu_ShowCelestialSphere,
GTK_SIGNAL_FUNC(menuShowCelestialSphere));
setupCheckItem(menuItemFactory, Menu_ShowLocTime,
GTK_SIGNAL_FUNC(menuShowLocTime));
if (appRenderer->fragmentShaderSupported())
setupCheckItem(menuItemFactory, Menu_PixelShaders,
GTK_SIGNAL_FUNC(menuPixelShaders));
if (appRenderer->vertexShaderSupported())
setupCheckItem(menuItemFactory, Menu_VertexShaders,
GTK_SIGNAL_FUNC(menuVertexShaders));
}
gint reshapeFunc(GtkWidget* widget, GdkEventConfigure* event)
{
if (gtk_gl_area_make_current(GTK_GL_AREA(widget)))
{
int w = widget->allocation.width;
int h = widget->allocation.height;
appCore->resize(w, h);
}
return TRUE;
}
bool bReady = false;
/*
* Definition of Gtk callback functions
*/
gint initFunc(GtkWidget* widget)
{
if (gtk_gl_area_make_current(GTK_GL_AREA(widget)))
{
if (!appCore->initRenderer())
{
cerr << "Failed to initialize renderer.\n";
return TRUE;
}
time_t curtime=time(NULL);
appCore->start((double) curtime / 86400.0 + (double) astro::Date(1970, 1, 1));
localtime(&curtime); /* Only doing this to set timezone as a side
effect*/
appCore->setTimeZoneBias(-timezone);
appCore->setTimeZoneName(tzname[daylight?0:1]);
timeOptions[1]=tzname[daylight?0:1];
}
return TRUE;
}
void Display(GtkWidget* widget)
{
if (bReady)
{
appCore->draw();
gtk_gl_area_swapbuffers(GTK_GL_AREA(widget));
}
}
gint glarea_idle(void*)
{
appCore->tick();
Display(GTK_WIDGET(oglArea));
return TRUE;
}
gint glarea_draw(GtkWidget* widget, GdkEventExpose* event)
{
// Draw only the last expose
if (event->count > 0)
return TRUE;
if (gtk_gl_area_make_current(GTK_GL_AREA(widget)))
Display(widget);
return TRUE;
}
gint glarea_motion_notify(GtkWidget* widget, GdkEventMotion* event)
{
int x = (int) event->x;
int y = (int) event->y;
int buttons = 0;
if ((event->state & GDK_BUTTON1_MASK) != 0)
buttons |= CelestiaCore::LeftButton;
if ((event->state & GDK_BUTTON2_MASK) != 0)
buttons |= CelestiaCore::MiddleButton;
if ((event->state & GDK_BUTTON3_MASK) != 0)
buttons |= CelestiaCore::RightButton;
appCore->mouseMove(x - lastX, y - lastY, buttons);
lastX = x;
lastY = y;
return TRUE;
}
gint glarea_button_press(GtkWidget* widget, GdkEventButton* event)
{
if (event->button == 4)
{
appCore->mouseWheel(-1.0f, 0);
}
else if (event->button == 5)
{
appCore->mouseWheel(1.0f, 0);
}
else if (event->button <= 3)
{
lastX = (int) event->x;
lastY = (int) event->y;
if (event->button == 1)
appCore->mouseButtonDown(event->x, event->y, CelestiaCore::LeftButton);
else if (event->button == 2)
appCore->mouseButtonDown(event->x, event->y, CelestiaCore::MiddleButton);
else if (event->button == 3)
appCore->mouseButtonDown(event->x, event->y, CelestiaCore::RightButton);
}
return TRUE;
}
gint glarea_button_release(GtkWidget* widget, GdkEventButton* event)
{
lastX = (int) event->x;
lastY = (int) event->y;
if (event->button == 1)
appCore->mouseButtonUp(event->x, event->y, CelestiaCore::LeftButton);
else if (event->button == 2)
appCore->mouseButtonUp(event->x, event->y, CelestiaCore::MiddleButton);
else if (event->button == 3)
appCore->mouseButtonUp(event->x, event->y, CelestiaCore::RightButton);
return TRUE;
}
static bool handleSpecialKey(int key, bool down)
{
int k = -1;
switch (key)
{
case GDK_Up:
k = CelestiaCore::Key_Up;
break;
case GDK_Down:
k = CelestiaCore::Key_Down;
break;
case GDK_Left:
k = CelestiaCore::Key_Left;
break;
case GDK_Right:
k = CelestiaCore::Key_Right;
break;
case GDK_Home:
k = CelestiaCore::Key_Home;
break;
case GDK_End:
k = CelestiaCore::Key_End;
break;
case GDK_F1:
k = CelestiaCore::Key_F1;
break;
case GDK_F2:
k = CelestiaCore::Key_F2;
break;
case GDK_F3:
k = CelestiaCore::Key_F3;
break;
case GDK_F4:
k = CelestiaCore::Key_F4;
break;
case GDK_F5:
k = CelestiaCore::Key_F5;
break;
case GDK_F6:
k = CelestiaCore::Key_F6;
break;
case GDK_F7:
k = CelestiaCore::Key_F7;
break;
case GDK_F10:
if (down)
menuCaptureImage();
break;
case GDK_KP_0:
k = CelestiaCore::Key_NumPad0;
break;
case GDK_KP_1:
k = CelestiaCore::Key_NumPad1;
break;
case GDK_KP_2:
k = CelestiaCore::Key_NumPad2;
break;
case GDK_KP_3:
k = CelestiaCore::Key_NumPad3;
break;
case GDK_KP_4:
k = CelestiaCore::Key_NumPad4;
break;
case GDK_KP_5:
k = CelestiaCore::Key_NumPad5;
break;
case GDK_KP_6:
k = CelestiaCore::Key_NumPad6;
break;
case GDK_KP_7:
k = CelestiaCore::Key_NumPad7;
break;
case GDK_KP_8:
k = CelestiaCore::Key_NumPad8;
break;
case GDK_KP_9:
k = CelestiaCore::Key_NumPad9;
break;
case GDK_A:
case GDK_a:
k = 'A';
break;
case GDK_Z:
case GDK_z:
k = 'Z';
break;
}
if (k >= 0)
{
if (down)
appCore->keyDown(k);
else
appCore->keyUp(k);
return (k < 'A' || k > 'Z');
}
else
{
return false;
}
}
gint glarea_key_press(GtkWidget* widget, GdkEventKey* event)
{
gtk_signal_emit_stop_by_name(GTK_OBJECT(widget),"key_press_event");
switch (event->keyval)
{
case GDK_Escape:
appCore->charEntered('\033');
break;
case 'q':
case 'Q':
if(event->state & GDK_CONTROL_MASK)
{ /* Why isn't Ctrl-Q sending char 21 ? I have no idea, but as
long as it isn't, this will work. */
gtk_main_quit();
}
// Intentional fallthrough if *not* Ctrl-Q
default:
if (!handleSpecialKey(event->keyval, true))
{
if (event->string != NULL)
{
char* s = event->string;
while (*s != '\0')
{
char c = *s++;
appCore->charEntered(c);
}
}
}
}
return TRUE;
}
gint glarea_key_release(GtkWidget* widget, GdkEventKey* event)
{
gtk_signal_emit_stop_by_name(GTK_OBJECT(widget),"key_release_event");
return handleSpecialKey(event->keyval, false);
}
struct poptOption options[] =
{
{
"verbose",
'v',
POPT_ARG_INT,
&verbose,
0,
"Lots of additional Messages",
NULL
},
{
NULL,
'\0',
0,
NULL,
0,
NULL,
NULL
}
};
int main(int argc, char* argv[])
{
// Say we're not ready to render yet.
bReady = false;
// Set starting filename for screen captures
captureFilename = new string(getcwd(NULL,0));
*captureFilename+="/celestia.jpg";
if (chdir(CONFIG_DATA_DIR) == -1)
{
cerr << "Cannot chdir to '" << CONFIG_DATA_DIR <<
"', probably due to improper installation\n";
}
// Now initialize OpenGL and Gnome
gnome_init_with_popt_table("Celestia", VERSION, argc, argv, options, 0,
NULL);
SetDebugVerbosity(verbose);
appCore = new CelestiaCore();
if (appCore == NULL)
{
cerr << "Out of memory.\n";
return 1;
}
if (!appCore->initSimulation())
{
return 1;
}
// Check if OpenGL is supported
if (gdk_gl_query() == FALSE)
{
g_print("OpenGL not supported\n");
return 0;
}
// Create the main window
mainWindow=gnome_app_new("Celestia",AppName);
gtk_container_set_border_width(GTK_CONTAINER(mainWindow), 1);
mainBox = GTK_WIDGET(gtk_vbox_new(FALSE, 0));
gtk_container_set_border_width(GTK_CONTAINER(mainBox), 0);
gtk_signal_connect(GTK_OBJECT(mainWindow), "delete_event",
GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
gtk_quit_add_destroy(1, GTK_OBJECT(mainWindow));
// Create the OpenGL widget
oglArea = GTK_WIDGET(gtk_gl_area_new(oglAttributeList));
gtk_widget_set_events(GTK_WIDGET(oglArea),
GDK_EXPOSURE_MASK |
GDK_KEY_PRESS_MASK |
GDK_KEY_RELEASE_MASK |
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_POINTER_MOTION_MASK);
// Connect signal handlers
gtk_signal_connect(GTK_OBJECT(oglArea), "expose_event",
GTK_SIGNAL_FUNC(glarea_draw), NULL);
gtk_signal_connect(GTK_OBJECT(oglArea), "configure_event",
GTK_SIGNAL_FUNC(reshapeFunc), NULL);
gtk_signal_connect(GTK_OBJECT(oglArea), "realize",
GTK_SIGNAL_FUNC(initFunc), NULL);
gtk_signal_connect(GTK_OBJECT(oglArea), "button_press_event",
GTK_SIGNAL_FUNC(glarea_button_press), NULL);
gtk_signal_connect(GTK_OBJECT(oglArea), "button_release_event",
GTK_SIGNAL_FUNC(glarea_button_release), NULL);
gtk_signal_connect(GTK_OBJECT(oglArea), "motion_notify_event",
GTK_SIGNAL_FUNC(glarea_motion_notify), NULL);
gtk_signal_connect(GTK_OBJECT(oglArea), "key_press_event",
GTK_SIGNAL_FUNC(glarea_key_press), NULL);
gtk_signal_connect(GTK_OBJECT(oglArea), "key_release_event",
GTK_SIGNAL_FUNC(glarea_key_release), NULL);
// Set the minimum size
// gtk_widget_set_usize(GTK_WIDGET(oglArea), 200, 150);
// Set the default size
gtk_gl_area_size(GTK_GL_AREA(oglArea), 640, 480);
createMainMenu(mainWindow, &mainMenu);
// gtk_container_add(GTK_CONTAINER(mainWindow), GTK_WIDGET(oglArea));
gnome_app_set_contents((GnomeApp *)mainWindow, GTK_WIDGET(mainBox));
gtk_box_pack_start(GTK_BOX(mainBox), mainMenu, FALSE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(mainBox), oglArea, TRUE, TRUE, 0);
gtk_widget_show(GTK_WIDGET(oglArea));
gtk_widget_show(GTK_WIDGET(mainBox));
gtk_widget_show(GTK_WIDGET(mainMenu));
gtk_widget_show(GTK_WIDGET(mainWindow));
// Set focus to oglArea widget
GTK_WIDGET_SET_FLAGS(oglArea, GTK_CAN_FOCUS);
gtk_widget_grab_focus(GTK_WIDGET(oglArea));
gtk_idle_add(glarea_idle, NULL);
bReady = true;
g_assert(menuItemFactory);
// Check all the toggle items that they are set on/off correctly
int i = sizeof(checks) / sizeof(checks[0]);
for(CheckFunc *cfunc=&checks[--i];i>=0;cfunc=&checks[--i])
{
if (!cfunc->active)
continue;
g_assert(cfunc->path);
cfunc->widget=GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(menuItemFactory, cfunc->path));
if (!cfunc->widget)
{
cfunc->active=0;
DPRINTF(0, "Menu item %s status checking deactivated due to being unable to find it!", cfunc->path);
continue;
}
g_assert(cfunc->func);
int res=(*cfunc->func)(cfunc->funcdata);
if (res)
{
if (cfunc->widget->active == FALSE)
{
// Change state of widget *without* causing a message to be
// sent (which would change the state again).
gtk_widget_hide(GTK_WIDGET(cfunc->widget));
cfunc->widget->active=TRUE;
gtk_widget_show(GTK_WIDGET(cfunc->widget));
}
}
}
gtk_main();
delete captureFilename;
return 0;
}