From 05b5d261682b9136fb46476a64eab6980b0dba64 Mon Sep 17 00:00:00 2001 From: taw27 Date: Mon, 5 Feb 2007 21:12:57 +0000 Subject: Initial import git-svn-id: svn://cook.msm.cam.ac.uk:745/diff-tomo/dtr@1 bf6ca9ba-c028-0410-8290-897cf20841d1 --- src/displaywindow.c | 543 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 543 insertions(+) create mode 100644 src/displaywindow.c (limited to 'src/displaywindow.c') diff --git a/src/displaywindow.c b/src/displaywindow.c new file mode 100644 index 0000000..58c9e10 --- /dev/null +++ b/src/displaywindow.c @@ -0,0 +1,543 @@ +/* + * displaywindow.c + * + * The display window + * + * (c) 2007 Thomas White + * dtr - Diffraction Tomography Reconstruction + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include + +#include "trackball.h" +#include "reflections.h" +#include "main.h" + +enum { + DW_ORTHO, + DW_PERSPECTIVE +}; + +GtkUIManager *displaywindow_ui; +GtkActionGroup *displaywindow_action_group; +GtkWidget *displaywindow_window; +GtkWidget *displaywindow_bigvbox; +GtkWidget *displaywindow_status_bar; +int displaywindow_view = DW_ORTHO; +GtkWidget *displaywindow_drawing_area; +GLfloat displaywindow_distance = 150; +GLfloat displaywindow_x_pos = 0; +GLfloat displaywindow_y_pos = 0; + +void error_report(const char *message) { + + GtkWidget *window; + + window = gtk_message_dialog_new(GTK_WINDOW(displaywindow_window), GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, message); + + g_signal_connect_swapped(window, "response", G_CALLBACK(gtk_widget_destroy), window); + gtk_widget_show(window); + +} + +static void displaywindow_about() { + + GtkWidget *window; + + const gchar *authors[] = { + "Thomas White ", + "Gordon Ball ", + "Paul Midgley ", + NULL + }; + + window = gtk_about_dialog_new(); + + gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(window), PACKAGE_NAME); + gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(window), PACKAGE_VERSION); + gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(window), "(c) 2006-2007 Thomas White "); + gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(window), "Diffraction Tomography Reconstruction"); + gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(window), "(c) 2006-2007 Thomas White \n" + "Virtual trackball (c) Copyright 1993, 1994, Silicon Graphics, Inc.\n" + "\n" + "Research funded by:\n" + "The Engineering and Physical Sciences Research Council\n" + "FEI Electron Optics B.V."); + gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(window), "http://www-hrem.msm.cam.ac.uk/"); + gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(window), authors); + + g_signal_connect(window, "response", G_CALLBACK(gtk_widget_destroy), NULL); + + gtk_widget_show_all(window); + +} + +static void displaywindow_close() { + gtk_exit(0); +} + +static void displaywindow_gl_set_ortho(GLfloat w, GLfloat h) { + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + if ( w > h ) { + GLfloat aspect = w/h; + glOrtho(-aspect*(displaywindow_distance/2), aspect*(displaywindow_distance/2), -(displaywindow_distance/2), (displaywindow_distance/2), 2.0, 1000.0); + } else { + GLfloat aspect = h/w; + glOrtho(-(displaywindow_distance/2), (displaywindow_distance/2), -aspect*(displaywindow_distance/2), aspect*(displaywindow_distance/2), 2.0, 1000.0); + } + glMatrixMode(GL_MODELVIEW); + +} + +static void displaywindow_gl_set_perspective(GLfloat w, GLfloat h) { + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + if ( w > h ) { + GLfloat aspect = w/h; + glFrustum(-aspect, aspect, -1.0, 1.0, 2.0, 1000.0); + } else { + GLfloat aspect = h/w; + glFrustum(-1.0, 1.0, -aspect, aspect, 2.0, 1000.0); + } + glMatrixMode(GL_MODELVIEW); + +} + +static gint displaywindow_changeview(GtkWidget *widget, GtkRadioAction *action) { + + GLfloat w = displaywindow_drawing_area->allocation.width; + GLfloat h = displaywindow_drawing_area->allocation.height; + displaywindow_view = gtk_radio_action_get_current_value(action); + + if ( displaywindow_view == DW_ORTHO ) { + displaywindow_gl_set_ortho(w, h); + } else { + displaywindow_gl_set_perspective(w, h); + } + + return 0; + +} + +static void displaywindow_addui_callback(GtkUIManager *ui, GtkWidget *widget, GtkContainer *container) { + + gtk_box_pack_start(GTK_BOX(container), widget, FALSE, FALSE, 0); + + /* Enable overflow menu if this is a toolbar */ + if ( GTK_IS_TOOLBAR(widget) ) { + gtk_toolbar_set_show_arrow(GTK_TOOLBAR(widget), TRUE); + } + +} + +static void displaywindow_addmenubar() { + + GtkActionEntry entries[] = { + + { "FileAction", NULL, "_File", NULL, NULL, NULL }, + { "SaveAction", GTK_STOCK_SAVE, "_Save Image...", NULL, NULL, G_CALLBACK(NULL) }, + { "CloseAction", GTK_STOCK_CLOSE, "_Close", NULL, NULL, G_CALLBACK(displaywindow_close) }, + + { "ViewAction", NULL, "_View", NULL, NULL, NULL }, + + { "ToolsAction", NULL, "_Tools", NULL, NULL, NULL }, + + { "HelpAction", NULL, "_Help", NULL, NULL, NULL }, + { "AboutAction", GTK_STOCK_ABOUT, "_About DTR...", NULL, NULL, G_CALLBACK(displaywindow_about) }, + + }; + guint n_entries = G_N_ELEMENTS(entries); + GtkRadioActionEntry toggles[] = { + { "OrthoAction", NULL, "_Orthographic", NULL, NULL, DW_ORTHO }, + { "PerspectiveAction", NULL, "_Perspective", NULL, NULL, DW_PERSPECTIVE }, + }; + guint n_toggles = G_N_ELEMENTS(toggles); + + GError *error = NULL; + + displaywindow_action_group = gtk_action_group_new("dtrdisplaywindow"); + gtk_action_group_add_actions(displaywindow_action_group, entries, n_entries, displaywindow_window); + gtk_action_group_add_radio_actions(displaywindow_action_group, toggles, n_toggles, -1, G_CALLBACK(displaywindow_changeview), NULL); + + displaywindow_ui = gtk_ui_manager_new(); + gtk_ui_manager_insert_action_group(displaywindow_ui, displaywindow_action_group, 0); + g_signal_connect(displaywindow_ui, "add_widget", G_CALLBACK(displaywindow_addui_callback), displaywindow_bigvbox); + if ( gtk_ui_manager_add_ui_from_file(displaywindow_ui, DATADIR"/dtr/displaywindow.ui", &error) == 0 ) { + fprintf(stderr, "Error loading message window menu bar: %s\n", error->message); + return; + } + + gtk_window_add_accel_group(GTK_WINDOW(displaywindow_window), gtk_ui_manager_get_accel_group(displaywindow_ui)); + gtk_ui_manager_ensure_update(displaywindow_ui); + +} + +static float displaywindow_x_start = 0.0; +static float displaywindow_y_start = 0.0; + +static float view_quat[4] = { 0.0, 0.0, 0.0, 1.0 }; + +static gboolean displaywindow_gl_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data) { + displaywindow_x_start = event->x; + displaywindow_y_start = event->y; + return FALSE; +} + +static gint displaywindow_gl_motion_notify(GtkWidget *widget, GdkEventMotion *event, gpointer data) { + + float w = widget->allocation.width; + float h = widget->allocation.height; + float x = event->x; + float y = event->y; + float d_quat[4]; + + if ( event->state & GDK_CONTROL_MASK ) { + + /* Control-click changes 'zoom' */ + displaywindow_distance += event->y - displaywindow_y_start; + if ( displaywindow_view == DW_ORTHO ) { + displaywindow_gl_set_ortho(w, h); + } + + } else if ( event->state & GDK_SHIFT_MASK ) { + + /* Shift-click translates */ + displaywindow_x_pos += (event->x - displaywindow_x_start)/5; + displaywindow_y_pos += (event->y - displaywindow_y_start)/5; + + } else { + + /* Click rotates */ + trackball(d_quat, (2.0*displaywindow_x_start - w)/w, (h-2.0*displaywindow_y_start)/h, (2.0*x-w)/w, (h-2.0*y)/h); + add_quats(d_quat, view_quat, view_quat); + + } + + displaywindow_x_start = x; + displaywindow_y_start = y; + + gdk_window_invalidate_rect(widget->window, &widget->allocation, FALSE); + return TRUE; +} + +static gint displaywindow_gl_expose(GtkWidget *widget, GdkEventExpose *event, ControlContext *ctx) { + + GdkGLContext *glcontext = gtk_widget_get_gl_context(widget); + GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget); + GLfloat light0_position[] = { 0.0, 0.0, 100.0, 0.0 }; + GLfloat light0_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; + GLfloat light0_specular[] = { 0.5, 0.5, 0.5, 1.0 }; + GLfloat light1_position[] = { 0.0, 0.0, -100.0, 0.0 }; + GLfloat light1_diffuse[] = { 0.8, 0.8, 0.8, 1.0 }; + GLfloat light1_specular[] = { 0.5, 0.5, 0.5, 1.0 }; + GLfloat green[] = { 0.0, 1.0, 0.0, 1.0 }; + GLfloat blue[] = { 0.0, 0.0, 1.0, 1.0 }; + GLfloat red[] = { 1.0, 0.0, 0.0, 1.0 }; + GLfloat gold[] = { 0.7, 0.7, 0.0, 1.0 }; + GLfloat yellow[] = { 1.0, 1.0, 0.0, 1.0 }; + GLfloat yellow_glass[] = { 1.0, 1.0, 0.0, 000.1 }; + float m[4][4]; +// GLfloat fog_density = 0.03; + Reflection *reflection; + GLUquadricObj *quadric; + + if ( !gdk_gl_drawable_gl_begin(gldrawable, glcontext) ) { + return 0; + } + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glEnable(GL_DEPTH_TEST); +// glEnable(GL_FOG); +// glFogfv(GL_FOG_DENSITY, &fog_density); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glLoadIdentity(); + glTranslatef(displaywindow_x_pos, -displaywindow_y_pos, -displaywindow_distance); + build_rotmatrix(m, view_quat); + glMultMatrixf(&m[0][0]); + + /* Set up lighting */ + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glLightfv(GL_LIGHT0, GL_POSITION, light0_position); + glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse); + glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular); + glEnable(GL_LIGHT1); + glLightfv(GL_LIGHT1, GL_POSITION, light1_position); + glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse); + glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular); + + /* Bounding cube: 100 nm^-1 side length */ + glBegin(GL_LINE_LOOP); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red); + glVertex3f(50, 50, 50); + glVertex3f(-50, 50, 50); + glVertex3f(-50, -50, 50); + glVertex3f(50, -50, 50); + glEnd(); + glBegin(GL_LINE_LOOP); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red); + glVertex3f(50, 50, -50); + glVertex3f(-50, 50, -50); + glVertex3f(-50, -50, -50); + glVertex3f(50, -50, -50); + glEnd(); + glBegin(GL_LINES); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red); + glVertex3f(50, 50, 50); + glVertex3f(50, 50, -50); + glVertex3f(-50, 50, 50); + glVertex3f(-50, 50, -50); + glVertex3f(-50, -50, 50); + glVertex3f(-50, -50, -50); + glVertex3f(50, -50, 50); + glVertex3f(50, -50, -50); + glEnd(); + + /* Tilt axis */ + glBegin(GL_LINES); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, yellow); + glVertex3f(50, 0.0, 0.0); + glVertex3f(-50, 0.0, 0.0); + glEnd(); + glBegin(GL_TRIANGLE_FAN); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, yellow); + glVertex3f(50, 0.0, 0.0); + glVertex3f(50-5, 1.0, 1.0); + glVertex3f(50-5, -1.0, 1.0); + glVertex3f(50-5, -1.0, -1.0); + glVertex3f(50-5, 1.0, -1.0); + glVertex3f(50-5, 1.0, 1.0); + glEnd(); + + /* Plot all the normal (measured) reflections */ + reflection = ctx->reflectionctx->reflections; + glBegin(GL_POINTS); + do { + if ( reflection->type == REFLECTION_NORMAL ) { + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, green); + glVertex3f(reflection->x/1e9, reflection->y/1e9, reflection->z/1e9); + } + reflection = reflection->next; + } while ( reflection != NULL ); + glEnd(); + + /* Plot the other reflections */ + reflection = ctx->reflectionctx->reflections; + quadric = gluNewQuadric(); + do { + if ( reflection->type == REFLECTION_CENTRAL ) { + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue); + glPushMatrix(); + glTranslatef(reflection->x/1e9, reflection->y/1e9, reflection->z/1e9); + gluSphere(quadric, 0.2, 32, 32); + glPopMatrix(); + } + if ( reflection->type == REFLECTION_GENERATED ) { + + /* Generated reflections are displayed by index, not coordinates. + xyz field in Reflection will be used later for "measured" location. */ + double x, y, z; + signed int h, k, l; + + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gold); + glPushMatrix(); + + /* Change hkl to xyz */ + h = reflection->h; k = reflection->k; l = reflection->l; + x = h*ctx->reflectionctx->basis->a.x + k*ctx->reflectionctx->basis->b.x + l*ctx->reflectionctx->basis->c.x; + y = h*ctx->reflectionctx->basis->a.y + k*ctx->reflectionctx->basis->b.y + l*ctx->reflectionctx->basis->c.y; + z = h*ctx->reflectionctx->basis->a.z + k*ctx->reflectionctx->basis->b.z + l*ctx->reflectionctx->basis->c.z; + glTranslatef(x/1e9, y/1e9, z/1e9); + + gluSphere(quadric, 0.2, 32, 32); + glPopMatrix(); + + } + reflection = reflection->next; + } while ( reflection != NULL ); + + /* If this is an iterative prediction-refinement reconstruction, draw the unit cell */ + if ( ctx->rmode == RECONSTRUCTION_PREDICTION ) { + glBegin(GL_LINE_STRIP); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue); + glVertex3f(0.0, 0.0, 0.0); + glVertex3f(ctx->reflectionctx->basis->a.x/1e9, ctx->reflectionctx->basis->a.y/1e9, ctx->reflectionctx->basis->a.z/1e9); + glVertex3f(ctx->reflectionctx->basis->a.x/1e9 + ctx->reflectionctx->basis->b.x/1e9, + ctx->reflectionctx->basis->a.y/1e9 + ctx->reflectionctx->basis->b.y/1e9, + ctx->reflectionctx->basis->a.z/1e9 + ctx->reflectionctx->basis->b.z/1e9); + glVertex3f(ctx->reflectionctx->basis->b.x/1e9, ctx->reflectionctx->basis->b.y/1e9, ctx->reflectionctx->basis->b.z/1e9); + glVertex3f(0.0, 0.0, 0.0); + glVertex3f(ctx->reflectionctx->basis->c.x/1e9, ctx->reflectionctx->basis->c.y/1e9, ctx->reflectionctx->basis->c.z/1e9); + glVertex3f(ctx->reflectionctx->basis->c.x/1e9 + ctx->reflectionctx->basis->a.x/1e9, + ctx->reflectionctx->basis->c.y/1e9 + ctx->reflectionctx->basis->a.y/1e9, + ctx->reflectionctx->basis->c.z/1e9 + ctx->reflectionctx->basis->a.z/1e9); + glVertex3f(ctx->reflectionctx->basis->c.x/1e9 + ctx->reflectionctx->basis->a.x/1e9 + ctx->reflectionctx->basis->b.x/1e9, + ctx->reflectionctx->basis->c.y/1e9 + ctx->reflectionctx->basis->a.y/1e9 + ctx->reflectionctx->basis->b.y/1e9, + ctx->reflectionctx->basis->c.z/1e9 + ctx->reflectionctx->basis->a.z/1e9 + ctx->reflectionctx->basis->b.z/1e9); + glVertex3f(ctx->reflectionctx->basis->c.x/1e9 + ctx->reflectionctx->basis->b.x/1e9, + ctx->reflectionctx->basis->c.y/1e9 + ctx->reflectionctx->basis->b.y/1e9, + ctx->reflectionctx->basis->c.z/1e9 + ctx->reflectionctx->basis->b.z/1e9); + glVertex3f(ctx->reflectionctx->basis->c.x/1e9, ctx->reflectionctx->basis->c.y/1e9, ctx->reflectionctx->basis->c.z/1e9); + + glVertex3f(ctx->reflectionctx->basis->c.x/1e9 + ctx->reflectionctx->basis->b.x/1e9, + ctx->reflectionctx->basis->c.y/1e9 + ctx->reflectionctx->basis->b.y/1e9, + ctx->reflectionctx->basis->c.z/1e9 + ctx->reflectionctx->basis->b.z/1e9); + glVertex3f(ctx->reflectionctx->basis->b.x/1e9, ctx->reflectionctx->basis->b.y/1e9, ctx->reflectionctx->basis->b.z/1e9); + glVertex3f(ctx->reflectionctx->basis->c.x/1e9 + ctx->reflectionctx->basis->b.x/1e9, + ctx->reflectionctx->basis->c.y/1e9 + ctx->reflectionctx->basis->b.y/1e9, + ctx->reflectionctx->basis->c.z/1e9 + ctx->reflectionctx->basis->b.z/1e9); + glVertex3f(ctx->reflectionctx->basis->c.x/1e9 + ctx->reflectionctx->basis->a.x/1e9 + ctx->reflectionctx->basis->b.x/1e9, + ctx->reflectionctx->basis->c.y/1e9 + ctx->reflectionctx->basis->a.y/1e9 + ctx->reflectionctx->basis->b.y/1e9, + ctx->reflectionctx->basis->c.z/1e9 + ctx->reflectionctx->basis->a.z/1e9 + ctx->reflectionctx->basis->b.z/1e9); + glVertex3f(ctx->reflectionctx->basis->a.x/1e9 + ctx->reflectionctx->basis->b.x/1e9, + ctx->reflectionctx->basis->a.y/1e9 + ctx->reflectionctx->basis->b.y/1e9, + ctx->reflectionctx->basis->a.z/1e9 + ctx->reflectionctx->basis->b.z/1e9); + glVertex3f(ctx->reflectionctx->basis->c.x/1e9 + ctx->reflectionctx->basis->a.x/1e9 + ctx->reflectionctx->basis->b.x/1e9, + ctx->reflectionctx->basis->c.y/1e9 + ctx->reflectionctx->basis->a.y/1e9 + ctx->reflectionctx->basis->b.y/1e9, + ctx->reflectionctx->basis->c.z/1e9 + ctx->reflectionctx->basis->a.z/1e9 + ctx->reflectionctx->basis->b.z/1e9); + glVertex3f(ctx->reflectionctx->basis->c.x/1e9 + ctx->reflectionctx->basis->a.x/1e9, + ctx->reflectionctx->basis->c.y/1e9 + ctx->reflectionctx->basis->a.y/1e9, + ctx->reflectionctx->basis->c.z/1e9 + ctx->reflectionctx->basis->a.z/1e9); + glVertex3f(ctx->reflectionctx->basis->a.x/1e9, ctx->reflectionctx->basis->a.y/1e9, ctx->reflectionctx->basis->a.z/1e9); + glEnd(); + } + + /* Zero plane */ + glBegin(GL_QUADS); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, yellow_glass); + glVertex3f(50, 50, 0.0); + glVertex3f(50, -50, 0.0); + glVertex3f(-50, -50, 0.0); + glVertex3f(-50, 50, 0.0); + glEnd(); + + if ( gdk_gl_drawable_is_double_buffered(gldrawable) ) { + gdk_gl_drawable_swap_buffers(gldrawable); + } else { + glFlush(); + } + + gdk_gl_drawable_gl_end(gldrawable); + + return 0; + +} + +static gint displaywindow_gl_realise(GtkWidget *widget, gpointer data) { + + GdkGLContext *glcontext = gtk_widget_get_gl_context(widget); + GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget); + GLfloat w = widget->allocation.width; + GLfloat h = widget->allocation.height; + + if ( !gdk_gl_drawable_gl_begin(gldrawable, glcontext) ) { + return 0; + } + + glClearColor(0.002, 0.0, 0.1, 1.0); + glClearDepth(1.0); + displaywindow_gl_set_ortho(w, h); + + gdk_gl_drawable_gl_end(gldrawable); + + return 0; + +} + +static gboolean displaywindow_gl_configure(GtkWidget *widget, GdkEventConfigure *event, gpointer data) { + + GdkGLContext *glcontext = gtk_widget_get_gl_context(widget); + GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget); + GLfloat w = widget->allocation.width; + GLfloat h = widget->allocation.height; + + /* Set viewport */ + if ( !gdk_gl_drawable_gl_begin(gldrawable, glcontext) ) { + return FALSE; + } + glViewport(0, 0, w, h); + gdk_gl_drawable_gl_end(gldrawable); + + /* Nudge the projection matrix routines to preserve the aspect ratio */ + if ( displaywindow_view == DW_ORTHO ) { + displaywindow_gl_set_ortho(w, h); + } else { + displaywindow_gl_set_perspective(w, h); + } + + return FALSE; + +} + +static gint displaywindow_closedown(GtkWidget *widget, gpointer data) { + + return 0; + +} + +void displaywindow_open(ControlContext *ctx) { + + const char *filename; + char *title; + GdkGLConfig *glconfig; + + filename = basename(ctx->filename); + title = malloc(10+strlen(filename)); + strcpy(title, "dtr: "); + strcat(title, filename); + + displaywindow_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(displaywindow_window), title); + free(title); + displaywindow_bigvbox = gtk_vbox_new(FALSE, FALSE); + gtk_container_add(GTK_CONTAINER(displaywindow_window), displaywindow_bigvbox); + displaywindow_addmenubar(); + + displaywindow_status_bar = gtk_statusbar_new(); + gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(displaywindow_status_bar), FALSE); + gtk_box_pack_end(GTK_BOX(displaywindow_bigvbox), displaywindow_status_bar, FALSE, FALSE, 0); + + g_signal_connect(GTK_OBJECT(displaywindow_window), "destroy", G_CALLBACK(displaywindow_closedown), NULL); + g_signal_connect_after(GTK_OBJECT(displaywindow_window), "destroy", G_CALLBACK(gtk_main_quit), NULL); + + /* GL stuff */ + glconfig = gdk_gl_config_new_by_mode(GDK_GL_MODE_RGB | GDK_GL_MODE_DEPTH | GDK_GL_MODE_DOUBLE); + if ( glconfig == NULL ) { + fprintf(stderr, "Can't find double-buffered visual.\n"); + exit(1); + } + gtk_container_set_reallocate_redraws(GTK_CONTAINER(displaywindow_window), TRUE); + displaywindow_drawing_area = gtk_drawing_area_new(); + gtk_widget_set_size_request(displaywindow_drawing_area, 640, 640); + gtk_widget_set_gl_capability(displaywindow_drawing_area, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE); + gtk_box_pack_start(GTK_BOX(displaywindow_bigvbox), displaywindow_drawing_area, TRUE, TRUE, 0); + gtk_widget_add_events(displaywindow_drawing_area, GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_VISIBILITY_NOTIFY_MASK); + g_signal_connect(GTK_OBJECT(displaywindow_drawing_area), "configure_event", G_CALLBACK(displaywindow_gl_configure), NULL); + g_signal_connect(GTK_OBJECT(displaywindow_drawing_area), "realize", G_CALLBACK(displaywindow_gl_realise), NULL); + g_signal_connect(GTK_OBJECT(displaywindow_drawing_area), "expose_event", G_CALLBACK(displaywindow_gl_expose), ctx); + g_signal_connect(GTK_OBJECT(displaywindow_drawing_area), "button_press_event", G_CALLBACK(displaywindow_gl_button_press), NULL); + g_signal_connect(GTK_OBJECT(displaywindow_drawing_area), "motion_notify_event", G_CALLBACK(displaywindow_gl_motion_notify), NULL); + + gtk_widget_show_all(displaywindow_window); + +} -- cgit v1.2.3