gitkrlayout.c

Go to the documentation of this file.
00001 
00012 #define GITK_RENDERER_C
00013 #define GITKR_LAYOUT_C
00014 
00015 #include "gitkrincludes.h"
00016 
00022 void gitkr_dialog_generate_layout(GitkDialogPtr dialog) {
00023   xmlXPathCompExprPtr xpath_get_widgets,xpath_get_root_widgetgroup;
00024 
00025   gitk_log("gitkr_dialog_generate_layout() beg");
00026 
00027   g_assert(dialog!=NULL);
00028 
00029   //-- free old layout
00030   gitkr_dialog_free_layout(dialog);
00031 
00032   //-- get the nodeset containing the widgets
00033   if((xpath_get_root_widgetgroup=xmlXPathCompile("/"GITK_NS_PREFIX":giml/"GITK_NS_PREFIX":dialog"))
00034     && (xpath_get_widgets=xmlXPathCompile("//"GITK_NS_PREFIX":widgetgroup/"GITK_NS_PREFIX":widget"))) {
00035     xmlXPathObjectPtr root_widgetgroup_xpoptr;
00036     if((root_widgetgroup_xpoptr=gitk_xpath_type_filter(
00037         gitk_cxpath_get_object(dialog,xpath_get_root_widgetgroup,NULL),
00038         XPATH_NODESET))) {
00039       xmlNodeSetPtr ns=(xmlNodeSetPtr)root_widgetgroup_xpoptr->nodesetval;
00040       if(xmlXPathNodeSetGetLength(ns)==1) {
00041         GitkrGtkLayoutPtr layout=g_new(GitkrGtkLayout,1);
00042         GtkWindow *window=GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
00043         xmlXPathObjectPtr widgets_xpoptr;
00044         GtkWidget *container,*sub_container;
00045         gboolean box_vert;
00046   
00047         dialog->layout=(GitkLayoutPtr)layout;
00048   
00049         //-- set layout parameter
00050         layout->focused_widget=NULL;
00051         layout->main.widgetsPerPage=0;
00052 
00053         //-- get number of widgets
00054         if((widgets_xpoptr=gitk_xpath_type_filter(
00055             gitk_cxpath_get_object(dialog,xpath_get_widgets,NULL),
00056             XPATH_NODESET))) {
00057           layout->main.widgetsPerPage+=xmlXPathNodeSetGetLength((xmlNodeSetPtr)widgets_xpoptr->nodesetval);
00058           xmlXPathFreeObject(widgets_xpoptr);
00059         }
00060         layout->main.widgets=(GitkrGtkWidgetPtr)g_new(GitkrGtkWidget,layout->main.widgetsPerPage);
00061         layout->window=window;
00062         layout->title=gitk_cxpath_get_string(dialog,xpath_get_dialog_name,NULL);
00063   
00064         gitk_log1("layout : %p",layout);
00065         gitk_log1("layout->main.widgetsPerPage : %d",layout->main.widgetsPerPage);
00066         gitk_log2("layout->title : %p,\"%s\"",layout->title,gitk_save_get_string(layout->title));
00067         gitk_log1("layout->window : %p",layout->window);
00068   
00069         //-- generate top-level container (window)
00070         gtk_window_set_title(window,layout->title);
00071         gtk_container_set_border_width(GTK_CONTAINER(window), 10);
00072         g_signal_connect(GTK_OBJECT(window), "delete-event",G_CALLBACK(sighandler_window_on_close),NULL);
00073         g_signal_connect(GTK_OBJECT(window), "destroy",G_CALLBACK(sighandler_window_on_destroy),(gpointer)layout);
00074 
00076         box_vert=TRUE; // ctrl are below 
00077         
00079         if(box_vert) container=gtk_vbox_new(FALSE, /*spacing=*/3);
00080         else container=gtk_hbox_new(FALSE, /*spacing=*/3);
00081         gtk_container_add(GTK_CONTAINER(window), container);
00082         //box_vert=!box_vert;
00083   
00084         //-- recursively step down widget-groups
00085         gitkr_dialog_generate_layout_walker(dialog,GTK_CONTAINER(container),xmlXPathNodeSetItem(ns,0)->children,box_vert,0);
00086         //-- ensure that all widgets have been initalised
00087         g_assert(layout->main.widgets[layout->main.widgetsPerPage-1].id!=NULL);
00088   
00089         //-- add default buttons
00090         if(box_vert) sub_container=gtk_hbox_new(FALSE, /*spacing=*/3);
00091         else sub_container=gtk_vbox_new(FALSE, /*spacing=*/3);
00092         gtk_container_add(GTK_CONTAINER(container), sub_container);
00093 
00094         if((widgets_xpoptr=gitk_xpath_type_filter(
00095             gitk_xpath_get_object(dialog,"/"GITK_NS_PREFIX":giml/"GITK_NS_PREFIX":dialog/"GITK_NS_PREFIX":dialogwidgets/"GITK_NS_PREFIX":widget",NULL),
00096             XPATH_NODESET))) {
00097           xmlNodeSetPtr widgets=(xmlNodeSetPtr)widgets_xpoptr->nodesetval;
00098           gint widgets_len=xmlXPathNodeSetGetLength(widgets);
00099           //gitk_log1("count(dialogwidgets)=%d",widgets_len);
00100           if(widgets_len>0) {
00101             gint j;
00102             GitkrGtkWidgetPtr widget;
00103             xmlNodePtr node;
00104             gchar *id,*label;
00105 
00106             layout->ctrl.widgetsPerPage=widgets_len;
00107             layout->ctrl.widgets=(GitkrGtkWidgetPtr)g_new(GitkrGtkWidget,layout->ctrl.widgetsPerPage);
00108             for(j=0;j<widgets_len;j++) {
00109               node=xmlXPathNodeSetItem(widgets,j);
00110               //-- add new widget
00111               if(!xmlNodeIsText(node)) {
00112                 //-- get widget data
00113                 widget=&layout->ctrl.widgets[j];
00114                 id=xmlGetProp(node,"id");
00115                 label=gitk_cxpath_get_string(dialog,xpath_get_label,node);
00116                 gitkr_widget_action_new(widget,id,dialog,label,GTK_CONTAINER(sub_container),TRUE,NULL);
00117                 gtk_signal_connect(GTK_OBJECT(widget->impl),"focus-in-event",GTK_SIGNAL_FUNC(sighandler_widget_on_focus_in),(gpointer)widget);
00118                 gtk_signal_connect(GTK_OBJECT(widget->impl),"focus-out-event",GTK_SIGNAL_FUNC(sighandler_widget_on_focus_out),(gpointer)widget);
00119               }
00120               else { gitk_err("unexpected textnode in dialog definition"); }
00121             }
00122           }
00123           else gitk_err("there should be more than zero widgets in dialogwidgets");
00124           xmlXPathFreeObject(widgets_xpoptr);
00125         }
00126         else gitk_err("failed to get dialog widgets");
00127       }
00128       else { gitk_err1("nodeset should contain only one node (but has %d nodes)",xmlXPathNodeSetGetLength(ns)); }
00129       xmlXPathFreeObject(root_widgetgroup_xpoptr);
00130     }
00131     else { gitk_err("failed to eval xpath expr"); }
00132     xmlXPathFreeCompExpr(xpath_get_root_widgetgroup);
00133     xmlXPathFreeCompExpr(xpath_get_widgets);
00134   }
00135   else { gitk_err("failed to compile xpath expression (get_root_widgetgroup, get_widgets)"); }
00136 }
00137 
00138 
00142 gint gitkr_dialog_generate_layout_walker(GitkDialogPtr dialog,GtkContainer *container,xmlNodePtr cur,gboolean box_vert,gint widget_index) {
00143   xmlNodePtr next;
00144   GitkrGtkWidgetPtr widget;
00145   gchar *label;
00146 
00147   gitk_log2("gitkr_dialog_generate_layout_walker(box_vert=%d,widget_index=%d) beg",box_vert,widget_index);
00148 
00149   while(cur!=NULL) {
00150     next=cur->next;
00151     if(!xmlNodeIsText(cur)) {
00152       if(!strcasecmp(cur->name,"widgetgroup")) {
00153         GtkWidget *sub_container;
00154         GtkContainer *root_container;
00155     
00156         //gitk_log("widgetgroup");
00157         //-- if widgetgroup has a label make a frame first and then put the box into the frame
00158         if(((label=gitk_cxpath_get_string(dialog,xpath_get_label,cur))!=NULL) && (*label)) {
00159           sub_container=gtk_frame_new(label);
00160           gtk_container_add(container,sub_container);
00161           root_container=GTK_CONTAINER(sub_container);
00162         }
00163         else {
00164           root_container=container;
00165         }
00166         //-- generate a layout box
00168         if(box_vert) sub_container=gtk_vbox_new(/*homogenous=*/FALSE, /*spacing=*/3);
00169         else sub_container=gtk_hbox_new(/*homogenous=*/FALSE, /*spacing=*/3);
00170         gtk_container_add(root_container,sub_container);
00171         gtk_container_set_border_width(GTK_CONTAINER(sub_container), 3);
00172         //-- requisively pack childen into the container
00173         if(cur->children!=NULL) {
00174           widget_index=gitkr_dialog_generate_layout_walker(dialog,GTK_CONTAINER(sub_container),cur->children,!box_vert,widget_index);
00175         }
00176       }
00177       else if(!strcasecmp(cur->name,"widget")) {
00178         gchar *id;
00179     
00180         gitk_log("widget");
00181         //-- get widget data
00182         widget=&((GitkrGtkLayoutPtr)(dialog->layout))->main.widgets[widget_index++];
00183         id=xmlGetProp(cur,"id");
00184         label=gitk_cxpath_get_string(dialog,xpath_get_label,cur);
00185         //-- allocate  and attach type specific widget data
00186         switch(gitk_widget_get_type(cur)) {
00187           case GITK_WIDGET_TYPE_ACTION:
00188             gitkr_widget_action_new(widget,id,dialog,label,container,box_vert,cur);
00189             break;
00190           case GITK_WIDGET_TYPE_CHARACTERINPUT:
00191           case GITK_WIDGET_TYPE_CHARACTERINPUT_ALPHABETIC:
00192             gitkr_widget_characterinput_new(widget,id,dialog,label,container,box_vert,cur);
00193             break;
00194           case GITK_WIDGET_TYPE_OPTIONCHOICE:
00195           case GITK_WIDGET_TYPE_OPTIONCHOICE_SINGLE:
00196           case GITK_WIDGET_TYPE_OPTIONCHOICE_SINGLE_COMPACT:
00197             gitkr_widget_optionchoice_new(widget,id,dialog,label,container,box_vert,cur);
00198             break;
00199           case GITK_WIDGET_TYPE_OPTIONCHOICE_BOOLEAN:
00200             gitkr_widget_optionchoice_boolean_new(widget,id,dialog,label,container,box_vert,cur);
00201             break;
00202           case GITK_WIDGET_TYPE_LABEL:
00203             gitkr_widget_label_new(widget,id,dialog,label,container,box_vert,cur);
00204             break;
00205           case GITK_WIDGET_TYPE_UNDEF:
00206           default:
00207             gitkr_widget_label_new(widget,id,dialog,label,container,box_vert,cur);
00208             gitk_log1("widget type not yet implemented %d",widget->type);
00209         }
00210         gtk_signal_connect(GTK_OBJECT(widget->impl),"focus-in-event",GTK_SIGNAL_FUNC(sighandler_widget_on_focus_in),(gpointer)widget);
00211         gtk_signal_connect(GTK_OBJECT(widget->impl),"focus-out-event",GTK_SIGNAL_FUNC(sighandler_widget_on_focus_out),(gpointer)widget);
00212 
00213         gitk_log1("   widget=0x%08lx",(unsigned long)widget);
00214         gitk_log1("   dialog=0x%08lx",(unsigned long)widget->dialog);
00215         gitk_log1("       id=\"%s\"" ,widget->id);
00216         gitk_log1("     impl=0x%08lx",(unsigned long)widget->impl);
00217       }
00218       else {
00219         gitk_log1("unexpected node in dialog definition : \"%s\"",cur->name);
00220       }
00221     }
00222     else {
00224       xmlChar *str=g_strstrip(xmlNodeGetContent(cur));
00225       if(str && *str) gitk_log1("unexpected textnode in dialog definition: \"%s\"",str);
00226     } 
00227     //-- recurse into node childen
00228     if(cur) cur=next;
00229   }
00230   return(widget_index);
00231 }
00232 
00233 
00238 void gitkr_dialog_output_layout(GitkDialogPtr dialog) {
00239   GitkrGtkLayoutPtr layout;
00240   xmlNodePtr node;
00241 
00242   g_assert(dialog!=NULL);
00243   g_assert(dialog->layout!=NULL);
00244 
00245   gitk_log_intro();
00246 
00247   //-- get dialog node and inspect style settings
00248   if((node=gitk_xpath_get_node(dialog,"/"GITK_NS_PREFIX":giml/"GITK_NS_PREFIX":dialog",NULL))) {
00249     gchar *theme;
00250     
00251     theme=xmlGetProp(node,"style");
00252     gitkr_theme_switch(theme);
00253     if(theme) xmlFree(theme);
00254     gtk_rc_reparse_all();
00255   }
00256   else { gitk_err("failed to get dialog"); }
00257 
00258   layout=(GitkrGtkLayoutPtr)dialog->layout;
00259   gtk_widget_show_all(GTK_WIDGET(layout->window));
00260 
00261   gitk_log_outro();
00262 }
00263 
00268 void gitkr_dialog_free_layout(GitkDialogPtr dialog) {
00269   g_assert(dialog!=NULL);
00270 
00271   gitk_log_intro();
00272 
00273   if(dialog->layout) {
00274     GitkrGtkLayoutPtr layout=(GitkrGtkLayoutPtr)dialog->layout;
00275   
00276     gitk_log2("layout->title : %p,\"%s\"",layout->title,gitk_save_get_string(layout->title));
00277     gitk_log1("layout->window : %p",layout->window);
00278     gitk_log1("current event loop level : %d",gtk_main_level());
00279 
00280     if(layout->window) {
00281       gtk_widget_hide_all(GTK_WIDGET(layout->window));
00282       gtk_widget_destroy(GTK_WIDGET(layout->window));
00283       // this is neccesary the gtk actually closes the window
00284       if(!gtk_main_level()) while(gtk_events_pending()) gtk_main_iteration_do(FALSE);
00285     }
00286     
00287     gitk_log1("layout->window : %p",layout->window);
00288   
00289     if(layout->main.widgets) {
00290       GitkrGtkWidgetPtr widget;
00291       gint i;
00292   
00293       for(i=0;i<layout->main.widgetsPerPage;i++) {
00294         widget=&layout->main.widgets[i];
00295         xmlFree(widget->id);
00296       }
00297       g_free(layout->main.widgets);
00298     }
00299     //gitk_log("gitkr_dialog_free_layout() chk4");
00300     if(layout->ctrl.widgets) {
00301       GitkrGtkWidgetPtr widget;
00302       gint i;
00303   
00304       for(i=0;i<layout->ctrl.widgetsPerPage;i++) {
00305         widget=&layout->ctrl.widgets[i];
00306         xmlFree(widget->id);
00307       }
00308       g_free(layout->ctrl.widgets);
00309     }
00310     //gitk_log("gitkr_dialog_free_layout() chk5");
00311     xmlFree(layout->title);
00312     g_free(layout);
00313     dialog->layout=NULL;
00314   }
00315   gitk_log_outro();
00316 }

Generated on Thu Oct 28 10:59:11 2004 for gitk by doxygen 1.3.6