/* pdnmesh - a 2D finite element solver Copyright (C) 2001-2005 Sarod Yatawatta 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 $Id: graphics.c,v 1.76 2005/04/26 05:16:47 sarod Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #ifndef WIN32 #include #include #include #endif/*WIN32*/ #ifdef WIN32 #include #endif/*!WIN32*/ #include #include #include "types.h" static float gl_bg_color[3]={0.0,0.0,0.0}; /* 3 x 1 array for background color */ /* function to interpolate potential within a triangle */ static MY_DOUBLE interpolate_potential(MY_DOUBLE x0, MY_DOUBLE y0, MY_DOUBLE z0, MY_DOUBLE x1, MY_DOUBLE y1, MY_DOUBLE z1, MY_DOUBLE x2, MY_DOUBLE y2, MY_DOUBLE z2, MY_DOUBLE x, MY_DOUBLE y) { MY_DOUBLE del,a,b,c,yy12,yy23,yy31,xx12,xx23,xx31; yy23 = y1-y2; yy31 = y2-y0; yy12 = y0-y1; xx23 = x1-x2; xx31 = x2-x0; xx12 = x0-x1; del = x0*yy23 + x1*yy31 + x2*yy12; if (!(IS_ZERO(del))) { del = 1.0/del; a = del*(z0*yy23 + z1*yy31 + z2*yy12); b = -del*(z0*xx23+z1*xx31+z2*xx12); c = z0 - a*x0 - b*x0; return(a*x+b*y+c); } return(0); } extern boundary bound; /* triangle used in info mode */ triangle *chosen_triangle; /* option flags for plotting */ int plot_mesh, plot_cont, plot_fill, plot_grad, plot_legend; int drawing_mode_flag; /* flag to detect existing mesh: 1 is mesh exists, 0 otherwise */ int mesh_already_present; #ifndef WIN32 GtkWidget *global_status_bar=0,*global_status_label=0,*global_mode_label=0; /* stuct to pass two widgets to a callback as data */ typedef struct dual_widget_ { GtkWidget *w1; GtkWidget *w2; } dual_widget; #endif/*WIN32*/ /* global to update status bar */ void update_status_bar(char *msg) { #ifndef WIN32 gchar buf[256]; if ( global_status_bar ) { g_snprintf(buf, 256, "%s", msg); gtk_label_set_markup(GTK_LABEL(global_status_bar),buf); } #endif/*WIN32*/ #ifdef WIN32 /* windows code goes here */ #endif /*!WIN32*/ } #ifndef WIN32 /* global to update mode label */ void update_mode_label(char *msg) { gchar buf[512]; int eigen_number; char xyz_component='x'; /* for helmholtz cases we can have 3 times deg of freedom contours */ eigen_number=current_plotting_contour/3; /* floor by 3 */ switch(current_plotting_contour%3) { /* mod by 3: x==0, y==1, z==2 */ case 0: xyz_component='x'; break; case 1: xyz_component='y'; break; case 2: xyz_component='z'; break; default: break; } /* if we are plotting an eigenvector, we display eigenvalue */ if ( solve_equation == POISSON || solve_equation== POISSON_SPARSE ) { g_snprintf(buf, 512, "|Poisson "); gtk_label_set_markup(GTK_LABEL(global_mode_label),buf); } else { /* we have an eigenvalue */ if (solve_equation == HELMHOLTZ ) { g_snprintf(buf, 512, "|Helmholtz(homo)%d:%5.3lf",current_plotting_contour,eig_array[current_plotting_contour]); } else if (solve_equation == HELMHOLTZ_INHOMO ) { g_snprintf(buf, 512, "|Helmholtz(inhomo)%d:%c %5.3lf",eigen_number,xyz_component,eig_array[eigen_number]); } else if (solve_equation == HELMHOLTZ_FREQ) { g_snprintf(buf, 512, "|Helmholtz(freq) %d:%c %5.3lf",eigen_number,xyz_component,eig_array[eigen_number]); } else if (solve_equation == HELMHOLTZ_BETA) { g_snprintf(buf, 512, "|Helmholtz(beta) %d:%c %5.3lf",eigen_number,xyz_component,eig_array[eigen_number]); } gtk_label_set_markup(GTK_LABEL(global_mode_label),buf); } } #endif/*WIN32*/ /* draw a polygon */ static void draw_polygon(polygon *poly) { glLineWidth(2.0); if (poly && poly->head ) { int i=poly->nedges; poly_elist *tempe=poly->head; for (;i;i--) { if (!plot_fill) { if ( tempe->data.type==DR) { glColor3f(0.9f, 1.0f, 0.4f); } else { glColor3f(0.1f, 1.0f, 0.9f); } } else { glColor3f(0.0f, 0.0f, 0.0f); } glBegin(GL_LINE_LOOP); glVertex2f( (GLfloat)Mx(tempe->data.p1,M), (GLfloat)My(tempe->data.p1,M)); glVertex2f( (GLfloat)Mx(tempe->data.p2,M), (GLfloat)My(tempe->data.p2,M)); glEnd(); tempe=tempe->next; } } glLineWidth(1.0); } /* rendering routine */ void global_render(void) { int i; triangle *rec; /* for boundary colors */ float bc,r,g,b; /**********************/ /* drawing routine */ glClear(GL_COLOR_BUFFER_BIT); /* change background colour */ glClearColor(gl_bg_color[0],gl_bg_color[1],gl_bg_color[2],0); glLineWidth(1.0); if(drawing_mode_flag==DRAW_OUTPUT) { /* plot mesh */ if ( plot_mesh ) { glColor3f(0.3f, 0.3f, 0.1f); DAG_traverse_list_reset(&dt); rec=DAG_traverse_prune_list(&dt); while (rec) { if (rec &&rec->status==LIVE) { /* bc=rec->boundary/(double)bound.npoly*0.5+0.2f; glColor3f((GLfloat)bc,(GLfloat)bc,(GLfloat)bc); */ glBegin(GL_LINE_LOOP); glVertex2f( (GLfloat)Mx(rec->p0,M), (GLfloat) My(rec->p0,M)); glVertex2f( (GLfloat)Mx(rec->p1,M), (GLfloat) My(rec->p1,M)); glVertex2f( (GLfloat)Mx(rec->p2,M), (GLfloat) My(rec->p2,M)); glEnd(); } /*rt.print_record(rec); */ rec=DAG_traverse_prune_list(&dt); } } if (plot_fill) { /* diffused mode */ glShadeModel(GL_SMOOTH); glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); glEnable(GL_POLYGON_SMOOTH); glEnable(GL_BLEND); glHint(GL_POLYGON_SMOOTH_HINT,GL_NICEST); glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_DITHER); DAG_traverse_list_reset(&dt); rec=DAG_traverse_prune_list(&dt); while (rec) { if (rec &&rec->status==LIVE) { glBegin(GL_TRIANGLES); get_colour(&r,&g,&b,(int)((Mzz(rec->p0,current_plotting_contour,M)-g_minpot)/(g_maxpot-g_minpot)*(float)contour_levels),contour_levels); glColor3f(r, g, b); glVertex2f( (GLfloat)Mx(rec->p0,M), (GLfloat) My(rec->p0,M)); get_colour(&r,&g,&b,(int)((Mzz(rec->p1,current_plotting_contour,M)-g_minpot)/(g_maxpot-g_minpot)*(float)contour_levels),contour_levels); glColor3f(r, g, b); glVertex2f( (GLfloat)Mx(rec->p1,M), (GLfloat) My(rec->p1,M)); get_colour(&r,&g,&b,(int)((Mzz(rec->p2,current_plotting_contour,M)-g_minpot)/(g_maxpot-g_minpot)*(float)contour_levels),contour_levels); glColor3f(r, g, b); glVertex2f( (GLfloat)Mx(rec->p2,M), (GLfloat) My(rec->p2,M)); glEnd(); } rec=DAG_traverse_prune_list(&dt); } glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_BLEND); glDisable(GL_DITHER); } for (i=0;istatus==LIVE ) { #ifdef DEBUG fprintf(stderr,"point inside %d->(%d,%d,%d)\n",chosen_triangle->n,chosen_triangle->p0,chosen_triangle->p1,chosen_triangle->p2); #endif /* draw */ /* plot this triangle */ glColor3f(1.0f, 0.3f, 1.0f); glLineWidth(1.0); glBegin(GL_LINE_LOOP); glVertex2f( (GLfloat)Mx(chosen_triangle->p0,M), (GLfloat)My(chosen_triangle->p0,M)); glVertex2f( (GLfloat)Mx(chosen_triangle->p1,M), (GLfloat)My(chosen_triangle->p1,M)); glVertex2f( (GLfloat)Mx(chosen_triangle->p2,M), (GLfloat)My(chosen_triangle->p2,M)); glEnd(); } /* draw zoom window */ if ( mouse_responce_flag == MENU_ZOOM_END ) { /* first point has been selected */ glBegin(GL_LINE_STRIP); glColor3f(0.0f, 1.0f, 1.0f); glVertex2f( (GLfloat)zoom_x1, (GLfloat)zoom_y1 ); glVertex2f( (GLfloat)zoom_x1, (GLfloat)zoom_y2 ); glVertex2f( (GLfloat)zoom_x2, (GLfloat)zoom_y2 ); glVertex2f( (GLfloat)zoom_x2, (GLfloat)zoom_y1 ); glVertex2f( (GLfloat)zoom_x1, (GLfloat)zoom_y1 ); glEnd(); } if ( plot_cont ) { plot_contour_all(M); } if ( plot_grad ) { plot_gradient(M); } } /* output mode */ /***********************************************/ if ( drawing_mode_flag== DRAW_INPUT ) { /* plot mesh with materials */ glColor3f(0.3f, 0.3f, 0.1f); DAG_traverse_list_reset(&dt); rec=DAG_traverse_prune_list(&dt); while (rec) { if (rec &&rec->status==LIVE) { bc=(float)(rec->boundary/(double)bound.npoly*0.5)+0.2f; glColor3f((GLfloat)bc,(GLfloat)bc,(GLfloat)bc); glBegin(GL_TRIANGLES); glVertex2f( (GLfloat)Mx(rec->p0,M), (GLfloat) My(rec->p0,M)); glVertex2f( (GLfloat)Mx(rec->p1,M), (GLfloat) My(rec->p1,M)); glVertex2f( (GLfloat)Mx(rec->p2,M), (GLfloat) My(rec->p2,M)); glEnd(); } /*rt.print_record(rec); */ rec=DAG_traverse_prune_list(&dt); } for (i=0;iallocation.width; GLfloat h=widget->allocation.height; #ifdef DEBUG g_print("%s: \"configure_event\"\n",gtk_widget_get_name(widget)); #endif if(!gdk_gl_drawable_gl_begin(gldrawable,glcontext)) return(FALSE); glViewport(0,0,w,h); /* FIXME */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(-1,1,-1,1); glMatrixMode(GL_MODELVIEW); gdk_gl_drawable_gl_end(gldrawable); return(TRUE); } /* drawing routine, expose event */ static gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data) { GdkGLContext *glcontext = gtk_widget_get_gl_context(widget); GdkGLDrawable *gldrawable=gtk_widget_get_gl_drawable(widget); #ifdef DEBUG g_print("%s: \"expose_event\"\n", gtk_widget_get_name(widget)); #endif if (!gdk_gl_drawable_gl_begin(gldrawable,glcontext)) return(FALSE); /**********************************/ global_render(); /**********************************/ /* this should not be in expose event routine */ update_mode_label(0); /* swap buffers */ if (gdk_gl_drawable_is_double_buffered(gldrawable)) gdk_gl_drawable_swap_buffers(gldrawable); else glFlush(); gdk_gl_drawable_gl_end(gldrawable); return(TRUE); } static int temp_scratch_arpack_max_iter; static int temp_scratch_arpack_subspace; static void configure_arpack_save_iter(GtkEntry *textbox) { temp_scratch_arpack_max_iter=(int)g_strtod(gtk_entry_get_text(textbox),0); } static void configure_arpack_save_subspace_dimension(GtkEntry *textbox) { temp_scratch_arpack_subspace=(int)g_strtod(gtk_entry_get_text(textbox),0); } static void configure_arpack_update_values(GtkWidget *widget,gpointer data) { if(temp_scratch_arpack_max_iter>0) arpack_max_iterations=temp_scratch_arpack_max_iter; if(temp_scratch_arpack_subspace>0) arpack_subspace_dimension=temp_scratch_arpack_subspace; /* close window */ gtk_widget_destroy(GTK_WIDGET(data)); } static void configure_arpack_close_window(GtkWidget *widget, gpointer data) { /* close window */ gtk_widget_destroy(GTK_WIDGET(data)); } static void configure_arpack_solver(void) { char buf[20]; GtkWidget *window,*box1,*box2,*label,*textbox,*separator,*button; /* initialize values */ temp_scratch_arpack_max_iter=arpack_max_iterations; temp_scratch_arpack_subspace=arpack_subspace_dimension; window=gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect_swapped(GTK_OBJECT(window),"delete_event", G_CALLBACK(gtk_widget_destroy),(gpointer)window); gtk_window_set_title(GTK_WINDOW(window),"ARPACK options"); box1=gtk_vbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(window),box1); gtk_widget_show(box1); /* text entry for max. iterations */ box2=gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); label=gtk_label_new("Iteration Limit:"); gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0); gtk_widget_show(label); textbox=gtk_entry_new(); g_snprintf(buf,20,"%d",arpack_max_iterations); gtk_entry_set_text(GTK_ENTRY(textbox),buf); gtk_box_pack_start(GTK_BOX(box2),textbox,FALSE,FALSE,0); gtk_widget_show(textbox); g_signal_connect(G_OBJECT(textbox),"changed", G_CALLBACK(configure_arpack_save_iter),NULL); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); /* text entry for Subspace dimension*/ box2=gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); label=gtk_label_new("Subspace Dimension:"); gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0); gtk_widget_show(label); textbox=gtk_entry_new(); g_snprintf(buf,20,"%d",arpack_subspace_dimension); gtk_entry_set_text(GTK_ENTRY(textbox),buf); gtk_box_pack_start(GTK_BOX(box2),textbox,FALSE,FALSE,0); gtk_widget_show(textbox); g_signal_connect(G_OBJECT(textbox),"changed", G_CALLBACK(configure_arpack_save_subspace_dimension),NULL); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); /* seperator and buttons */ separator=gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(box1),separator,FALSE,TRUE,0); gtk_widget_show(separator); box2=gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); gtk_box_pack_start(GTK_BOX(box1),box2,FALSE,TRUE,0); gtk_widget_show(box2); button=gtk_button_new_with_label("OK"); g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(configure_arpack_update_values), window); gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,0); GTK_WIDGET_SET_FLAGS(button,GTK_CAN_DEFAULT); gtk_widget_grab_default(button); gtk_widget_show(button); button=gtk_button_new_with_label("Cancel"); g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK(configure_arpack_close_window), window); gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,0); gtk_widget_show(button); gtk_widget_show(window); } /* global for changing triangle boundary */ static int temp_scratch_boundary; static void change_triangle_boundary(GtkWidget *widget, gpointer data) { temp_scratch_boundary=GPOINTER_TO_INT(data); } static void update_triangle_info(GtkWidget *widget, gpointer data) { if ( chosen_triangle ) chosen_triangle->boundary=temp_scratch_boundary; chosen_triangle=0; gtk_widget_destroy(GTK_WIDGET(data)); } static void cancel_triangle_info(GtkWidget *widget, gpointer *data) { chosen_triangle=0; gtk_widget_destroy(GTK_WIDGET(data)); } /* utility functions */ static GtkWidget * make_menu_item(gchar *name, GCallback callback, gpointer data) { GtkWidget *item; item=gtk_menu_item_new_with_label(name); g_signal_connect(G_OBJECT(item),"activate", callback,(gpointer)data); gtk_widget_show(item); return(item); } /* popup window for information of a triangle */ static void dialog_display_triangle_info(void) { GtkWidget *window,*label, *box1, *box2, *opt, *item, *menu; GtkWidget *button; static gchar buf[128]; int i; window=gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect_swapped(GTK_OBJECT(window),"delete_event", G_CALLBACK(gtk_widget_destroy),(gpointer)window); gtk_window_set_title(GTK_WINDOW(window),"Triangle properties"); box1=gtk_vbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(window),box1); gtk_widget_show(box1); box2=gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); label=gtk_label_new(NULL); g_snprintf(buf,128,"Triangle %d, (%d,%d,%d)",chosen_triangle->n,chosen_triangle->p0,chosen_triangle->p1,chosen_triangle->p2); gtk_label_set_markup(GTK_LABEL(label),buf); gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0); gtk_widget_show(label); box2=gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); label=gtk_label_new("Boundary="); gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0); gtk_widget_show(label); /* boundary */ opt=gtk_option_menu_new(); menu=gtk_menu_new(); for (i=0;iboundary); gtk_box_pack_start(GTK_BOX(box2),opt,TRUE,TRUE,0); gtk_widget_show(opt); /* buttons */ box2=gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); button=gtk_button_new_with_label("OK"); g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(update_triangle_info), window); gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,0); GTK_WIDGET_SET_FLAGS(button,GTK_CAN_DEFAULT); gtk_widget_grab_default(button); gtk_widget_show(button); button=gtk_button_new_with_label("Cancel"); g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(cancel_triangle_info), window); gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,0); gtk_widget_show(button); gtk_widget_show(window); } static char *temp_scratch_epsilon=0; static char *temp_scratch_mu=0; static char *temp_scratch_rho=0; static void dialog_material_info_change_eps(GtkEntry *textbox) { #ifdef DEBUG printf("dialog_material_info_change_eps value=%s\n",gtk_entry_get_text(textbox)); #endif if((temp_scratch_epsilon=(char*)realloc((void*)temp_scratch_epsilon, sizeof(char)*(size_t)(strlen(gtk_entry_get_text(textbox))+1)))==0) { fprintf(stderr,"%s: %d: No free memory\n",__FILE__,__LINE__); exit(1); } strcpy(temp_scratch_epsilon,gtk_entry_get_text(textbox)); } static void dialog_material_info_change_mu(GtkEntry *textbox) { #ifdef DEBUG printf("dialog_material_info_change_eps value=%s\n",gtk_entry_get_text(textbox)); #endif if((temp_scratch_mu=(char*)realloc((void*)temp_scratch_mu, sizeof(char)*(size_t)(strlen(gtk_entry_get_text(textbox))+1)))==0) { fprintf(stderr,"%s: %d: No free memory\n",__FILE__,__LINE__); exit(1); } strcpy(temp_scratch_mu,gtk_entry_get_text(textbox)); } static void dialog_material_info_change_rho(GtkEntry *textbox) { #ifdef DEBUG printf("dialog_material_info_change_eps value=%s\n",gtk_entry_get_text(textbox)); #endif if((temp_scratch_rho=(char*)realloc((void*)temp_scratch_rho, sizeof(char)*(size_t)(strlen(gtk_entry_get_text(textbox))+1)))==0) { fprintf(stderr,"%s: %d: No free memory\n",__FILE__,__LINE__); exit(1); } strcpy(temp_scratch_rho,gtk_entry_get_text(textbox)); } static void update_material_info(GtkWidget *widget, gpointer data) { exp_nodetype *pp=0; if ( chosen_triangle ) { free(bound.poly_array[chosen_triangle->boundary].mustr); bound.poly_array[chosen_triangle->boundary].mustr=temp_scratch_mu; free(bound.poly_array[chosen_triangle->boundary].epsstr); bound.poly_array[chosen_triangle->boundary].epsstr=temp_scratch_epsilon; free(bound.poly_array[chosen_triangle->boundary].rhostr); bound.poly_array[chosen_triangle->boundary].rhostr=temp_scratch_rho; /* parse the strings */ pp=0; equation_parse(bound.poly_array[chosen_triangle->boundary].mustr,&pp); bound.poly_array[chosen_triangle->boundary].muexp=pp; pp=0; equation_parse(bound.poly_array[chosen_triangle->boundary].epsstr,&pp); bound.poly_array[chosen_triangle->boundary].epsexp=pp; pp=0; equation_parse(bound.poly_array[chosen_triangle->boundary].rhostr,&pp); bound.poly_array[chosen_triangle->boundary].rhoexp=pp; } else { free(temp_scratch_mu); free(temp_scratch_epsilon); free(temp_scratch_rho); } chosen_triangle=0; gtk_widget_destroy(GTK_WIDGET(data)); } static void close_material_info(GtkWidget *widget, gpointer data) { free(temp_scratch_mu); free(temp_scratch_epsilon); free(temp_scratch_rho); chosen_triangle=0; gtk_widget_destroy(GTK_WIDGET(data)); } /* popup window to modify material properties of an area */ static void dialog_display_material_info(int boundary_no){ GtkWidget *window,*box1,*box2,*label,*textbox,*button; static gchar buf[128]; if ( boundary_no < bound.npoly ) { /* intialize temp variables */ temp_scratch_epsilon=0; temp_scratch_mu=0; temp_scratch_rho=0; /* copy original value to temp variables */ if((temp_scratch_epsilon=(char*)malloc(sizeof(char)*(size_t)(strlen(bound.poly_array[chosen_triangle->boundary].epsstr)+1)))==0) { fprintf(stderr,"%s: %d: No free memory\n",__FILE__,__LINE__); exit(1); } if((temp_scratch_mu=(char*)malloc(sizeof(char)*(size_t)(strlen(bound.poly_array[chosen_triangle->boundary].mustr)+1)))==0) { fprintf(stderr,"%s: %d: No free memory\n",__FILE__,__LINE__); exit(1); } if((temp_scratch_rho=(char*)malloc(sizeof(char)*(size_t)(strlen(bound.poly_array[chosen_triangle->boundary].rhostr)+1)))==0) { fprintf(stderr,"%s: %d: No free memory\n",__FILE__,__LINE__); exit(1); } strcpy(temp_scratch_rho,bound.poly_array[chosen_triangle->boundary].rhostr); strcpy(temp_scratch_mu,bound.poly_array[chosen_triangle->boundary].mustr); strcpy(temp_scratch_epsilon,bound.poly_array[chosen_triangle->boundary].epsstr); window=gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect_swapped(GTK_OBJECT(window),"delete_event", G_CALLBACK(gtk_widget_destroy),(gpointer)window); gtk_window_set_title(GTK_WINDOW(window),"Modify Material Properties"); box1=gtk_vbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(window),box1); gtk_widget_show(box1); box2=gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); g_snprintf(buf,128,"Boundary %d",boundary_no); label=gtk_label_new(NULL); gtk_label_set_markup(GTK_LABEL(label),buf); gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0); gtk_widget_show(label); box2=gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); label=gtk_label_new("epsilon (Permittivity)"); gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0); gtk_widget_show(label); textbox=gtk_entry_new(); g_snprintf(buf,20,"%s",bound.poly_array[boundary_no].epsstr); gtk_entry_set_text(GTK_ENTRY(textbox),buf); gtk_box_pack_start(GTK_BOX(box2),textbox,TRUE,TRUE,0); gtk_widget_show(textbox); g_signal_connect(G_OBJECT(textbox), "changed", G_CALLBACK(dialog_material_info_change_eps),NULL); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); box2=gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); label=gtk_label_new("mu (Permeability)"); gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0); gtk_widget_show(label); textbox=gtk_entry_new(); g_snprintf(buf,20,"%s",bound.poly_array[boundary_no].mustr); gtk_entry_set_text(GTK_ENTRY(textbox),buf); gtk_box_pack_start(GTK_BOX(box2),textbox,TRUE,TRUE,0); gtk_widget_show(textbox); g_signal_connect(G_OBJECT(textbox), "changed", G_CALLBACK(dialog_material_info_change_mu),NULL); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); box2=gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); label=gtk_label_new("rho (charge)"); gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0); gtk_widget_show(label); textbox=gtk_entry_new(); g_snprintf(buf,20,"%s",bound.poly_array[boundary_no].rhostr); gtk_entry_set_text(GTK_ENTRY(textbox),buf); gtk_box_pack_start(GTK_BOX(box2),textbox,TRUE,TRUE,0); gtk_widget_show(textbox); g_signal_connect(G_OBJECT(textbox), "changed", G_CALLBACK(dialog_material_info_change_rho),NULL); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); /* buttons */ box2=gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); button=gtk_button_new_with_label("OK"); g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(update_material_info), (gpointer)window); gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,0); GTK_WIDGET_SET_FLAGS(button,GTK_CAN_DEFAULT); gtk_widget_grab_default(button); gtk_widget_show(button); button=gtk_button_new_with_label("Cancel"); g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(close_material_info), (gpointer)window); gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,0); gtk_widget_show(button); gtk_widget_show(window); } } /* mouse button press */ static gboolean button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data) { GLfloat mx,my; point p; DAG_node *current_dag_node; double temp; #ifdef DEBUG g_print("%s: \"button_press_event\"\n",gtk_widget_get_name(widget)); #endif if ( event->button == 1 && mouse_responce_flag==MENU_INFO ) { #ifdef DEBUG g_print("info coords: (%lf, %lf)\n",event->x,event->y); #endif /* we are in info mode, query a point */ /* get point coordinates */ mx=widget->allocation.width; my=widget->allocation.height; #ifdef DEBUG g_print("window size (%f %f)\n",mx,my); #endif p.x = (2*( double )event->x/( double ) mx-1.0); p.y = -2*( double )event->y/( double ) my+1.0; /* transform back to global coords */ glGetDoublev(GL_MODELVIEW_MATRIX,current_mat); #ifdef DEBUG g_print("finding "MDF","MDF"\n",p.x,p.y); #endif p.x=(p.x-current_mat[12])/current_mat[0]; p.y=(p.y-current_mat[13])/current_mat[5]; current_dag_node=DAG_find(&dt, (void *)&p,(void*)&M); if ( current_dag_node ) { chosen_triangle=(triangle *)current_dag_node->rec; if (chosen_triangle->status==LIVE ) { if ( drawing_mode_flag== DRAW_OUTPUT ) { dialog_display_triangle_info(); } else { /* DRAW_INPUT */ /* modify material properties */ dialog_display_material_info(chosen_triangle->boundary); } /* refine_this_triangle(chosen_triangle,0,1); */ #ifdef DEBUG printf("menu_info: point inside %d->(%d,%d,%d), status %d boundary %d\n",chosen_triangle->n,chosen_triangle->p0,chosen_triangle->p1,chosen_triangle->p2,chosen_triangle->status,chosen_triangle->boundary); printf("menu_info: points %d(%s), %d(%s), %d(%s)\n",chosen_triangle->p0,(Mval(chosen_triangle->p0,M)==FX? "fixed":"variable"), chosen_triangle->p1,(Mval(chosen_triangle->p1,M)==FX? "fixed":"variable"), chosen_triangle->p2,(Mval(chosen_triangle->p2,M)==FX? "fixed":"variable")); printf("menu_info: potentials %d("MDF"), %d("MDF"), %d("MDF")\n",chosen_triangle->p0,Mz(chosen_triangle->p0,M),chosen_triangle->p1,Mz(chosen_triangle->p1,M),chosen_triangle->p2,Mz(chosen_triangle->p2,M)); #endif /* redraw */ gdk_window_invalidate_rect(widget->window, &widget->allocation ,FALSE); return(TRUE); } } } else if ( event->button == 1 && mouse_responce_flag==MENU_SPLIT_TRIANGLE ) { #ifdef DEBUG g_print("info coords: (%lf, %lf)\n",event->x,event->y); #endif /* we are in info mode, query a point */ /* get point coordinates */ mx=widget->allocation.width; my=widget->allocation.height; #ifdef DEBUG g_print("window size (%f %f)\n",mx,my); #endif p.x = (2*( double )event->x/( double ) mx-1.0); p.y = -2*( double )event->y/( double ) my+1.0; /* transform back to global coords */ glGetDoublev(GL_MODELVIEW_MATRIX,current_mat); #ifdef DEBUG g_print("finding "MDF","MDF"\n",p.x,p.y); #endif p.x=(p.x-current_mat[12])/current_mat[0]; p.y=(p.y-current_mat[13])/current_mat[5]; current_dag_node=DAG_find(&dt, (void *)&p,(void*)&M); if ( current_dag_node ) { chosen_triangle=(triangle *)current_dag_node->rec; if (chosen_triangle->status==LIVE ) { refine_this_triangle(chosen_triangle,1,1); /* redraw */ gdk_window_invalidate_rect(widget->window, &widget->allocation ,FALSE); return(TRUE); } } } else if ( (event->button == 1) && (mouse_responce_flag==MENU_ZOOM_START)) { #ifdef DEBUG g_print("zoom start coords: (%lf, %lf)\n",event->x,event->y); #endif /* get click point coordinates */ mx=widget->allocation.width; my=widget->allocation.height; zoom_x1 = (2*( double )event->x/( double ) mx-1.0); zoom_y1 = -2*( double )event->y/( double ) my+1.0; /* convert back to world coords */ glGetDoublev(GL_MODELVIEW_MATRIX,current_mat); zoom_x1=(zoom_x1-current_mat[12])/current_mat[0]; zoom_y1=(zoom_y1-current_mat[13])/current_mat[5]; /* eliminate previous zoom window */ zoom_x2=zoom_x1; zoom_y2=zoom_y1; mouse_responce_flag=MENU_ZOOM_END; return(TRUE); } else if ( (event->button == 1) && (mouse_responce_flag==MENU_ZOOM_END)) { #ifdef DEBUG g_print("zoom stop coords: (%lf, %lf)\n",event->x,event->y); #endif /* get click point coordinates */ mx=widget->allocation.width; my=widget->allocation.height; zoom_x2 = (2*( double )event->x/( double ) mx-1.0); zoom_y2 = -2*( double )event->y/( double ) my+1.0; /* convert back to world coords */ glGetDoublev(GL_MODELVIEW_MATRIX,current_mat); zoom_x2=(zoom_x2-current_mat[12])/current_mat[0]; zoom_y2=(zoom_y2-current_mat[13])/current_mat[5]; /*printf("zoom window (%lf %lf) (%lf %lf)\n",zoom_x1,zoom_y1,zoom_x2,zoom_y2); */ /* now zoom */ if ( zoom_x1 != zoom_x2 ) { /* first arrange points in zoom window */ if ( zoom_x1 > zoom_x2 ) { temp=zoom_x1; zoom_x1=zoom_x2; zoom_x2=temp; } if ( zoom_y1 < zoom_y2 ) { temp=zoom_y1; zoom_y1=zoom_y2; zoom_y2=temp; } /* now keep same aspect ratio as the figure */ zoom_y2=-(double)my/(double)mx*(zoom_x2-zoom_x1)+zoom_y1; /*printf("zoom window (%lf %lf) (%lf %lf)\n",zoom_x1,zoom_y1,zoom_x2,zoom_y2); */ /* preserve the current matrix on the stack */ glPushMatrix(); /* first zoom all */ glLoadIdentity(); /* then do the real zoom */ glScalef(-2.0/(zoom_x1-zoom_x2),2.0/(zoom_y1-zoom_y2),1.0); glTranslatef(-0.5*(zoom_x1+zoom_x2),-0.5*(zoom_y1+zoom_y2),0); /* redisplay */ gdk_window_invalidate_rect(widget->window, &widget->allocation ,FALSE); } mouse_responce_flag=MENU_ZOOM_START; return(TRUE); } return(FALSE); } /* mouse right button press menu */ static gboolean button_press_event_popup_menu(GtkWidget *widget, GdkEventButton *event, gpointer data) { #ifdef DEBUG g_print("%s: \"button_press_event_popup\": ",gtk_widget_get_name(widget)); #endif if ( event->button==3) { #ifdef DEBUG g_print("button 3\n"); #endif gtk_menu_popup(GTK_MENU(widget),NULL,NULL,NULL,NULL, event->button, event->time); return(TRUE); } return(FALSE); } /* mouse motion */ static gboolean motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer data) { GLfloat mx,my; double cx,cy,cz; gchar buf[128]; triangle *t; point p; DAG_node *current_dag_node; /* track coordinates */ mx=widget->allocation.width; my=widget->allocation.height; p.x=cx=2*(double)event->x/(double)mx -1.0; p.y=cy=-2*(double)event->y/(double)my +1.0; glGetDoublev(GL_MODELVIEW_MATRIX,current_mat); cx=((cx-current_mat[12])/current_mat[0])*g_xscale-g_xoff; cy=((cy-current_mat[13])/current_mat[5])*g_yscale-g_yoff; /* switch back to global coords */ /* find triangle */ cz=0.0; p.x=(p.x-current_mat[12])/current_mat[0]; p.y=(p.y-current_mat[13])/current_mat[5]; current_dag_node=DAG_find(&dt, (void *)&p,(void*)&M); if ( current_dag_node ) { t=(triangle *)current_dag_node->rec; if (t->status==LIVE ) { /* cz=interpolate_potential(Mx(t->p0),My(t->p0),Mzz(t->p0,current_plotting_contour), Mx(t->p1),My(t->p1),Mzz(t->p1,current_plotting_contour), Mx(t->p2),My(t->p2),Mzz(t->p2,current_plotting_contour), p.x,p.y);*/ cz=interpolate_potential(Mx(t->p0,M)*g_xscale-g_xoff,My(t->p0,M)*g_yscale-g_yoff,Mzz(t->p0,current_plotting_contour,M), Mx(t->p1,M)*g_xscale-g_xoff,My(t->p1,M)*g_yscale-g_yoff,Mzz(t->p1,current_plotting_contour,M), Mx(t->p2,M)*g_xscale-g_xoff,My(t->p2,M)*g_yscale-g_yoff,Mzz(t->p2,current_plotting_contour,M), cx,cy); } } g_snprintf(buf, 128, "x: %5.3lf y: %5.3lf z: %5.3lf", cx,cy,cz); gtk_label_set_markup(GTK_LABEL(global_status_label),buf); if ( mouse_responce_flag==MENU_ZOOM_END ) { /* g_print("%s: \"motion_notify_event\": button",gtk_widget_get_name(widget)); g_print(" 1 (%lf, %lf)\n",event->x,event->y); */ /* get click point coordinates */ zoom_x2 = (2*( double )event->x/( double ) mx-1.0); zoom_y2 = -2*( double )event->y/( double ) my+1.0; /* convert back to world coords */ glGetDoublev(GL_MODELVIEW_MATRIX,current_mat); zoom_x2=(zoom_x2-current_mat[12])/current_mat[0]; zoom_y2=(zoom_y2-current_mat[13])/current_mat[5]; gdk_window_invalidate_rect(widget->window, &widget->allocation ,FALSE); return(TRUE); } return(FALSE); } /* menu handlers */ static void switch_to_0_mode(GtkWidget *widget) { mouse_responce_flag=MENU_0; #ifdef DEBUG g_print("%s: \"menu 0\"\n",gtk_widget_get_name(widget)); #endif update_status_bar("0 Mode"); } static void switch_to_info_mode(GtkWidget *widget) { mouse_responce_flag=MENU_INFO; #ifdef DEBUG g_print("%s: \"menu info\"\n",gtk_widget_get_name(widget)); #endif update_status_bar("Info Mode"); } static void switch_to_split_mode(GtkWidget *widget) { mouse_responce_flag=MENU_SPLIT_TRIANGLE; #ifdef DEBUG g_print("%s: \"menu split\"\n",gtk_widget_get_name(widget)); #endif update_status_bar("Triangle Split Mode"); } static void switch_to_zoom_start(GtkWidget *widget) { mouse_responce_flag=MENU_ZOOM_START; #ifdef DEBUG g_print("%s: \"menu zoom start\"\n",gtk_widget_get_name(widget)); #endif update_status_bar("Zooming..."); } static void switch_to_zoom_all(GtkWidget *widget) { glLoadIdentity(); #ifdef DEBUG g_print("%s: \"menu zoom all\"\n",gtk_widget_get_name(widget)); #endif gdk_window_invalidate_rect(widget->window, &widget->allocation ,TRUE); } /* callback for toolbar */ static void switch_to_zoom_all_button(GtkWidget *widget, gpointer data) { GtkWidget *w=GTK_WIDGET(data); glLoadIdentity(); #ifdef DEBUG g_print("%s: \"menu zoom all\"\n",gtk_widget_get_name(w)); #endif gdk_window_invalidate_rect(w->window, &w->allocation ,TRUE); } static void switch_to_zoom_back(GtkWidget *widget) { glPopMatrix(); #ifdef DEBUG g_print("%s: \"menu zoom back\"\n",gtk_widget_get_name(widget)); #endif gdk_window_invalidate_rect(widget->window, &widget->allocation ,TRUE); } /* callback for toolbar */ static void switch_to_zoom_back_button(GtkWidget *widget, gpointer data) { GtkWidget *w=GTK_WIDGET(data); glPopMatrix(); #ifdef DEBUG g_print("%s: \"menu zoom back\"\n",gtk_widget_get_name(w)); #endif gdk_window_invalidate_rect(w->window, &w->allocation ,TRUE); } /* used when degree of freedom of points > 1 */ static void switch_to_next_eigenmode(GtkWidget *widget) { /* switch to next eigenmode */ if (solve_equation== POISSON || solve_equation == POISSON_SPARSE ) { current_plotting_contour=0; } else if (solve_equation == HELMHOLTZ ) { current_plotting_contour++; if ( current_plotting_contour >=degree_of_freedom ) current_plotting_contour=0; } else if ((solve_equation == HELMHOLTZ_INHOMO) || (solve_equation == HELMHOLTZ_FREQ) || (solve_equation == HELMHOLTZ_BETA)) { current_plotting_contour++; if ( current_plotting_contour >=3*degree_of_freedom ) current_plotting_contour=0; } #ifdef DEBUG g_print("%s: \" %d th eigenmode\"\n",gtk_widget_get_name(widget),current_plotting_contour); #endif gdk_window_invalidate_rect(widget->window, &widget->allocation ,FALSE); if( global_surf_mesh_window != NULL ) gdk_window_invalidate_rect(global_surf_mesh_window->window, &global_surf_mesh_window->allocation,TRUE); } /* key press */ static gboolean key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer data) { GtkWidget *drawing_area=GTK_WIDGET(data); switch (event->keyval) { case GDK_n: /* switch to next eigenmode */ switch_to_next_eigenmode(drawing_area); /* explicitly send a redraw to drawing area */ gdk_window_invalidate_rect(widget->window, &widget->allocation ,FALSE); if( global_surf_mesh_window != NULL ) gdk_window_invalidate_rect(global_surf_mesh_window->window, &global_surf_mesh_window->allocation,TRUE); break; case GDK_Escape: /* quit the program */ gtk_main_quit(); break; default: return FALSE; } return TRUE; } /*static void switch_to_full_screen(GtkWidget *widget) { gtk_window_fullscreen((GtkWindow*)widget->window); gdk_window_invalidate_rect(widget->window, &widget->allocation ,FALSE); }*/ /* static void switch_to_original_size(GtkWidget *widget) { gtk_window_unfullscreen((GtkWindow*)widget->window); gdk_window_invalidate_rect(widget->window, &widget->allocation ,FALSE); } */ /* popup menu creation */ static GtkWidget * create_popup_menu(GtkWidget *drawing_area) { GtkWidget *menu; GtkWidget *menu_item; menu=gtk_menu_new(); /* neutral mode */ menu_item=gtk_menu_item_new_with_label("0_Mode"); gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); g_signal_connect_swapped(G_OBJECT(menu_item),"activate", G_CALLBACK(switch_to_0_mode),drawing_area); gtk_widget_show(menu_item); /* info mode */ menu_item=gtk_menu_item_new_with_label("Triangle Info Mode"); gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); g_signal_connect_swapped(G_OBJECT(menu_item),"activate", G_CALLBACK(switch_to_info_mode),drawing_area); gtk_widget_show(menu_item); /* split mode */ menu_item=gtk_menu_item_new_with_label("Triangle Split Mode"); gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); g_signal_connect_swapped(G_OBJECT(menu_item),"activate", G_CALLBACK(switch_to_split_mode),drawing_area); gtk_widget_show(menu_item); /* zoom states */ menu_item=gtk_menu_item_new_with_label("Zoom Window"); gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); g_signal_connect_swapped(G_OBJECT(menu_item),"activate", G_CALLBACK(switch_to_zoom_start),drawing_area); gtk_widget_show(menu_item); menu_item=gtk_menu_item_new_with_label("Zoom Back"); gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); g_signal_connect_swapped(G_OBJECT(menu_item),"activate", G_CALLBACK(switch_to_zoom_back),drawing_area); gtk_widget_show(menu_item); menu_item=gtk_menu_item_new_with_label("Zoom All"); gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); g_signal_connect_swapped(G_OBJECT(menu_item),"activate", G_CALLBACK(switch_to_zoom_all),drawing_area); gtk_widget_show(menu_item); menu_item=gtk_menu_item_new_with_label("3D Window"); gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); g_signal_connect(G_OBJECT(menu_item),"activate", G_CALLBACK(display_mesh_grid),(gpointer)drawing_area); gtk_widget_show(menu_item); /* only in HELMHOLTZ equation */ /* if ( solve_equation==HELMHOLTZ ) { */ menu_item=gtk_menu_item_new_with_label("Next Eigenmode"); gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); g_signal_connect_swapped(G_OBJECT(menu_item),"activate", G_CALLBACK(switch_to_next_eigenmode),drawing_area); gtk_widget_show(menu_item); /*} */ /* full screen and back */ /* menu_item=gtk_menu_item_new_with_label("Full Screen"); gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); g_signal_connect_swapped(G_OBJECT(menu_item),"activate", G_CALLBACK(switch_to_full_screen),drawing_area); gtk_widget_show(menu_item); menu_item=gtk_menu_item_new_with_label("Resize"); gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); g_signal_connect_swapped(G_OBJECT(menu_item),"activate", G_CALLBACK(switch_to_original_size),drawing_area); gtk_widget_show(menu_item); */ /* quit option */ menu_item=gtk_menu_item_new_with_label("Quit"); gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(gtk_main_quit), NULL); gtk_widget_show(menu_item); return(menu); } static void menubar_file_open_response_store_filename(GtkWidget *widget, gpointer data) { GtkWidget *file_selector=(GtkWidget*)data; const gchar *tempnam; tempnam=gtk_file_selection_get_filename(GTK_FILE_SELECTION(file_selector)); input_cord_filename=(char*)realloc((void*)input_cord_filename,sizeof(char)*(size_t)(strlen((char*)tempnam)+1)); if ( input_cord_filename == 0 ) { fprintf(stderr,"%s: %d: no free memory",__FILE__,__LINE__); exit(1); } strcpy(input_cord_filename,(char*)tempnam); #ifdef DEBUG g_print("menubar_file_open: filename %s\n",input_cord_filename); #endif /* if a new file name was opened, need to generate mesh so set flag to zero */ mesh_already_present=0; } static void menubar_file_import_response_store_filename(GtkWidget *widget, gpointer data) { GtkWidget *file_selector=(GtkWidget*)data; const gchar *tempnam; tempnam=gtk_file_selection_get_filename(GTK_FILE_SELECTION(file_selector)); #ifdef DEBUG g_print("menubar_file_import: filename %s\n",(char*)tempnam); #endif /* process the DXF file */ free_everything(); if ( tempnam ) { read_dxf_file_and_triangulate(tempnam); /* now open a new window to edit the mesh */ /* since we are not gettting input from a coord file * the user will need to modify properties of each triangle, * each boundary edge and each vertex. since this is a big task, * we move everything related to this to a new file. (dxf.c) */ /* note because of this, we do not need explicit definition of boundaries * in terms of edges etc. etc */ display_edit_window(tempnam); } /* if a new file name was opened, need to generate mesh so set flag to zero */ mesh_already_present=0; } /* menu bar callback functions */ static void menubar_file_open_response( GtkWidget *widget) { GtkWidget *file_selector; /* create fileselector */ file_selector=gtk_file_selection_new("Please select a file"); g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(file_selector)->ok_button), "clicked", G_CALLBACK(menubar_file_open_response_store_filename), (gpointer)file_selector); /* ensure that the dialog box is destroyed when user clicks a button */ g_signal_connect_swapped(GTK_OBJECT(GTK_FILE_SELECTION(file_selector)->ok_button), "clicked", G_CALLBACK(gtk_widget_destroy), (gpointer)file_selector); g_signal_connect_swapped(GTK_OBJECT(GTK_FILE_SELECTION(file_selector)->cancel_button), "clicked", G_CALLBACK(gtk_widget_destroy), (gpointer)file_selector); /* display */ gtk_widget_show(file_selector); } /* importing a DXF file */ /* note: input_cord_filename will store the filename */ static void menubar_file_import_response( gchar *string ) { #ifdef DEBUG printf ("menubar_file_import: %s\n", string); #endif GtkWidget *file_selector; /* create fileselector */ file_selector=gtk_file_selection_new("Please select a DXF file"); g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(file_selector)->ok_button), "clicked", G_CALLBACK(menubar_file_import_response_store_filename), (gpointer)file_selector); /* ensure that the dialog box is destroyed when user clicks a button */ g_signal_connect_swapped(GTK_OBJECT(GTK_FILE_SELECTION(file_selector)->ok_button), "clicked", G_CALLBACK(gtk_widget_destroy), (gpointer)file_selector); g_signal_connect_swapped(GTK_OBJECT(GTK_FILE_SELECTION(file_selector)->cancel_button), "clicked", G_CALLBACK(gtk_widget_destroy), (gpointer)file_selector); /* display */ gtk_widget_show(file_selector); } static void menubar_file_save_response( GtkWidget *widget) { generate_output_files(); } static void menubar_solve_only_response(GtkWidget *widget) { /* if mesh already exists, we only solve if no mesh exists, we generate the mesh before solving */ if (!mesh_already_present) { free_everything(); if ( input_cord_filename ) { solve_problem_from_scratch(input_cord_filename); mesh_already_present=1; } } else { if ( solve_equation==HELMHOLTZ ) { re_number_and_solve_helmholtz_sparse(M,dt); } else if ( (solve_equation==HELMHOLTZ_INHOMO) || (solve_equation == HELMHOLTZ_FREQ) || (solve_equation == HELMHOLTZ_BETA)) { buildup_hash_table_and_equation(M,dt); } else if(solve_equation==POISSON_SPARSE) { re_number_and_solve_poisson_sparse(); } else { re_number_and_solve_poisson(); } } gdk_window_invalidate_rect(widget->window, &widget->allocation ,FALSE); } static void menubar_solve_mesh_response( gchar *string ) { #ifdef DEBUG printf ("menubar_solve_mesh: %s\n", string); #endif free_everything(); if ( input_cord_filename ) { generate_mesh(input_cord_filename); mesh_already_present=1; } } static void menubar_solve_iterative_response( gchar *string ) { int i; MY_DOUBLE priority; #ifdef DEBUG printf ("menubar_solve_solve: %s\n", string); #endif if (mesh_already_present==0) { free_everything(); if ( input_cord_filename ) { solve_problem_from_scratch(input_cord_filename); } else { return; } } #ifdef DEBUG printf("mesh=%d, iterations=%d solver=%d\n",mesh_already_present,max_iteration_limit, solve_equation); #endif UPDATE_GUI for ( i=0; i< max_iteration_limit; i++) { #ifdef DEBUG printf ("menubar_solve_solve: iteration %d of %d\n", i,max_iteration_limit); #endif priority=(MY_DOUBLE)(i+1)/(MY_DOUBLE)max_iteration_limit; /* refine mesh */ if (refine_mesh_with_iterations(priority)) { UPDATE_GUI if ( solve_equation==HELMHOLTZ ) { re_number_and_solve_helmholtz_sparse(M,dt); } else if ( (solve_equation==HELMHOLTZ_INHOMO) || (solve_equation == HELMHOLTZ_FREQ) || (solve_equation == HELMHOLTZ_BETA)) { buildup_hash_table_and_equation(M,dt); } else if(solve_equation==POISSON_SPARSE) { re_number_and_solve_poisson_sparse(); } else { re_number_and_solve_poisson(); } UPDATE_GUI } else { break; } } } /* integrates to find charge */ static void menubar_solve_integrate_responce(gchar *str) { calc_integral(current_plotting_contour); } /* edit material properties */ static void menubar_solve_materials_responce(GtkWidget *menuitem, gpointer data) { /* get the active state of menu item */ GtkWidget *menu=(GtkWidget *)data; if(!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu))) { /* revert to normal mode */ drawing_mode_flag= DRAW_OUTPUT; mouse_responce_flag=MENU_0; } else { /* change drawing mode to draw material */ drawing_mode_flag= DRAW_INPUT; /* respond to mouse clicks */ mouse_responce_flag=MENU_INFO; } } /* globals for menubar_solve_options */ static double temp_scratch_area_floor; static double temp_scratch_area_ceil; static double temp_scratch_triangle_badness; static double temp_scratch_wave_k0; static double temp_scratch_wave_beta; static int temp_scratch_contour_levels; static int temp_scratch_equation_type; static int temp_scratch_iteration_limit; static int temp_scratch_degree_of_freedom; /* callbacks for menubar_solve_options */ static void menubar_save_cb_area_floor(GtkAdjustment *adj) { #ifdef DEBUG printf("menubar_save_cb_area_floor: value=%lf\n",adj->value); #endif temp_scratch_area_floor=(double)adj->value; } static void menubar_save_cb_area_ceil(GtkAdjustment *adj) { #ifdef DEBUG printf("menubar_save_cb_area_ceil: value=%lf\n",adj->value); #endif temp_scratch_area_ceil=(double)adj->value; } static void menubar_save_cb_badness_limit(GtkAdjustment *adj) { #ifdef DEBUG printf("menubar_save_cb_badness_limit: value=%lf\n",adj->value); #endif temp_scratch_triangle_badness=(double)adj->value; } static void menubar_save_cb_contour_levels(GtkAdjustment *adj) { #ifdef DEBUG printf("menubar_save_cb_contour_levels: value=%d\n",(int)adj->value); #endif temp_scratch_contour_levels=(int)adj->value; } static void menubar_save_cb_degree_of_freedom(GtkAdjustment *adj) { #ifdef DEBUG printf("menubar_save_cb_degree_of_freedom: value=%d\n",(int)adj->value); #endif temp_scratch_degree_of_freedom=(int)adj->value; } static void menubar_save_cb_iteration_limit(GtkAdjustment *adj) { #ifdef DEBUG printf("menubar_save_cb_iteration_limit: value=%d\n",(int)adj->value); #endif temp_scratch_iteration_limit=(int)adj->value; } static void menubar_save_cb_equation_type(GtkWidget *item, gpointer data) { #ifdef DEBUG printf("menubar_save_cb_equation_type: type=%d\n",GPOINTER_TO_INT(data)); #endif temp_scratch_equation_type=GPOINTER_TO_INT(data); } static void menubar_save_cb_wave_k0(GtkEntry *textbox) { #ifdef DEBUG printf("menubar_save_cb_wave_k0: value=%s\n",gtk_entry_get_text(textbox)); #endif temp_scratch_wave_k0=g_strtod(gtk_entry_get_text(textbox),0); } static void menubar_save_cb_wave_beta(GtkEntry *textbox) { #ifdef DEBUG printf("menubar_save_cb_wave_k0: value=%s\n",gtk_entry_get_text(textbox)); #endif temp_scratch_wave_beta=g_strtod(gtk_entry_get_text(textbox),0); } static void menubar_save_cb_update_values(GtkWidget *widget, gpointer data) { /* sanity check values obtained from options window and * update global values */ /* if any mesh parameter was changed, regenerate mesh */ if (g_area_floor!=temp_scratch_area_floor ||g_area_ceil!=temp_scratch_area_ceil ||g_badness_limit!=temp_scratch_triangle_badness) { mesh_already_present=0; } if (temp_scratch_area_floor< temp_scratch_area_ceil) { g_area_floor=temp_scratch_area_floor; g_area_ceil=temp_scratch_area_ceil; } g_badness_limit=temp_scratch_triangle_badness; contour_levels=temp_scratch_contour_levels; max_iteration_limit=temp_scratch_iteration_limit; /* if we have currently solved an eigenproblem and we switch back to a Poisson problem, since potential data is lost, we need to re-read the input file */ if((solve_equation!=POISSON) && (solve_equation != POISSON_SPARSE) && (temp_scratch_equation_type!=solve_equation)) { mesh_already_present=0; } solve_equation=temp_scratch_equation_type; if ((solve_equation == HELMHOLTZ) || (solve_equation == HELMHOLTZ_INHOMO) || (solve_equation == HELMHOLTZ_FREQ) || (solve_equation == HELMHOLTZ_BETA)) { requested_degree_of_freedom=temp_scratch_degree_of_freedom; degree_of_freedom=temp_scratch_degree_of_freedom; current_plotting_contour=0; } else { /* POISSON */ requested_degree_of_freedom=1; degree_of_freedom=1; current_plotting_contour=0; /* do not use ARPACK - not an eigenproblem */ use_arpack_solver=0; } /* resize eigenvalue array */ if((eig_array= (MY_DOUBLE*) realloc((void*)eig_array,(size_t)degree_of_freedom*sizeof(MY_DOUBLE)))==0){ fprintf(stderr, "%s: %d: no free memory\n", __FILE__,__LINE__); exit(1); } if (temp_scratch_wave_k0>=1.0) { global_wave_k0=temp_scratch_wave_k0; } if (temp_scratch_wave_beta>=1.0) { global_wave_beta=temp_scratch_wave_beta; } gtk_widget_destroy(GTK_WIDGET(data)); } static void menubar_save_cb_close_window(GtkWidget *widget, gpointer data) { gtk_widget_destroy(GTK_WIDGET(data)); } static void scale_set_default_values(GtkScale *scale) { gtk_range_set_update_policy(GTK_RANGE(scale), GTK_UPDATE_CONTINUOUS); gtk_scale_set_digits(scale,5); gtk_scale_set_value_pos(scale,GTK_POS_TOP); gtk_scale_set_draw_value(scale,TRUE); } static void menubar_save_cb_full_solver(GtkWidget *widget, gpointer data) { if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) { use_full_eigensolver=1; } else { use_full_eigensolver=0; } } static void menubar_save_cb_arpack_solver(GtkWidget *widget, gpointer data) { if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) { use_arpack_solver=1; } else { use_arpack_solver=0; } } static void menubar_solve_options_response( gchar *string ) { #ifdef DEBUG printf ("menubar_solve_options: %s\n", string); #endif GtkWidget *window; GtkWidget *box1, *box2; GtkWidget *button; GtkWidget *separator; GtkWidget *opt, *menu, *item; GtkWidget *check1; GtkWidget *label; GtkWidget *scale; GtkWidget *adj1; GtkWidget *textbox; gchar buf[20]; temp_scratch_area_floor=g_area_floor; temp_scratch_area_ceil=g_area_ceil; temp_scratch_triangle_badness=g_badness_limit; temp_scratch_contour_levels=contour_levels; temp_scratch_iteration_limit=max_iteration_limit; temp_scratch_wave_k0=global_wave_k0; temp_scratch_wave_beta=global_wave_beta; if ( solve_equation == POISSON ) { temp_scratch_degree_of_freedom=1; } else { /* not POISSON */ temp_scratch_degree_of_freedom=requested_degree_of_freedom; } temp_scratch_equation_type=solve_equation; /*contour_levels=40; no of contour levels */ /*current_plotting_contour=0; number in z array < degree_of_freedom */ /*g_badness_limit=2; max triangle badness */ /*g_area_floor=0.001; min triangle area */ /*g_area_ceil=0.005; max triangle area */ /*solve_equation = POISSON; POISSON, HELMHOLTZ */ /* create menu window */ window=gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect_swapped(GTK_OBJECT(window),"delete_event", G_CALLBACK(gtk_widget_destroy),(gpointer)window); gtk_window_set_title(GTK_WINDOW(window),"Change Options"); box1=gtk_vbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(window),box1); gtk_widget_show(box1); /* scale for area_floor */ box2=gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); label=gtk_label_new("Min Area:"); gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0); gtk_widget_show(label); /* value,lower,upper,step_increment,page_increment,page_size */ adj1=(GtkWidget*)gtk_adjustment_new((gdouble)g_area_floor,0.0,0.1,0.00005,1.0,0.0); g_signal_connect(G_OBJECT(adj1), "value_changed", G_CALLBACK(menubar_save_cb_area_floor),NULL); scale=gtk_hscale_new(GTK_ADJUSTMENT(adj1)); scale_set_default_values(GTK_SCALE(scale)); gtk_box_pack_start(GTK_BOX(box2),scale,TRUE,TRUE,0); gtk_widget_show(scale); /* scale for area_ceil*/ box2=gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); label=gtk_label_new("Max Area:"); gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0); gtk_widget_show(label); /* value,lower,upper,step_increment,page_increment,page_size */ adj1=(GtkWidget*)gtk_adjustment_new((gdouble)g_area_ceil,0.0,0.1,0.00005,1.0,0.0); g_signal_connect(G_OBJECT(adj1), "value_changed", G_CALLBACK(menubar_save_cb_area_ceil),NULL); scale=gtk_hscale_new(GTK_ADJUSTMENT(adj1)); scale_set_default_values(GTK_SCALE(scale)); gtk_box_pack_start(GTK_BOX(box2),scale,TRUE,TRUE,0); gtk_widget_show(scale); /* scale for badness_max */ box2=gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); label=gtk_label_new("Tri Badness:"); gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0); gtk_widget_show(label); /* value,lower,upper,step_increment,page_increment,page_size */ adj1=(GtkWidget*)gtk_adjustment_new((gdouble)g_badness_limit,1.0,5.0,0.1,1.0,0.0); g_signal_connect(G_OBJECT(adj1), "value_changed", G_CALLBACK(menubar_save_cb_badness_limit),NULL); scale=gtk_hscale_new(GTK_ADJUSTMENT(adj1)); scale_set_default_values(GTK_SCALE(scale)); gtk_box_pack_start(GTK_BOX(box2),scale,TRUE,TRUE,0); gtk_widget_show(scale); /* type of equation to solve */ box2=gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); label=gtk_label_new("Equation type:"); gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0); gtk_widget_show(label); opt=gtk_option_menu_new(); menu=gtk_menu_new(); item=make_menu_item("Poisson", G_CALLBACK(menubar_save_cb_equation_type), GINT_TO_POINTER(POISSON)); gtk_menu_shell_append(GTK_MENU_SHELL(menu),item); item=make_menu_item("Poisson (Sparse)", G_CALLBACK(menubar_save_cb_equation_type), GINT_TO_POINTER(POISSON_SPARSE)); gtk_menu_shell_append(GTK_MENU_SHELL(menu),item); item=make_menu_item("Homogeneous Helmholtz", G_CALLBACK(menubar_save_cb_equation_type), GINT_TO_POINTER(HELMHOLTZ)); gtk_menu_shell_append(GTK_MENU_SHELL(menu),item); item=make_menu_item("InHomogeneous Helmholtz", G_CALLBACK(menubar_save_cb_equation_type), GINT_TO_POINTER(HELMHOLTZ_INHOMO)); gtk_menu_shell_append(GTK_MENU_SHELL(menu),item); item=make_menu_item("Helmholtz (find beta)", G_CALLBACK(menubar_save_cb_equation_type), GINT_TO_POINTER(HELMHOLTZ_FREQ)); gtk_menu_shell_append(GTK_MENU_SHELL(menu),item); item=make_menu_item("Helmholtz (find k_o)", G_CALLBACK(menubar_save_cb_equation_type), GINT_TO_POINTER(HELMHOLTZ_BETA)); gtk_menu_shell_append(GTK_MENU_SHELL(menu),item); gtk_option_menu_set_menu(GTK_OPTION_MENU(opt),menu); gtk_option_menu_set_history(GTK_OPTION_MENU(opt),(gint)solve_equation); gtk_box_pack_start(GTK_BOX(box2),opt,TRUE,TRUE,0); gtk_widget_show(opt); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); /* create check button to choose full or symmetrix matrix solver for eigenequation */ check1=gtk_check_button_new_with_label("Use Full Matrix Eigensolver"); if(use_full_eigensolver) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check1),TRUE); g_signal_connect(G_OBJECT(check1),"clicked", G_CALLBACK(menubar_save_cb_full_solver), NULL); gtk_widget_show(check1); box2=gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); gtk_box_pack_start(GTK_BOX(box2),check1,FALSE,FALSE,0); gtk_widget_show(box2); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); #ifdef USE_ARPACK /* create check button to choose ARPACK eigensolver for eigenequation */ check1=gtk_check_button_new_with_label("Use ARPACK Eigensolver"); if(use_arpack_solver) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check1),TRUE); g_signal_connect(G_OBJECT(check1),"clicked", G_CALLBACK(menubar_save_cb_arpack_solver), NULL); gtk_widget_show(check1); box2=gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); gtk_box_pack_start(GTK_BOX(box2),check1,FALSE,FALSE,0); /* button to change ARPACK params */ button=gtk_button_new_with_label("Configure"); g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(configure_arpack_solver), window); gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,0); gtk_widget_show(button); GTK_WIDGET_SET_FLAGS(button,GTK_CAN_DEFAULT); gtk_widget_show(box2); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); #endif /* !USE_ARPACK */ /* for Helmholtz only: no. of eigenmodes */ box2=gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); label=gtk_label_new("No. of Eigenmodes:"); gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0); gtk_widget_show(label); adj1=(GtkWidget*)gtk_adjustment_new(requested_degree_of_freedom,1.0,150.0,5.0,1.0,0.0); g_signal_connect(G_OBJECT(adj1), "value_changed", G_CALLBACK(menubar_save_cb_degree_of_freedom),NULL); scale=gtk_hscale_new(GTK_ADJUSTMENT(adj1)); gtk_scale_set_digits(GTK_SCALE(scale),0); gtk_box_pack_start(GTK_BOX(box2),scale,TRUE,TRUE,0); gtk_widget_show(scale); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); /* scale for contour levels */ box2=gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); label=gtk_label_new("Contour Levels:"); gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0); gtk_widget_show(label); adj1=(GtkWidget*)gtk_adjustment_new(contour_levels,5.0,150.0,5.0,1.0,0.0); g_signal_connect(G_OBJECT(adj1), "value_changed", G_CALLBACK(menubar_save_cb_contour_levels),NULL); scale=gtk_hscale_new(GTK_ADJUSTMENT(adj1)); gtk_scale_set_digits(GTK_SCALE(scale),0); gtk_box_pack_start(GTK_BOX(box2),scale,TRUE,TRUE,0); gtk_widget_show(scale); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); /* iteration limit */ box2=gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); label=gtk_label_new("Iteration Limit:"); gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0); gtk_widget_show(label); adj1=(GtkWidget*)gtk_adjustment_new(max_iteration_limit,1.0,150.0,5.0,1.0,0.0); g_signal_connect(G_OBJECT(adj1), "value_changed", G_CALLBACK(menubar_save_cb_iteration_limit),NULL); scale=gtk_hscale_new(GTK_ADJUSTMENT(adj1)); gtk_scale_set_digits(GTK_SCALE(scale),0); gtk_box_pack_start(GTK_BOX(box2),scale,TRUE,TRUE,0); gtk_widget_show(scale); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); /* text entry for k0 */ box2=gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); label=gtk_label_new("Wave Frequency k0:"); gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0); gtk_widget_show(label); textbox=gtk_entry_new(); g_snprintf(buf,20,"%5.2lf",global_wave_k0); gtk_entry_set_text(GTK_ENTRY(textbox),buf); gtk_box_pack_start(GTK_BOX(box2),textbox,TRUE,TRUE,0); gtk_widget_show(textbox); g_signal_connect(G_OBJECT(textbox), "changed", G_CALLBACK(menubar_save_cb_wave_k0),NULL); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); /* text entry for beta*/ box2=gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); label=gtk_label_new("Wave Propagation beta:"); gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0); gtk_widget_show(label); textbox=gtk_entry_new(); g_snprintf(buf,20,"%5.2lf",global_wave_beta); gtk_entry_set_text(GTK_ENTRY(textbox),buf); gtk_box_pack_start(GTK_BOX(box2),textbox,TRUE,TRUE,0); gtk_widget_show(textbox); g_signal_connect(G_OBJECT(textbox), "changed", G_CALLBACK(menubar_save_cb_wave_beta),NULL); gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0); gtk_widget_show(box2); /* seperator and buttons */ separator=gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(box1),separator,FALSE,TRUE,0); gtk_widget_show(separator); box2=gtk_hbox_new(FALSE,10); gtk_container_set_border_width(GTK_CONTAINER(box2),10); gtk_box_pack_start(GTK_BOX(box1),box2,FALSE,TRUE,0); gtk_widget_show(box2); button=gtk_button_new_with_label("OK"); g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(menubar_save_cb_update_values), window); gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,0); GTK_WIDGET_SET_FLAGS(button,GTK_CAN_DEFAULT); gtk_widget_grab_default(button); gtk_widget_show(button); button=gtk_button_new_with_label("Cancel"); g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK(menubar_save_cb_close_window), window); gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,0); gtk_widget_show(button); gtk_widget_show(window); } static void menubar_plot_toggle_option(gpointer data) { int opt; opt=GPOINTER_TO_INT(data); #ifdef DEBUG printf ("menubar_plot_option: %d\n",opt); #endif switch (opt) { case PLOT_MESH: plot_mesh =(plot_mesh?0:1); break; case PLOT_CONT: plot_cont =(plot_cont?0:1); break; case PLOT_FILL: plot_fill=(plot_fill?0:1); break; case PLOT_GRAD: plot_grad=(plot_grad?0:1); break; default: break; } } static void menubar_plot_display_legend_window( gchar *data ) { #ifdef DEBUG printf ("menubar_plot_display_legend: %s\n", data); #endif display_legend_window(); } static void menubar_plot_draw_mode(gpointer data) { drawing_mode_flag=GPOINTER_TO_INT(data); #ifdef DEBUG printf("switch_drawing_mode: mode=%d IN=%d OUT=%d\n",drawing_mode_flag,DRAW_INPUT,DRAW_OUTPUT); #endif update_status_bar("Redrawing..."); } /* global color to remember background color */ static GdkColor bg_color; static GdkColor tmp_bg_color; static void change_bg_color(GtkWidget *widget, GtkColorSelection *colorsel) { gtk_color_selection_get_current_color(colorsel,&tmp_bg_color); } static void menubar_plot_preference_change_bg(GtkWidget *widget, gpointer data) { GtkWidget *w=GTK_WIDGET(data); /* copy temp color to actual */ bg_color.red=tmp_bg_color.red; bg_color.blue=tmp_bg_color.blue; bg_color.green=tmp_bg_color.green; /* change GTK color to OpenGL color */ gl_bg_color[0]=(float)bg_color.red/65536; gl_bg_color[1]=(float)bg_color.green/65536; gl_bg_color[2]=(float)bg_color.blue/65536; /* send redraw to drawing area (or main window w)*/ if(w != NULL) gdk_window_invalidate_rect(w->window, &w->allocation ,TRUE); } static void menubar_plot_preferences(gpointer data) { GtkWidget *colorseldlg; GtkColorSelection *colorsel; colorseldlg=gtk_color_selection_dialog_new("change background color"); colorsel=GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(colorseldlg)->colorsel); /* set intial color value */ gtk_color_selection_set_previous_color(colorsel,&bg_color); gtk_color_selection_set_current_color(colorsel,&bg_color); /* handle changes in color */ g_signal_connect(G_OBJECT(colorsel),"color_changed", G_CALLBACK(change_bg_color),(gpointer)colorsel); /* change actual background color if OK button is pressed */ g_signal_connect(GTK_OBJECT(GTK_COLOR_SELECTION_DIALOG(colorseldlg)->ok_button), "clicked", G_CALLBACK(menubar_plot_preference_change_bg), (gpointer)data); /* callbacks for proper closing of dialog */ g_signal_connect_swapped(GTK_OBJECT(colorseldlg), "delete_event", G_CALLBACK(gtk_widget_destroy),(gpointer)colorseldlg); g_signal_connect_swapped(GTK_OBJECT(GTK_COLOR_SELECTION_DIALOG(colorseldlg)->ok_button), "clicked", G_CALLBACK(gtk_widget_destroy), (gpointer)colorseldlg); g_signal_connect_swapped(GTK_OBJECT(GTK_COLOR_SELECTION_DIALOG(colorseldlg)->cancel_button), "clicked", G_CALLBACK(gtk_widget_destroy), (gpointer)colorseldlg); /* display */ gtk_widget_show(colorseldlg); } static void menubar_help_about_problem( void ) { GtkWidget *window, *vbox, *hbox, *llabel, *rlabel, *button; gchar buf[256]; #ifdef DEBUG printf ("menubar_help_about problem:\n"); #endif window=gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect_swapped(GTK_OBJECT(window),"delete_event", G_CALLBACK(gtk_widget_destroy),(gpointer)window); gtk_window_set_title(GTK_WINDOW(window),"About Problem"); vbox=gtk_vbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(window),vbox); gtk_container_set_border_width(GTK_CONTAINER(vbox),10); gtk_widget_show(vbox); hbox=gtk_hbox_new(FALSE,0); gtk_container_set_border_width(GTK_CONTAINER(hbox),0); gtk_box_pack_start(GTK_BOX(vbox),hbox,TRUE,FALSE,0); gtk_widget_show(hbox); llabel=gtk_label_new(""); gtk_box_pack_start(GTK_BOX(hbox),llabel,FALSE,FALSE,0); gtk_widget_show(llabel); gtk_label_set_justify(GTK_LABEL(llabel),GTK_JUSTIFY_CENTER); g_snprintf(buf, 256, "Mesh"); gtk_label_set_markup(GTK_LABEL(llabel),buf); hbox=gtk_hbox_new(FALSE,0); gtk_container_set_border_width(GTK_CONTAINER(hbox),0); gtk_box_pack_start(GTK_BOX(vbox),hbox,TRUE,FALSE,0); gtk_widget_show(hbox); llabel=gtk_label_new(""); gtk_box_pack_start(GTK_BOX(hbox),llabel,FALSE,FALSE,0); gtk_widget_show(llabel); gtk_label_set_justify(GTK_LABEL(llabel),GTK_JUSTIFY_CENTER); g_snprintf(buf, 256, "Points:"); gtk_label_set_markup(GTK_LABEL(llabel),buf); rlabel=gtk_label_new(""); gtk_box_pack_start(GTK_BOX(hbox),rlabel,FALSE,FALSE,0); gtk_widget_show(rlabel); gtk_label_set_justify(GTK_LABEL(rlabel),GTK_JUSTIFY_CENTER); g_snprintf(buf, 256, ""MIF"",M.count); gtk_label_set_markup(GTK_LABEL(rlabel),buf); hbox=gtk_hbox_new(FALSE,0); gtk_container_set_border_width(GTK_CONTAINER(hbox),0); gtk_box_pack_start(GTK_BOX(vbox),hbox,TRUE,FALSE,0); gtk_widget_show(hbox); llabel=gtk_label_new(""); gtk_box_pack_start(GTK_BOX(hbox),llabel,FALSE,FALSE,0); gtk_widget_show(llabel); gtk_label_set_justify(GTK_LABEL(llabel),GTK_JUSTIFY_CENTER); g_snprintf(buf, 256, "Triangles:"); gtk_label_set_markup(GTK_LABEL(llabel),buf); rlabel=gtk_label_new(""); gtk_box_pack_start(GTK_BOX(hbox),rlabel,FALSE,FALSE,0); gtk_widget_show(rlabel); gtk_label_set_justify(GTK_LABEL(rlabel),GTK_JUSTIFY_CENTER); g_snprintf(buf, 256, ""MIF"",ntriangles); gtk_label_set_markup(GTK_LABEL(rlabel),buf); hbox=gtk_hbox_new(FALSE,0); gtk_container_set_border_width(GTK_CONTAINER(hbox),0); gtk_box_pack_start(GTK_BOX(vbox),hbox,TRUE,FALSE,0); gtk_widget_show(hbox); llabel=gtk_label_new(""); gtk_box_pack_start(GTK_BOX(hbox),llabel,FALSE,FALSE,0); gtk_widget_show(llabel); gtk_label_set_justify(GTK_LABEL(llabel),GTK_JUSTIFY_CENTER); g_snprintf(buf, 256, "Input"); gtk_label_set_markup(GTK_LABEL(llabel),buf); hbox=gtk_hbox_new(FALSE,0); gtk_container_set_border_width(GTK_CONTAINER(hbox),0); gtk_box_pack_start(GTK_BOX(vbox),hbox,TRUE,FALSE,0); gtk_widget_show(hbox); llabel=gtk_label_new(""); gtk_box_pack_start(GTK_BOX(hbox),llabel,FALSE,FALSE,0); gtk_widget_show(llabel); gtk_label_set_justify(GTK_LABEL(llabel),GTK_JUSTIFY_CENTER); g_snprintf(buf, 256, "Filename:"); gtk_label_set_markup(GTK_LABEL(llabel),buf); rlabel=gtk_label_new(""); gtk_box_pack_start(GTK_BOX(hbox),rlabel,FALSE,FALSE,0); gtk_widget_show(rlabel); gtk_label_set_justify(GTK_LABEL(rlabel),GTK_JUSTIFY_CENTER); if(input_cord_filename){ g_snprintf(buf, 256, "%s",input_cord_filename); } else { g_snprintf(buf, 256, "None"); } gtk_label_set_markup(GTK_LABEL(rlabel),buf); hbox=gtk_hbox_new(FALSE,0); gtk_container_set_border_width(GTK_CONTAINER(hbox),0); gtk_box_pack_start(GTK_BOX(vbox),hbox,TRUE,FALSE,0); gtk_widget_show(hbox); llabel=gtk_label_new(""); gtk_box_pack_start(GTK_BOX(hbox),llabel,FALSE,FALSE,0); gtk_widget_show(llabel); gtk_label_set_justify(GTK_LABEL(llabel),GTK_JUSTIFY_CENTER); g_snprintf(buf, 256, "Edges:"); gtk_label_set_markup(GTK_LABEL(llabel),buf); rlabel=gtk_label_new(""); gtk_box_pack_start(GTK_BOX(hbox),rlabel,FALSE,FALSE,0); gtk_widget_show(rlabel); gtk_label_set_justify(GTK_LABEL(rlabel),GTK_JUSTIFY_CENTER); g_snprintf(buf, 256, "%d",nedges); gtk_label_set_markup(GTK_LABEL(rlabel),buf); hbox=gtk_hbox_new(FALSE,0); gtk_container_set_border_width(GTK_CONTAINER(hbox),0); gtk_box_pack_start(GTK_BOX(vbox),hbox,TRUE,FALSE,0); gtk_widget_show(hbox); llabel=gtk_label_new(""); gtk_box_pack_start(GTK_BOX(hbox),llabel,FALSE,FALSE,0); gtk_widget_show(llabel); gtk_label_set_justify(GTK_LABEL(llabel),GTK_JUSTIFY_CENTER); g_snprintf(buf, 256, "Equation:"); gtk_label_set_markup(GTK_LABEL(llabel),buf); rlabel=gtk_label_new(""); gtk_box_pack_start(GTK_BOX(hbox),rlabel,FALSE,FALSE,0); gtk_widget_show(rlabel); gtk_label_set_justify(GTK_LABEL(rlabel),GTK_JUSTIFY_CENTER); switch (solve_equation) { case POISSON: g_snprintf(buf, 256, "Poisson"); break; case POISSON_SPARSE: g_snprintf(buf, 256, "Poisson with sparse storage"); break; case HELMHOLTZ: g_snprintf(buf, 256, "Homogeneous Helmholtz"); break; case HELMHOLTZ_INHOMO: g_snprintf(buf, 256, "Inhomogeneous Helmholtz"); break; case HELMHOLTZ_FREQ: g_snprintf(buf, 256, "Inhomogeneous Helmholtz, find cutoff"); break; case HELMHOLTZ_BETA: g_snprintf(buf, 256, "Inhomogeneous Helmholtz, find propagation const."); break; default: g_snprintf(buf, 256, "Unknown"); } gtk_label_set_markup(GTK_LABEL(rlabel),buf); button=gtk_button_new_with_label("OK"); g_signal_connect_swapped(G_OBJECT(button),"clicked",G_CALLBACK(gtk_widget_destroy), G_OBJECT(window)); gtk_box_pack_start(GTK_BOX(vbox),button,TRUE,FALSE,0); gtk_widget_show(button); gtk_widget_show(window); } static void menubar_help_about_responce( void ) { GtkWidget *window, *box, *label,*button; gchar buf[1024]; #ifdef DEBUG printf ("menubar_help_about:\n"); #endif window=gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect_swapped(GTK_OBJECT(window),"delete_event", G_CALLBACK(gtk_widget_destroy),(gpointer)window); gtk_window_set_title(GTK_WINDOW(window),"About pdnMesh"); box=gtk_vbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(window),box); gtk_container_set_border_width(GTK_CONTAINER(box),10); gtk_widget_show(box); label=gtk_label_new(""); gtk_box_pack_start(GTK_BOX(box),label,FALSE,FALSE,0); gtk_widget_show(label); gtk_label_set_justify(GTK_LABEL(label),GTK_JUSTIFY_CENTER); g_snprintf(buf, 1024, ""PACKAGE" "VERSION"\nCopyright (C) 2001-2005 Sarod Yatawatta\n"PACKAGE" comes with ABSOLUTELY NO WARRANTY.\nThis is Free Software, and you are welcome to redistribute\nit under conditions given by GNU GENERAL PUBLIC LICENSE.\nFor more information visit http://pdnmesh.sf.net/\n Please report bugs to pdnmesh-bugs@lists.sourceforge.net\n"); gtk_label_set_markup(GTK_LABEL(label),buf); button=gtk_button_new_with_label("OK"); g_signal_connect_swapped(G_OBJECT(button),"clicked",G_CALLBACK(gtk_widget_destroy), G_OBJECT(window)); gtk_box_pack_start(GTK_BOX(box),button,TRUE,FALSE,0); gtk_widget_show(button); gtk_widget_show(window); } /* callbacks for toolbar */ static void toolbar_plot_toggle_option_contours(GtkWidget *widget, gpointer data) { GtkWidget *w,*menu; int i; /* remember value of plot_cont */ dual_widget *WW=(dual_widget *)data; i=plot_cont; if(WW!=NULL) { w=GTK_WIDGET(WW->w1); menu=GTK_WIDGET(WW->w2); #ifdef DEBUG printf("toolbar: starting flag=%d\n",plot_cont); #endif if ( plot_cont ==0 ) { #ifdef DEBUG printf("toolbar: menu_item: setting active\n"); #endif gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu),TRUE); } else { #ifdef DEBUG printf("toolbar: menu_item: unsetting active\n"); #endif gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu),FALSE); } /* we have to use remembered value because when we toggle menu, plot_cont will change automatically */ plot_cont =(i?0:1); #ifdef DEBUG printf("toolbar: just set to flag=%d\n",plot_cont); #endif if(w != NULL) gdk_window_invalidate_rect(w->window, &w->allocation ,TRUE); #ifdef DEBUG printf("toolbar: ending flag=%d\n",plot_cont); #endif } #ifdef DEBUG printf("toolbar: callback 1\n"); #endif } static void toolbar_plot_toggle_option_fill(GtkWidget *widget, gpointer data) { GtkWidget *w,*menu; int i; /* remember value of plot_fill*/ dual_widget *WW=(dual_widget *)data; i=plot_fill; if(WW!=NULL) { w=GTK_WIDGET(WW->w1); menu=GTK_WIDGET(WW->w2); #ifdef DEBUG printf("toolbar: starting flag=%d\n",plot_fill); #endif if ( plot_fill==0 ) { #ifdef DEBUG printf("toolbar: menu_item: setting active\n"); #endif gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu),TRUE); } else { #ifdef DEBUG printf("toolbar: menu_item: unsetting active\n"); #endif gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu),FALSE); } /* we have to use remembered value because when we toggle menu, plot_fill will change automatically */ plot_fill=(i?0:1); #ifdef DEBUG printf("toolbar: just set to flag=%d\n",plot_fill); #endif if(w != NULL) gdk_window_invalidate_rect(w->window, &w->allocation ,TRUE); #ifdef DEBUG printf("toolbar: ending flag=%d\n",plot_fill); #endif } #ifdef DEBUG printf("toolbar: callback 1\n"); #endif } static void toolbar_plot_toggle_option_mesh(GtkWidget *widget, gpointer data) { GtkWidget *w,*menu; int i; /* remember value of plot_mesh*/ dual_widget *WW=(dual_widget *)data; i=plot_mesh; if(WW!=NULL) { w=GTK_WIDGET(WW->w1); menu=GTK_WIDGET(WW->w2); #ifdef DEBUG printf("toolbar: starting flag=%d\n",plot_mesh); #endif if ( plot_mesh==0 ) { #ifdef DEBUG printf("toolbar: menu_item: setting active\n"); #endif gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu),TRUE); } else { #ifdef DEBUG printf("toolbar: menu_item: unsetting active\n"); #endif gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu),FALSE); } /* we have to use remembered value because when we toggle menu, plot_mesh will change automatically */ plot_mesh=(i?0:1); #ifdef DEBUG printf("toolbar: just set to flag=%d\n",plot_mesh); #endif if(w != NULL) gdk_window_invalidate_rect(w->window, &w->allocation ,TRUE); #ifdef DEBUG printf("toolbar: ending flag=%d\n",plot_mesh); #endif } #ifdef DEBUG printf("toolbar: callback 1\n"); #endif } static void toolbar_plot_toggle_option_gradient(GtkWidget *widget, gpointer data) { GtkWidget *w,*menu; int i; /* remember value of plot_mesh*/ dual_widget *WW=(dual_widget *)data; i=plot_grad; if(WW!=NULL) { w=GTK_WIDGET(WW->w1); menu=GTK_WIDGET(WW->w2); #ifdef DEBUG printf("toolbar: starting flag=%d\n",plot_grad); #endif if ( plot_grad==0 ) { #ifdef DEBUG printf("toolbar: menu_item: setting active\n"); #endif gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu),TRUE); } else { #ifdef DEBUG printf("toolbar: menu_item: unsetting active\n"); #endif gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu),FALSE); } /* we have to use remembered value because when we toggle menu, plot_mesh will change automatically */ plot_grad=(i?0:1); #ifdef DEBUG printf("toolbar: just set to flag=%d\n",plot_grad); #endif if(w != NULL) gdk_window_invalidate_rect(w->window, &w->allocation ,TRUE); #ifdef DEBUG printf("toolbar: ending flag=%d\n",plot_grad); #endif } #ifdef DEBUG printf("toolbar: callback 1\n"); #endif } /* used when degree of freedom of points > 1 */ static void toolbar_switch_to_next_eigenmode(GtkWidget *widget,gpointer data) { GtkWidget *w=GTK_WIDGET(data); /* switch to next eigenmode */ if (solve_equation== POISSON || solve_equation == POISSON_SPARSE ) { current_plotting_contour=0; } else if (solve_equation == HELMHOLTZ ) { current_plotting_contour++; if ( current_plotting_contour >=degree_of_freedom ) current_plotting_contour=0; } else if ((solve_equation == HELMHOLTZ_INHOMO) || (solve_equation == HELMHOLTZ_FREQ) || (solve_equation == HELMHOLTZ_BETA)) { current_plotting_contour++; if ( current_plotting_contour >=3*degree_of_freedom ) current_plotting_contour=0; } #ifdef DEBUG g_print("%s: \" %d th eigenmode\"\n",gtk_widget_get_name(w),current_plotting_contour); #endif gdk_window_invalidate_rect(w->window, &w->allocation,TRUE); if( global_surf_mesh_window != NULL ) gdk_window_invalidate_rect(global_surf_mesh_window->window, &global_surf_mesh_window->allocation,TRUE); } /************************************/ /* main window creation */ GtkWidget * create_window (GdkGLConfig *glconfig) { GtkWidget *window; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *drawing_area; GtkWidget *menu; GtkWidget *bar_menu,*menu_item,*root_menu,*menu_bar; GtkWidget *handlebox,*toolbar,*iconw,*button; GtkWidget *menu_item_plot_contour,*menu_item_plot_fill,*menu_item_plot_mesh, *menu_item_plot_gradient; GtkWidget *pref_menu_item; dual_widget *WW; gchar buf[128]; GSList *radio_menu_group = NULL; /* top level */ window=gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window),DEFAULT_TITLE); gtk_container_set_reallocate_redraws(GTK_CONTAINER(window),FALSE); g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(gtk_main_quit),NULL); /* vbox */ vbox=gtk_vbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(window),vbox); gtk_widget_show(vbox); /* menu bar */ menu_bar=gtk_menu_bar_new(); gtk_box_pack_start(GTK_BOX(vbox),menu_bar,FALSE,FALSE,2); gtk_widget_show(menu_bar); /***** start of file menu **********/ /* File menu bar and assorted functions */ bar_menu=gtk_menu_new(); /* menu items */ menu_item=gtk_menu_item_new_with_label("Open..."); gtk_menu_shell_append(GTK_MENU_SHELL(bar_menu),menu_item); g_signal_connect_swapped(G_OBJECT(menu_item),"activate", G_CALLBACK(menubar_file_open_response), (gpointer)menu_item); gtk_widget_show(menu_item); menu_item=gtk_menu_item_new_with_label("Import DXF..."); gtk_menu_shell_append(GTK_MENU_SHELL(bar_menu),menu_item); g_signal_connect_swapped(G_OBJECT(menu_item),"activate", G_CALLBACK(menubar_file_import_response), (gpointer)g_strdup("Import")); gtk_widget_show(menu_item); menu_item=gtk_menu_item_new_with_label("Save..."); gtk_menu_shell_append(GTK_MENU_SHELL(bar_menu),menu_item); g_signal_connect_swapped(G_OBJECT(menu_item),"activate", G_CALLBACK(menubar_file_save_response), (gpointer)menu_item); gtk_widget_show(menu_item); menu_item=gtk_menu_item_new_with_label("Quit"); gtk_menu_shell_append(GTK_MENU_SHELL(bar_menu),menu_item); g_signal_connect_swapped(G_OBJECT(menu_item),"activate", G_CALLBACK(gtk_main_quit), NULL); gtk_widget_show(menu_item); /* File menu */ root_menu=gtk_menu_item_new_with_label("File"); gtk_widget_show(root_menu); /* attach menu to root menu */ gtk_menu_item_set_submenu(GTK_MENU_ITEM(root_menu),bar_menu); /* attach root menu to menu bar */ gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar),root_menu); /***** end of file menu **********/ /***** start of plot menu **********/ /* File menu bar and assorted functions */ bar_menu=gtk_menu_new(); /* menu items */ menu_item_plot_mesh=gtk_check_menu_item_new_with_label("Mesh"); gtk_menu_shell_append(GTK_MENU_SHELL(bar_menu),menu_item_plot_mesh); if ( plot_mesh ) { gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_item_plot_mesh),TRUE); } g_signal_connect_swapped(G_OBJECT(menu_item_plot_mesh),"toggled", G_CALLBACK(menubar_plot_toggle_option), GINT_TO_POINTER(PLOT_MESH)); gtk_widget_show(menu_item_plot_mesh); menu_item_plot_contour=gtk_check_menu_item_new_with_label("Contours"); gtk_menu_shell_append(GTK_MENU_SHELL(bar_menu),menu_item_plot_contour); if ( plot_cont ) { gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_item_plot_contour),TRUE); } g_signal_connect_swapped(G_OBJECT(menu_item_plot_contour),"toggled", G_CALLBACK(menubar_plot_toggle_option), GINT_TO_POINTER(PLOT_CONT)); gtk_widget_show(menu_item_plot_contour); menu_item_plot_fill=gtk_check_menu_item_new_with_label("ColourFill"); gtk_menu_shell_append(GTK_MENU_SHELL(bar_menu),menu_item_plot_fill); if ( plot_fill ) { gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_item_plot_fill),TRUE); } g_signal_connect_swapped(G_OBJECT(menu_item_plot_fill),"toggled", G_CALLBACK(menubar_plot_toggle_option), GINT_TO_POINTER(PLOT_FILL)); gtk_widget_show(menu_item_plot_fill); menu_item_plot_gradient=gtk_check_menu_item_new_with_label("Gradient"); gtk_menu_shell_append(GTK_MENU_SHELL(bar_menu),menu_item_plot_gradient); if ( plot_grad ) { gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_item_plot_gradient),TRUE); } g_signal_connect_swapped(G_OBJECT(menu_item_plot_gradient),"toggled", G_CALLBACK(menubar_plot_toggle_option), GINT_TO_POINTER(PLOT_GRAD)); gtk_widget_show(menu_item_plot_gradient); menu_item=gtk_menu_item_new_with_label("Legend"); gtk_menu_shell_append(GTK_MENU_SHELL(bar_menu),menu_item); g_signal_connect_swapped(G_OBJECT(menu_item),"activate", G_CALLBACK(menubar_plot_display_legend_window), (gpointer)g_strdup("Options")); gtk_widget_show(menu_item); menu_item = gtk_radio_menu_item_new_with_label(radio_menu_group, "Draw Output"); radio_menu_group= gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menu_item)); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (menu_item), TRUE); gtk_menu_shell_append(GTK_MENU_SHELL(bar_menu),menu_item); g_signal_connect_swapped(G_OBJECT(menu_item),"activate", G_CALLBACK(menubar_plot_draw_mode), (gpointer)DRAW_OUTPUT); gtk_widget_show(menu_item); menu_item = gtk_radio_menu_item_new_with_label(radio_menu_group, "Draw Input"); gtk_menu_shell_append(GTK_MENU_SHELL(bar_menu),menu_item); g_signal_connect_swapped(G_OBJECT(menu_item),"activate", G_CALLBACK(menubar_plot_draw_mode), (gpointer)DRAW_INPUT); gtk_widget_show(menu_item); pref_menu_item=gtk_menu_item_new_with_label("Preferences..."); gtk_menu_shell_append(GTK_MENU_SHELL(bar_menu),pref_menu_item); /* See section (1) */ /* g_signal_connect_swapped(G_OBJECT(pref_menu_item),"activate", G_CALLBACK(menubar_plot_preferences), (gpointer)drawing_area); */ gtk_widget_show(pref_menu_item); root_menu=gtk_menu_item_new_with_label("View"); gtk_widget_show(root_menu); /* attach menu to root menu */ gtk_menu_item_set_submenu(GTK_MENU_ITEM(root_menu),bar_menu); /* attach root menu to menu bar */ gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar),root_menu); /***** end of plot menu **********/ /***** start of solve menu **********/ /* File menu bar and assorted functions */ bar_menu=gtk_menu_new(); /* menu items */ menu_item=gtk_menu_item_new_with_label("Solve Problem"); gtk_menu_shell_append(GTK_MENU_SHELL(bar_menu),menu_item); g_signal_connect_swapped(G_OBJECT(menu_item),"activate", G_CALLBACK(menubar_solve_only_response), (gpointer)menu_item); gtk_widget_show(menu_item); menu_item=gtk_menu_item_new_with_label("Generate Mesh"); gtk_menu_shell_append(GTK_MENU_SHELL(bar_menu),menu_item); g_signal_connect_swapped(G_OBJECT(menu_item),"activate", G_CALLBACK(menubar_solve_mesh_response), (gpointer)g_strdup("Mesh")); gtk_widget_show(menu_item); menu_item=gtk_menu_item_new_with_label("Mesh+Solve Iteratively"); gtk_menu_shell_append(GTK_MENU_SHELL(bar_menu),menu_item); g_signal_connect_swapped(G_OBJECT(menu_item),"activate", G_CALLBACK(menubar_solve_iterative_response), (gpointer)g_strdup("Solve iter")); gtk_widget_show(menu_item); menu_item=gtk_menu_item_new_with_label("Integrate.."); gtk_menu_shell_append(GTK_MENU_SHELL(bar_menu),menu_item); g_signal_connect_swapped(G_OBJECT(menu_item),"activate", G_CALLBACK(menubar_solve_integrate_responce), (gpointer)g_strdup("Intergate")); gtk_widget_show(menu_item); menu_item=gtk_check_menu_item_new_with_label("Edit Material..."); gtk_menu_shell_append(GTK_MENU_SHELL(bar_menu),menu_item); g_signal_connect(G_OBJECT(menu_item),"activate", G_CALLBACK(menubar_solve_materials_responce), (gpointer)menu_item); gtk_widget_show(menu_item); menu_item=gtk_menu_item_new_with_label("Change Options..."); gtk_menu_shell_append(GTK_MENU_SHELL(bar_menu),menu_item); g_signal_connect_swapped(G_OBJECT(menu_item),"activate", G_CALLBACK(menubar_solve_options_response), (gpointer)g_strdup("Options")); gtk_widget_show(menu_item); root_menu=gtk_menu_item_new_with_label("Solve"); gtk_widget_show(root_menu); /* attach menu to root menu */ gtk_menu_item_set_submenu(GTK_MENU_ITEM(root_menu),bar_menu); /* attach root menu to menu bar */ gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar),root_menu); /***** end of solve menu **********/ /****** help menu *******************/ bar_menu=gtk_menu_new(); /* menu items */ menu_item=gtk_menu_item_new_with_label("About Problem..."); gtk_menu_shell_append(GTK_MENU_SHELL(bar_menu),menu_item); g_signal_connect_swapped(G_OBJECT(menu_item),"activate", G_CALLBACK(menubar_help_about_problem), NULL); gtk_widget_show(menu_item); menu_item=gtk_menu_item_new_with_label("About pdnMesh..."); gtk_menu_shell_append(GTK_MENU_SHELL(bar_menu),menu_item); g_signal_connect_swapped(G_OBJECT(menu_item),"activate", G_CALLBACK(menubar_help_about_responce), NULL); gtk_widget_show(menu_item); root_menu=gtk_menu_item_new_with_label("Help"); gtk_widget_show(root_menu); /* attach menu to root menu */ gtk_menu_item_set_submenu(GTK_MENU_ITEM(root_menu),bar_menu); /* attach root menu to menu bar */ gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar),root_menu); /********* end help menu ****************/ /********** tool bar ******************/ handlebox=gtk_handle_box_new(); gtk_box_pack_start(GTK_BOX(vbox),handlebox,FALSE,FALSE,0); toolbar=gtk_toolbar_new(); gtk_toolbar_set_orientation(GTK_TOOLBAR(toolbar),GTK_ORIENTATION_HORIZONTAL); gtk_toolbar_set_style(GTK_TOOLBAR(toolbar),GTK_TOOLBAR_ICONS); gtk_container_add(GTK_CONTAINER(handlebox),toolbar); iconw=gtk_image_new_from_file(PIXMAPS_DIR"/open.xpm"); button=gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), "Open", /* button label */ "Open File...", /* button tooltip */ "Private", /* tooltip private info */ iconw, /* icon */ GTK_SIGNAL_FUNC(menubar_file_open_response), /* callback */ (gpointer)toolbar); iconw=gtk_image_new_from_file(PIXMAPS_DIR"/save.xpm"); button=gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), "Save", /* button label */ "Save As...", /* button tooltip */ "Private", /* tooltip private info */ iconw, /* icon */ GTK_SIGNAL_FUNC(menubar_file_save_response), /* callback */ (gpointer)toolbar); gtk_toolbar_append_space(GTK_TOOLBAR(toolbar)); iconw=gtk_image_new_from_file(PIXMAPS_DIR"/zoom_window.xpm"); button=gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), "Zoom Window", /* button label */ "Zoom Window", /* button tooltip */ "Private", /* tooltip private info */ iconw, /* icon */ GTK_SIGNAL_FUNC(switch_to_zoom_start), /* callback */ (gpointer)window); iconw=gtk_image_new_from_file(PIXMAPS_DIR"/zoom_back.xpm"); button=gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), "Zoom Back", /* button label */ "Zoom Back", /* button tooltip */ "Private", /* tooltip private info */ iconw, /* icon */ GTK_SIGNAL_FUNC(switch_to_zoom_back_button), /* callback */ (gpointer)window); iconw=gtk_image_new_from_file(PIXMAPS_DIR"/zoom_all.xpm"); button=gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), "Zoom All", /* button label */ "Zoom All", /* button tooltip */ "Private", /* tooltip private info */ iconw, /* icon */ GTK_SIGNAL_FUNC(switch_to_zoom_all_button), /* callback */ (gpointer)window); gtk_toolbar_append_space(GTK_TOOLBAR(toolbar)); iconw=gtk_image_new_from_file(PIXMAPS_DIR"/plot_cont.xpm"); /* allocate memory for WW - NOTE: cannot free this memory inside function */ if((WW=(dual_widget*)malloc(sizeof(dual_widget)))==NULL) { fprintf(stderr,"%s: %d: no free memory\n",__FILE__,__LINE__); exit(1); } WW->w1=window; WW->w2=menu_item_plot_contour; button=gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), "Contours", /* button label */ "Plot Contours", /* button tooltip */ "Private", /* tooltip private info */ iconw, /* icon */ GTK_SIGNAL_FUNC(toolbar_plot_toggle_option_contours), /* callback */ (gpointer)WW); /* allocate memory for WW - NOTE: cannot free this memory inside function */ if((WW=(dual_widget*)malloc(sizeof(dual_widget)))==NULL) { fprintf(stderr,"%s: %d: no free memory\n",__FILE__,__LINE__); exit(1); } WW->w1=window; WW->w2=menu_item_plot_fill; iconw=gtk_image_new_from_file(PIXMAPS_DIR"/plot_fill.xpm"); button=gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), "Fill", /* button label */ "Plot ColorFill", /* button tooltip */ "Private", /* tooltip private info */ iconw, /* icon */ GTK_SIGNAL_FUNC(toolbar_plot_toggle_option_fill), /* callback */ (gpointer)WW); /* allocate memory for WW - NOTE: cannot free this memory inside function */ if((WW=(dual_widget*)malloc(sizeof(dual_widget)))==NULL) { fprintf(stderr,"%s: %d: no free memory\n",__FILE__,__LINE__); exit(1); } WW->w1=window; WW->w2=menu_item_plot_gradient; iconw=gtk_image_new_from_file(PIXMAPS_DIR"/plot_grad.xpm"); button=gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), "Gradient", /* button label */ "Plot Gradient", /* button tooltip */ "Private", /* tooltip private info */ iconw, /* icon */ GTK_SIGNAL_FUNC(toolbar_plot_toggle_option_gradient), /* callback */ (gpointer)WW); /* allocate memory for WW - NOTE: cannot free this memory inside function */ if((WW=(dual_widget*)malloc(sizeof(dual_widget)))==NULL) { fprintf(stderr,"%s: %d: no free memory\n",__FILE__,__LINE__); exit(1); } WW->w1=window; WW->w2=menu_item_plot_mesh; iconw=gtk_image_new_from_file(PIXMAPS_DIR"/plot_mesh.xpm"); button=gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), "Mesh", /* button label */ "Plot Mesh", /* button tooltip */ "Private", /* tooltip private info */ iconw, /* icon */ GTK_SIGNAL_FUNC(toolbar_plot_toggle_option_mesh), /* callback */ (gpointer)WW); gtk_toolbar_append_space(GTK_TOOLBAR(toolbar)); iconw=gtk_image_new_from_file(PIXMAPS_DIR"/next_eigenmode.xpm"); button=gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), "Next Eigenmode", /* button label */ "Switch to next Eigenmode",/* button tooltip */ "Private", /* tooltip private info */ iconw, /* icon */ GTK_SIGNAL_FUNC(toolbar_switch_to_next_eigenmode), /* callback */ (gpointer)window); gtk_toolbar_append_space(GTK_TOOLBAR(toolbar)); iconw=gtk_image_new_from_file(PIXMAPS_DIR"/help_about.xpm"); button=gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), "About...", /* button label */ "About...",/* button tooltip */ "Private", /* tooltip private info */ iconw, /* icon */ GTK_SIGNAL_FUNC(menubar_help_about_responce), /* callback */ NULL); gtk_widget_show(toolbar); gtk_widget_show(handlebox); /********** end tool bar **************/ /************status bar ***********************/ handlebox=gtk_handle_box_new(); gtk_box_pack_start(GTK_BOX(vbox),handlebox,FALSE,FALSE,0); gtk_widget_show(handlebox); /* hbox */ hbox=gtk_hbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(handlebox),hbox); gtk_widget_show(hbox); /* label to display coords */ global_status_label=gtk_label_new("x: 0.000 y: 0.000 z: 0.000"); g_snprintf(buf, 128, "x: 0.000 y: 0.000 z: 0.000"); gtk_label_set_markup(GTK_LABEL(global_status_label),buf); gtk_label_set_justify(GTK_LABEL(global_status_label),GTK_JUSTIFY_LEFT); gtk_box_pack_start(GTK_BOX(hbox),global_status_label,FALSE,TRUE,0); gtk_widget_show(global_status_label); /* label to display eigenvalues and mode */ global_mode_label=gtk_label_new("|"); gtk_label_set_justify(GTK_LABEL(global_mode_label),GTK_JUSTIFY_LEFT); gtk_box_pack_start(GTK_BOX(hbox),global_mode_label,FALSE,TRUE,0); gtk_widget_show(global_mode_label); /************** end status bar *************/ /**************** drawing area for output */ drawing_area=gtk_drawing_area_new(); gtk_widget_set_size_request(drawing_area,DEFAULT_WIDTH,DEFAULT_HEIGHT); /* set openGL capability */ gtk_widget_set_gl_capability(drawing_area, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE); gtk_widget_add_events(drawing_area, GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | GDK_POINTER_MOTION_MASK | /* passive motion of mouse */ GDK_BUTTON_PRESS_MASK | /* mouse clicks */ GDK_VISIBILITY_NOTIFY_MASK); /* connect signal handlers for drawing area */ g_signal_connect_after(G_OBJECT(drawing_area), "realize", G_CALLBACK(realize), NULL); g_signal_connect(G_OBJECT(drawing_area), "configure_event", G_CALLBACK(configure_event), NULL); g_signal_connect(G_OBJECT(drawing_area), "expose_event", G_CALLBACK(expose_event), NULL); g_signal_connect(G_OBJECT(drawing_area), "button_press_event", G_CALLBACK(button_press_event), NULL); g_signal_connect(G_OBJECT(drawing_area),"motion_notify_event", G_CALLBACK(motion_notify_event), NULL); /* key press event handled by top level window */ g_signal_connect_swapped(G_OBJECT(window),"key_press_event", G_CALLBACK(key_press_event),drawing_area); /* pack */ /* attach drawing area to notebook */ gtk_box_pack_start(GTK_BOX(vbox),drawing_area,TRUE,TRUE,0); gtk_widget_show(drawing_area); /**************** additional callbacks related to drawing area */ g_signal_connect_swapped(G_OBJECT(pref_menu_item),"activate", G_CALLBACK(menubar_plot_preferences), (gpointer)drawing_area); /**************** popup menu */ menu=create_popup_menu(drawing_area); g_signal_connect_swapped(G_OBJECT(drawing_area), "button_press_event", G_CALLBACK(button_press_event_popup_menu), menu); hbox=gtk_hbox_new(FALSE,0); gtk_box_pack_start(GTK_BOX(vbox),hbox,FALSE,FALSE,0); gtk_widget_show(hbox); /* finally, a status bar */ global_status_bar=gtk_label_new(PACKAGE":"VERSION); gtk_label_set_justify(GTK_LABEL(global_status_bar),GTK_JUSTIFY_LEFT); gtk_box_pack_start(GTK_BOX (hbox), global_status_bar, FALSE, TRUE, 0); gtk_widget_show(global_status_bar); return(window); } /* openGL framebuffer configuratiion */ GdkGLConfig * configure_gl(void) { GdkGLConfig *glconfig; /* try double buffered */ glconfig=gdk_gl_config_new_by_mode(GDK_GL_MODE_RGB | GDK_GL_MODE_DEPTH | GDK_GL_MODE_DOUBLE); if (glconfig==NULL) { #ifdef DEBUG g_print("\n connot find double buffered visual, tring single\n"); #endif glconfig=gdk_gl_config_new_by_mode(GDK_GL_MODE_RGB | GDK_GL_MODE_DEPTH); if (glconfig==NULL) { #ifdef DEBUG g_print("*** No OpenGL capable visual, quitting\n"); #endif exit(1); } } return(glconfig); } #endif /*WIN32*/