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 
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);// LINES, COLS are terminal lines and columns
00033   g_assert(dialog!=NULL);
00034 
00035   //-- free old layout
00036   gitkr_dialog_free_layout(dialog);
00037 
00038   //-- and generate a new empty one
00039   layout=gitkr_dialog_new_layout(dialog);
00040   dialog->layout=(GitkLayoutPtr)layout;
00041   
00057   //-- get root node (where all widgetgroups and widgets are below
00058   //if((node=gitk_xpath_get_node(dialog,"/"GITK_NS_PREFIX":giml/"GITK_NS_PREFIX":dialog/"GITK_NS_PREFIX":widgetgroup",NULL))) {
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     //node=xmlXPathNodeSetItem(ns,0);
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     // debug
00075     //xmlSaveFormatFile("/tmp/gitk.xml",gitk_dialog_get_dst(dialog),TRUE);
00076     // debug
00077     gitk_log("starting recursion ...");
00079     gitkr_dialog_generate_sequential_layout(dialog,node);
00080     //gitkr_dialog_generate_hierarchical_layout(dialog,node);
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   //-- set default layout parameter
00094   layout->focus=GITK_FOCUS_TYPE_CTRL;
00095   layout->currentPage=0;
00096   layout->currentWidget=0;
00097   layout->maxWidgetsPerPage=LINES-GITK_LINE_OFFSET; /* title line + one spacer line + one spacer line + footer line */
00098   layout->pages=NULL;
00099   layout->title=gitkr_cxpath_get_string(dialog,xpath_get_dialog_name,NULL);
00100   //-- allocate memory for the ctrl widgets
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         //-- allocate  and attach type specific widget data
00120         //gitkr_widget_optionchoice_new(widget,"__ctrl",dialog,NULL);
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     //-- get number of pages (widgetgroups which are not empty)
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       //-- count pages
00163       layout->numberOfPages=gitkr_dialog_generate_sequential_layout_count_pages(dialog,root,pages,xpath_get_widgets);
00164       //-- allocate memory for the widgets
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       //-- build pages
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   //-- first check root widgetgroup ...
00210   if((widgets_xpoptr=gitk_xpath_type_filter(
00211       gitk_cxpath_get_object(dialog,xpath_get_widgets,root),
00212       XPATH_NODESET))) {
00213     //-- if root page is not empty, add at least one page 
00214     if(xmlXPathNodeSetGetLength((xmlNodeSetPtr)widgets_xpoptr->nodesetval)) numberOfPages++;
00215     //-- if number of widgets is larger than layout->maxWidgetsPerPages correct numberOfPages
00216     numberOfPages+=xmlXPathNodeSetGetLength((xmlNodeSetPtr)widgets_xpoptr->nodesetval)/layout->maxWidgetsPerPage;
00217     gitk_log1("  numberOfPages[r] %d",numberOfPages);
00218     xmlXPathFreeObject(widgets_xpoptr);
00219   }
00220   //-- now check for each widgetgroup ...
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       //-- if number of widgets is larger than layout->maxWidgetsPerPages correct numberOfPages
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   //-- get widgetgroup title
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     //-- do not add empty pages
00271     if(widgets_len) {
00272       //-- now add widgets
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         //-- add new widget
00279         if(!xmlNodeIsText(node)) {
00280           //-- check if this widget has the focus
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           //-- get widget data
00290           widget=&layout->pages[pageIx].widgets[widgetIx];
00291           //-- allocate  and attach type specific widget data
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         //-- if page is full do next page
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   //xmlXPathCompExprPtr xpath_get_pages;
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   // LINES, COLS are terminal lines and columns
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     //-- clear the screen
00403     erase();/*clearok(stdscr,TRUE);*/
00404   
00405     //-- display the title line
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       // @todo see http://sourceforge.net/tracker/index.php?func=detail&aid=955749&group_id=29795&atid=397305
00430       //gitk_log2("fmt=\"%s\", title=\"%s\"",fmt,title);
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     //-- display the widgets
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     //-- display the navigation line
00456     if(layout->ctrl.widgetsPerPage==1) {
00457       GitkrTextWidgetPtr widget=&layout->ctrl.widgets[0];
00458       /* order is ["help"], "okay","cancel" */
00459       /* order is ["help"], "apply","okay","cancel" */
00460       /* order is ["help"], "try","revert","okay","cancel" */
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     //-- now set the cursor to the active widget
00472     move(GITK_LINE_OFFSET+layout->currentWidget,0);
00473     //-- now refresh curses screen
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 

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