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
00030 gitkr_dialog_free_layout(dialog);
00031
00032
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
00050 layout->focused_widget=NULL;
00051 layout->main.widgetsPerPage=0;
00052
00053
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
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;
00077
00079 if(box_vert) container=gtk_vbox_new(FALSE, 3);
00080 else container=gtk_hbox_new(FALSE, 3);
00081 gtk_container_add(GTK_CONTAINER(window), container);
00082
00083
00084
00085 gitkr_dialog_generate_layout_walker(dialog,GTK_CONTAINER(container),xmlXPathNodeSetItem(ns,0)->children,box_vert,0);
00086
00087 g_assert(layout->main.widgets[layout->main.widgetsPerPage-1].id!=NULL);
00088
00089
00090 if(box_vert) sub_container=gtk_hbox_new(FALSE, 3);
00091 else sub_container=gtk_vbox_new(FALSE, 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
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
00111 if(!xmlNodeIsText(node)) {
00112
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
00157
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
00168 if(box_vert) sub_container=gtk_vbox_new(FALSE, 3);
00169 else sub_container=gtk_hbox_new(FALSE, 3);
00170 gtk_container_add(root_container,sub_container);
00171 gtk_container_set_border_width(GTK_CONTAINER(sub_container), 3);
00172
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
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
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
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
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
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
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
00311 xmlFree(layout->title);
00312 g_free(layout);
00313 dialog->layout=NULL;
00314 }
00315 gitk_log_outro();
00316 }