/* Copyright (C) 2003 by Sean David Fleming sean@ivec.org This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. The GNU GPL can also be found at http://www.gnu.org */ #include #include #include #include #include #include #include #include #include #include #include "gdis.h" #include "coords.h" #include "edit.h" #include "file.h" #include "graph.h" #include "task.h" #include "morph.h" #include "model.h" #include "module.h" #include "matrix.h" #include "render.h" #include "select.h" #include "space.h" #include "sginfo.h" #include "spatial.h" #include "opengl.h" #include "quaternion.h" #include "surface.h" #include "gui_shorts.h" #include "interface.h" #include "dialog.h" #include "zmatrix.h" #include "gui_image.h" #include "undo.h" #include "logo_left.xpm" #include "logo_right.xpm" /* top level data structure */ extern struct sysenv_pak sysenv; extern GMutex *gdk_threads_mutex; /* bit messy - put some of these in sysenv? */ /* main window */ GtkWidget *window; /* backing pixmap */ GdkPixmap *pixmap = NULL; /* model tree (put in sysenv?) */ GtkWidget *tree; /* model pane stuff */ GtkWidget *scrolled_window, *clist; /* gdisrc? */ gint pane_width=65; /* current viewing mode combo box */ GtkWidget *viewing_mode; /************************/ /* EVENT - button press */ /************************/ #define DEBUG_BUTTON_PRESS_EVENT 0 gint gui_press_event(GtkWidget *w, GdkEventButton *event) { gint refresh=0, x, y; gint shift=FALSE, ctrl=FALSE; GdkModifierType state; struct model_pak *data; struct bond_pak *bond; struct core_pak *core; /* HACK */ if (sysenv.stereo) return(FALSE); /* get model */ data = sysenv.active_model; if (!data) return(FALSE); /* event info */ x = event->x; y = event->y; sysenv.moving = FALSE; canvas_select(x, y); /* analyse the current state */ state = (GdkModifierType) event->state; if ((state & GDK_SHIFT_MASK)) shift = TRUE; if ((state & GDK_CONTROL_MASK)) ctrl = TRUE; /* only want button 1 (for now) */ if (event->button != 1) return(FALSE); /* NEW - diffraction peak search */ if (data->graph_active) { diffract_select_peak(x, y, data); return(FALSE); } /* can we assoc. with a single atom */ core = gl_seek_core(x, y, data); /* allow shift+click to add/remove single atoms in the selection */ /* TODO - depending on mode add/remove objects in selection eg atom/mols */ if (shift) { switch(data->mode) { default: if (core) { select_core(core, TRUE, data); refresh++; } else { /* otherwise start a box selection */ update_box(x,y,data,START); } break; } } else { /* determine the type of action required */ switch(data->mode) { case BOND_INFO: info_bond(w,x,y,data); break; case BOND_DELETE: /* or by bond midpoints */ bond = gl_seek_bond(x,y,data); if (bond) { connect_user_bond(bond->atom1, bond->atom2, BOND_DELETE, data); refresh++; } break; case BOND_SINGLE: case BOND_DOUBLE: case BOND_TRIPLE: if (core) { connect_make_bond(core, data->mode, data); refresh++; } break; case ATOM_ADD: add_atom(x, y, data); refresh++; break; case DEFINE_RIBBON: if (core) construct_backbone(core, data); break; case DEFINE_VECTOR: case DEFINE_PLANE: if (core) spatial_point_add(core, data); break; /* selection stuff */ default: select_clear(data); /* don't select if a core is under the mouse */ /* instead we allow the selection box to be drawn */ update_box(x,y,data,START); refresh++; break; } } /* CURRENT */ if (refresh) gui_active_refresh(); return(FALSE); } /***************************/ /* EVENT - button released */ /***************************/ gint gui_release_event(GtkWidget *w, GdkEventButton *event) { gint x, y; struct model_pak *data; GdkModifierType state; /* get model */ data = sysenv.active_model; if (!data) return(FALSE); /* get event info */ x = event->x; y = event->y; state = (GdkModifierType) event->state; /* NEW - motion flag */ sysenv.moving = FALSE; /* first mouse button */ switch (event->button) { case 1: /* HACK */ if (sysenv.stereo) return(FALSE); /* clean up after move operations */ switch(data->mode) { case DIST_INFO: info_dist(x,y,data); break; case ANGLE_INFO: info_angle(x,y,data); break; case DIHEDRAL_INFO: info_torsion(x,y,data); break; default: /* commit the box contents to the selection */ /* if shift pressed - append selection, otherwise create new */ if (data->box_on) gl_select_box(w); /* turn the box off */ data->box_on = FALSE; break; } break; case 2: /* hack to only update zoom factor when button released */ /* ie continuous update causes significant slowdown */ gui_camera_refresh(); break; } redraw_canvas(SINGLE); return(FALSE); } /************************/ /* EVENT - mouse scroll */ /************************/ gint gui_scroll_event(GtkWidget *w, GdkEventScroll *event) { /* change zoom -- based on "zoom section" of gui_press_event() */ const gdouble scroll_factor = 10.0; gdouble scroll, v[3]; struct model_pak *data; struct camera_pak *camera; /* get model */ data = sysenv.active_model; if (!data) return(FALSE); camera = data->camera; sysenv.moving = FALSE; switch (event->direction) { case GDK_SCROLL_UP: scroll = -scroll_factor; break; case GDK_SCROLL_DOWN: scroll = scroll_factor; break; default: /* left and right are not used yet */ return FALSE; } scroll *= PIX2SCALE; if (camera->perspective) { ARR3SET(v, camera->v); VEC3MUL(v, -scroll*10.0); ARR3ADD(camera->x, v); } else camera->zoom += scroll; data->zoom = data->rmax; gui_camera_refresh(); sysenv.moving = TRUE; redraw_canvas(SINGLE); return FALSE; } /************************/ /* EVENT - mouse motion */ /************************/ #define DEBUG_MOTION 0 gint gui_motion_event(GtkWidget *w, GdkEventMotion *event) { gint x, y, dx, dy, fx, fy, refresh; gint shift=FALSE, ctrl=FALSE; gdouble da, dv, zoom, v[3], mat[9]; GdkModifierType state; static gint ox=0, oy=0; struct model_pak *data; struct camera_pak *camera; /* get model */ data = sysenv.active_model; if (!data) return(FALSE); camera = data->camera; /* get mouse data */ if (event->is_hint) gdk_window_get_pointer(event->window, &x, &y, &state); else { /* MS windows apparently reaches this */ x = event->x; y = event->y; state = (GdkModifierType) event->state; } /* discard discontinuous jumps (ie ox,oy are invalid on 1st call) */ if (!sysenv.moving) { ox = x; oy = y; sysenv.moving = TRUE; return(TRUE); } /* convert relative mouse motion to an increment */ dx = x-ox; dy = oy-y; /* inverted y */ /* single update */ refresh=0; /* analyse the current state */ if ((state & GDK_SHIFT_MASK)) shift = TRUE; if ((state & GDK_CONTROL_MASK)) ctrl = TRUE; /* first mouse button - mostly selection stuff */ if (state & GDK_BUTTON1_MASK) { switch(data->mode) { case FREE: update_box(x, y, data, UPDATE); refresh++; break; default: break; } /* don't switch to low quality drawing */ sysenv.moving = FALSE; if (refresh) redraw_canvas(SINGLE); ox=x; oy=y; return(TRUE); } /* NEW - disallow rotations (redraws) when graph is displayed */ if (data->graph_active) return(TRUE); /* second mouse button */ if (state & GDK_BUTTON2_MASK) { if (shift) { /* zoom */ zoom = PIX2SCALE * (dx+dy); if (camera->perspective) { ARR3SET(v, camera->v); VEC3MUL(v, zoom*10.0); ARR3ADD(camera->x, v); } else { camera->zoom -= zoom; data->zoom = data->rmax; } sysenv.moving = TRUE; refresh++; } else { if (ctrl) { /* selection only translation */ select_translate(x-ox, y-oy, data); sysenv.moving = TRUE; refresh++; } else { /* horizontal camera translation */ dv = ox-x; ARR3SET(v, camera->e); VEC3MUL(v, dv*PIX2ANG); ARR3ADD(camera->x, v); /* vertical camera translation */ dv = y-oy; ARR3SET(v, camera->o); VEC3MUL(v, dv*PIX2ANG); ARR3ADD(camera->x, v); sysenv.moving = TRUE; refresh++; } } } /* third mouse button clicked? */ if (state & GDK_BUTTON3_MASK) { /* shift clicked? */ if (shift) { /* yaw */ if (dx || dy) { /* rotation amount */ da = abs(dx) + abs(dy); /* vector from center to mouse pointer (different for OpenGL window) */ /* FIXME - if ctrl is pressed, the center should be the selection */ /* centroid & not the middle of the window */ fx = x - data->offset[0] - (sysenv.x + sysenv.width/2); fy = data->offset[1] + (sysenv.y + sysenv.height/2 - y); /* rotation direction via z component of cross product (+=clock, -=anti) */ if ((fx*dy - dx*fy) < 0) da *= -1.0; #if DEBUG_MOTION printf("(%d,%d) x (%d,%d) : %f\n",dx,dy,fx,fy, da); #endif /* assign and calculate */ da *= D2R * ROTATE_SCALE; if (ctrl) { matrix_relative_rotation(mat, da, ROLL, data); rotate_select(data, mat); } else { if (camera->mode == LOCKED) quat_concat_euler(camera->q, ROLL, da); else { matrix_v_rotation(mat, camera->v, -da); vecmat(mat, camera->o); vecmat(mat, camera->e); } } } sysenv.moving = TRUE; refresh++; } else { #if DEBUG_MOTION printf("(%d,%d)\n",dx,dy); #endif /* pitch and roll */ if (dy) { da = D2R * ROTATE_SCALE * dy; if (ctrl) { matrix_relative_rotation(mat, -da, PITCH, data); rotate_select(data, mat); } else { if (camera->mode == LOCKED) quat_concat_euler(camera->q, PITCH, da); else { matrix_v_rotation(mat, camera->e, -da); vecmat(mat, camera->v); vecmat(mat, camera->o); } } sysenv.moving = TRUE; refresh++; } if (dx) { da = D2R * ROTATE_SCALE * dx; if (ctrl) { matrix_relative_rotation(mat, -da, YAW, data); rotate_select(data, mat); } else { if (camera->mode == LOCKED) quat_concat_euler(camera->q, YAW, -da); else { matrix_v_rotation(mat, camera->o, da); vecmat(mat, camera->v); vecmat(mat, camera->e); } } sysenv.moving = TRUE; refresh++; } } } /* save old values */ ox=x; oy=y; /* redraw? */ if (refresh) redraw_canvas(SINGLE); return(TRUE); } /***************************/ /* expose all hidden atoms */ /***************************/ void unhide_atoms(void) { GSList *list; struct model_pak *data; struct core_pak *core; /* deletion for the active model only */ data = sysenv.active_model; /* unhide */ for (list=data->cores ; list ; list=g_slist_next(list)) { core = list->data; core->status &= ~HIDDEN; } /* update */ redraw_canvas(SINGLE); } /****************/ /* change mode */ /***************/ void gui_mode_switch(gint new_mode) { GSList *list; struct model_pak *data; struct core_pak *core1; /* get selected model */ data = sysenv.active_model; if (!data) return; /* special case for morphology */ if (data->id == MORPH) { switch(new_mode) { case FREE: case RECORD: break; default: gui_text_show(WARNING, "Disallowed mode.\n"); return; } } /* clean up (if necessary) from previous mode */ switch (data->mode) { case DIST_INFO: case BOND_INFO: for (list=data->cores ; list ; list=g_slist_next(list)) { core1 = list->data; core1->status &= ~SELECT; } break; case RECORD: if (data->num_frames > 2) { /* CURRENT - I don't know why, but we seem to get a duplicate of the 1st frame */ /* revert to original orientation */ camera_init(data); data->num_frames = g_slist_length(data->transform_list); } else { /* if no extra frames - it's not an animation any more */ data->num_frames = 1; data->animation = FALSE; } break; } /* special initialization */ switch (new_mode) { case RECORD: /* NEW - disallow transformation record mode if file is */ /* a standard animation as this will confuse read_frame() */ if (data->frame_list || data->gulp.trj_file) { gui_text_show(ERROR, "Disallowed mode change.\n"); return; } data->animation = TRUE; break; } /* general initialization */ select_clear(data); data->mode = new_mode; data->state = 0; redraw_canvas(SINGLE); } /* Need this for the menu item factory widget */ void gtk_mode_switch(GtkWidget *w, gint new_mode) { gui_mode_switch(new_mode); } /***************/ /* change view */ /***************/ void switch_view(gint new_mode) { } /************/ /* GTK hook */ /************/ void gtk_switch_view(GtkWidget *w, gint new_mode) { switch_view(new_mode); } /**************************************/ /* symmetry list store free primitive */ /**************************************/ gboolean symmetry_free(GtkTreeModel *treemodel, GtkTreePath *path, GtkTreeIter *iter, gpointer data) { gchar *a, *b; gtk_tree_model_get(treemodel, iter, 0, &a, 1, &b, -1); if (a) g_free(a); if (b) g_free(b); return(TRUE); } /*****************************/ /* redraw the content widget */ /*****************************/ void gui_content_refresh(GtkWidget *box) { GSList *list; GtkTreeIter iter; GtkCellRenderer *renderer; GtkTreeViewColumn *column; static GtkListStore *ls=NULL; static GtkWidget *tv=NULL; if (box) { g_assert(ls == NULL); g_assert(tv == NULL); /* new tree list */ ls = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); tv = gtk_tree_view_new_with_model(GTK_TREE_MODEL(ls)); gtk_box_pack_start(GTK_BOX(box), tv, TRUE, TRUE, 0); /* setup cell renderers */ renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes(" ", renderer, "text", 0, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(tv), column); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes(" ", renderer, "text", 1, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(tv), column); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tv), FALSE); /* currently, allow nothing to be selected */ gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(tv)), GTK_SELECTION_NONE); } else { struct model_pak *model = sysenv.active_model; g_assert(ls != NULL); g_assert(tv != NULL); gtk_list_store_clear(ls); if (!model) return; /* model content */ model_content_refresh(model); for (list=model->property_list ; list ; list=g_slist_next(list)) { if (property_rank(list->data)) { gtk_list_store_append(ls, &iter); gtk_list_store_set(ls, &iter, 0, property_label(list->data), -1); gtk_list_store_set(ls, &iter, 1, property_value(list->data), -1); } } } } /*************************/ /* module widget gloabls */ /*************************/ GtkTreeStore *module_ts=NULL; GtkWidget *module_tv=NULL; /******************************/ /* module invocation callback */ /******************************/ void cb_module_activate(GtkTreeView *tree_view, GtkTreePath *tree_path, GtkTreeViewColumn *tree_view_column, gpointer data) { gchar *symbol; gpointer module; GtkTreeModel *tree_model; GtkTreeIter iter; struct model_pak *model; model = sysenv.active_model; tree_model = gtk_tree_view_get_model(GTK_TREE_VIEW(tree_view)); if (gtk_tree_model_get_iter(tree_model, &iter, tree_path)) { gtk_tree_model_get(tree_model, &iter, 0, &symbol, 1, &module, -1); if (module) module_invoke(symbol, model, module); else gui_text_show(ERROR, "Please select function(s) listed below the module.\n"); } } /***********************/ /* refresh module list */ /***********************/ void module_widget_redraw(void) { GSList *list1, *list2; GtkTreeIter root, branch; /* checks */ g_assert(GTK_IS_TREE_STORE(module_ts)); g_assert(GTK_IS_TREE_VIEW(module_tv)); /* populate with valid modules */ for (list1=sysenv.module_list ; list1 ; list1=g_slist_next(list1)) { gtk_tree_store_append(module_ts, &root, NULL); gtk_tree_store_set(module_ts, &root, 0, module_label(list1->data), -1); gtk_tree_store_set(module_ts, &root, 1, NULL, -1); /* populate with module symbols */ for (list2=module_symbols(list1->data) ; list2 ; list2=g_slist_next(list2)) { gtk_tree_store_append(module_ts, &branch, &root); gtk_tree_store_set(module_ts, &branch, 0, (gchar *) list2->data, -1); gtk_tree_store_set(module_ts, &branch, 1, (gpointer) list1->data, -1); } } } /***********************************************/ /* init the available module (plug-in) listing */ /***********************************************/ void module_widget_setup(GtkWidget *box) { GtkWidget *label; GtkCellRenderer *renderer; GtkTreeViewColumn *column; label = gtk_label_new("Loaded modules"); gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); /* underlying data storage */ module_ts = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_POINTER); /* actual tree widget */ module_tv = gtk_tree_view_new_with_model(GTK_TREE_MODEL(module_ts)); gtk_box_pack_start(GTK_BOX(box), module_tv, TRUE, TRUE, 0); /* setup the text rendering colum */ renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("a", renderer, "text", 0, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(module_tv), column); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(module_tv), FALSE); /* fill in with valid modules */ module_widget_redraw(); /* setup the selection handler */ g_signal_connect(G_OBJECT(module_tv), "row-activated", G_CALLBACK(cb_module_activate), NULL); } /************************************/ /* pick a (loaded) model to display */ /************************************/ #define DEBUG_PICK_MODEL 0 void gui_model_select(struct model_pak *model) { /* checks */ if (!model) return; /* make the model active */ sysenv.active_model = model; model->graph_active = NULL; /* TODO - combine all these into a dialog refresh callback */ gui_relation_update(model); /* this update could replace the auto version of the relation shortcuts */ dialog_refresh_all(); canvas_shuffle(); gui_refresh(GUI_MODEL_PROPERTIES); gui_refresh(GUI_CANVAS); } /************************************************/ /* reset the scale and viewing angle to default */ /************************************************/ void gui_view_default(void) { struct model_pak *model; /* do we have a loaded model? */ model = sysenv.active_model; if (!model) return; /* NEW - recentre (eg if atoms added -> centroid change) */ coords_init(CENT_COORDS, model); /* make the changes */ VEC3SET(model->offset, 0.0, 0.0, 0.0); /* update */ camera_init(model); /* trigger any dialog updates */ gui_model_select(model); } /************************/ /* view down the x axis */ /************************/ void gui_view_x(void) { struct camera_pak *camera; struct model_pak *model = sysenv.active_model; if (model) { camera_init(model); camera = model->camera; quat_concat_euler(camera->q, YAW, 0.5*G_PI); gui_model_select(model); } } /************************/ /* view down the y axis */ /************************/ void gui_view_y(void) { struct camera_pak *camera; struct model_pak *model = sysenv.active_model; if (model) { camera_init(model); camera = model->camera; quat_concat_euler(camera->q, YAW, G_PI); gui_model_select(model); } } /************************/ /* view down the z axis */ /************************/ void gui_view_z(void) { struct camera_pak *camera; struct model_pak *model = sysenv.active_model; if (model) { camera_init(model); camera = model->camera; quat_concat_euler(camera->q, PITCH, -0.5*G_PI); gui_model_select(model); } } /************************/ /* view down the a axis */ /************************/ void gui_view_a(void) { gui_view_x(); } /************************/ /* view down the b axis */ /************************/ void gui_view_b(void) { struct camera_pak *camera; struct model_pak *model = sysenv.active_model; if (model) { if (model->periodic > 1 || model->id == MORPH) { gui_view_x(); camera = model->camera; quat_concat_euler(camera->q, YAW, model->pbc[5]); gui_model_select(model); } else gui_view_y(); } } /************************/ /* view down the c axis */ /************************/ void gui_view_c(void) { gdouble a, c[3], v[3]; struct camera_pak *camera; struct model_pak *model = sysenv.active_model; if (model) { if (model->periodic > 2 || model->id == MORPH) { camera_init(model); camera = model->camera; /* c axis vector */ VEC3SET(c, 0.0, 0.0, -1.0); vecmat(model->latmat, c); /* angle */ a = via(camera->v,c,3); /* rotation axis */ crossprod(v, camera->v, c); normalize(v, 3); /* align */ quat_concat(camera->q, v, a); gui_model_select(model); } else gui_view_z(); } } /**********************/ /* viewing widget box */ /**********************/ /* TODO - add camera properties? */ void gui_view_widget(GtkWidget *w) { GtkWidget *hbox; hbox = gtk_hbox_new(TRUE, PANEL_SPACING); gtk_box_pack_start(GTK_BOX(w), hbox, FALSE, FALSE, 0); gui_button(" x ", gui_view_x, NULL, hbox, TT); gui_button(" y ", gui_view_y, NULL, hbox, TT); gui_button(" z ", gui_view_z, NULL, hbox, TT); gui_button(" a ", gui_view_a, NULL, hbox, TT); gui_button(" b ", gui_view_b, NULL, hbox, TT); gui_button(" c ", gui_view_c, NULL, hbox, TT); } /***************************/ /* create/update text tray */ /***************************/ void gui_text_show(gint type, gchar *message) { static GtkWidget *view=NULL; static GtkTextBuffer *buffer=NULL; static GtkTextIter iter; /* checks */ if (!message) return; /* try this for improved stability of tasks */ /* if (sysenv.running_tasks) return; */ if (sysenv.canvas) { if (!buffer) { /* first time init */ view = gtk_text_view_new(); gtk_text_view_set_editable(GTK_TEXT_VIEW(view), FALSE); buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view)); gtk_container_add(GTK_CONTAINER(sysenv.tpane), view); gtk_widget_show(view); /* tags */ gtk_text_buffer_create_tag(buffer, "fg_blue", "foreground", "blue", NULL); gtk_text_buffer_create_tag(buffer, "fg_red", "foreground", "red", NULL); gtk_text_buffer_create_tag(buffer, "italic", "style", PANGO_STYLE_ITALIC, NULL); /* position iterator */ gtk_text_buffer_get_iter_at_line(buffer, &iter, 0); } /* assign colour via message type */ switch(type) { case ERROR: gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, message, -1, "fg_red", NULL); break; case WARNING: gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, message, -1, "fg_blue", NULL); break; case ITALIC: gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, message, -1, "italic", NULL); break; default: gtk_text_buffer_insert(buffer, &iter, message, -1); } /* NEW - scroll to the end, so recent message is visible */ if (GTK_IS_TEXT_VIEW(view)) { /* FIXME - doesn't quite work as this only ensures the 1st printed line is visible */ gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(view), &iter, 0.0, FALSE, 0.0, 0.0); } /* TODO - delete items from buffer when line gets too big */ } else printf("[%s]\n", message); } /***********************************/ /* general panel visibility toggle */ /***********************************/ void pane_toggle(GtkWidget *w, GtkWidget *frame) { sysenv.write_gdisrc = TRUE; if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) gtk_widget_show(frame); else gtk_widget_hide(frame); } /*****************************************/ /* cleanup/save state before actual exit */ /*****************************************/ void gdis_exit(void) { /* if user has changed element colours, but doesn't want them saved */ /* this will do it anyway - but they can just click reset next time */ if (sysenv.write_gdisrc) { sysenv.x = sysenv.display_box->allocation.x; sysenv.y = sysenv.display_box->allocation.y; sysenv.width = sysenv.display_box->allocation.width; sysenv.height = sysenv.display_box->allocation.height; write_gdisrc(); } /* cleanup */ sys_free(); /* unlink("gdis.ps"); */ task_queue_free(); if (sysenv.canvas) { gtk_widget_pop_visual(); gtk_widget_pop_colormap(); gtk_exit(0); } exit(0); } /************************************************/ /* exit confirmation if jobs are still runnning */ /************************************************/ gint gdis_exit_event(void) { gint button; GtkWidget *dialog; if (g_thread_pool_get_num_threads(sysenv.thread_pool)) { dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, "There are running tasks. Really exit?"); button = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); if (button != -8) return(TRUE); } return(FALSE); } /************************************************/ /* exit confirmation if jobs are still runnning */ /************************************************/ void gdis_exit_test(void) { gint button; GtkWidget *dialog; if (g_thread_pool_get_num_threads(sysenv.thread_pool)) { dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, "There are running tasks. Really exit?"); button = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); if (button != -8) return; } gdis_exit(); } /***************************************/ /* display available modules & symbols */ /***************************************/ void mod_widget(void) { GSList *list, *list2; for (list=sysenv.module_list ; list ; list=g_slist_next(list)) { printf("module: %s\n", module_label(list->data)); for (list2=module_symbols(list->data) ; list2 ; list2=g_slist_next(list2)) { printf(" - %s\n", (gchar *) list2->data); } } } /**********************/ /* geomview importing */ /**********************/ /* TODO - put elsewhere */ void import_off(gchar *filename) { struct model_pak *model; model = sysenv.active_model; if (!model) return; read_off(filename, model); redraw_canvas(SINGLE); } void gui_import_geomview(void) { file_dialog("Import Geomview", NULL, FILE_LOAD, (gpointer) import_off, GEOMVIEW_OFF); } /*********************/ /* project importing */ /*********************/ void import_pcf(gchar *filename) { struct model_pak *model; dialog_destroy_type(FILE_SELECT); model = sysenv.active_model; if (!model) return; project_read(filename, model); redraw_canvas(SINGLE); } void gui_import_project(void) { file_dialog("Import Project", NULL, FILE_LOAD, (gpointer) import_pcf, PROJECT); } void gui_import_graph(void) { file_dialog("Import Graph", NULL, FILE_LOAD, (gpointer) graph_read, TEXT); } /*****************/ /* mode switches */ /*****************/ void gui_mode_record(void) { gui_mode_switch(RECORD); } void gui_mode_default(void) { gui_mode_switch(FREE); } /******************/ /* MENU structure */ /******************/ static GtkItemFactoryEntry menu_items[] = { { "/_File", NULL, NULL, 0, "" }, /* { "/File/_New", NULL, create_new_model, 1, NULL }, { "/File/sep1", NULL, NULL, 0, "" }, */ { "/File/_Open...", NULL, file_load_dialog, 1, NULL }, { "/File/_Save...", NULL, file_save_dialog, 1, NULL }, { "/File/_Close", NULL, tree_select_delete, 1, NULL }, { "/File/sep1", NULL, NULL, 0, "" }, { "/File/Import", NULL, NULL, 0, "" }, { "/File/Import/Geomview...", NULL, gui_import_geomview, 1, NULL }, { "/File/Import/Project...", NULL, gui_import_project, 1, NULL }, { "/File/Import/Graph...", NULL, gui_import_graph, 1, NULL }, { "/File/Export", NULL, NULL, 0, "" }, { "/File/Export/Canvas snapshot...", NULL, image_export_dialog, 1, NULL }, { "/File/Export/Graph data...", NULL, analysis_export_dialog, 1, NULL }, { "/File/sep1", NULL, NULL, 0, "" }, { "/File/_Quit", NULL, gdis_exit_test, 0, NULL }, { "/_Edit", NULL, NULL, 0, "" }, { "/Edit/_Copy", NULL, select_copy, 0, NULL }, { "/Edit/_Paste", NULL, select_paste, 0, NULL }, { "/Edit/sep1", NULL, NULL, 0, "" }, { "/Edit/Delete", NULL, select_delete, 0, NULL }, { "/Edit/Undo", NULL, undo_active, 0, NULL }, { "/Edit/sep1", NULL, NULL, 0, "" }, { "/Edit/Colour...", NULL, select_colour, 0, NULL }, { "/Edit/Hide", NULL, select_hide, 0, NULL }, { "/Edit/Unhide all", NULL, unhide_atoms, 0, NULL }, { "/Edit/sep1", NULL, NULL, 0, "" }, { "/Edit/Select all", NULL, select_all, 0, NULL }, { "/Edit/Invert", NULL, select_invert, 0, NULL }, { "/_Tools", NULL, NULL, 0, "" }, { "/Tools/Visualization", NULL, NULL, 0, "" }, { "/Tools/Visualization/Animation...", NULL, gui_animate_dialog, 0, NULL }, { "/Tools/Visualization/Iso-surfaces...", NULL, gui_isosurf_dialog, 0, NULL }, { "/Tools/Visualization/Periodic table...", NULL, gui_gperiodic_dialog, 0, NULL }, { "/Tools/Building", NULL, NULL, 0, "" }, { "/Tools/Building/Editing...", NULL, gui_edit_dialog, 0, NULL }, { "/Tools/Building/Dislocations...", NULL, gui_defect_dialog, 0, NULL }, { "/Tools/Building/Docking...", NULL, gui_dock_dialog, 0, NULL }, { "/Tools/Building/Dynamics...", NULL, gui_mdi_dialog, 0, NULL }, { "/Tools/Building/Surfaces...", NULL, surface_dialog, 0, NULL }, { "/Tools/Building/Zmatrix...", NULL, gui_zmat_dialog, 0, NULL }, { "/Tools/Computation", NULL, NULL, 0, "" }, { "/Tools/Computation/Diffraction...", NULL, gui_diffract_dialog, 0, NULL }, { "/Tools/Computation/GULP...", NULL, gulp_dialog, 0, NULL }, { "/Tools/Computation/GAMESS...", NULL, gamess_dialog, 0, NULL }, { "/Tools/Computation/Monty...", NULL, monty_dialog, 0, NULL }, { "/Tools/Computation/SIESTA...", NULL, gui_siesta_dialog, 0, NULL }, { "/Tools/Analysis", NULL, NULL, 0, "" }, { "/Tools/Analysis/Dynamics...", NULL, gui_analysis_dialog, 0, NULL }, { "/Tools/Analysis/Measurements...", NULL, gui_measure_dialog, 0, NULL }, { "/_View", NULL, NULL, 0, ""}, { "/View/Display properties...", NULL, gui_render_dialog, 0, NULL}, { "/View/sep1", NULL, NULL, 0, ""}, { "/View/Reset model images", NULL, space_image_widget_reset, 0, NULL}, { "/View/sep1", NULL, NULL, 0, ""}, { "/View/Normal mode", NULL, gui_mode_default, 0, NULL}, { "/View/Recording mode", NULL, gui_mode_record, 0, NULL}, { "/View/sep1", NULL, NULL, 0, ""}, { "/View/Task manager...", NULL, task_dialog, 0, NULL}, #ifdef WITH_GRISU { "/View/Grid manager...", NULL, gui_grid_dialog, 0, NULL}, #endif { "/View/Executable paths...", NULL, gui_setup_dialog, 0, NULL}, { "/_Help", NULL, NULL, 0, ""}, /* about info -> manual acknowlegements */ /* { "/Help/About...", NULL, gui_help_dialog, 0, NULL}, */ { "/Help/Manual...", NULL, gui_help_dialog, 0, NULL}, }; /********************************/ /* process key presses directly */ /********************************/ gint cb_key_press(GtkWidget *w, GdkEventKey *event, gpointer dummy) { switch(event->keyval) { /* selection delete */ case GDK_Insert: undo_active(); break; /* selection delete */ case GDK_Delete: select_delete(); break; /* fullscreen */ case GDK_F1: if (!sysenv.stereo) { sysenv.stereo = TRUE; sysenv.stereo_fullscreen = TRUE; sysenv.render.perspective = TRUE; stereo_open_window(); } break; /* windowed */ /* CURRENT - hacked to work with new camera code */ case GDK_F2: /* if (!sysenv.stereo && sysenv.stereo_windowed) */ if (!sysenv.stereo) { sysenv.stereo = TRUE; sysenv.stereo_fullscreen = FALSE; sysenv.render.perspective = TRUE; redraw_canvas(SINGLE); } break; /* NEW - switching between windowed/fullscreen stereo while in */ /* stereo mode can screw things up - so just use esc to exit */ /* for both. ie F1/F2 do not act as stereo toggles */ case GDK_Escape: sysenv.stereo = FALSE; sysenv.render.perspective = FALSE; stereo_close_window(); redraw_canvas(SINGLE); break; } return(FALSE); } /*******************************************************/ /* record current model/property pane divider position */ /*******************************************************/ gboolean cb_pane_refresh(GtkPaned *w, gpointer data) { sysenv.tree_divider = gtk_paned_get_position(w); return(FALSE); } /***************************************/ /* update the GDIS information widgets */ /***************************************/ gint gui_widget_handler(void) { /* TODO - all components of the gui */ if (sysenv.refresh_properties) { gui_active_refresh(); sysenv.refresh_properties = FALSE; } return(TRUE); } /*****************************/ /* schedule widget update(s) */ /*****************************/ /* TODO - include all update request (including canvas) */ /* TODO - make type a mask so that multiple updates can be done */ void gui_refresh(gint type) { switch (type) { case GUI_CANVAS: redraw_canvas(SINGLE); break; case GUI_MODEL_TREE: sysenv.refresh_tree = TRUE; break; case GUI_MODEL_PROPERTIES: sysenv.refresh_properties = TRUE; break; case GUI_TEXT_BUFFER: sysenv.refresh_text = TRUE; break; } } /****************************/ /* selection model callback */ /****************************/ void gui_selection_mode_set(GtkWidget *w, gpointer dummy) { const gchar *line; g_assert(GTK_IS_ENTRY(w)); line = gtk_entry_get_text(GTK_ENTRY(w)); gui_mode_switch(FREE); if (g_strrstr(line, "Atoms")) { sysenv.select_mode = CORE; return; } if (g_strrstr(line, "Label")) { sysenv.select_mode = ATOM_LABEL; return; } if (g_strrstr(line, "Type")) { sysenv.select_mode = ATOM_TYPE; return; } if (g_strrstr(line, "Elements")) { if (g_strrstr(line, "molecule")) sysenv.select_mode = ELEM_MOL; else sysenv.select_mode = ELEM; return; } if (g_strrstr(line, "Molecules")) { sysenv.select_mode = MOL; return; } if (g_strrstr(line, "fragments")) { sysenv.select_mode = FRAGMENT; gui_mode_switch(SELECT_FRAGMENT); return; } if (g_strrstr(line, "Regions")) { sysenv.select_mode = REGION; return; } } /* CURRENT */ /* functionality for extending active model pulldown capabilities */ /* TODO - put in shortcuts */ struct active_pak { gchar *label; void (*setup)(gpointer); void (*refresh)(gpointer); GtkWidget *vbox; }; GList *active_list=NULL; struct active_pak *active_data=NULL; /***********************************/ /* refresh the active model widget */ /***********************************/ void gui_active_refresh(void) { GList *list; struct active_pak *current; for (list=active_list ; list ; list=g_list_next(list)) { current = list->data; if (active_data == current) { /* restore "proper" size */ gtk_widget_set_size_request(current->vbox, -1, -1); gtk_widget_show(current->vbox); } else gtk_widget_hide(current->vbox); } if (active_data) { if (active_data->refresh) active_data->refresh(NULL); } } /****************************************/ /* active pulldown change event handler */ /****************************************/ void gui_active_handler(GtkWidget *w, gpointer dummy) { const gchar *tmp; GList *list; struct active_pak *active; tmp = gtk_entry_get_text(GTK_ENTRY(w)); for (list=active_list ; list ; list=g_list_next(list)) { active = list->data; if (g_strcasecmp(active->label, tmp) == 0) { active_data = active; gui_active_refresh(); return; } } } /*********************************/ /* setup the active model widget */ /*********************************/ void gui_active_setup(GtkWidget *box) { gpointer entry; GList *list, *menu; struct active_pak *active; /* build the list of labels */ menu = NULL; for (list=active_list ; list ; list=g_list_next(list)) { active = list->data; menu = g_list_append(menu, g_strdup(active->label)); } /* create the header pulldown */ entry = gui_pulldown_new(NULL, menu, FALSE, box); /* create and pack the data boxes */ for (list=active_list ; list ; list=g_list_next(list)) { active = list->data; gtk_box_pack_start(GTK_BOX(box), active->vbox, FALSE, FALSE, 0); /* stop GTK maxing out the allocated height for all active model children */ gtk_widget_set_size_request(active->vbox, -1, 1); if (active->setup) active->setup(active->vbox); } /* top item is active by default */ if (active_list) active_data = active_list->data; g_signal_connect(GTK_OBJECT(entry), "changed", GTK_SIGNAL_FUNC(gui_active_handler), NULL); } /*************************************************/ /* create a new entry in the active model widget */ /*************************************************/ void gui_active_new(const gchar *label, gpointer setup, gpointer refresh) { struct active_pak *active; active = g_malloc(sizeof(struct active_pak)); active->label = g_strdup(label); active->setup = setup; active->refresh = refresh; active->vbox = gtk_vbox_new(FALSE, 0); active_list = g_list_append(active_list, active); } /*********/ /* SETUP */ /*********/ void gui_init(int argc, char *argv[]) { gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]); gchar *text; GList *list; gpointer ptr; GtkWidget *gdis_wid; GtkWidget *hpaned, *vpaned; GtkWidget *vbox, *hbox, *vbox_lower, *menu_bar, *toolbar; GtkWidget *frame, *event_box; GdkBitmap *mask; GdkPixmap *gdis_pix=NULL; GdkPixbuf *pixbuf; GtkStyle *style; GtkItemFactory *item; GdkColor colour; gtk_init(&argc, &argv); gtk_gl_init(&argc, &argv); /* enforce true colour (fixes SG problems) */ sysenv.visual = gdk_visual_get_best_with_type(GDK_VISUAL_TRUE_COLOR); if (!sysenv.visual) { printf("Error: could not get requested visual.\n"); exit(1); } sysenv.depth = sysenv.visual->depth; sysenv.colourmap = gdk_colormap_new(sysenv.visual, TRUE); if (!sysenv.colourmap) { printf("Error: could not allocate colourmap.\n"); exit(1); } gtk_widget_push_colormap(sysenv.colourmap); gtk_widget_push_visual(sysenv.visual); /* NB: GTK graphical init needs to be done before this is called, */ /* NB: but this must be done before we build the GDIS interface */ image_table_init(); /* main window */ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, FALSE); gtk_window_set_title(GTK_WINDOW(window),"GTK Display Interface for Structures"); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); g_signal_connect(GTK_OBJECT(window), "key_press_event", (GtkSignalFunc) cb_key_press, NULL); /* vbox for the menubar */ vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(window), vbox); /* item factory menu creation */ item = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "
", NULL); gtk_item_factory_create_items(item, nmenu_items, menu_items, NULL); menu_bar = gtk_item_factory_get_widget(item, "
"); /* FALSE,FALSE => don't expand to fill (eg on resize) */ gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 0); /* hbox for the toolbar */ hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); toolbar = gtk_toolbar_new(); gtk_box_pack_start(GTK_BOX(hbox), toolbar, FALSE, FALSE, 0); /* extract some important style info */ gtk_widget_realize(window); style = gtk_widget_get_style(window); sysenv.gtk_fontsize = pango_font_description_get_size(style->font_desc) / PANGO_SCALE; /* printf("psize = %d\n", pango_font_description_get_size(style->font_desc)); printf("scale = %d\n", PANGO_SCALE); printf(" size = %d\n", sysenv.gtk_fontsize); */ /* load button */ pixbuf = image_table_lookup("image_folder"); gdis_wid = gtk_image_new_from_pixbuf(pixbuf); gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), NULL, "Open new model", "Private", gdis_wid, GTK_SIGNAL_FUNC(file_load_dialog), NULL); /* save button */ pixbuf = image_table_lookup("image_disk"); gdis_wid = gtk_image_new_from_pixbuf(pixbuf); gtk_toolbar_append_item(GTK_TOOLBAR (toolbar), NULL, "Save active model", "Private", gdis_wid, GTK_SIGNAL_FUNC(file_save_dialog), NULL); /* NEW: a 'new model' button */ pixbuf = image_table_lookup("image_plus"); gdis_wid = gtk_image_new_from_pixbuf(pixbuf); gtk_toolbar_append_item(GTK_TOOLBAR (toolbar), NULL, "New model", "Private", gdis_wid, GTK_SIGNAL_FUNC(edit_model_create), NULL); /* delete button */ pixbuf = image_table_lookup("image_cross"); gdis_wid = gtk_image_new_from_pixbuf(pixbuf); gtk_toolbar_append_item(GTK_TOOLBAR (toolbar), NULL, "Close active model", "Private", gdis_wid, GTK_SIGNAL_FUNC(tree_select_delete), NULL); gtk_toolbar_append_space(GTK_TOOLBAR(toolbar)); /* animation */ pixbuf = image_table_lookup("image_animate"); gdis_wid = gtk_image_new_from_pixbuf(pixbuf); gtk_toolbar_append_item(GTK_TOOLBAR (toolbar), NULL, "Animation", "Private", gdis_wid, GTK_SIGNAL_FUNC(gui_animate_dialog), NULL); /* model editing */ pixbuf = image_table_lookup("image_tools"); gdis_wid = gtk_image_new_from_pixbuf(pixbuf); gtk_toolbar_append_item(GTK_TOOLBAR (toolbar), NULL, "Model editing", "Private", gdis_wid, GTK_SIGNAL_FUNC(gui_edit_dialog), NULL); /* iso surfaces */ pixbuf = image_table_lookup("image_isosurface"); gdis_wid = gtk_image_new_from_pixbuf(pixbuf); gtk_toolbar_append_item(GTK_TOOLBAR (toolbar), NULL, "Iso-surfaces", "Private", gdis_wid, GTK_SIGNAL_FUNC(gui_isosurf_dialog), NULL); /* gperiodic button */ pixbuf = image_table_lookup("image_element"); gdis_wid = gtk_image_new_from_pixbuf(pixbuf); gtk_toolbar_append_item(GTK_TOOLBAR (toolbar), NULL, "Periodic table", "Private", gdis_wid, GTK_SIGNAL_FUNC(gui_gperiodic_dialog), NULL); gtk_toolbar_append_space(GTK_TOOLBAR(toolbar)); /* diffraction button */ pixbuf = image_table_lookup("image_diffraction"); gdis_wid = gtk_image_new_from_pixbuf(pixbuf); gtk_toolbar_append_item(GTK_TOOLBAR (toolbar), NULL, "Diffraction", "Private", gdis_wid, GTK_SIGNAL_FUNC(gui_diffract_dialog), NULL); /* surface button */ pixbuf = image_table_lookup("image_surface"); gdis_wid = gtk_image_new_from_pixbuf(pixbuf); gtk_toolbar_append_item(GTK_TOOLBAR (toolbar), NULL, "Surface construction", "Private", gdis_wid, GTK_SIGNAL_FUNC(surface_dialog), NULL); gtk_toolbar_append_space(GTK_TOOLBAR(toolbar)); /* geometry button */ pixbuf = image_table_lookup("image_compass"); gdis_wid = gtk_image_new_from_pixbuf(pixbuf); gtk_toolbar_append_item(GTK_TOOLBAR (toolbar), NULL, "Measurements", "Private", gdis_wid, GTK_SIGNAL_FUNC(gui_measure_dialog), NULL); gtk_toolbar_append_space(GTK_TOOLBAR(toolbar)); /* display properties */ pixbuf = image_table_lookup("image_palette"); gdis_wid = gtk_image_new_from_pixbuf(pixbuf); gtk_toolbar_append_item(GTK_TOOLBAR (toolbar), NULL, "Display properties", "Private", gdis_wid, GTK_SIGNAL_FUNC(gui_render_dialog), NULL); /* model geomtry */ pixbuf = image_table_lookup("image_axes"); gdis_wid = gtk_image_new_from_pixbuf(pixbuf); gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), NULL, "Reset model geometry", "Private", gdis_wid, GTK_SIGNAL_FUNC(gui_view_default), NULL); /* model images */ pixbuf = image_table_lookup("image_periodic"); gdis_wid = gtk_image_new_from_pixbuf(pixbuf); gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), NULL, "Reset model images", "Private", gdis_wid, GTK_SIGNAL_FUNC(space_image_widget_reset), NULL); /* transformation record button */ pixbuf = image_table_lookup("image_camera"); gdis_wid = gtk_image_new_from_pixbuf(pixbuf); gtk_toolbar_append_item(GTK_TOOLBAR (toolbar), NULL, "Record mode", "Private", gdis_wid, GTK_SIGNAL_FUNC(gtk_mode_switch), GINT_TO_POINTER(RECORD)); gtk_toolbar_append_space(GTK_TOOLBAR(toolbar)); /* single canvas */ pixbuf = image_table_lookup("image_canvas_single"); gdis_wid = gtk_image_new_from_pixbuf(pixbuf); gtk_toolbar_append_item(GTK_TOOLBAR (toolbar), NULL, "Single canvas", "Private", gdis_wid, GTK_SIGNAL_FUNC(canvas_single), GINT_TO_POINTER(CANVAS_SINGLE)); /* create canvas */ pixbuf = image_table_lookup("image_canvas_create"); gdis_wid = gtk_image_new_from_pixbuf(pixbuf); gtk_toolbar_append_item(GTK_TOOLBAR (toolbar), NULL, "increase canvases", "Private", gdis_wid, GTK_SIGNAL_FUNC(canvas_create), NULL); /* delete canvas */ pixbuf = image_table_lookup("image_canvas_delete"); gdis_wid = gtk_image_new_from_pixbuf(pixbuf); gtk_toolbar_append_item(GTK_TOOLBAR (toolbar), NULL, "decrease canvases", "Private", gdis_wid, GTK_SIGNAL_FUNC(canvas_delete), NULL); gtk_toolbar_append_space(GTK_TOOLBAR(toolbar)); /* normal viewing button */ pixbuf = image_table_lookup("image_arrow"); gdis_wid = gtk_image_new_from_pixbuf(pixbuf); gtk_toolbar_append_item(GTK_TOOLBAR (toolbar), NULL, "Reset model mode", "Private", gdis_wid, GTK_SIGNAL_FUNC(gtk_mode_switch), GINT_TO_POINTER(FREE)); /* MAIN LEFT/RIGHT HBOX PANE */ /* paned window */ hpaned = gtk_hpaned_new(); gtk_container_add(GTK_CONTAINER(GTK_BOX(vbox)), hpaned); /* LEFT PANE */ sysenv.mpane = gtk_vbox_new(FALSE, 0); gtk_paned_pack1(GTK_PANED(hpaned), sysenv.mpane, TRUE, TRUE); gtk_widget_set_size_request(sysenv.mpane, sysenv.tree_width, -1); /* model tree box */ vbox = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(sysenv.mpane), vbox, TRUE, TRUE, 0); tree_init(vbox); /* model pulldown */ vbox_lower = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(sysenv.mpane), vbox_lower, FALSE, FALSE, 0); /* general model data box */ vbox = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox_lower), vbox, FALSE, FALSE, 0); /* CURRENT */ gui_active_new("Model : Content", gui_content_refresh, gui_content_refresh); gui_active_new("Model : Editing", gui_edit_widget, gui_refresh_selection); gui_active_new("Model : Display", gui_display_widget, NULL); gui_active_new("Model : Images", space_image_widget_setup, space_image_widget_redraw); gui_active_new("Model : Symmetry", gui_symmetry_refresh, gui_symmetry_refresh); gui_active_new("Model : Viewing", gui_view_widget, NULL); gui_active_setup(vbox); /* GTK is a bit dumb when it sets the initial sizes of the two panes */ /* set the pane position and store when changed */ /* gtk_paned_set_position(GTK_PANED(vpaned), sysenv.tree_divider); g_signal_connect(GTK_OBJECT(vpaned), "size-request", G_CALLBACK(cb_pane_refresh), NULL); */ /* selection pulldown */ vbox_lower = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(sysenv.mpane), vbox_lower, FALSE, FALSE, 0); list = NULL; list = g_list_append(list, "Select : Atoms"); list = g_list_append(list, "Select : Atom Label"); list = g_list_append(list, "Select : Atom FF Type"); list = g_list_append(list, "Select : Elements"); list = g_list_append(list, "Select : Elements in Molecule"); list = g_list_append(list, "Select : Molecules"); list = g_list_append(list, "Select : Molecule Fragments"); list = g_list_append(list, "Select : Regions"); ptr = gui_pulldown_new(NULL, list, FALSE, vbox_lower); g_signal_connect(GTK_OBJECT(ptr), "changed", GTK_SIGNAL_FUNC(gui_selection_mode_set), NULL); /* GDIS logo */ frame = gtk_frame_new(NULL); gtk_box_pack_end(GTK_BOX(sysenv.mpane), frame, FALSE, TRUE, 0); /* event box (get an x window for setting black background) */ event_box = gtk_event_box_new(); gtk_container_add(GTK_CONTAINER(frame), event_box); /* black background */ colour.red = 0.0; colour.green = 0.0; colour.blue = 0.0; gtk_widget_modify_bg(event_box, GTK_STATE_NORMAL, &colour); hbox = gtk_hbox_new (FALSE, 10); gtk_container_add (GTK_CONTAINER(event_box), hbox); gtk_container_set_border_width(GTK_CONTAINER(hbox), PANEL_SPACING); gdis_pix = gdk_pixmap_create_from_xpm_d(window->window, &mask, &style->bg[GTK_STATE_NORMAL], logo_left_xpm); gdis_wid = gtk_image_new_from_pixmap(gdis_pix, mask); gtk_box_pack_start(GTK_BOX(hbox), gdis_wid, FALSE, FALSE, 0); gdis_pix = gdk_pixmap_create_from_xpm_d(window->window, &mask, &style->bg[GTK_STATE_NORMAL], logo_right_81_xpm); gdis_wid = gtk_image_new_from_pixmap(gdis_pix, mask); gtk_box_pack_end(GTK_BOX(hbox), gdis_wid, FALSE, FALSE, 0); /* RIGHT PANE */ vbox = gtk_vbox_new(FALSE, 0); gtk_paned_pack2(GTK_PANED(hpaned), vbox, TRUE, TRUE); /* paned window */ vpaned = gtk_vpaned_new(); gtk_container_add(GTK_CONTAINER(vbox), vpaned); sysenv.display_box = gtk_vbox_new(FALSE, 0); gtk_paned_pack1(GTK_PANED(vpaned), sysenv.display_box, TRUE, TRUE); /* create the main drawing area */ if (gl_init_visual()) exit(1); canvas_init(sysenv.display_box); canvas_new(0, 0, sysenv.width, sysenv.height); /* text status pane */ sysenv.tpane = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sysenv.tpane), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_paned_pack2(GTK_PANED(vpaned), sysenv.tpane, TRUE, TRUE); gtk_widget_set_size_request(sysenv.tpane, -1, sysenv.tray_height); gtk_widget_show(sysenv.tpane); text = g_strdup_printf("This is free software, distributed under the terms of the GNU public license (GPL).\nFor more information visit http://www.gnu.org\n"); gui_text_show(WARNING, text); g_free(text); text = g_strdup_printf("Welcome to GDIS version %4.2f.%d, Copyright (C) %d by Sean Fleming\n",VERSION,PATCH,YEAR); gui_text_show(STANDARD, text); g_free(text); /* confirmation callback (ie really exit?) */ g_signal_connect(GTK_OBJECT(window), "delete-event", GTK_SIGNAL_FUNC(gdis_exit_event), NULL); /* save gdisrc callback */ g_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(gdis_exit), NULL); /* show all */ gtk_widget_show_all(window); /* CURRENT */ gui_active_refresh(); }