treeviewer.cxx

Go to the documentation of this file.
00001 //
00002 // Copyright 2011, Lowell Boggs Jr.
00003 //
00004 // This file or directory, containing source code for a computer program,
00005 // is Copyrighted by Lowell Boggs, Jr.  987 Regency Drive, Lewisville
00006 // TX (USA), 75067.  You may use, copy, modify, and distribute this
00007 // source file without charge or obligation so long as you agree to
00008 // the following:
00009 //
00010 //  1.  You must indemnify Lowell Boggs against any and all financial
00011 //      obligations caused by its use, misuse, function, or malfunction.
00012 //      Further, you acknowledge that there is no warranty of any kind,
00013 //      whatsoever.
00014 //
00015 //  2.  You agree not to attempt to patent any portion of this original
00016 //      work -- though you may attempt to patent your own extensions to
00017 //      it if you so choose.
00018 //
00019 //  3.  You keep this copyright notice with the file and all copies
00020 //      of the file and do not change it anyway except language translation.
00021 //
00022 // You are responsible for enforcing your own compliance with these
00023 // conditions and may not use this source file if you cannot agree to the
00024 // above terms and conditions.
00025 //
00026 // Warning:  not all files in this directory structure are covered by the
00027 // same copyright.  Some of them are part of the GNU source distribution
00028 // and you must obey the GPL copyright for those files.
00029 
00030 #include <cxxtls/treeviewer.h>
00031 #include <cxxtls/viewermanager.h>
00032 #include <algorithm>
00033 
00034 using namespace std;
00035 //===================================================================================
00036 //===================================================================================
00037 //===================================================================================
00038 
00039 namespace cxxtls
00040 {
00041 
00042 //-----------------------------------------------------------------------------------
00043 
00044 int 
00045 TreeViewerNode::
00046 height() const
00047 {
00048     int rv= 1;
00049 
00050     ChildrenList::const_iterator first = children_.begin(),
00051                                  last  = children_.end();
00052 
00053     while(first != last)
00054     {
00055         rv += (*first++).height();
00056     }
00057 
00058     return rv;
00059     
00060 }
00061 
00062 //-----------------------------------------------------------------------------------
00063 
00064 void 
00065 TreeViewerNode::
00066 close(bool childrenToo)
00067 {
00068     opened_ = false;
00069 
00070     if(childrenToo)
00071     {
00072         
00073         ChildrenList::iterator first = children_.begin(),
00074                                last  = children_.end();
00075         
00076         while(first != last)
00077         {
00078            (*first++).close(childrenToo);
00079         }
00080         
00081     }
00082 }
00083 
00084 //-----------------------------------------------------------------------------------
00085 
00086 void 
00087 TreeViewerNode::
00088 open(bool childrenToo)
00089 {
00090     opened_ = true;
00091 
00092     if(childrenToo)
00093     {
00094         ChildrenList::iterator first = children_.begin(),
00095                                last  = children_.end();
00096         
00097         while(first != last)
00098         {
00099            (*first++).open(childrenToo);
00100         }
00101     }
00102 
00103 }
00104 
00105 //-----------------------------------------------------------------------------------
00106 
00107 void 
00108 TreeViewerNode::
00109 flatten(FlatForm &output, int depth)
00110 {
00111     std::pair<TreeViewerNode*, int> me(this,depth);
00112 
00113     output.push_back(me);
00114 
00115     if(opened_)
00116     {
00117         ChildrenList::iterator first = children_.begin(),
00118                                last  = children_.end();
00119     
00120         while(first != last)
00121         {
00122            (*first++).flatten(output, depth+1);
00123         }
00124     }
00125 }
00126 
00127 //-----------------------------------------------------------------------------------
00128 
00129 Viewer* 
00130 TreeViewer::
00131 app(ViewerManager*vm, std::string &fullname)
00132 {
00133    TreeViewer *rv =new TreeViewer(vm);  
00134 
00135    rv->application_name_ = fullname;
00136 
00137    return rv;
00138 }
00139 
00140 //-----------------------------------------------------------------------------------
00141 void
00142 TreeViewer::
00143 operator() ( CursorWindow::viewport * vp,
00144              int                      cmd
00145            )
00146 {
00147     // paint the visible parts of the flattened form of the tree in the
00148     // specified viewport.
00149 
00150     if(cmd == CursorWindow::viewport::repaint_handler::activate)
00151       active_ = true;
00152     else
00153     if(cmd == CursorWindow::viewport::repaint_handler::deactivate)
00154     {
00155       active_ = false;
00156     }
00157 
00158     if(flattenedNodes_.empty())
00159     {
00160        // first time through, initialize the display variables.
00161 
00162        nodes_.flatten(flattenedNodes_);
00163 
00164     }
00165 
00166     paintViewport(vp);
00167 
00168     positionCursor(vp);
00169 
00170 }
00171 
00172 //-----------------------------------------------------------------------------------
00173 void
00174 TreeViewer::
00175 acknowledgeViewport( CursorWindow::viewport * vp)
00176 {
00177     // adjust display variables to the available space
00178 
00179     CursorWindow::row_col size = vp->size();
00180 
00181     enum constants
00182     {
00183         TITLE_HEIGHT=1,   // row 0 is the title row
00184     };
00185 
00186     // compute the first node on which to display tree nodes
00187 
00188     treeStartRow_ = TITLE_HEIGHT;
00189 
00190     // compute the number of rows available for tree node to be displayed on
00191 
00192     displayRows_ = size.row_ - TITLE_HEIGHT;   
00193 
00194     // compute the number of nodes to actually display, given the 
00195     // space avaiable and the total number of nodes.
00196 
00197     displayNodes_= displayRows_;    // adjusted below
00198 
00199     int nodeCount = flattenedNodes_.size();
00200 
00201     if(nodeCount < displayNodes_)
00202     {
00203         displayNodes_ = nodeCount;
00204     }
00205 
00206     if(topNode_ + displayNodes_ >= nodeCount)
00207     {
00208       if(topNode_ >= nodeCount)
00209         topNode_ = nodeCount - 1;
00210 
00211         displayNodes_ = nodeCount - topNode_;
00212     }
00213 
00214     if(cursorNode_ < topNode_)   // first time through, topNode_ will be 0
00215     {
00216         cursorNode_ = topNode_;
00217     }
00218     else
00219     if(cursorNode_ >= topNode_ + displayNodes_)
00220     {
00221         // the cursor is off the bottom of the screen
00222 
00223         if(cursorNode_ >= nodeCount)
00224         {
00225           // how did this happen?
00226 
00227           if(nodeCount)
00228           {
00229              cursorNode_ = nodeCount - 1 ;
00230           }
00231           else
00232           {
00233              cursorNode_ = 0; // we have no nodes, 0 is as good as anything
00234           }
00235         }
00236 
00237         topNode_ = cursorNode_ - displayNodes_ / 2;
00238 
00239         if(topNode_ < 0)
00240         {
00241            topNode_ = 0;
00242         }
00243 
00244     }
00245 
00246     // At this point, all the display helper variables should be set
00247     // correctly.  That is the goal of this function.
00248     //
00249     // If the displayHeight_ is zero, then we shouldn't be painting anything.
00250 
00251 }
00252 
00253 //-----------------------------------------------------------------------------------
00254 void
00255 TreeViewer::
00256 paintViewport( CursorWindow::viewport * vp)
00257 {
00258     acknowledgeViewport(vp);
00259     
00260     paintTitle(vp);
00261     
00262     for(int i = 0; i < displayRows_; ++i)
00263     {
00264         // populate each row of the display area
00265     
00266         vp->set_curpos(i + treeStartRow_, 0);
00267 
00268         // vp->set_text_attribute(manager()->normal_att);
00269 
00270         vp->set_text_attribute(manager()->inactive_mark_att);
00271 
00272     
00273         if( i < displayNodes_)
00274         {
00275            // display an node from the flattened node list
00276 
00277            bool isCursor = false;
00278 
00279            if( i == cursorNode_ - topNode_)
00280            {
00281               isCursor = true;
00282 
00283               vp->set_text_attribute(active_ ? manager()->highlighted_att
00284                                              : manager()->normal_att
00285                                     );
00286            }
00287 
00288            paintNodeText(vp, topNode_+i, isCursor);
00289         
00290         }
00291         else
00292         {
00293             if(vp->origin().col_)
00294             {
00295                // if we are not exactly left aligned, eat 1 character as a border
00296         
00297                vp->write('|');
00298         
00299             }
00300 
00301             vp->fill_to_eol();
00302         }
00303     
00304     }
00305 
00306 
00307 }
00308 
00309 //-----------------------------------------------------------------------------------
00310 void
00311 TreeViewer::
00312 paintNodeText(CursorWindow::viewport * vp, int nodeNumber, bool isCursor)
00313 {
00314 
00315     if(vp->origin().col_)
00316     {
00317        // if we are not exactly left aligned, eat 1 character as a border
00318 
00319        vp->write('|');
00320 
00321     }
00322     
00323     int nodeCount = flattenedNodes_.size();
00324 
00325     if(nodeNumber < nodeCount)
00326     { 
00327         TreeViewerNode * node = flattenedNodes_[nodeNumber].first;
00328         int              depth= flattenedNodes_[nodeNumber].second;
00329         
00330         std::string const &name = node->name();
00331         
00332         vp->write(' ', depth * 4);  // 4 is length of "[-] "
00333 
00334         if(node->hasChildren())
00335         {
00336             if(node->opened())
00337                 vp->write("[-] ");
00338             else
00339                 vp->write("[+] ");
00340         }
00341         else
00342         {
00343             vp->write("[ ] ");
00344         }
00345 
00346         int savedTextAttribute = vp->text_attribute();
00347 
00348 
00349         if(node->highlighted() )
00350         {
00351           if(isCursor)
00352               vp->set_text_attribute( CursorWindow::active_mark_att );
00353           else
00354               vp->set_text_attribute( CursorWindow::normal_att );
00355         }
00356 
00357 
00358         *vp << name;
00359 
00360         vp->set_text_attribute(savedTextAttribute);
00361 
00362     }
00363 
00364     vp->fill_to_eol();
00365 
00366 
00367 }
00368 
00369 
00370 //-----------------------------------------------------------------------------------
00371 void
00372 TreeViewer::
00373 paintTitle( CursorWindow::viewport * vp)
00374 {
00375     vp->set_curpos(0,0);
00376     vp->set_text_attribute(active_ ?  manager()->active_title_att
00377                                    :  manager()->inactive_title_att
00378                           );
00379                           
00380     *vp << application_name();
00381   
00382     vp->fill_to_eol();
00383 
00384 }
00385 
00386 
00387 //-----------------------------------------------------------------------------------
00388 
00389 bool 
00390 TreeViewer::
00391 handle_event( CursorWindow::input_event const * e,
00392               CursorWindow::viewport          * vp
00393             )
00394 {
00395 
00396       if(    e->type_ == CursorWindow::input_event::DataKey
00397          ||  e->type_ == CursorWindow::input_event::FunctionKey 
00398         )
00399       {
00400 
00401         // first, check to see if this is part 2 of a two part
00402         // command key sequence.  Part 1 is always ^X,
00403 
00404         if(keyKludge_)
00405         {
00406             keyKludge_ = false;
00407 
00408             switch(e->value_)
00409             {
00410                 case 0x03: // ^X^C quit editing
00411                    return true;
00412 
00413                 case 0x0b: // ^X^K quit editing
00414 
00415                    return true;  // when out of sessions, quit
00416 
00417                 default: vp->beep(); break;
00418             }
00419 
00420             return false;
00421         }
00422 
00423         // ok, this is not part two a two part key sequence
00424 
00425 
00426          switch(e->value_)
00427          {
00428              case 0x18:  // ^X
00429              {
00430                 keyKludge_ = true;
00431              }
00432              return false;
00433 
00434              case  'q': return true;
00435              case  'Q': return true;
00436              case 0x1b: return true; // escape key
00437              
00438 
00439              case  '+':                     toggle(vp);            positionCursor(vp); return false; 
00440              case  '=':                     toggle(vp);            positionCursor(vp); return false; 
00441              case  'o':                     toggleAll(vp);         positionCursor(vp); return false; 
00442              case  'O':                     toggleAll(vp);         positionCursor(vp); return false; 
00443              case  '<':                     findMyParent(vp);      positionCursor(vp); return false;
00444              case  '>':                     findNextParent(vp);    positionCursor(vp); return false;
00445 
00446 
00447              case CursorWindow::key_up:     moveUp(vp);            positionCursor(vp); return false;
00448              case CursorWindow::key_down:   moveDown(vp);          positionCursor(vp); return false;
00449              case CursorWindow::key_home:   pageTop(vp);           positionCursor(vp); return false;
00450              case CursorWindow::key_next:   pageDown(vp);          positionCursor(vp); return false;
00451              case CursorWindow::key_prior:  pageUp(vp);            positionCursor(vp); return false;
00452              case CursorWindow::key_end:    pageBottom(vp);        positionCursor(vp); return false;
00453              case 0x02:                     pageBottom(vp);        positionCursor(vp); return false; // ^B
00454              case 0x14:                     pageTop(vp);           positionCursor(vp); return false; // ^T
00455              case 0x13:                     findFirst(vp);         positionCursor(vp); return false; // ^S
00456              case 0x0e:                     findNext(vp);          positionCursor(vp); return false; // ^N
00457 
00458              default:
00459 
00460 
00461 
00462 
00463                if(!flattenedNodes_.empty() && flattenedNodes_[cursorNode_].first->info())
00464                {
00465                   // the current node does have user defined data -- let it handle the command key
00466 
00467                   positionCursor(vp);
00468 
00469                   return (*flattenedNodes_[cursorNode_].first->info())(manager(), vp, e->value_, rootDir_);
00470 
00471                }
00472                else
00473                if(   (e->value_ == '\r' || e->value_ == '\n') 
00474                   && !flattenedNodes_.empty() 
00475                  )
00476                {
00477                   // do nothing
00478                }
00479                else
00480                {
00481                   vp->beep();
00482                }
00483 
00484          }
00485       }
00486       else
00487       if(e->type_ == CursorWindow::input_event::ForceExitKey)
00488       {
00489           positionCursor(vp);
00490 
00491           return true; // don't ignore forced exits!
00492       }
00493 
00494    positionCursor(vp);
00495 
00496    return false; // in general, events do not terminate the viewer
00497 }
00498 //-----------------------------------------------------------------------------------
00499 
00500 void 
00501 TreeViewer::
00502 moveUp(CursorWindow::viewport * vp)
00503 {
00504    if(cursorNode_ == 0)
00505       return;
00506 
00507    if(cursorNode_ <= topNode_)
00508    {
00509       if(topNode_ == 0)
00510       {
00511         cursorNode_ = topNode_; // just to be sure
00512         return;
00513       }
00514 
00515       --topNode_;
00516       cursorNode_ = topNode_;
00517 
00518       if(topNode_ < 0)
00519         {
00520           topNode_ = 0;
00521           cursorNode_ = 0;
00522         }
00523 
00524       paintViewport(vp);
00525       return;
00526    }
00527 
00528    // if we get here, cursorNode_ > topNode_
00529 
00530    displayCurrentLine(vp,false);  // remove cursor
00531 
00532    --cursorNode_;
00533 
00534    displayCurrentLine(vp,true);     // display cursor in new position.
00535 
00536 
00537 }
00538 
00539 //-----------------------------------------------------------------------------------
00540 
00541 void 
00542 TreeViewer::
00543 toggle(CursorWindow::viewport * vp)
00544 {
00545 
00546     if(flattenedNodes_[cursorNode_].first->opened())
00547         close(vp);
00548     else
00549         open(vp);
00550 
00551 }
00552 
00553 //-----------------------------------------------------------------------------------
00554 
00555 void 
00556 TreeViewer::
00557 toggleAll(CursorWindow::viewport * vp)
00558 {
00559    TreeViewerNode * node= flattenedNodes_[cursorNode_].first;
00560 
00561 
00562     if(node->opened())
00563     {
00564        node->close();
00565     }
00566     else
00567     {
00568       node->open();
00569     }
00570 
00571    flattenedNodes_.clear();
00572    nodes_.flatten(flattenedNodes_);
00573 
00574    paintViewport(vp);
00575 
00576 
00577 
00578 }
00579 
00580 //-----------------------------------------------------------------------------------
00581 
00582 void 
00583 TreeViewer::
00584 close(CursorWindow::viewport * vp)
00585 {
00586    TreeViewerNode * node= flattenedNodes_[cursorNode_].first;
00587 
00588    if(node->opened())
00589    {
00590       node->close();  // close children trees as well
00591    }
00592 
00593    flattenedNodes_.clear();
00594    nodes_.flatten(flattenedNodes_);
00595 
00596    paintViewport(vp);
00597 
00598 
00599 }
00600 
00601 //-----------------------------------------------------------------------------------
00602 
00603 void 
00604 TreeViewer::
00605 open(CursorWindow::viewport * vp)
00606 {
00607    TreeViewerNode * node= flattenedNodes_[cursorNode_].first;
00608 
00609 
00610    if(!node->opened())
00611    {
00612       node->open(false);  // open doesn't open entire tree -- only
00613                           // first level deep
00614    }
00615 
00616    flattenedNodes_.clear();
00617 
00618    nodes_.flatten(flattenedNodes_);
00619 
00620 
00621    paintViewport(vp);
00622 
00623 
00624 }
00625 
00626 //-----------------------------------------------------------------------------------
00627 
00628 void 
00629 TreeViewer::
00630 displayCurrentLine(CursorWindow::viewport * vp, bool highlighted)
00631 {
00632    int offsetFromTopNode = cursorNode_ - topNode_;
00633 
00634    vp->set_curpos(offsetFromTopNode + treeStartRow_, 0);
00635 
00636    if(highlighted)
00637    {
00638        vp->set_text_attribute(active_ ? manager()->highlighted_att
00639                                       : manager()->normal_att
00640                              );
00641    }
00642    else
00643        vp->set_text_attribute(manager()->inactive_mark_att);
00644 
00645    paintNodeText(vp, cursorNode_);
00646 
00647 }
00648 
00649 
00650 //-----------------------------------------------------------------------------------
00651 void 
00652 TreeViewer::
00653 moveDown(CursorWindow::viewport * vp)
00654 {
00655    int nodeCount = flattenedNodes_.size();
00656 
00657    if(cursorNode_ > nodeCount-1)
00658        return;
00659 
00660    if(cursorNode_ == nodeCount-1)
00661    {
00662        // cursor sits on last valid line of the display
00663        // scroll the screen up
00664 
00665        if(cursorNode_ == topNode_)
00666           return; // can't scroll past top
00667        
00668        ++topNode_;
00669        --displayNodes_;
00670 
00671        if(displayNodes_ > displayRows_)
00672           displayNodes_ = displayRows_;
00673 
00674        paintViewport(vp);
00675        return;
00676    }
00677 
00678    int offset = cursorNode_ - topNode_;
00679 
00680    if(offset == displayNodes_-1)
00681    {
00682       // we are sitting on the last line on the screen in the middle of
00683       // the list -- scroll the page down
00684 
00685       ++topNode_;
00686       ++cursorNode_;
00687       paintViewport(vp);
00688       return;
00689 
00690    }
00691 
00692    // we are in the middle of the page in the middle of the list with the
00693    // end of the list way off the bottom
00694 
00695    displayCurrentLine(vp, false);
00696    ++cursorNode_;
00697    displayCurrentLine(vp, true);
00698 
00699 }
00700 
00701 
00702 //-----------------------------------------------------------------------------------
00703 void 
00704 TreeViewer::
00705 pageTop(CursorWindow::viewport * vp)
00706 {
00707    topNode_ = 0;
00708    cursorNode_ = 0;
00709    paintViewport(vp);
00710 }
00711 
00712 //-----------------------------------------------------------------------------------
00713 void 
00714 TreeViewer::
00715 pageBottom(CursorWindow::viewport * vp)
00716 {
00717     topNode_ = flattenedNodes_.size() - 1;
00718 
00719     if(topNode_ < 0)
00720     {
00721        topNode_ = 0;
00722        cursorNode_ = 0;
00723        return;
00724     }
00725 
00726     // show only the last line of the list
00727 
00728     displayNodes_ = 1;
00729     cursorNode_ = topNode_;
00730 
00731     paintViewport(vp);
00732 
00733 }
00734 
00735 //-----------------------------------------------------------------------------------
00736 void 
00737 TreeViewer::
00738 pageDown(CursorWindow::viewport * vp)
00739 {
00740     topNode_     += displayRows_;
00741     cursorNode_  += displayRows_;
00742 
00743     if(topNode_ >= int(flattenedNodes_.size())-1)
00744     {
00745        topNode_ = flattenedNodes_.size()-1;
00746     }
00747 
00748     if(cursorNode_ >= int(flattenedNodes_.size()) - 1)
00749     {
00750       cursorNode_ = flattenedNodes_.size()-1;
00751     }
00752 
00753 
00754     paintViewport(vp);
00755 
00756 }
00757 
00758 //-----------------------------------------------------------------------------------
00759 void 
00760 TreeViewer::
00761 pageUp(CursorWindow::viewport * vp)
00762 {
00763 
00764     topNode_     -= displayRows_;
00765     cursorNode_  -= displayRows_;
00766 
00767     if(topNode_ < 0)
00768     {
00769         topNode_    = 0;
00770         cursorNode_ = 0;
00771     }
00772 
00773 
00774     paintViewport(vp);
00775 
00776 }
00777 
00778 //-----------------------------------------------------------------------------------
00779 void 
00780 TreeViewer::
00781 findFirst(CursorWindow::viewport * vp)
00782 {
00783   CursorWindow::Dialog dialog("Find string");
00784 
00785 
00786   dialog += new CursorWindow::Dialog::String("mode",
00787                                              "(R)egexp, or (S)tring",
00788                                              (is_regex_ ? "R" : "S"),
00789                                              2
00790                                             );
00791 
00792   dialog += new CursorWindow::Dialog::String("text",
00793                                              "Search for",
00794                                              search_text_,
00795                                              40
00796                                             );
00797 
00798   dialog += new CursorWindow::Dialog::Ok("ok","");
00799 
00800   dialog.set_first_input_field("text");
00801 
00802 
00803   if( dialog.popup(vp->window()) )
00804     return;
00805 
00806 
00807   std::string match_words = dialog.element_value("mode");
00808 
00809   is_regex_    = false;
00810 
00811   if(   match_words.size() 
00812      && (match_words[0] == 'r' || match_words[0] == 'R')
00813     )
00814   {
00815     is_regex_ =  true;
00816   }
00817 
00818   std::string search_text = dialog.element_value("text");
00819 
00820   if(search_text.size() == 0)
00821     return;
00822 
00823   search_text_ = search_text;
00824 
00825   int    saved_line   = cursorNode_;
00826 
00827   displayCurrentLine(vp,false);  // remove cursor
00828 
00829 
00830   if(!findNextHelper(vp, false))
00831   {
00832     cursorNode_ = saved_line;
00833     vp->beep();
00834   }
00835   else
00836   {
00837     make_line_visible(vp);
00838   }
00839 
00840   displayCurrentLine(vp,true);  
00841   
00842 
00843 
00844 }
00845 
00846 //-----------------------------------------------------------------------------------
00847 void 
00848 TreeViewer::
00849 findNext(CursorWindow::viewport * vp)
00850 {
00851   int    saved_line   = cursorNode_;
00852 
00853   displayCurrentLine(vp,false);  // remove cursor
00854 
00855   if(!findNextHelper(vp, true))
00856   {
00857     cursorNode_ = saved_line;
00858     vp->beep();
00859   }
00860   else
00861   {
00862     make_line_visible(vp);
00863   }
00864 
00865   displayCurrentLine(vp,true); // restore cursor
00866   
00867 
00868 }
00869 
00870 namespace
00871 {
00872   struct CharCompare
00873   {
00874 
00875     bool operator() (char a, char b) const
00876     {
00877         {
00878           if( isupper(a) )
00879             a = tolower(a);
00880         
00881           if( isupper(b) )
00882             b = tolower(b);
00883         
00884           return a == b;
00885         }
00886         
00887         return a == b;
00888     }
00889 
00890 
00891   };
00892 
00893 }
00894 
00895 
00896 
00897 bool
00898 TreeViewer::
00899 findNextHelper(CursorWindow::viewport* vp, bool skipCurrentLine)
00901 {
00902   // the caller must save/restore cursorNode_ as needed.
00903 
00904 
00905   if(is_regex_)
00906   {
00907     SimpleRegex *p = &regexp_;
00908 
00909     p->SimpleRegex::~SimpleRegex();  // destruct current regex
00910 
00911     new(&regexp_) SimpleRegex(search_text_,  "i" );
00912 
00913 
00914   }
00915 
00916 
00917   if(skipCurrentLine)
00918   {
00919       cursorNode_++;
00920   }
00921 
00922 
00923   while(cursorNode_ < int(flattenedNodes_.size()) )
00924   { // search all lines till eof
00925 
00926     std::string curline = flattenedNodes_[cursorNode_].first->name();
00927 
00928     size_t memberStart;
00929 
00930     if(curline.size() > (memberStart = curline.find_last_of(':')) )
00931     {
00932         ++memberStart;
00933 
00934         if(memberStart < curline.size())
00935         {
00936             curline = curline.substr( memberStart, curline.size() - memberStart );
00937         }
00938     }
00939 
00940     {
00941 
00942       std::string::iterator where;
00943 
00944 
00945       if(is_regex_)
00946       {
00947 
00948         int count = regexp_(curline, 0, curline.size());
00949         
00950         if(count > 0)
00951         {
00952           where = (curline.begin() + 0 + regexp_.matches()[0].offset);
00953         }
00954         else
00955           where = curline.end();
00956         
00957       }
00958       else
00959       {
00960         where = std::search(curline.begin() + 0,
00961                                                   curline.end(),
00962                                                   search_text_.begin(),
00963                                                   search_text_.end(),
00964                                                   CharCompare()
00965                                                  );
00966       }
00967                                         
00968       if(where != curline.end())
00969       {
00970            return true;
00971       }
00972     }
00973 
00974     ++cursorNode_;
00975 
00976   }
00977 
00978 
00979   return false;
00980 
00981 }
00982 
00983 
00984 
00985 //-----------------------------------------------------------------------------------
00986 
00987 void
00988 TreeViewer::make_line_visible(CursorWindow::viewport *vp)
00989 {
00990     if(cursorNode_ - topNode_ >= displayNodes_)
00991     {
00992         // cursor is not visible.
00993 
00994         topNode_ = cursorNode_ - displayRows_ / 2;
00995 
00996         if(topNode_ < 0)
00997           topNode_ = 0;
00998 
00999         paintViewport(vp);
01000     }
01001 }
01002 
01003 
01004 //-----------------------------------------------------------------------------------
01005 void 
01006 TreeViewer::
01007 findMyParent(CursorWindow::viewport * vp)
01008 {
01009 
01010    int myDepth = flattenedNodes_[cursorNode_].second;
01011 
01012    while(    cursorNode_ > 0
01013          &&  flattenedNodes_[cursorNode_].second  >= myDepth
01014         )
01015    {
01016       --cursorNode_;
01017    }
01018 
01019    if(cursorNode_ < topNode_)
01020    {
01021       topNode_ = cursorNode_;
01022    }
01023 
01024    paintViewport(vp);
01025 
01026 
01027 
01028 }
01029 
01030 //-----------------------------------------------------------------------------------
01031 void 
01032 TreeViewer::
01033 findNextParent(CursorWindow::viewport * vp)
01034 {
01035    int myDepth = flattenedNodes_[cursorNode_].second;
01036 
01037    int maxNode = flattenedNodes_.size();
01038 
01039    while(    cursorNode_ < maxNode
01040          &&  flattenedNodes_[cursorNode_].second  >= myDepth
01041         )
01042    {
01043       ++cursorNode_;
01044    }
01045 
01046    if(cursorNode_ >= maxNode)
01047    {
01048      cursorNode_ = maxNode-1;
01049    }
01050 
01051    if(cursorNode_ >= topNode_ + displayNodes_)
01052    {
01053       topNode_ = cursorNode_;
01054    }
01055 
01056    paintViewport(vp);
01057 
01058 }
01059 
01060 //-----------------------------------------------------------------------------------
01061 
01062 std::string const &
01063 TreeViewer::
01064 application_name() const
01065 {
01066     return application_name_;
01067 }
01068 
01069 //-----------------------------------------------------------------------------------
01070 
01071 
01072 TreeViewer::~TreeViewer()
01073 {
01074 }
01075 //-----------------------------------------------------------------------------------
01076 
01077 std::string TreeViewer::description() const 
01078 {
01079    return "TreeViewer";
01080 }
01081 
01082 //-----------------------------------------------------------------------------------
01083 void
01084 TreeViewer::helpHeader(list<string> &help_text)
01085 {
01086   help_text.push_back("TreeViewer help");
01087 }
01088 
01089 
01090 //-----------------------------------------------------------------------------------
01091 
01092 void
01093 TreeViewer::help()
01094 {
01095   list<string> help_text;
01096 
01097   helpHeader(help_text); // derived class supply their own title and other info
01098 
01099   help_text.push_back("");
01100   help_text.push_back("");
01101   help_text.push_back("Command keys:");
01102   help_text.push_back("  enter     -- open the file defining the symbol under the cursor.");
01103   help_text.push_back("  +         -- open or close the current item (if it has children).");
01104   help_text.push_back("  o         -- completely open or close the entire current item's children  ");
01105   help_text.push_back("  <         -- move up to the current row's parent");
01106   help_text.push_back("  >         -- move down to the next parent higher than the current row");
01107   help_text.push_back("  ^T        -- move to the top of the tree");
01108   help_text.push_back("  ^B        -- move to the bottom of the tree");
01109   help_text.push_back("  ^S        -- search for a string string the tree");
01110   help_text.push_back("  ^N        -- search next");
01111 
01112 
01113   manager()->help_helper(help_text);
01114 }
01115 
01116 TreeViewerNodeInfo::
01117 ~TreeViewerNodeInfo()
01118 {
01119 }
01120 
01121 
01122 void 
01123 TreeViewer::
01124 positionCursor(CursorWindow::viewport *vp)
01125 {
01126     int col=0;
01127 
01128     if(cursorNode_ < int(flattenedNodes_.size()))
01129     {
01130        col = 4 * flattenedNodes_[cursorNode_].second;
01131 
01132        if(vp->origin().col_ != 0)
01133           ++col;
01134     }
01135 
01136     ++col;  // Step over one to account for the open bracket.  All rows
01137             // have something that looks like this one them:
01138             //
01139             //    [+] Name
01140             //     ^
01141             //    col
01142 
01143     vp->set_curpos((cursorNode_ - topNode_) + treeStartRow_, col);
01144 }
01145 
01146 }; // namespace cxxtls
01147 
Generated on Wed Feb 29 22:50:05 2012 for CXXUtilities by  doxygen 1.6.3