00001
00012 #define GITK_RENDERER_C
00013 #define GITKR_LAYOUT_C
00014
00015 #include "gitkrincludes.h"
00016
00018 #define giml_ctrl_text N_("Previous");
00019 #undef giml_ctrl_text
00020 #define giml_ctrl_text N_("Next");
00021 #undef giml_ctrl_text
00022
00027 void gitkr_dialog_generate_layout(GitkDialogPtr dialog) {
00028 GitkrTextLayoutPtr layout;
00029 xmlNodePtr node;
00030
00031 gitk_log("gitkr_dialog_generate_layout() beg");
00032 gitk_log2("terminal dimensions %d x %d",LINES,COLS);
00033 g_assert(dialog!=NULL);
00034
00035
00036 gitkr_dialog_free_layout(dialog);
00037
00038
00039 layout=gitkr_dialog_new_layout(dialog);
00040 dialog->layout=(GitkLayoutPtr)layout;
00041
00057
00058
00059 if((node=gitk_xpath_get_node(dialog,"/"GITK_NS_PREFIX":giml/"GITK_NS_PREFIX":dialog",NULL))) {
00060 gchar *fg_color,*bg_color;
00061
00062
00063
00064 fg_color=xmlGetProp(node,"fgcolor");
00065 bg_color=xmlGetProp(node,"bgcolor");
00066 layout->bg_color=color_name_to_code(bg_color,COLOR_BLACK);
00067 layout->fg_color=color_name_to_code(fg_color,COLOR_WHITE);
00068 layout->dim_bold=color_name_to_attr(fg_color,FALSE);
00069 xmlFree(fg_color);
00070 xmlFree(bg_color);
00071
00073 gitkr_dialog_generate_dialog_widgets(dialog);
00074
00075
00076
00077 gitk_log("starting recursion ...");
00079 gitkr_dialog_generate_sequential_layout(dialog,node);
00080
00081 gitk_log("finished recursion ...");
00082 }
00083 else { gitk_err("failed to get root widgetgroup"); }
00084 }
00085
00090 GitkrTextLayoutPtr gitkr_dialog_new_layout(GitkDialogPtr dialog) {
00091 GitkrTextLayoutPtr layout=g_new(GitkrTextLayout,1);
00092
00093
00094 layout->focus=GITK_FOCUS_TYPE_CTRL;
00095 layout->currentPage=0;
00096 layout->currentWidget=0;
00097 layout->maxWidgetsPerPage=LINES-GITK_LINE_OFFSET;
00098 layout->pages=NULL;
00099 layout->title=gitkr_cxpath_get_string(dialog,xpath_get_dialog_name,NULL);
00100
00101 layout->ctrl.widgets=g_new0(GitkrTextWidget,1);
00102 return(layout);
00103 }
00104
00109 void gitkr_dialog_generate_dialog_widgets(GitkDialogPtr dialog) {
00110 GitkrTextLayoutPtr layout=(GitkrTextLayoutPtr)dialog->layout;
00111 xmlNodePtr node;
00112
00113 if((node=gitk_xpath_get_node(dialog,"/"GITK_NS_PREFIX":giml/"GITK_NS_PREFIX":dialog/"GITK_NS_PREFIX":dialogwidgets/"GITK_NS_PREFIX":widget",NULL))) {
00114 if(!xmlNodeIsText(node)) {
00115 if(!strncasecmp(node->name,"widget",7)) {
00116 GitkrTextWidgetPtr widget;
00117 widget=&layout->ctrl.widgets[0];
00118 gitkr_widget_optionchoice_new(widget,dialog,node);
00119
00120
00121 gitk_log3(" dialogwidget 0x%08x <%s id=\"%s\">",(gint)widget,node->name,widget->id);
00122 layout->ctrl.widgetsPerPage=1;
00123 gitk_log1(" => %d",layout->ctrl.widgetsPerPage);
00124 }
00125 else gitk_err1("expecting 'widget' node, got '%s'",node->name);
00126 }
00127 else gitk_err("unexpected textnode in dialog definition");
00128 }
00129 else gitk_err("failed to get dialog widgets");
00130 }
00131
00137 void gitkr_dialog_generate_sequential_layout(GitkDialogPtr dialog,xmlNodePtr root) {
00138 GitkrTextLayoutPtr layout;
00139 xmlXPathCompExprPtr xpath_get_pages,xpath_get_widgets;
00140
00141 g_assert(dialog!=NULL);
00142 g_assert(dialog->layout!=NULL);
00143
00144 gitk_log("gitkr_dialog_generate_sequential_layout() beg");
00145
00150 layout=(GitkrTextLayoutPtr)dialog->layout;
00151 if((xpath_get_pages=xmlXPathCompile("./"GITK_NS_PREFIX":widgetgroup/"GITK_NS_PREFIX":*/parent::*"))
00152 && (xpath_get_widgets=xmlXPathCompile("./"GITK_NS_PREFIX":widget"))) {
00153
00154
00155 xmlXPathObjectPtr pages_xpoptr;
00156 if((pages_xpoptr=gitk_xpath_type_filter(
00157 gitk_cxpath_get_object(dialog,xpath_get_pages,root),
00158 XPATH_NODESET))) {
00159 gint i,pageIx;
00160 xmlNodeSetPtr pages=(xmlNodeSetPtr)pages_xpoptr->nodesetval;
00161 gint pages_len=xmlXPathNodeSetGetLength(pages);
00162
00163 layout->numberOfPages=gitkr_dialog_generate_sequential_layout_count_pages(dialog,root,pages,xpath_get_widgets);
00164
00165 layout->pages=g_new0(GitkrTextLayoutPage,layout->numberOfPages);
00166 for(i=0;i<layout->numberOfPages;i++) {
00167 layout->pages[i].widgets=g_new0(GitkrTextWidget,layout->maxWidgetsPerPage);
00168 }
00169
00170 pageIx=0;
00171 pageIx=gitkr_dialog_generate_sequential_layout_build_page(dialog,root,xpath_get_widgets,pageIx);
00172 for(i=0;i<pages_len;i++) {
00173 pageIx=gitkr_dialog_generate_sequential_layout_build_page(dialog,xmlXPathNodeSetItem(pages,i),xpath_get_widgets,pageIx);
00174 }
00175 xmlXPathFreeObject(pages_xpoptr);
00176 }
00177 xmlXPathFreeCompExpr(xpath_get_pages);
00178 xmlXPathFreeCompExpr(xpath_get_widgets);
00179
00180 gitk_log1("layout->maxWidgetsPerPage : %d",layout->maxWidgetsPerPage);
00181 gitk_log1("layout->numberOfPages : %d",layout->numberOfPages);
00182 gitk_log1("layout->title : \"%s\"",layout->title);
00183 }
00184 else { gitk_err("failed to compile xpath expression (get_pages, get_widgets)"); }
00185 }
00186
00194 gint gitkr_dialog_generate_sequential_layout_count_pages(GitkDialogPtr dialog,xmlNodePtr root,xmlNodeSetPtr pages,xmlXPathCompExprPtr xpath_get_widgets) {
00195 GitkrTextLayoutPtr layout;
00196 xmlXPathObjectPtr widgets_xpoptr;
00197 gint pages_len=xmlXPathNodeSetGetLength(pages);
00198 gint numberOfPages=pages_len;
00199 gint i;
00200
00201 g_assert(dialog!=NULL);
00202 g_assert(dialog->layout!=NULL);
00203
00204 gitk_log_intro();
00205
00206 layout=(GitkrTextLayoutPtr)dialog->layout;
00207
00208 gitk_log1(" initial numberOfPages %d",numberOfPages);
00209
00210 if((widgets_xpoptr=gitk_xpath_type_filter(
00211 gitk_cxpath_get_object(dialog,xpath_get_widgets,root),
00212 XPATH_NODESET))) {
00213
00214 if(xmlXPathNodeSetGetLength((xmlNodeSetPtr)widgets_xpoptr->nodesetval)) numberOfPages++;
00215
00216 numberOfPages+=xmlXPathNodeSetGetLength((xmlNodeSetPtr)widgets_xpoptr->nodesetval)/layout->maxWidgetsPerPage;
00217 gitk_log1(" numberOfPages[r] %d",numberOfPages);
00218 xmlXPathFreeObject(widgets_xpoptr);
00219 }
00220
00221 for(i=0;i<pages_len;i++) {
00222 if((widgets_xpoptr=gitk_xpath_type_filter(
00223 gitk_cxpath_get_object(dialog,xpath_get_widgets,xmlXPathNodeSetItem(pages,i)),
00224 XPATH_NODESET))) {
00225
00226 numberOfPages+=xmlXPathNodeSetGetLength((xmlNodeSetPtr)widgets_xpoptr->nodesetval)/layout->maxWidgetsPerPage;
00227 gitk_log2(" numberOfPages[%d] %d",i,numberOfPages);
00228 xmlXPathFreeObject(widgets_xpoptr);
00229 }
00230 }
00231 gitk_log1(" final numberOfPages %d",numberOfPages);
00232 gitk_log_outro();
00233 return(numberOfPages);
00234 }
00235
00243 gint gitkr_dialog_generate_sequential_layout_build_page(GitkDialogPtr dialog,xmlNodePtr root,xmlXPathCompExprPtr xpath_get_widgets,gint pageIx) {
00244 GitkrTextLayoutPtr layout;
00245 xmlXPathObjectPtr widgets_xpoptr;
00246 gchar *title;
00247
00248 gitk_log("gitkr_dialog_generate_sequential_layout_build_page() beg");
00249
00250 g_assert(dialog!=NULL);
00251 g_assert(dialog->layout!=NULL);
00252 layout=(GitkrTextLayoutPtr)dialog->layout;
00253 g_assert(layout->pages!=NULL);
00254
00255
00256 title=gitkr_cxpath_get_string(dialog,xpath_get_label,root);
00257 gitk_log1("====> widgetgroup title \"%s\"",title);
00258
00259 if((widgets_xpoptr=gitk_xpath_type_filter(
00260 gitk_cxpath_get_object(dialog,xpath_get_widgets,root),
00261 XPATH_NODESET))) {
00262 gint j;
00263 xmlNodeSetPtr widgets=(xmlNodeSetPtr)widgets_xpoptr->nodesetval;
00264 gint widgets_len=xmlXPathNodeSetGetLength(widgets);
00265 xmlNodePtr node;
00266 gint widgetIx;
00267 GitkrTextWidgetPtr widget;
00268 gchar *focus;
00269
00270
00271 if(widgets_len) {
00272
00273 g_assert(layout->pages[pageIx].widgets!=NULL);
00274 widgetIx=0;
00275 gitk_log2("====> starting at page %2d with %2d widgets",pageIx,widgets_len);
00276 for(j=0;j<widgets_len;j++) {
00277 node=xmlXPathNodeSetItem(widgets,j);
00278
00279 if(!xmlNodeIsText(node)) {
00280
00281 if(focus=xmlGetProp(node,"hasFocus")) {
00282 if(!strncmp(focus,"true\0",5)) {
00283 layout->currentPage=pageIx;
00284 layout->currentWidget=widgetIx;
00285 layout->focus=GITK_FOCUS_TYPE_MAIN;
00286 }
00287 xmlFree(focus);
00288 }
00289
00290 widget=&layout->pages[pageIx].widgets[widgetIx];
00291
00292 switch(gitk_widget_get_type(node)) {
00293 case GITK_WIDGET_TYPE_ACTION:
00294 gitkr_widget_action_new(widget,dialog,node);
00295 break;
00296 case GITK_WIDGET_TYPE_CHARACTERINPUT:
00297 gitkr_widget_characterinput_new(widget,dialog,node);
00299 break;
00300 case GITK_WIDGET_TYPE_CHARACTERINPUT_ALPHABETIC:
00301 gitkr_widget_characterinput_alphabetic_new(widget,dialog,node);
00303 break;
00304 case GITK_WIDGET_TYPE_OPTIONCHOICE:
00305 case GITK_WIDGET_TYPE_OPTIONCHOICE_SINGLE:
00306 case GITK_WIDGET_TYPE_OPTIONCHOICE_SINGLE_COMPACT:
00308 gitkr_widget_optionchoice_new(widget,dialog,node);
00310 break;
00311 case GITK_WIDGET_TYPE_OPTIONCHOICE_BOOLEAN:
00312 gitkr_widget_optionchoice_boolean_new(widget,dialog,node);
00313 break;
00314 case GITK_WIDGET_TYPE_LABEL:
00315 gitkr_widget_label_new(widget,dialog,node);
00316 break;
00317 case GITK_WIDGET_TYPE_UNDEF:
00318 default:
00319 gitk_log("widget type not yet implemented");
00320 gitkr_widget_new(widget,dialog,node);
00321 }
00322 gitk_log1(" widget=0x%08lx",(unsigned long)widget);
00323 gitk_log1(" id=\"%s\"" ,widget->id);
00324 gitk_log1(" label=\"%s\"" ,widget->label);
00325 gitk_log2(" color=%d/%d" ,widget->fg_color,widget->bg_color);
00326 widgetIx++;
00327 }
00328 else { gitk_err("unexpected textnode in dialog definition"); }
00329
00330 if(widgetIx==layout->maxWidgetsPerPage){
00331 layout->pages[pageIx].title=title;
00332 layout->pages[pageIx].widgetsPerPage=widgetIx;
00333 gitk_log2(" widgetsPerPages[%2d]=%2d",pageIx,layout->pages[pageIx].widgetsPerPage);
00334 pageIx++;
00335 g_assert(layout->pages[pageIx].widgets!=NULL);
00336 widgetIx=0;
00337 }
00338 }
00339 layout->pages[pageIx].title=title;
00340 layout->pages[pageIx].widgetsPerPage=widgetIx;
00341 gitk_log2(" widgetsPerPages[%2d]=%2d",pageIx,layout->pages[pageIx].widgetsPerPage);
00342 pageIx++;
00343 }
00344 xmlXPathFreeObject(widgets_xpoptr);
00345 }
00346
00347 gitk_log("gitkr_dialog_generate_sequential_layout_build_page() end");
00348
00349 return(pageIx);
00350 }
00351
00357 void gitkr_dialog_generate_hierarchical_layout(GitkDialogPtr dialog,xmlNodePtr root) {
00358 GitkrTextLayoutPtr layout;
00359
00360
00361 g_assert(dialog!=NULL);
00362 g_assert(dialog->layout!=NULL);
00363
00364 gitk_log("gitkr_dialog_generate_hierarchical_layout() beg");
00365
00366 layout=(GitkrTextLayoutPtr)dialog->layout;
00369 }
00370
00375 void gitkr_dialog_output_layout(GitkDialogPtr dialog) {
00376 GitkrTextLayoutPtr layout;
00377 GitkrTextWidgetPtr page;
00378
00379 g_assert(dialog!=NULL);
00380 g_assert(dialog->layout!=NULL);
00381
00382 gitk_log("gitkr_layout_output() beg");
00383
00384 gitk_log2("terminal dimensions %d x %d",LINES,COLS);
00385
00386 layout=(GitkrTextLayoutPtr)dialog->layout;
00387 g_assert(layout->pages!=NULL);
00388 g_assert((&layout->pages[layout->currentPage])!=NULL);
00389 g_assert(layout->currentPage<layout->numberOfPages);
00390
00391 if((page=layout->pages[layout->currentPage].widgets)) {
00392 GitkrTextWidgetPtr widget;
00393 guint j;
00394 guint color_index=1,display_attrs;
00395
00396 gitk_log("starting output");
00397
00399 init_pair(color_index,layout->fg_color,layout->bg_color);
00400 display_attrs=COLOR_PAIR(color_index++)|(layout->dim_bold?A_BOLD:A_DIM);
00401 attrset(display_attrs);bkgdset(display_attrs);
00402
00403 erase();
00404
00405
00406 if((layout->title) || (layout->pages[layout->currentPage].title)) {
00407 gchar fmt[10];
00408 gchar *title;
00409 gboolean newtitle=FALSE;
00410
00411 if((layout->title) && (layout->pages[layout->currentPage].title)) {
00412 guint len=strlen(layout->title)+strlen(layout->pages[layout->currentPage].title)+4;
00413 title=g_new(gchar,len);newtitle=TRUE;
00414 snprintf(title,len,"%s / %s",layout->title,layout->pages[layout->currentPage].title);
00415 }
00416 else if(layout->title) {
00417 title=layout->title;
00418 }
00419 else {
00420 title=layout->pages[layout->currentPage].title;
00421 }
00422
00423 if(strlen(title)<=(COLS-(7+2))) {
00424 sprintf(fmt,"= %%-%ds",COLS-(7+2));
00425 }
00426 else {
00427 sprintf(fmt,"= %%-%ds...",COLS-(7+5));
00428 }
00429
00430
00431 attron(A_REVERSE);
00432 mvprintw(0,0,fmt,title);
00433 attroff(A_REVERSE);
00434
00435 if(newtitle) g_free(title);
00436 }
00437 attron(A_REVERSE);
00438 mvprintw(0,COLS-7, "[%2d/%2d]",(layout->currentPage+1),layout->numberOfPages);
00439 attroff(A_REVERSE);
00440
00441 gitk_log1("before widgets : %d",layout->pages[layout->currentPage].widgetsPerPage);
00442
00443
00444 for(j=0;j<layout->pages[layout->currentPage].widgetsPerPage;j++) {
00445 widget=&page[j];
00446 if(widget && widget->id && widget->output) {
00447 gitk_log2(" color=%d/%d" ,widget->fg_color,widget->bg_color);
00449 init_pair(color_index,widget->fg_color,widget->bg_color);
00450 widget->display_attrs=COLOR_PAIR(color_index++)|(widget->dim_bold?A_BOLD:A_DIM);
00451 widget->output(widget,GITK_LINE_OFFSET+j,(layout->currentWidget==j));
00452 }
00453 }
00454
00455
00456 if(layout->ctrl.widgetsPerPage==1) {
00457 GitkrTextWidgetPtr widget=&layout->ctrl.widgets[0];
00458
00459
00460
00461 gitk_log("displaying dialogwidgets");
00462 move(LINES-1,0);
00463 if(widget && widget->id && widget->output) {
00464 gitk_log2(" color=%d/%d" ,widget->fg_color,widget->bg_color);
00466 init_pair(color_index,widget->fg_color,widget->bg_color);
00467 widget->display_attrs=COLOR_PAIR(color_index++)|(widget->dim_bold?A_BOLD:A_DIM);
00468 widget->output(widget,LINES-1,(layout->currentWidget==GITKR_TEXT_NAVIGATION));
00469 }
00470 }
00471
00472 move(GITK_LINE_OFFSET+layout->currentWidget,0);
00473
00474 refresh();
00475 }
00476 }
00477
00482 void gitkr_dialog_free_layout(GitkDialogPtr dialog) {
00483 g_assert(dialog!=NULL);
00484
00485 gitk_log("gitkr_dialog_layout_free() beg");
00486
00487 if(dialog->layout) {
00488 GitkrTextLayoutPtr layout=(GitkrTextLayoutPtr)dialog->layout;
00489
00490 if(layout->pages) {
00491 GitkrTextWidgetPtr page;
00492 GitkrTextWidgetPtr widget;
00493 gint i;
00494
00495 for(i=0;i<layout->numberOfPages;i++) {
00496 if(layout->pages[i].widgets) {
00497 gint j;
00498 page=layout->pages[i].widgets;
00499 for(j=0;j<layout->maxWidgetsPerPage;j++) {
00500 widget=&page[j];
00501 xmlFree(widget->id);
00502 xmlFree(widget->label);
00503 }
00504 g_free(page);
00505 }
00506 }
00507 g_free(layout->pages);
00508 }
00509 g_free(layout->ctrl.widgets);
00510 xmlFree(layout->title);
00511 g_free(layout);
00512 dialog->layout=NULL;
00513 }
00514 }
00515
00521 GitkrTextWidgetPtr gitkr_layout_get_current_widget(GitkrTextLayoutPtr layout) {
00522 GitkrTextWidgetPtr page;
00523
00524 if((page=layout->pages[layout->currentPage].widgets)) {
00525 return(&page[layout->currentWidget]);
00526 }
00527 return(NULL);
00528 }
00529
00534 gint gitkr_layout_get_current_widget_line(GitkrTextLayoutPtr layout) {
00535 return(GITK_LINE_OFFSET+layout->currentWidget);
00536 }
00537