home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / DCLAP 4j / DClap / DTableView.cpp < prev    next >
Encoding:
Text File  |  1995-12-17  |  28.1 KB  |  1,210 lines  |  [TEXT/R*ch]

  1. // DTableView.cp
  2. // d.g.gilbert
  3.  
  4. // this class is used a lot for various display/user interaction arrays of items
  5. // still needs work for multiple selections, run arrays for height/width?
  6. // 
  7.  
  8. #include "DTableView.h"
  9. #include <DPanel.h>
  10. #include <DUtil.h>
  11. #include <Dvibrant.h>
  12. #include <DTracker.h>
  13. #include <ncbi.h>
  14. #include <dgg.h>
  15.  
  16.  
  17.  
  18.  
  19. DTabSelector::DTabSelector( DTableView* itsTable)
  20. {
  21.     ITabSelector( itsTable); // in constructor !?
  22. }
  23.  
  24. DTabSelector::~DTabSelector() 
  25. {
  26. #if 0
  27.     fOldSelection= Nlm_DestroyRgn( fOldSelection);
  28.     fNewSelection= Nlm_DestroyRgn( fNewSelection);
  29. #endif
  30. }
  31.  
  32. void DTabSelector::ITabSelector( DTableView* itsTable)
  33. {
  34.     ITracker( cTabSelCmd, itsTable, "selection", true, false, itsTable); 
  35.     // ITracker() calls Reset()
  36. }
  37.  
  38.  
  39. void DTabSelector::Reset()
  40. {
  41.     DTracker::Reset();
  42.     fDoExtend= gKeys->shift();
  43. #if 1
  44.     fOldSelection= ((DTableView*)fView)->GetSelRect();
  45.     fNewSelection= fOldSelection;
  46. #else
  47.     fOldSelection= Nlm_NewRgn(); 
  48.     fNewSelection= Nlm_NewRgn();  
  49.     CopyRgn( ((DTableView*)fView)->fSelections, fOldSelection);
  50.     CopyRgn( fOldSelection, fNewSelection);
  51. #endif
  52. }
  53.  
  54.  
  55. void DTabSelector::DoItWork()  
  56. {
  57.     if (fMovedOnce || fDoExtend) {
  58.         ((DTableView*)fView)->SelectCells( fNewSelection, 
  59.                 fDoExtend, DTableView::kHighlight, DTableView::kSelect);
  60.         }
  61. }
  62.  
  63. void DTabSelector::UndoWork()  
  64. {
  65. #if 1
  66.     Nlm_RecT tmpRect= fNewSelection;
  67.     fNewSelection= fOldSelection;
  68.     fOldSelection= tmpRect;
  69. #else
  70.     Nlm_RgN tmpRgn= fNewSelection;
  71.     fNewSelection= fOldSelection;
  72.     fOldSelection= tmpRgn;
  73. #endif
  74.     DoItWork();
  75. }
  76.  
  77.  
  78. void DTabSelector::DoIt()  
  79. {
  80.     DCommand::DoIt();
  81.     
  82.     Nlm_PoinT pt1, pt2;
  83.     Nlm_RecT    selr;
  84.         // +1 is messy fix to stop left/top -1 creap !
  85.     pt1.x= MIN( fAnchorPoint.x+1, fNextPoint.x);
  86.     pt2.x= MAX( fAnchorPoint.x-1, fNextPoint.x);
  87.     pt1.y= MIN( fAnchorPoint.y+1, fNextPoint.y);
  88.     pt2.y= MAX( fAnchorPoint.y-1, fNextPoint.y);
  89.  
  90.     ((DTableView*)fView)->PointToCell( pt1, selr.top, selr.left);
  91.     ((DTableView*)fView)->PointToCell( pt2, selr.bottom, selr.right);
  92.     selr.bottom++;
  93.     selr.right++;
  94.     fNewSelection= selr;
  95.     if (!fDoExtend) fDoExtend= gKeys->shift(); // give'em another chance to shift
  96.     
  97.     DoItWork();
  98. }
  99.  
  100. void DTabSelector::Undo()  
  101. {
  102.     DCommand::Undo();
  103.     Boolean saveext= fDoExtend;
  104.     fDoExtend= false;
  105.     UndoWork();
  106.     fDoExtend= saveext;
  107. }
  108.  
  109. void DTabSelector::Redo()  
  110. {
  111.     DCommand::Redo();
  112.     UndoWork();
  113. }
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121. //class DTableView : public DPanel
  122.  
  123.  
  124. DTableView::DTableView(long id, DView* itsSuperior, short pixwidth, short pixheight, 
  125.                                                 short nrows, short ncols, short itemwidth, short itemheight,
  126.                                                 Boolean hasVscroll, Boolean hasHscroll):
  127.         DAutoPanel( id, itsSuperior, pixwidth, pixheight, hasVscroll, hasHscroll),
  128.         fItemWidth(itemwidth), fItemHeight(itemheight),
  129.         fTop(0), fLeft(0), fColsDrawn(0), fMaxRows(nrows), fMaxCols(ncols), 
  130.         fSelectedRow(kNoSelection), fSelectedCol(kNoSelection),
  131.         fCanSelectRow(true), fCanSelectCol(false),fIsPrinting(false),
  132.         fWidths(NULL), fHeights(NULL),
  133.         fFont(Nlm_programFont)
  134. {
  135.     Nlm_BaR sb;
  136.     sb = Nlm_GetSlateVScrollBar((Nlm_SlatE) GetNlmObject());
  137.   fHasVbar= (sb != NULL);
  138.   sb = Nlm_GetSlateHScrollBar((Nlm_SlatE) GetNlmObject());
  139.   fHasHbar= (sb != NULL);
  140.   FindLocation();
  141.   SetTableSize( fMaxRows, fMaxCols);
  142.     SetEmptySelection(false); 
  143.     
  144.     fTabSelector= new DTabSelector( this);
  145.     //fTabSelector->ITabSelector( this);
  146.     fCurrentTracker= fTabSelector;
  147. }
  148.         
  149. DTableView::~DTableView()
  150. {
  151.     if (fWidths) MemFree(fWidths);
  152.     if (fHeights) MemFree(fHeights);
  153.     //if (fTabSelector) delete fTabSelector; //<< causing Motif crashes !?
  154. }
  155.  
  156. void DTableView::SetCanSelect(Boolean canrow, Boolean cancol)
  157. {
  158.     fCanSelectRow= canrow;
  159.     fCanSelectCol= cancol;
  160. }
  161.  
  162.  
  163. static Boolean didscroll;
  164.  
  165. void DTableView::SelectCells( short row, short col, 
  166.                         Nlm_Boolean extend, Nlm_Boolean highlight, Nlm_Boolean select)
  167. {
  168.     if (row>=fMaxRows || row<0 || col>=fMaxCols || col<0) return;
  169.  
  170.     if (highlight) InvertSelection(); // hide old
  171.     if (fCanSelectRow) fSelectedRow= row; 
  172.     if (fCanSelectCol) fSelectedCol= col;
  173.          
  174.     if (!select) ; // deselect cells !!
  175.     
  176.     if (extend) {
  177.         if (fSelrect.top == kNoSelection) fSelrect.top= row;
  178.         else if (fSelrect.top > row) fSelrect.top= row;
  179.         if (fSelrect.bottom <= row) fSelrect.bottom= row+1; 
  180.     
  181.         if (fSelrect.left == kNoSelection) fSelrect.left= col;
  182.         else if (fSelrect.left > col) fSelrect.left= col;
  183.         if (fSelrect.right <= col) fSelrect.right= col+1; 
  184.         }
  185.     else {
  186.         fSelrect.left= col;
  187.         fSelrect.right= col+1; 
  188.         fSelrect.top= row;
  189.         fSelrect.bottom= row+1; 
  190.         }
  191.         
  192.     didscroll= false;
  193.     ScrollIntoView( fSelrect);
  194.     if (!didscroll && highlight) InvertSelection(); // show new
  195. }
  196.  
  197. void DTableView::SelectCells( Nlm_RecT selrect,  
  198.                         Nlm_Boolean extend, Nlm_Boolean highlight, Nlm_Boolean select)
  199. {
  200.     if (selrect.top>= fMaxRows || selrect.bottom<0 
  201.      || selrect.left>=fMaxCols || selrect.right<0) return;
  202.     selrect.left= Max(0,selrect.left);
  203.     selrect.right= Min(fMaxCols, selrect.right);
  204.     selrect.top= Max(0,selrect.top);
  205.     selrect.bottom= Min(fMaxRows, selrect.bottom);
  206.     
  207.     if (highlight) InvertSelection();  
  208.     if (fCanSelectRow) fSelectedRow= selrect.top; 
  209.     if (fCanSelectCol) fSelectedCol= selrect.left;
  210.     
  211.     if (extend)  {
  212.         if (fSelrect.top == kNoSelection) fSelrect.top= selrect.top;
  213.         if (fSelrect.bottom == kNoSelection) fSelrect.bottom= selrect.bottom;
  214.         if (fSelrect.left == kNoSelection) fSelrect.left= selrect.left;
  215.         if (fSelrect.right == kNoSelection) fSelrect.right= selrect.right;
  216.       Nlm_UnionRect( &fSelrect, &selrect, &fSelrect);
  217.       }
  218.     else   
  219.         fSelrect= selrect; // ?? add +1 to .right & .bottom ??
  220.  
  221.     didscroll= false;
  222.     ScrollIntoView( fSelrect);
  223.     if (!didscroll && highlight) InvertSelection();  
  224. }
  225.  
  226.  
  227. void DTableView::ScrollIntoView(Nlm_RecT itemr)
  228. {
  229.     enum { horizontal= false, vertical= true };
  230.     short    lastitem;
  231.     long    atpix;
  232.     Nlm_BaR sb;
  233.  
  234.      // fItemWidth << this isn't accurate for variable width/height.
  235.     if (fWidths) {
  236.         for (lastitem= fLeft, atpix= 0; lastitem< fMaxCols; lastitem++) { 
  237.             atpix += fWidths[lastitem]; 
  238.             if (atpix > fRect.right) break;
  239.             }
  240.         }
  241.     else
  242.         lastitem= fLeft + (fRect.right - fRect.left)/fItemWidth;
  243.      
  244.     if (itemr.left > lastitem || itemr.left < fLeft) {
  245.          didscroll= true;
  246.         sb = Nlm_GetSlateHScrollBar((Nlm_SlatE) GetNlmObject());
  247.         if (sb) { 
  248.             //Nlm_ResetClip(); // ! TEST: are we losing scrollbar update due to cliprect?
  249.             Nlm_SetValue(sb, Max(0, itemr.left - 1));  // calls our scroll funct
  250.             }
  251.         }
  252.     
  253.     if (fHeights) {
  254.         for (lastitem= fTop, atpix= 0; lastitem< fMaxRows; lastitem++) { 
  255.             atpix += fHeights[lastitem]; 
  256.             if (atpix > fRect.bottom) break;
  257.             }
  258.         }
  259.     else
  260.         lastitem= fTop + (fRect.bottom - fRect.top)/fItemHeight;
  261.         
  262.     if (itemr.top > lastitem || itemr.top < fTop) {
  263.          didscroll= true;
  264.         sb = Nlm_GetSlateVScrollBar((Nlm_SlatE) GetNlmObject());
  265.         if (sb) Nlm_SetValue(sb,  Max(0, itemr.top - 1));  
  266.         }
  267. }
  268.  
  269.  
  270. void DTableView::SetEmptySelection(Boolean redraw)
  271. {
  272.     if (redraw) {
  273.         //InvertSelection();
  274.         InvalidateSelection();
  275.         }
  276.     fSelectedRow = kNoSelection;
  277.     fSelectedCol = kNoSelection;
  278.     //Nlm_SetRect
  279.     Nlm_LoadRect( &fSelrect, kNoSelection, kNoSelection, kNoSelection, kNoSelection);
  280. }
  281.  
  282. void DTableView::InvalidateSelection()
  283. {
  284.     Nlm_RecT r, r2;
  285.     if (!Nlm_EmptyRect(&fSelrect)) {
  286.         r2= fSelrect;
  287.         GetCellRect( r2, r);
  288.         InvalRect( r);
  289.         }
  290.     else if (fSelectedRow>=0 && fSelectedCol>=0) {
  291.         GetCellRect( fSelectedRow, fSelectedCol, r);
  292.         InvalRect( r);
  293.         }
  294.     else if (fSelectedRow>=0) {
  295.         GetRowRect( fSelectedRow, r);
  296.         InvalRect( r);
  297.         }
  298.     else if (fSelectedCol>=0) {
  299.         GetRowRect( fSelectedCol, r);
  300.         InvalRect( r);
  301.         }
  302. }
  303.  
  304.  
  305. Boolean DTableView::IsSelected()
  306. {
  307.     return (!Nlm_EmptyRect( &fSelrect));
  308.     //return (fSelectedRow == kNoSelection && fSelectedCol == kNoSelection);
  309.  
  310.  
  311. Boolean DTableView::IsSelected(short row, short col)
  312. {
  313.     Nlm_PoinT pt;
  314.     pt.y= row; pt.x= col;
  315.     Boolean issel= Nlm_PtInRect( pt, &fSelrect);
  316.     return issel;
  317. }  
  318.  
  319.  
  320.  
  321.  
  322. void DTableView::SetTableFont( Nlm_FonT itsFont)
  323. {
  324.     fFont= itsFont;
  325. }
  326.  
  327. void DTableView::SetTableSize( short rows, short cols)
  328. {
  329.     short i;
  330.     
  331.     if (fWidths && cols!=fMaxCols) {
  332.         fWidths= (short*)MemMore( fWidths, (cols+1) * sizeof(short));
  333.         for (i= fMaxCols; i<=cols; i++) fWidths[i]= fItemWidth;
  334.         }
  335.         
  336.     if (fHeights && rows!=fMaxRows) {
  337.         fHeights= (short*)MemMore( fHeights, (rows+1) * sizeof(short));
  338.         for (i= fMaxRows; i<=rows; i++) fHeights[i]= fItemHeight;
  339.         }
  340.     
  341.     fMaxRows= rows; 
  342.     fMaxCols= cols;
  343.  
  344.     SetScrollPage();
  345. }
  346.  
  347. void DTableView::ChangeRowSize( short atrow, short deltarows)
  348. {
  349.     Boolean needupdate;
  350.     short newrows= Max(0, fMaxRows + deltarows);
  351. #if 1
  352.     Nlm_RecT  r;
  353.     ViewRect(fRect); 
  354.     Nlm_InsetRect( &fRect, 1, 1);
  355.     GetRowRect( atrow, r, (fMaxRows - atrow));
  356.     needupdate= Nlm_SectRect( &r, &fRect, &r);
  357.     SetTableSize( newrows, fMaxCols);
  358.     if (needupdate) this->InvalRect( r);
  359. #else
  360.     short viewrows=  (fRect.bottom - fRect.top) / fItemHeight;
  361.     needupdate= (atrow >= fTop && atrow <= viewrows);
  362.         // ^^ needs work
  363.     SetTableSize( newrows, fMaxCols);
  364.     if (needupdate) {
  365.         //this->Invalidate(); // locate just update rect??    
  366.         Nlm_RecT r;
  367.         short nrows= viewrows - atrow;
  368.         GetRowRect( atrow, r, nrows);
  369.         this->InvalRect( r);
  370.         }
  371. #endif
  372. }
  373.  
  374. void DTableView::ChangeColSize( short atcol, short deltacols)
  375. {
  376.     short newcols= Max(0, fMaxCols + deltacols);
  377.     Boolean needupdate= (atcol >= fLeft && atcol <= (fRect.right - fRect.left) / fItemWidth);
  378.         // ^^ needs work
  379.     SetTableSize( fMaxRows, newcols);
  380.     if (needupdate) {
  381.         //this->Invalidate(); // locate just update rect??    
  382.         Nlm_RecT r;
  383.         short ncols= ((fRect.right - fRect.left) / fItemWidth) - atcol;
  384.         GetColRect( atcol, r, ncols);
  385.         this->InvalRect( r);
  386.         }
  387. }
  388.  
  389.         
  390. void DTableView::SetItemWidth(short atcol, short ncols, short itemwidth)
  391. {
  392.     short i;
  393.     if (ncols >= fMaxCols && !fWidths) {
  394.         fItemWidth= itemwidth;
  395.         }
  396.     else {
  397.         if (!fWidths) {
  398.             // make fWidths
  399.             fWidths= (short*)MemNew( (fMaxCols+1)*sizeof(short));
  400.             for (i= 0; i<=fMaxCols; i++) fWidths[i]= fItemWidth;
  401.             }
  402.         short ncol= Min(fMaxCols, atcol+ncols);
  403.         for (i= atcol; i<ncol; i++) fWidths[i]= itemwidth;
  404.     fItemWidth= Max( fItemWidth, itemwidth);
  405.         }
  406.   SetScrollPage();
  407. }
  408.  
  409. void DTableView::SetItemHeight(short atrow, short nrows, short itemheight)
  410. {
  411.     short i;
  412.     if (nrows >= fMaxRows && !fHeights) {
  413.         fItemHeight= itemheight;
  414.         }
  415.     else {
  416.         if (!fHeights) {
  417.             fHeights= (short*)MemNew( (fMaxRows+1)*sizeof(short));
  418.             for (i= 0; i<=fMaxRows; i++) fHeights[i]= fItemHeight;
  419.             }
  420.         short nrow= Min(fMaxRows, atrow+nrows);
  421.         for (i= atrow; i<nrow; i++) fHeights[i]= itemheight;
  422. #if 0
  423.     if (itemheight) fItemHeight= MIN( fItemHeight, itemheight);
  424. #else
  425.     fItemHeight= MAX( fItemHeight, itemheight);
  426. #endif
  427.         }
  428.   SetScrollPage();
  429. }
  430.         
  431. void DTableView::SetScrollPage()
  432. {
  433.     // set paging size of hor/vert sbars.. need to do on open & on resize
  434.     Nlm_BaR sb;
  435.     short pgDn, pg, maxn;
  436.     if (fHasHbar) {
  437.         pg= (fRect.right - fRect.left) / fItemWidth;
  438.         pgDn= Max(1, pg - 1);
  439.         maxn= Max( fMaxCols - pgDn, 1);
  440.         sb = Nlm_GetSlateHScrollBar((Nlm_SlatE) GetNlmObject());
  441.         if (sb) Nlm_SetRange(sb, pgDn, pgDn, maxn);
  442.         }
  443.     if (fHasVbar) {
  444.         pg= (fRect.bottom - fRect.top) / fItemHeight;
  445.         pgDn= Max(1, pg - 1);
  446.         maxn= Max( fMaxRows - pgDn, 1);
  447.         sb = Nlm_GetSlateVScrollBar((Nlm_SlatE) GetNlmObject());
  448.         if (sb) Nlm_SetRange(sb, pgDn, pgDn, maxn);
  449.         }
  450. }
  451.  
  452. void DTableView::FindLocation()
  453. {
  454.     ViewRect(fRect); //this->GetPosition(fRect); // ?? this isn't changing except w/ resize ??
  455.     Nlm_InsetRect( &fRect, 1, 1);
  456.     SetScrollPage();
  457. }
  458.         
  459. void DTableView::SizeToSuperview( DView* super, Boolean horiz, Boolean vert)
  460. {
  461. #ifndef WIN_MSWIN
  462.     DView::SizeToSuperview(super, horiz, vert);
  463. #else
  464.     Nlm_RecT r, myr;
  465.     super->ViewRect(r);
  466.     ViewRect(myr);
  467.             // these sizes draw off by -1... thus the +1
  468.     if (horiz) {
  469.         myr.left = 0;
  470.         myr.right= myr.left + (r.right - r.left) +1;
  471. #ifdef WIN_MSWIN
  472.         if (fHasVbar) myr.right -= (Nlm_vScrollBarWidth - 8);
  473. #endif
  474.         }
  475.     if (vert) {
  476.         myr.top = 0;
  477.         myr.bottom = myr.top + (r.bottom - r.top) +1;
  478. #ifdef WIN_MSWIN
  479.         if (fHasHbar) myr.bottom -= (Nlm_hScrollBarHeight + 10);
  480. #endif
  481.         }
  482.     SetPosition( myr);
  483. #endif
  484.     this->FindLocation(); //?? added 14Mar94, gopher tables were doing this
  485. }
  486.  
  487.  
  488. void DTableView::Resize(DView* superview, Nlm_PoinT sizechange)
  489. {
  490.         // !! need this fRect change to deal w/ Resize() update event, 
  491.         // which isn't put in a nice event queue, but is done immediately !!
  492.     fRect.right  += sizechange.x;
  493.     fRect.bottom += sizechange.y;
  494.     DPanel::Resize(superview, sizechange);
  495.     FindLocation();
  496. }
  497.  
  498. void DTableView::Scroll(Boolean vertical, DView* scrollee, short newval, short oldval)
  499. {
  500.     Nlm_RecT    r = fRect;
  501.     short delta, i;
  502.     short diff= newval-oldval;
  503.     this->Select(); // need for motif !
  504.     if (vertical) {
  505.  
  506.       if (fHeights) {
  507.         delta= 0;
  508.             if (oldval>newval) {
  509.                 for (i=oldval-1; i>=newval; i--) delta -= fHeights[i];
  510.                 }
  511.         else {
  512.                 for (i=oldval; i<newval; i++) delta += fHeights[i];
  513.                 }
  514.             }
  515.         else
  516.             delta= diff * fItemHeight;
  517.  
  518.         fTop += diff;
  519.         Nlm_ScrollRect (&r, 0, -delta);
  520.         if (diff<0) r.bottom= r.top - delta + Min(10,-delta/2);
  521.         else r.top= r.bottom - delta - Min(10,delta/2);
  522.         }
  523.         
  524.     else {
  525. #if 1
  526.       if (fWidths) {
  527.         delta= 0;
  528.             if (oldval>newval) {
  529.                 for (i=oldval-1; i>=newval; i--) delta -= fWidths[i];
  530.                 }
  531.         else {
  532.                 for (i=oldval; i<newval; i++) delta += fWidths[i];
  533.                 }
  534.             }
  535.         else
  536.             delta= diff * fItemWidth;
  537.             
  538.         fLeft += diff;
  539.         Nlm_ScrollRect (&r, -delta, 0);
  540.         if (diff<0) r.right= Min(r.right, r.left - delta + Min(20,-delta/2));
  541.         else r.left= Max(r.left, r.right - delta - Min(20,delta/2));
  542. #else
  543.         if (fWidths) {
  544.             // fix later, for now redraw all w/o bitscroll
  545.             fLeft += diff;
  546.             }
  547.         else {
  548.             fLeft += diff;
  549.             delta= diff * fItemWidth;
  550.             Nlm_ScrollRect (&r, -delta, 0);
  551.             if (diff<0) r.right= r.left - delta + Min(10,-delta/2);
  552.             else r.left= r.right - delta - Min(10,delta/2);
  553.             }
  554. #endif
  555.         }
  556.     this->InvalRect( r);
  557.   Nlm_Update(); //!? need since took out vibwnds autoupdate for RestorePort
  558. }
  559.             
  560.  
  561. void DTableView::GetRowRect( short row, Nlm_RecT& r, short nrows)
  562. {
  563.     short i;
  564.     r= fRect;
  565.     if (fHeights) {
  566.         for (i= fTop; i<row; i++) r.top += fHeights[i];
  567.         r.bottom= r.top;
  568.         for (i= 0; i<nrows; i++) r.bottom += fHeights[row+i];
  569.         }
  570.     else {
  571.         r.top += (row-fTop) * fItemHeight;
  572.         r.bottom = r.top + nrows*fItemHeight;
  573.         }
  574. }
  575.  
  576. void DTableView::GetColRect( short col, Nlm_RecT& r, short ncols)
  577. {
  578.     short i;
  579.     r= fRect;
  580.     if (fWidths) {
  581.         for (i= fLeft; i<col; i++) r.left += fWidths[i];
  582.         r.right= r.left;
  583.         for (i= 0; i<ncols; i++) r.right += fWidths[col+i];
  584.         }
  585.     else {
  586.         r.left += (col-fLeft) * fItemWidth;
  587.         r.right = r.left + ncols*fItemWidth;
  588.         }
  589. }
  590.  
  591. void DTableView::GetCellRect( short row, short col, Nlm_RecT& r)
  592. {
  593.     short i;
  594.     r= fRect;
  595.     if (fWidths) {
  596.         for (i= fLeft; i<col; i++) r.left += fWidths[i];
  597.         r.right= r.left + fWidths[col];
  598.         }
  599.     else {
  600.         r.left += (col-fLeft) * fItemWidth;
  601.         r.right = r.left + fItemWidth;
  602.         }
  603.     if (fHeights) {
  604.         for (i= fTop; i<row; i++) r.top += fHeights[i];
  605.         r.bottom= r.top + fHeights[row];
  606.         }
  607.     else {
  608.         r.top += (row-fTop) * fItemHeight;
  609.         r.bottom = r.top + fItemHeight;
  610.         }
  611. }
  612.  
  613. void DTableView::GetCellRect(Nlm_RecT cellr, Nlm_RecT& r)
  614. {
  615.     short i;
  616.     r= fRect;
  617.     if (fWidths) {
  618.         for (i= fLeft; i<cellr.left; i++) r.left += fWidths[i];
  619.         r.right= r.left;
  620.         for (i=cellr.left; i<cellr.right; i++) r.right += fWidths[i];
  621.         }
  622.     else {
  623.         r.left += (cellr.left-fLeft) * fItemWidth;
  624.         r.right = r.left + (cellr.right - cellr.left) * fItemWidth;
  625.         }
  626.         
  627.     if (fHeights) {
  628.         for (i= fTop; i<cellr.top; i++) r.top += fHeights[i];
  629.         r.bottom= r.top;
  630.         for (i=cellr.top; i<cellr.bottom; i++) r.bottom += fHeights[i];
  631.         }
  632.     else {
  633.         r.top += (cellr.top-fTop) * fItemHeight;
  634.         r.bottom = r.top + (cellr.bottom - cellr.top) * fItemHeight;
  635.         }
  636. }
  637.  
  638.     
  639. short DTableView::GetSelectedRow()
  640.     return fSelectedRow; 
  641. }
  642.  
  643. short DTableView::GetSelectedCol() 
  644.     return fSelectedCol; 
  645. }
  646.  
  647. void DTableView::GetFirstSelectedCell( short& row, short& col)
  648. #if 0
  649.     row= fSelectedRow; 
  650.     col= fSelectedCol; 
  651. #else
  652.     row= fSelrect.top;
  653.     col= fSelrect.left;
  654. #endif
  655. }
  656.  
  657. void DTableView::GetLastSelectedCell( short& row, short& col)
  658. #if 0
  659.     row= fSelectedRow; 
  660.     col= fSelectedCol; 
  661. #else
  662.     row= fSelrect.bottom;
  663.     col= fSelrect.right;
  664. #endif
  665. }
  666.     
  667.  
  668.  
  669. #ifdef WIN_MOTIF
  670.  
  671. #include <ncbi.h>
  672. #include <ncbidraw.h>
  673. //typedef unsigned long XID; // this is failing in X.h !?
  674. //#define XID  unsigned long
  675. #include <ncbiwin.h>
  676. #include <ncbiport.h>
  677.  
  678. extern Display      *Nlm_currentXDisplay;
  679. extern int          Nlm_currentXScreen;
  680. extern Window       Nlm_currentXWindow;
  681. extern GC           Nlm_currentXGC;
  682. extern Nlm_Uint4    Nlm_XbackColor;
  683. extern Nlm_Uint4    Nlm_XforeColor;
  684. extern Nlm_Int2     Nlm_XOffset;
  685. extern Nlm_Int2     Nlm_YOffset;
  686. extern Nlm_RegioN   Nlm_clpRgn;
  687.  
  688. #endif
  689.  
  690. inline void DTableInvertRect( Nlm_RecT& r)
  691. {    
  692. #ifdef WIN_MOTIF
  693. // vals: GXcopy  GXand  GXor GXequiv GXinvert GXorInverted
  694. // !! GXor looks GOOD for colored x -- makes gray rect
  695. // but isn't reverting to regular on deselect, unless click is in selrect !?? 
  696. // GXxor looks okay at start, but repeated calls mess it up (conflict??)
  697. #define newfunc  GXxor
  698. #define currentFunction  GXcopy
  699. // vals: FillStippled  FillOpaqueStippled  FillSolid  FillTiled
  700. #define newfill  FillStippled
  701. #define currentFillStyle   FillStippled
  702.   Nlm_RectTool  rtool;
  703.  
  704.   if (Nlm_currentXDisplay != NULL &&
  705.       Nlm_currentXWindow != 0 && Nlm_currentXGC != NULL) {
  706.     rtool.x = MIN (r.left, r.right);
  707.     rtool.y = MIN (r.top, r.bottom);
  708.     rtool.width = ABS (r.right - r.left);
  709.     rtool.height = ABS (r.bottom - r.top);
  710.  
  711.     XSetFunction (Nlm_currentXDisplay, Nlm_currentXGC, newfunc);
  712.     XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, newfill);
  713.     XFillRectangle (Nlm_currentXDisplay, Nlm_currentXWindow, Nlm_currentXGC,
  714.                     rtool.x - Nlm_XOffset, rtool.y - Nlm_YOffset,
  715.                     rtool.width, rtool.height);
  716.     XSetFunction (Nlm_currentXDisplay, Nlm_currentXGC, currentFunction);
  717.     XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, currentFillStyle);
  718.    }
  719.  
  720. #if 0
  721.     Nlm_InvertMode();
  722.     Nlm_FillRect( &r);
  723.     Nlm_CopyMode();
  724. #endif
  725.  
  726. #else
  727.     // patched both Nlm_InvertMode & Nlm_InvertRect for Motif
  728.   Nlm_InvertRect( &r);
  729. #endif 
  730. }
  731.  
  732. void DTableView::InvertRect( Nlm_RecT& r)
  733. {    
  734.     Nlm_WindoW w= Nlm_SavePort( fNlmObject);
  735. #ifdef WIN_MOTIF
  736.     this->Select();
  737. #endif
  738.     ::DTableInvertRect( r);
  739.     if (w) Nlm_UseWindow (w); 
  740. }
  741.  
  742. void DTableView::InvertSelection()
  743. {    
  744.     Nlm_RecT r, r2;
  745.     if (!Nlm_EmptyRect(&fSelrect)) {
  746.         r2= fSelrect;
  747.         //r2.bottom--;
  748.         //r2.right--;
  749.         GetCellRect( r2, r);
  750.         }
  751.     else if (fSelectedRow>=0 && fSelectedCol>=0) 
  752.         GetCellRect( fSelectedRow, fSelectedCol, r);
  753.     else if (fSelectedRow>=0) 
  754.         GetRowRect( fSelectedRow, r);
  755.     else if (fSelectedCol>=0) 
  756.         GetRowRect( fSelectedCol, r);
  757.   else
  758.       return;
  759.     InvertRect( r);
  760. }
  761.  
  762.  
  763.  
  764. void DTableView::DoubleClickAt(short row, short col)
  765. {
  766. }
  767.  
  768.  
  769. void DTableView::SingleClickAt(short row, short col)
  770. {
  771.     Nlm_PoinT pt;
  772.     pt.x= col; pt.y= row;
  773.     if (Nlm_PtInRect( pt, &fSelrect) && !gKeys->shift()) {
  774.         SetEmptySelection( true);
  775.         }
  776.     else {
  777.         SelectCells(  row, col, gKeys->shift(), kHighlight, kSelect);
  778.         }
  779. }
  780.             
  781.  
  782. void DTableView::PointToCell(Nlm_PoinT mouse, short& row, short& col)
  783. {
  784.     if (fHeights) {
  785.         row= fTop - 1;
  786.         short yrow= fRect.top;
  787.         do {
  788.             row++;
  789.             if (row<=fMaxRows) yrow += fHeights[row];
  790.             else yrow= mouse.y;
  791.             } while (yrow < mouse.y);
  792.         }
  793.     else
  794.         row= fTop  + (mouse.y - fRect.top)  / fItemHeight;
  795.  
  796.     if (fWidths) {
  797.         col= fLeft - 1;
  798.         short xcol= fRect.left;
  799.         do {
  800.             col++;
  801.             if (col<=fMaxCols) xcol += fWidths[col];
  802.             else xcol= mouse.x;
  803.             } while (xcol < mouse.x);
  804.         }
  805.     else
  806.         col= fLeft + (mouse.x - fRect.left) / fItemWidth;
  807. }
  808.  
  809.  
  810.  
  811. void DTableView::Click(Nlm_PoinT mouse)
  812. {
  813.     short row, col;
  814.     
  815.     //if (gLastCommand) gLastCommand->Commit();    //?? prevent bombs from prev. cmds ?
  816.     //if (fCurrentTracker) fCurrentTracker->Reset();
  817.     SetTracker( fCurrentTracker); // ??  make new one each click?
  818.     DAutoPanel::Click(mouse);         // sets fMouseStillDown= false
  819.  
  820.     if (!fCurrentTracker) {
  821.         // TrackMouse::trackEnd does this now, if click is tracked...
  822.         PointToCell( mouse, row, col);
  823.         if (row >=0 && row < fMaxRows && col >= 0 && col < fMaxCols) {
  824.             if (Nlm_dblClick) DoubleClickAt( row, col);
  825.             else SingleClickAt( row, col);
  826.             }
  827.         }
  828. }
  829.  
  830. void DTableView::Drag(Nlm_PoinT mouse)
  831. {
  832.     DAutoPanel::Drag(mouse); // sets fMouseStillDown= true,... 
  833. }
  834.  
  835. void DTableView::Release(Nlm_PoinT mouse)
  836. {
  837.     DAutoPanel::Release(mouse); // sets fMouseStillDown= false,... 
  838. }
  839.  
  840.  
  841. void DTableView::TrackMouse( short aTrackPhase,
  842.                     Nlm_PoinT& anchorPoint, Nlm_PoinT& previousPoint,
  843.                     Nlm_PoinT& nextPoint,    Nlm_Boolean mouseDidMove)
  844. {
  845.  
  846.     switch (aTrackPhase) {
  847.     
  848.         case DTracker::trackBegin:
  849.             if (gKeys->shift()) {  
  850.                 Nlm_PoinT pt;
  851.                 Nlm_RecT  pixr;
  852.                 short    diff1, diff2;
  853.                 
  854.                 GetCellRect( fSelrect, pixr);
  855.                 diff1= anchorPoint.x - pixr.left;
  856.                 diff2= anchorPoint.x - pixr.right;
  857.                 if (abs(diff1) > abs(diff2)) pt.x= pixr.left; 
  858.                 else pt.x= pixr.right;
  859.                 diff1= anchorPoint.y - pixr.top;
  860.                 diff2= anchorPoint.y - pixr.bottom;
  861.                 if (abs(diff1) > abs(diff2)) pt.y= pixr.top; 
  862.                 else pt.y= pixr.bottom;
  863.                 
  864.                 // tracker::Start makes 3 pts all same
  865.                 anchorPoint = pt;
  866.                 previousPoint = pt;
  867.                 nextPoint = pt;
  868.                 //fTracker->fMovedOnce= true; // force it for single-click extend?
  869.                 }
  870.              break;
  871.     
  872.         case DTracker::trackContinue:
  873.             break;
  874.             
  875.         case DTracker::trackEnd:
  876.             {
  877.             short row, col;
  878.             Boolean moved= gKeys->shift() // extend
  879.                     || abs(anchorPoint.x - nextPoint.x) > 2
  880.                     || abs(anchorPoint.y - nextPoint.y) > 2;
  881.             if (!moved) {
  882.                 PointToCell( nextPoint, row, col);
  883.                 if (row >=0 && row < fMaxRows && col >= 0 && col < fMaxCols) {
  884.                     if (Nlm_dblClick) DoubleClickAt( row, col);
  885.                     else SingleClickAt( row, col);
  886.                     }
  887.                 }
  888.             }
  889.             break;
  890.             
  891.         }
  892. }
  893.  
  894. void DTableView::TrackFeedback( short aTrackPhase,
  895.                     const Nlm_PoinT& anchorPoint, const Nlm_PoinT& previousPoint,
  896.                     const Nlm_PoinT& nextPoint, Nlm_Boolean mouseDidMove, Nlm_Boolean turnItOn)
  897. {
  898.     if (mouseDidMove) {
  899.         Nlm_RecT    pixr;
  900.  
  901.         pixr.left= MIN( anchorPoint.x, nextPoint.x);
  902.         pixr.right= MAX( anchorPoint.x, nextPoint.x);
  903.         pixr.top= MIN( anchorPoint.y, nextPoint.y);
  904.         pixr.bottom= MAX( anchorPoint.y, nextPoint.y);
  905.         
  906.         Nlm_InsetRect( &pixr, 1,1); //??
  907.         Nlm_InvertMode();
  908.         Nlm_FrameRect( &pixr);
  909.         Nlm_CopyMode();
  910.         }
  911. }
  912.  
  913.  
  914.  
  915.  
  916. void DTableView::DrawCell(Nlm_RecT r, short row, short col)
  917. {
  918.     char    snum[80];
  919.     sprintf(snum,"r%d,c%d", row, col);
  920.     Nlm_DrawString( &r, snum, 'c', false);
  921. }
  922.     
  923. void DTableView::DrawRow(Nlm_RecT r, short row)
  924. {
  925.     short col = fLeft; 
  926.     if (fWidths && col <= fMaxCols) r.right= r.left + fWidths[col];
  927.     else r.right= r.left + fItemWidth;
  928.     while (r.left < fRect.right && col < fMaxCols) {
  929.         if (Nlm_RectInRgn (&r, Nlm_updateRgn))  
  930.             DrawCell( r, row, col);
  931.         if (fWidths) {
  932.             Nlm_OffsetRect( &r, fWidths[col], 0);
  933.             r.right= r.left + fWidths[col+1];
  934.             }
  935.         else
  936.             Nlm_OffsetRect( &r, fItemWidth, 0);
  937.         col++;
  938.         }
  939.     fColsDrawn= col - fLeft;
  940. }
  941.  
  942.  
  943. void DTableView::GetPageCount(Nlm_RecT pagerect, short& rowpages, short& colpages)
  944. {
  945.     long left, top, row, col;     
  946.     rowpages= colpages= 1;
  947.     
  948.     for (col=0, left=0; col < fMaxCols; col++) {
  949.         if (fWidths) left += fWidths[col];  
  950.         else left += fItemWidth;
  951.         if (left >= pagerect.right) { 
  952.             colpages++; 
  953.             left= 0; 
  954.             }
  955.         }
  956.     for (row=0, top=0; row < fMaxRows; row++) {
  957.         if (fHeights) top += fHeights[row];  
  958.         else top += fItemHeight;
  959.         if (top >= pagerect.bottom) { 
  960.             rowpages++; 
  961.             top= 0; 
  962.             }
  963.         }
  964. }
  965.  
  966.  
  967. void DTableView::Draw()
  968. {
  969.     Nlm_RecT         r2, r = fRect;
  970.     Nlm_PoinT      pt;
  971.     short             row = fTop; 
  972.     Boolean            hasSel;
  973.     
  974.     if (fHeights) r.bottom= r.top + fHeights[row];
  975.     else r.bottom= r.top + fItemHeight;
  976.     Nlm_SelectFont(fFont); //?? here
  977.     hasSel= !Nlm_EmptyRect(&fSelrect);
  978.     if (hasSel) {
  979.         pt.x= fSelrect.left;
  980.         r2= fSelrect;
  981.         GetCellRect( r2, r2);
  982.         }
  983.         
  984.     while (r.top < fRect.bottom && row < fMaxRows) {
  985.         if (Nlm_RectInRgn (&r, Nlm_updateRgn)) { 
  986.             DrawRow( r, row);
  987.              pt.y= row;
  988.              if (hasSel && Nlm_PtInRect( pt, &fSelrect)) {
  989.                  Nlm_RecT ir= r;
  990.                  ir.left= r2.left;
  991.                  ir.right= r2.right;
  992.                 InvertRect( ir);
  993.                  }
  994.           }
  995.         if (fHeights) {
  996.             Nlm_OffsetRect( &r, 0, fHeights[row]);
  997.             r.bottom= r.top + fHeights[row+1];
  998.             }
  999.         else
  1000.             Nlm_OffsetRect( &r, 0, fItemHeight);
  1001.         row++;
  1002.         }
  1003. }
  1004.         
  1005.  
  1006. enum { kWritingAsPICT = 9 };
  1007.  
  1008. void DTableView::ViewRect(Nlm_RecT& r) 
  1009.     if (fIsPrinting == kWritingAsPICT) {
  1010.         r= fRect; // fRect is set at start of AsPICT
  1011.         }
  1012.     else if (fIsPrinting) {
  1013.         r= fRect; //fRect is set at start of Print 
  1014.         // Nlm_PrintingRect(&r);
  1015.         }
  1016.     else
  1017.         DView::ViewRect(r);  
  1018. }
  1019.         
  1020. void DTableView::Print()  
  1021. {
  1022. #if (defined(WIN_MAC) || defined (WIN_MSWIN))
  1023.   Nlm_WindoW    w;
  1024.   Boolean           goOn, newPage, widerThanPage;
  1025.   Nlm_RecT        pager, r, saverect;
  1026.     short                 row = 0, rowpages, colpages; 
  1027.     long                    saveleft;
  1028.     
  1029.     // problems: assumes each row < page height
  1030.     
  1031.   w = Nlm_StartPrinting();
  1032.   if (w) {
  1033.       fIsPrinting= true;
  1034.         gCursor->watch();    
  1035.         saverect= fRect;
  1036.         Nlm_PrintingRect(&pager);
  1037.         fRect= pager;
  1038.         Nlm_SelectFont(fFont); 
  1039.         saveleft= fLeft; fLeft= 0; 
  1040.         //savetop= fTop; fTop= 0; 
  1041.         GetPageCount( pager, rowpages, colpages);
  1042.         
  1043.     newPage = true;
  1044.     goOn = row < fMaxRows;
  1045.     widerThanPage= colpages > 1; 
  1046.     
  1047.     // make update region large...
  1048.     if (Nlm_updateRgn != NULL)  
  1049.             Nlm_LoadRectRgn(Nlm_updateRgn, -32767, -32767, 32767, 32767);
  1050.     
  1051.     while (goOn) {
  1052.     
  1053.       if (newPage) {
  1054.         goOn = Nlm_StartPage();
  1055.         newPage = false;
  1056.           r= pager;
  1057.           
  1058.                 if (fHeights) r.bottom= r.top + fHeights[row];
  1059.                 else r.bottom= r.top + fItemHeight;
  1060.            }
  1061.       
  1062.       if (goOn) {
  1063.                 fColsDrawn= fMaxCols; // in case DrawRow forgets to set this
  1064.                 DrawRow( r, row);
  1065.                 
  1066.                 if (widerThanPage) {
  1067.                   fLeft +=     fColsDrawn;
  1068.                     newPage = (fLeft < fMaxCols);
  1069.                     if (newPage) goOn = Nlm_EndPage();    
  1070.                     else fLeft= 0;
  1071.                     }
  1072.                 
  1073.                 if (!newPage) {    
  1074.                     if (fHeights) {
  1075.                         Nlm_OffsetRect( &r, 0, fHeights[row]);
  1076.                         r.bottom= r.top + fHeights[row+1];
  1077.                         }
  1078.                     else
  1079.                         Nlm_OffsetRect( &r, 0, fItemHeight);
  1080.                     newPage = (r.bottom > pager.bottom);
  1081.                     if (newPage) goOn = Nlm_EndPage();    
  1082.                     row++;
  1083.                     if (goOn) goOn= (row < fMaxRows);
  1084.                     }
  1085.                     
  1086.                 }
  1087.             }
  1088.             
  1089.           if (!newPage) (void) Nlm_EndPage();
  1090.       Nlm_EndPrinting(w);
  1091.         fIsPrinting= false;
  1092.         fRect= saverect;
  1093.         fLeft= saveleft;
  1094.         gCursor->arrow();
  1095.         }       
  1096. #else
  1097.     Nlm_Message(MSG_OK,"Printing is not yet defined for this window system");
  1098. #endif
  1099. }
  1100.  
  1101.  
  1102. #ifdef WIN_MAC
  1103. #undef Handle
  1104. #undef true
  1105. #undef false
  1106. #undef Rect
  1107. #include <QuickDraw.h>
  1108. #include <Memory.h>
  1109. #endif
  1110.  
  1111. #ifdef WIN_MSWIN
  1112. #include <windows.h>
  1113. extern "C" HWND         Nlm_currentHWnd;
  1114. extern "C" HDC          Nlm_currentHDC;
  1115. #endif
  1116.  
  1117. void DTableView::WriteToPICT(DFile* afile)  
  1118. {
  1119.     if (!afile) return;
  1120.     
  1121. #ifdef WIN_MAC
  1122.   Nlm_RecT        pager, saverect, cellr;
  1123.     
  1124.     gCursor->watch();    
  1125.     saverect= fRect;
  1126.      fIsPrinting= kWritingAsPICT;
  1127.      Nlm_LoadRect( &cellr, 0, 0, fMaxCols, fMaxRows);
  1128.     this->GetCellRect( cellr, pager);
  1129.     fRect= pager;
  1130.     
  1131.   Rect  picrect;
  1132.   picrect.left= pager.left;
  1133.   picrect.right= pager.right;
  1134.   picrect.top = pager.top;
  1135.   picrect.bottom= pager.bottom;
  1136.     Handle pic= (Handle) OpenPicture( &picrect); 
  1137.     
  1138.   if (pic) { 
  1139.       enum { kPicHeadsize = 512 };
  1140.       ulong count;
  1141.         // make update region large...
  1142.     if (Nlm_updateRgn != NULL)  
  1143.             Nlm_LoadRectRgn(Nlm_updateRgn, -32767, -32767, 32767, 32767);
  1144.     Draw();                
  1145.       ClosePicture();
  1146.       
  1147.           // now write pic to file
  1148.       afile->Delete();
  1149.       afile->Create("PICT","ttxt"); 
  1150.         afile->Open("wb"); // Damn "wb" -- must by BINARY 
  1151.       count= kPicHeadsize;
  1152.       char * header = (char *) Nlm_MemGet(kPicHeadsize,MGET_CLEAR);
  1153.       afile->WriteData( header, count);
  1154.       Nlm_MemFree( header);
  1155.         HLock(pic);
  1156.       count= GetHandleSize(pic);
  1157.       afile->WriteData( *pic, count);
  1158.       afile->Close();
  1159.       HUnlock(pic);
  1160.       KillPicture ( (PicHandle)pic);
  1161.         } 
  1162.     fIsPrinting= false;        
  1163.     fRect= saverect;
  1164.     gCursor->arrow();
  1165.     return;
  1166. #endif
  1167.  
  1168. #ifdef WIN_MSWIN
  1169.   Nlm_RecT        pager, saverect, cellr;
  1170.     
  1171.     gCursor->watch();    
  1172.     saverect= fRect;
  1173.      fIsPrinting= kWritingAsPICT;
  1174.      Nlm_LoadRect( &cellr, 0, 0, fMaxCols, fMaxRows);
  1175.     this->GetCellRect( cellr, pager);
  1176.     fRect= pager;
  1177.     
  1178.     char* fname= (char*) afile->GetName();
  1179.     HDC hdcMeta= CreateMetaFile(fname);
  1180.   if (hdcMeta) { 
  1181.       HDC savehdc= Nlm_currentHDC;
  1182.       Nlm_currentHDC= hdcMeta;  
  1183.       SetMapMode( hdcMeta, MM_ANISOTROPIC);
  1184.       Nlm_ResetDrawingTools();
  1185.       
  1186.         // make update region large...
  1187.     if (Nlm_updateRgn != NULL)  
  1188.             Nlm_LoadRectRgn(Nlm_updateRgn, -32767, -32767, 32767, 32767);
  1189.     Draw();  
  1190.       
  1191.       HMETAFILE hmf = CloseMetaFile( hdcMeta);
  1192.       DeleteMetaFile( hmf); // just deletes handle, not disk file !
  1193.       Nlm_currentHDC= savehdc;  
  1194.         }       
  1195.     fIsPrinting= false;        
  1196.     fRect= saverect;
  1197.     gCursor->arrow();
  1198.     return;
  1199. #endif
  1200.       
  1201.     Nlm_Message(MSG_OK,"DrawToPicture is not yet defined for this window system");
  1202. }
  1203.  
  1204.