home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / MiscKit1.7.1 / MiscKit / Palettes / MiscTableScroll / MiscTableScrollData.M < prev    next >
Encoding:
Text File  |  1996-02-11  |  23.2 KB  |  826 lines

  1. //=============================================================================
  2. //
  3. //        Copyright (C) 1995 by Paul S. McCarthy and Eric Sunshine.
  4. //                Written by Paul S. McCarthy and Eric Sunshine.
  5. //                            All Rights Reserved.
  6. //
  7. //        This notice may not be removed from this source code.
  8. //
  9. //        This object is included in the MiscKit by permission from the authors
  10. //        and its use is governed by the MiscKit license, found in the file
  11. //        "License.rtf" in the MiscKit distribution.    Please refer to that file
  12. //        for a list of all applicable permissions and restrictions.
  13. //        
  14. //=============================================================================
  15. //-----------------------------------------------------------------------------
  16. // MiscTableScrollData.M
  17. //
  18. //        The (DATA) category of MiscTableScroll.     Implements the management
  19. //        of the cells of the table.
  20. //
  21. //-----------------------------------------------------------------------------
  22. //-----------------------------------------------------------------------------
  23. // $Id: MiscTableScrollData.M,v 1.9 96/01/13 23:43:48 zarnuk Exp $
  24. // $Log:        MiscTableScrollData.M,v $
  25. //    Revision 1.9  96/01/13    23:43:48  zarnuk
  26. //    Fixed bug: -lazyCellAt:: was not asking the dataDelegate.
  27. //    Added value-At:: methods.
  28. //    All allocations are now done from [self zone].
  29. //    
  30. //    Revision 1.8  95/10/20    00:13:00  sunshine
  31. //    Was including MiscTableScroll.h and MiscTableCell.h with "" instead of <>.
  32. //    
  33. //    Revision 1.7  95/10/14    16:50:58  zarnuk
  34. //    Fixed bug: -renewRows: was getting the prototype from the wrong slot.
  35. //    
  36. //    Revision 1.6  95/10/08    16:13:38  zarnuk
  37. //    Cell* --> id.
  38. //-----------------------------------------------------------------------------
  39. #import <misckit/MiscTableScroll.h>
  40. #import <misckit/MiscTableCell.h>
  41. #import "MiscTableBorder.h"
  42. extern "Objective-C" {
  43. #import <appkit/Cell.h>
  44. }
  45. extern "C" {
  46. #import <assert.h>
  47. #import <limits.h>
  48. #import <stdlib.h>
  49. #import <string.h>
  50. }
  51.  
  52. @implementation MiscTableScroll(DATA)
  53.  
  54. //-----------------------------------------------------------------------------
  55. // - dummyCellAt::
  56. //-----------------------------------------------------------------------------
  57. - dummyCellAt:(int)row :(int)col
  58.     {
  59.     id p = colInfo.border->getPrototype_P( col );
  60.     [self retireCell:p at:row:col];
  61.     [self reviveCell:p at:row:col];
  62.     if ([p respondsTo: @selector(setStringValue:)])
  63.         {
  64.         char buff[64];
  65.         sprintf( buff, "(r%d,c%d)", row, col );
  66.         [p setStringValue:buff];
  67.         }
  68.     return p;
  69.     }
  70.  
  71.  
  72. //-----------------------------------------------------------------------------
  73. // - lazyCellAt::
  74. //-----------------------------------------------------------------------------
  75. - lazyCellAt:(int)row :(int)col
  76.     {
  77.     if (delegate != 0 &&
  78.         [delegate respondsTo: @selector(tableScroll:cellAt: :)])
  79.             return [delegate tableScroll:self cellAt:row :col];
  80.     if (dataDelegate != 0 &&
  81.         [dataDelegate respondsTo: @selector(tableScroll:cellAt: :)])
  82.             return [dataDelegate tableScroll:self cellAt:row :col];
  83.     return 0;
  84.     }
  85.  
  86.  
  87. //-----------------------------------------------------------------------------
  88. // - eagerCellAt::
  89. //-----------------------------------------------------------------------------
  90. - eagerCellAt:(int)row :(int)col
  91.     {
  92.     return cells[ row * num_cols + col ];
  93.     }
  94.  
  95.  
  96. //-----------------------------------------------------------------------------
  97. // - cellAt::
  98. //-----------------------------------------------------------------------------
  99. - cellAt:(int)row :(int)col
  100.     {
  101.     id cell = 0;
  102.     if ((unsigned int) row < (unsigned int) num_rows &&
  103.         (unsigned int) col < (unsigned int) num_cols)
  104.         {
  105.         if (!lazy)
  106.             cell = [self eagerCellAt:row:col];
  107.         else if (![self respondsTo: @selector(isInIB)])
  108.             cell = [self lazyCellAt:row:col];
  109.         else
  110.             cell = [self dummyCellAt:row:col];
  111.  
  112.         MiscCoord_V vRow = rowInfo.border->physicalToVisual(row);
  113.         MiscCoord_V vCol = colInfo.border->physicalToVisual(col);
  114.         if ([cell respondsTo:@selector(setState:)])
  115.             [cell setState: colInfo.border->selectionSet().contains(vCol) ||
  116.                             rowInfo.border->selectionSet().contains(vRow)];
  117.         }
  118.     return cell;
  119.     }
  120.  
  121.  
  122. //-----------------------------------------------------------------------------
  123. // tagAt::, intValueAt::, floatValueAt::, doubleValueAt::,
  124. // stringValueAt::, titleAt::, stateAt::
  125. //-----------------------------------------------------------------------------
  126. #define MISC_CELL_VAL( DATA_TYPE, NAME )\
  127. - (DATA_TYPE) NAME##At:(int) r :(int) c\
  128.     {\
  129.     if (lazy)\
  130.         {\
  131.         if (delegate != 0 &&\
  132.             [delegate respondsTo:@selector(tableScroll:NAME##At: :)])\
  133.             return [delegate tableScroll:self NAME##At:r:c];\
  134.         if (dataDelegate != 0 &&\
  135.             [dataDelegate respondsTo:@selector(tableScroll:NAME##At: :)])\
  136.             return [dataDelegate tableScroll:self NAME##At:r:c];\
  137.         }\
  138.     id cell = [self cellAt:r:c];\
  139.     if (cell != 0 && [cell respondsTo:@selector(NAME)])\
  140.         return [cell NAME];\
  141.     return 0;\
  142.     }
  143.  
  144. MISC_CELL_VAL( int, tag )                        // tagAt::
  145. MISC_CELL_VAL( int, intValue )                    // intValueAt::
  146. MISC_CELL_VAL( float, floatValue )                // floatValueAt::
  147. MISC_CELL_VAL( double, doubleValue )            // doubleValueAt::
  148. MISC_CELL_VAL( char const*, stringValue )        // stringValueAt::
  149. MISC_CELL_VAL( int, state )                        // stateAt::
  150. MISC_CELL_VAL( char const*, title )                // titleAt::
  151. #undef MISC_CELL_VAL
  152.  
  153.  
  154. //-----------------------------------------------------------------------------
  155. // - buffCount
  156. //        For lazy-mode tables that perform multiple-buffering.  This can
  157. //        avoid copying when accessing more than one cell at a time (such
  158. //        as during sorting.)
  159. //-----------------------------------------------------------------------------
  160. - (int) buffCount
  161.     {
  162.     if (delegate != 0 &&
  163.         [delegate respondsTo:@selector(tableScrollBuffCount:)])
  164.         return [delegate tableScrollBuffCount:self];
  165.     if (dataDelegate != 0 &&
  166.         [dataDelegate respondsTo:@selector(tableScrollBuffCount:)])
  167.         return [dataDelegate tableScrollBuffCount:self];
  168.     return 1;
  169.     }
  170.  
  171.  
  172. //-----------------------------------------------------------------------------
  173. // - expandIfNeeded
  174. //-----------------------------------------------------------------------------
  175. - (void) expandIfNeeded
  176.     {
  177.     int const num_cells = max_rows * num_cols;
  178.     if (num_cells > max_cells)
  179.         {
  180.         NXZone* const z = [self zone];
  181.         int const nbytes = num_cells * sizeof(*cells);
  182.         if (max_cells == 0)
  183.             cells = (id*) NXZoneMalloc( z, nbytes );
  184.         else
  185.             cells = (id*) NXZoneRealloc( z, cells, nbytes );
  186.         max_cells = num_cells;
  187.         }
  188.     }
  189.  
  190.  
  191. //-----------------------------------------------------------------------------
  192. // - lazyInsertColAt:
  193. //-----------------------------------------------------------------------------
  194. - (void) lazyInsertColAt:(int)n
  195.     {
  196.     colInfo.border->insertAt(n,n);        // FIXME: Check this.
  197.     num_cols++;
  198.     }
  199.  
  200.  
  201. //-----------------------------------------------------------------------------
  202. // - eagerInsertColAt:
  203. //-----------------------------------------------------------------------------
  204. - (void) eagerInsertColAt:(int)n
  205.     {
  206.     assert( 0 <= n );  assert( n <= num_cols );
  207.     assert( 0 < num_cols );                // lazyInsert must increment num_cols.
  208.  
  209.     if (max_rows > 0 || num_rows > 0)
  210.         {
  211.         if (max_rows == 0)
  212.             max_rows = num_rows;
  213.         [self expandIfNeeded];
  214.         int const num_new = num_cols;
  215.         int const num_old = num_cols - 1;
  216.         if (num_old > 0)                // Shift old, existing cells.
  217.             {
  218.             int const frag = num_old - n; // #cols right of insert col.
  219.             id* src = cells + (max_rows * num_old) - frag;
  220.             id* dst = cells + (max_rows * num_new) - frag;
  221.             if (frag > 0)                // Last partial row.
  222.                 memmove( dst, src, frag * sizeof(*dst) );
  223.  
  224.             int const nbytes = num_old * sizeof(*dst);
  225.             src -= num_old;
  226.             dst -= num_new;
  227.             while (src > cells)            // All full rows.
  228.                 {
  229.                 memmove( dst, src, nbytes );
  230.                 src -= num_old;
  231.                 dst -= num_new;
  232.                 }
  233.             }
  234.         int row = 0;
  235.         id const proto = colInfo.border->getPrototype_P(n);
  236.         id* const plim = cells + (max_rows * num_new);
  237.         id* p = cells + n;
  238.         while (p < plim)                // Initialize cells in new column.
  239.             {
  240.             *p = [self reviveCell:[proto copy] at:row++ :n];
  241.             p += num_new;
  242.             }
  243.         }
  244.     }
  245.  
  246.  
  247. //-----------------------------------------------------------------------------
  248. // - insertColAt:
  249. //-----------------------------------------------------------------------------
  250. - insertColAt:(int)n
  251.     {
  252.     if (0 <= n && n <= num_cols)
  253.         {
  254.         [self lazyInsertColAt:n];
  255.         if (!lazy)
  256.             [self eagerInsertColAt:n];
  257.         [self constrainSize];
  258.         [self update];
  259.         return self;
  260.         }
  261.     return 0;
  262.     }
  263.  
  264.  
  265. //-----------------------------------------------------------------------------
  266. // - addCol
  267. //-----------------------------------------------------------------------------
  268. - addCol
  269.     {
  270.     return [self insertColAt: num_cols];
  271.     }
  272.  
  273.  
  274. //-----------------------------------------------------------------------------
  275. // - lazyDeleteColAt:
  276. //-----------------------------------------------------------------------------
  277. - (void) lazyDeleteColAt:(int)n
  278.     {
  279.     colInfo.border->deleteAt_P(n);
  280.     num_cols--;
  281.     }
  282.  
  283.  
  284. //-----------------------------------------------------------------------------
  285. // - eagerDeleteColAt:
  286. //-----------------------------------------------------------------------------
  287. - (void) eagerDeleteColAt:(int)n
  288.     {
  289.     assert( 0 < num_cols );
  290.     assert( 0 <= n );  assert( n < num_cols );
  291.     if (max_rows > 0)
  292.         {
  293.         int const num_old = num_cols;
  294.         int const num_new = num_cols - 1;
  295.         id* dst = cells + n;
  296.         id* src = dst + 1;
  297.         id* const dst_lim = cells + (num_old * max_rows);
  298.         while (dst < dst_lim)            // Destroy deleted cells.
  299.             {
  300.             [*dst free];
  301.             dst += num_old;
  302.             }
  303.         if (num_new > 0)                // Shift remaining columns.
  304.             {
  305.             dst = cells + n;
  306.             int const nbytes = num_new * sizeof(*dst);
  307.             id* const src_lim = cells + (max_rows - 1) * num_old + n;
  308.             while (src < src_lim)
  309.                 {
  310.                 memmove( dst, src, nbytes );
  311.                 dst += num_new;
  312.                 src += num_old;
  313.                 }
  314.             if (n < num_new)            // Shift last partial row.
  315.                 memmove( dst, src, (num_new - n) * sizeof(*dst) );
  316.             }
  317.         else // (num_new <= 0)
  318.             {
  319.             max_rows = 0;
  320.             }
  321.         }
  322.     }
  323.  
  324.  
  325. //-----------------------------------------------------------------------------
  326. // - deleteColAt:
  327. //-----------------------------------------------------------------------------
  328. - deleteColAt:(int)n
  329.     {
  330.     if (0 <= n && n < num_cols)
  331.         {
  332.         if (!lazy)
  333.             [self eagerDeleteColAt:n];
  334.         [self lazyDeleteColAt:n];
  335.         [self constrainSize];
  336.         [self update];
  337.         return self;
  338.         }
  339.     return 0;
  340.     }
  341.  
  342.  
  343. //-----------------------------------------------------------------------------
  344. // - numCols
  345. //-----------------------------------------------------------------------------
  346. - (int) numCols
  347.     {
  348.     return num_cols;
  349.     }
  350.  
  351.  
  352. //-----------------------------------------------------------------------------
  353. // - lazyInsertRowAt:
  354. //-----------------------------------------------------------------------------
  355. - (void) lazyInsertRowAt:(int)n
  356.     {
  357.     rowInfo.border->insertAt(n,n);        // FIXME.  Check this.
  358.     num_rows++;
  359.     }
  360.  
  361.  
  362. //-----------------------------------------------------------------------------
  363. // - eagerInsertRowAt:
  364. //-----------------------------------------------------------------------------
  365. - (void) eagerInsertRowAt:(int)n
  366.     {
  367.     assert( 0 < num_rows );                // lazy-insert must increment num_rows
  368.     assert( 0 <= n );  assert( n < num_rows );
  369.  
  370.     if (num_cols > 0)
  371.         {
  372.         max_rows++;                                // Incremental growth.
  373.         assert( num_rows <= max_rows );
  374.         [self expandIfNeeded];
  375.  
  376.         int const old_max = max_rows - 1;
  377.         id* p = cells + n * num_cols;
  378.         if (n < old_max)                        // Shift other rows.
  379.             {
  380.             id* src = p;
  381.             id* dst = src + num_cols;
  382.             memmove( dst, src, (old_max - n) * num_cols * sizeof(*dst) );
  383.             }
  384.         MiscTableBorder* const bp = colInfo.border;
  385.         for (int c = 0;     c < num_cols;    c++)    // Initialize new cells.
  386.             *p++ = [self reviveCell:[bp->getPrototype_P(c) copy] at:n :c];
  387.         }
  388.     }
  389.  
  390.  
  391. //-----------------------------------------------------------------------------
  392. // - insertRowAt:
  393. //-----------------------------------------------------------------------------
  394. - insertRowAt:(int)n
  395.     {
  396.     if (0 <= n && n <= num_rows)
  397.         {
  398.         [self lazyInsertRowAt:n];
  399.         if (!lazy)
  400.             [self eagerInsertRowAt:n];
  401.         [self constrainSize];
  402.         [self update];
  403.         return self;
  404.         }
  405.     return 0;
  406.     }
  407.  
  408.  
  409. //-----------------------------------------------------------------------------
  410. // - eagerAddRow
  411. //
  412. // NOTE *1*
  413. //        We always initialize new rows when they are created, so if num_rows
  414. //        is less than max_rows, the new row has already been initialized.
  415. //
  416. // NOTE *2*
  417. //        The initialization loop is organized in column-major order because
  418. //        we want to maximize locality of reference for both code and data
  419. //        during the -copy calls.
  420. //-----------------------------------------------------------------------------
  421. - (void) eagerAddRow
  422.     {
  423.     assert( 0 < num_rows );        // lazy insertRowAt: must increment num_rows.
  424.     if (num_cols > 0)
  425.         {
  426.         if (num_rows >= max_rows)                        // NOTE *1*
  427.             {
  428.             int const MISC_TS_MAX_ROWS = ((INT_MAX >> 1) + 1);
  429.             assert( num_rows <= MISC_TS_MAX_ROWS );
  430.  
  431.             int const old_max = max_rows;
  432.             int n = ( max_rows ? max_rows : 16 );
  433.             while (n < num_rows)
  434.                 n <<= 1;
  435.             int const new_max = max_rows = n;
  436.  
  437.             [self expandIfNeeded];
  438.             id* p0 = cells + old_max * num_cols;
  439.             for (int c = 0;     c < num_cols;    c++)        // NOTE *2*
  440.                 {
  441.                 id const proto = colInfo.border->getPrototype_P(c);
  442.                 id* p = p0++;
  443.                 id* const plim = p + (new_max - old_max) * num_cols;
  444.                 while (p < plim)
  445.                     {
  446.                     *p = [proto copy];                    // Initialize new cells.
  447.                     p += num_cols;
  448.                     }
  449.                 }
  450.             }
  451.         int const row = num_rows - 1;
  452.         id* p = cells + (num_cols * row);
  453.         for (int col = 0;  col < num_cols;    col++)
  454.             *p++ = [self reviveCell:*p at:row :col];
  455.         }
  456.     }
  457.  
  458.  
  459. //-----------------------------------------------------------------------------
  460. // - addRow
  461. //
  462. // NOTE: We explicitly do NOT -constrainSize and -update here, because we
  463. // expect that the user will call this routine many times successively.
  464. //-----------------------------------------------------------------------------
  465. - addRow
  466.     {
  467.     [self lazyInsertRowAt:num_rows];
  468.     if (!lazy)
  469.         [self eagerAddRow];
  470.     return self;
  471.     }
  472.  
  473.  
  474. //-----------------------------------------------------------------------------
  475. // - lazyDeleteRowAt:
  476. //-----------------------------------------------------------------------------
  477. - (void) lazyDeleteRowAt:(int)n
  478.     {
  479.     rowInfo.border->deleteAt_P(n);
  480.     num_rows--;
  481.     }
  482.  
  483.  
  484. //-----------------------------------------------------------------------------
  485. // - eagerDeleteRowAt:
  486. //-----------------------------------------------------------------------------
  487. - (void) eagerDeleteRowAt:(int)n
  488.     {
  489.     assert( 0 < num_rows );
  490.     assert( 0 <= n );  assert( n < num_rows );
  491.     if (num_cols > 0)
  492.         {
  493.         assert( num_rows <= max_rows );
  494.         max_rows--;
  495.         id* const dst = cells + (n * num_cols );
  496.         id* p = dst;
  497.         id* const plim = p + num_cols;
  498.         while (p < plim)        // Destroy the cells.
  499.             {
  500.             [*p free];
  501.             p++;
  502.             }
  503.         if (n < max_rows)
  504.             memmove( dst, plim, (max_rows - n) * num_cols * sizeof(*dst) );
  505.         }
  506.     }
  507.  
  508.  
  509. //-----------------------------------------------------------------------------
  510. // - deleteRowAt:
  511. //-----------------------------------------------------------------------------
  512. - deleteRowAt:(int)n
  513.     {
  514.     if (0 <= n && n < num_rows)
  515.         {
  516.         if (!lazy)
  517.             [self eagerDeleteRowAt:n];
  518.         [self lazyDeleteRowAt:n];
  519.         [self constrainSize];
  520.         [self update];
  521.         return self;
  522.         }
  523.     return 0;
  524.     }
  525.  
  526.  
  527. //-----------------------------------------------------------------------------
  528. // - numRows
  529. //-----------------------------------------------------------------------------
  530. - (int) numRows
  531.     {
  532.     return num_rows;
  533.     }
  534.  
  535.  
  536. //-----------------------------------------------------------------------------
  537. // - lazyRenewRows:
  538. //-----------------------------------------------------------------------------
  539. - (void) lazyRenewRows:(int)n
  540.     {
  541.     rowInfo.border->setCount(n);
  542.     num_rows = n;
  543.     }
  544.  
  545.  
  546. //-----------------------------------------------------------------------------
  547. // - eagerRenewRows:
  548. //
  549. // NOTE *1*
  550. //        Since we initialize all cells when they are allocated, we only have
  551. //        to do extra work if we need to allocate more rows.
  552. //
  553. // NOTE *2*
  554. //        The initialization loop is organized in column-major order to
  555. //        increase locality of reference for both code and data during the
  556. //        call to -copy.
  557. //-----------------------------------------------------------------------------
  558. - (void) eagerRenewRows:(int)n
  559.     {
  560.     assert( 0 <= n );
  561.     if (num_cols > 0)
  562.         {
  563.         int const old_num_rows = num_rows;
  564.         int const new_num_rows = n;
  565.         if (n > max_rows)                                // NOTE *1*
  566.             {
  567.             int const max_old = max_rows;
  568.             int const max_new = max_rows = n;
  569.             [self expandIfNeeded];
  570.             id* p0 = cells + max_old * num_cols;
  571.             id* const plim = cells + max_new * num_cols;
  572.             for (int c = 0; c < num_cols; c++)            // NOTE *2*
  573.                 {
  574.                 id* p = p0++;
  575.                 id const proto = colInfo.border->getPrototype_P(c);
  576.                 while (p < plim)
  577.                     {
  578.                     *p = [proto copy];
  579.                     p += num_cols;
  580.                     }
  581.                 }
  582.             }
  583.         if (old_num_rows < new_num_rows)                // Growing
  584.             {
  585.             id* p0 = cells + old_num_rows * num_cols;
  586.             id* const plim = cells + new_num_rows * num_cols;
  587.             for (int c = 0; c < num_cols; c++)            // NOTE *2*
  588.                 {
  589.                 int r = old_num_rows;
  590.                 id* p = p0++;
  591.                 while (p < plim)
  592.                     {
  593.                     *p = [self reviveCell:*p at:r++ :c];
  594.                     p += num_cols;
  595.                     }
  596.                 }
  597.             }
  598.         else if (old_num_rows > new_num_rows)            // Shrinking
  599.             {
  600.             id* p0 = cells + new_num_rows * num_cols;
  601.             id* const plim = cells + old_num_rows * num_cols;
  602.             for (int c = 0; c < num_cols; c++)            // NOTE *2*
  603.                 {
  604.                 int r = new_num_rows;
  605.                 id* p = p0++;
  606.                 while (p < plim)
  607.                     {
  608.                     *p = [self retireCell:*p at:r++ :c];
  609.                     p += num_cols;
  610.                     }
  611.                 }
  612.             }
  613.         }
  614.     }
  615.  
  616.  
  617. //-----------------------------------------------------------------------------
  618. // - renewRows:
  619. //-----------------------------------------------------------------------------
  620. - renewRows:(int)n
  621.     {
  622.     [self clearSelection];
  623.     if (0 <= n && n != num_rows)
  624.         {
  625.         if (!lazy)
  626.             [self eagerRenewRows:n];
  627.         [self lazyRenewRows:n];
  628.         }
  629.     [self constrainSize];
  630.     [self update];
  631.     return self;
  632.     }
  633.  
  634.  
  635. //-----------------------------------------------------------------------------
  636. // - empty
  637. //-----------------------------------------------------------------------------
  638. - empty
  639.     {
  640.     return [self renewRows:0];
  641.     }
  642.  
  643.  
  644. //-----------------------------------------------------------------------------
  645. // - freeCells
  646. //-----------------------------------------------------------------------------
  647. - (void) freeCells
  648.     {
  649.     if (max_rows > 0 && num_cols > 0)
  650.         {
  651.         id* p0 = cells;
  652.         for (int c = 0;     c < num_cols;    c++)
  653.             {
  654.             id* p = p0++;
  655.             for (int r = 0;     r < max_rows;    r++)
  656.                 {
  657.                 [*p free];
  658.                 p += num_cols;
  659.                 }
  660.             }
  661.         }
  662.     if (cells != 0)
  663.         NXZoneFree( [self zone], cells );
  664.     cells = 0;
  665.     max_cells = 0;
  666.     max_rows = 0;
  667.     }
  668.  
  669.  
  670. //-----------------------------------------------------------------------------
  671. // - emptyAndFreeCells
  672. //-----------------------------------------------------------------------------
  673. - emptyAndFreeCells
  674.     {
  675.     [self empty];
  676.     [self freeCells];
  677.     return self;
  678.     }
  679.  
  680.  
  681. //-----------------------------------------------------------------------------
  682. // - setLazy:
  683. //-----------------------------------------------------------------------------
  684. - (void) setLazy:(BOOL)flag
  685.     {
  686.     if (lazy != flag)
  687.         {
  688.         lazy = flag;
  689.         if (lazy)
  690.             [self freeCells];
  691.         else
  692.             [self eagerRenewRows:num_rows];
  693.         }
  694.     }
  695.  
  696.  
  697. //-----------------------------------------------------------------------------
  698. // - isLazy
  699. //-----------------------------------------------------------------------------
  700. - (BOOL) isLazy
  701.     {
  702.     return lazy;
  703.     }
  704.  
  705.  
  706. //-----------------------------------------------------------------------------
  707. // Generic Slot methods
  708. //-----------------------------------------------------------------------------
  709. - addSlot:(MiscBorderType)b
  710.         { return (b == MISC_COL_BORDER) ? [self addCol] : [self addRow]; }
  711.  
  712. - border:(MiscBorderType)b insertSlotAt:(int)n
  713.         { return (b == MISC_COL_BORDER) ?
  714.                 [self insertColAt:n] : [self insertRowAt:n]; }
  715.  
  716. - border:(MiscBorderType)b deleteSlotAt:(int)n
  717.         { return (b == MISC_COL_BORDER) ?
  718.                 [self deleteColAt:n] : [self deleteRowAt:n]; }
  719.  
  720. - (int) numSlots:(MiscBorderType)b
  721.         { return (b == MISC_COL_BORDER) ? [self numCols] : [self numRows]; }
  722.  
  723.  
  724. //-----------------------------------------------------------------------------
  725. // REVIVE
  726. //-----------------------------------------------------------------------------
  727. - doReviveCell:cell at:(int)row:(int)col
  728.     {
  729.     if (cell != 0)
  730.         {
  731.         if ([cell respondsTo:@selector(setOwner:)])
  732.             [cell setOwner:self];
  733.  
  734.         if ([cell respondsTo:@selector(setUseOwnerFont:)])
  735.             [cell setUseOwnerFont:YES];
  736.         if ([cell respondsTo:@selector(setUseOwnerTextColor:)])
  737.             [cell setUseOwnerTextColor:YES];
  738.         if ([cell respondsTo:@selector(setUseOwnerBackgroundColor:)])
  739.             [cell setUseOwnerBackgroundColor:YES];
  740.         if ([cell respondsTo:@selector(setUseOwnerHighlightTextColor:)])
  741.             [cell setUseOwnerHighlightTextColor:YES];
  742.         if ([cell respondsTo:@selector(setUseOwnerHighlightBackgroundColor:)])
  743.             [cell setUseOwnerHighlightBackgroundColor:YES];
  744.  
  745.         if ([cell respondsTo:@selector(setOwnerFont:)])
  746.             [cell setOwnerFont:[self font]];
  747.         else if ([cell respondsTo:@selector(setFont:)])
  748.             [cell setFont:[self font]];
  749.  
  750.         if ([cell respondsTo:@selector(setOwnerTextColor:)])
  751.             [cell setOwnerTextColor:[self textColor]];
  752.         else if ([cell respondsTo:@selector(setTextColor:)])
  753.             [cell setTextColor:[self textColor]];
  754.  
  755.         if ([cell respondsTo:@selector(setOwnerBackgroundColor:)])
  756.             [cell setOwnerBackgroundColor:[self backgroundColor]];
  757.         else if ([cell respondsTo:@selector(setBackgroundColor:)])
  758.             [cell setBackgroundColor:[self backgroundColor]];
  759.  
  760.         if ([cell respondsTo:@selector(setOwnerHighlightTextColor:)])
  761.             [cell setOwnerHighlightTextColor:[self highlightTextColor]];
  762.         else if ([cell respondsTo:@selector(setHighlightTextColor:)])
  763.             [cell setHighlightTextColor:[self highlightTextColor]];
  764.  
  765.         if ([cell respondsTo:@selector(setOwnerHighlightBackgroundColor:)])
  766.             [cell setOwnerHighlightBackgroundColor:
  767.                                         [self highlightBackgroundColor]];
  768.         else if ([cell respondsTo:@selector(setHighlightBackgroundColor:)])
  769.             [cell setHighlightBackgroundColor:[self highlightBackgroundColor]];
  770.         }
  771.     return cell;
  772.     }
  773.  
  774.  
  775. - reviveCell:cell at:(int)row :(int)col
  776.     {
  777.     if (delegate != 0 &&
  778.         [delegate respondsTo:@selector(tableScroll:reviveCell:at: :)])
  779.         return [delegate tableScroll:self reviveCell:cell at:row :col];
  780.  
  781.     if (dataDelegate != 0 &&
  782.         [dataDelegate respondsTo:@selector(tableScroll:reviveCell:at: :)])
  783.         return [dataDelegate tableScroll:self reviveCell:cell at:row :col];
  784.  
  785.     if (cell != 0 && [cell respondsTo:@selector(tableScroll:reviveAt: :)])
  786.         return [cell tableScroll:self reviveAt:row :col];
  787.  
  788.     return [self doReviveCell:cell at:row :col];
  789.     }
  790.  
  791.  
  792. //-----------------------------------------------------------------------------
  793. // RETIRE
  794. //-----------------------------------------------------------------------------
  795. - doRetireCell:cell at:(int)row:(int)col
  796.     {
  797.     if ([cell respondsTo:@selector(type)] && [cell type] == NX_ICONCELL)
  798.         [cell setIcon:0];
  799.     else if ([cell respondsTo:@selector(setTitle:)])
  800.         [cell setTitle:""];
  801.     else if ([cell respondsTo:@selector(setStringValueNoCopy:)])
  802.         [cell setStringValueNoCopy:""];
  803.     else if ([cell respondsTo:@selector(setStringValue:)])
  804.         [cell setStringValue:""];
  805.     return cell;
  806.     }
  807.  
  808.  
  809. - retireCell:cell at:(int)row:(int)col
  810.     {
  811.     if (delegate != 0 &&
  812.         [delegate respondsTo:@selector(tableScroll:retireCell:at: :)])
  813.         return [delegate tableScroll:self retireCell:cell at:row :col];
  814.  
  815.     if (dataDelegate != 0 &&
  816.         [dataDelegate respondsTo:@selector(tableScroll:retireCell:at: :)])
  817.         return [dataDelegate tableScroll:self retireCell:cell at:row :col];
  818.  
  819.     if (cell != 0 && [cell respondsTo:@selector(tableScroll:retireAt: :)])
  820.         return [cell tableScroll:self retireAt:row :col];
  821.  
  822.     return [self doRetireCell:cell at:row :col];
  823.     }
  824.  
  825. @end
  826.