home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / mac / UserInterface / Tables / LTableRowSelector.cp < prev    next >
Encoding:
Text File  |  1998-04-08  |  10.6 KB  |  465 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /*
  20.     
  21.     Created 3/25/96 - Tim Craycroft
  22.  
  23.     To Do: fix DragSelect
  24. */
  25.  
  26.  
  27. #include "LTableRowSelector.h"
  28.  
  29. #include "CStandardFlexTable.h"
  30.  
  31. /*
  32.     LTableRowSelector::LTableRowSelector
  33. */
  34. LTableRowSelector::LTableRowSelector(LTableView *inTableView, Boolean inAllowMultiple)
  35. :    LTableSelector(inTableView)
  36. ,    LArray(1)
  37. ,    mAnchorRow(0)
  38. ,    mExtensionRow(0)
  39. ,    mAllowMultiple(inAllowMultiple)
  40. ,    mSelectedRowCount(0)
  41. {
  42. }
  43.  
  44. // TSM - Added two methods below for compatibility with PP 1.5
  45.  
  46. /*
  47.     GetFirstSelectedCell
  48.     
  49.     Return the first selected cell, defined as the min row & col (closest to
  50.     top-left corner). Return (0, 0) if no cell is selected.
  51. */
  52. STableCell
  53. LTableRowSelector::GetFirstSelectedCell() const
  54. {
  55.     TableIndexT firstSelectedRow = GetFirstSelectedRow();
  56.     
  57.     return (firstSelectedRow ? STableCell(firstSelectedRow, 1) : STableCell(0, 0));
  58. }
  59.  
  60.  
  61. /*
  62.     GetFirstSelectedRow
  63.     
  64.     Return the first selected cell's row, defined as the min row & col (closest to
  65.       top-left corner). Return 0 if no row is selected.
  66. */
  67. TableIndexT
  68. LTableRowSelector::GetFirstSelectedRow() const
  69. {
  70.     if ( GetSelectedRowCount() > 0 ) {
  71.         // We have selected cells
  72.         STableCell curCell(1, 1);
  73.         TableIndexT endRow, numCol;
  74.         mTableView->GetTableSize(endRow, numCol);
  75.         
  76.         Assert_(endRow >= 1);    // If (mSelectedRowCount > 0), should always have (endRow >= 1)!
  77.         do {
  78.             if ( CellIsSelected(curCell) ) {
  79.                 // This is our first row
  80.                 return curCell.row;
  81.             }
  82.         } while ( ++curCell.row <= endRow );
  83.     }
  84.     
  85.     return 0;
  86. }
  87.  
  88.  
  89. /*
  90.     LTableRowSelector::CellIsSelected
  91. */
  92. Boolean
  93. LTableRowSelector::CellIsSelected(const STableCell    &inCell) const
  94. {
  95.     char item;
  96.     
  97.     FetchItemAt(inCell.row, &item);
  98.     return (item != 0);
  99. }
  100.  
  101.  
  102. /*
  103.     LTableRowSelector::SelectCell
  104. */
  105. void    
  106. LTableRowSelector::SelectCell(const STableCell    &inCell)
  107. {
  108.     if (mSelectedRowCount == 0)
  109.     {
  110.         // We must maintain the anchor row even if called without clicking.
  111.         // Bug #57637 mcmullen 97/04/29.  In particular, for key selection,
  112.         // UnselectAllCells will be called before reselecting, so we can use
  113.         // an empty selection as the prerequisite for resetting the anchor row.
  114.         mAnchorRow = inCell.row;
  115.         mExtensionRow    = mAnchorRow;
  116.     }
  117.     DoSelect(inCell.row, true, true, true);
  118. }
  119.     
  120. /*
  121.     LTableRowSelector::UnselectCell
  122. */
  123. void        
  124. LTableRowSelector::UnselectCell(const STableCell &inCell)
  125. {
  126.     DoSelect(inCell.row, false, true, true);
  127.     if (inCell.row == mAnchorRow)
  128.     {
  129.         mAnchorRow         = 0;
  130.         mExtensionRow     = 0;
  131.     }
  132. }
  133.  
  134. /*
  135.     LTableRowSelector::DoSelect
  136. */
  137. void
  138. LTableRowSelector::DoSelect(    const TableIndexT     inRow, 
  139.                                 Boolean             inSelect, 
  140.                                 Boolean             inHilite,
  141.                                 Boolean                inNotify    )
  142. {
  143.     if (inRow < 1 || inRow > GetCount())
  144.         return;
  145.     
  146.     char oldRowValue;
  147.     FetchItemAt(inRow, &oldRowValue);
  148.     char newRowValue = (inSelect) ? 1 : 0;        
  149.     if (newRowValue == oldRowValue)
  150.         return;
  151.     // mark the row's new selected state
  152.     AssignItemsAt(1, inRow, &newRowValue);
  153.     // Maintain the count
  154.     if (inSelect)
  155.         mSelectedRowCount++;
  156.     else
  157.         mSelectedRowCount--;    
  158.  
  159.     // hilite (or unhilite) the entire row
  160.     if (inHilite)
  161.     {
  162.         CStandardFlexTable* sft = dynamic_cast<CStandardFlexTable*>(mTableView);
  163.         if (sft)
  164.             sft->HiliteRow(inRow, inSelect);
  165.         else
  166.         {
  167.             UInt32 nCols, nRows;            
  168.             mTableView->GetTableSize(nRows, nCols);
  169.             
  170.             STableCell    cell(inRow, 1);
  171.             cell.row = inRow;
  172.             
  173.             for (cell.col = 1;  cell.col <= nCols; cell.col++)
  174.             {
  175.                 mTableView->HiliteCell(cell, inSelect);
  176.             }
  177.         }
  178.     }
  179.  
  180.     if (inNotify)
  181.         mTableView->SelectionChanged();
  182. } // LTableRowSelector::DoSelect
  183.  
  184. /*
  185.     LTableRowSelector::SelectAllCells
  186. */
  187. void    
  188. LTableRowSelector::SelectAllCells()
  189. {
  190.     DoSelectAll(true, true);
  191. }
  192.  
  193. /*
  194.     LTableRowSelector::UnselectAllCells
  195. */
  196. void
  197. LTableRowSelector::UnselectAllCells()
  198. {
  199.     if ( mSelectedRowCount > 0 ) {
  200.         DoSelectAll(false, true);
  201.         mSelectedRowCount = 0; // to be safe
  202.     }
  203. }
  204.  
  205. /*
  206.     LTableRowSelector::DoSelectAll
  207. */
  208. void
  209. LTableRowSelector::DoSelectAll(Boolean inSelect, Boolean inNotify)
  210. {
  211.     UInt32 nCols, nRows;
  212.     mTableView->GetTableSize(nRows, nCols);
  213.  
  214.     if (nRows) // Prevents bug: DoSelectRange won't check!
  215.         DoSelectRange(1, nRows, inSelect, inNotify);
  216.     else
  217.     {
  218.         mSelectedRowCount = 0;
  219.         if (inNotify)
  220.             mTableView->SelectionChanged();
  221.     }
  222. }
  223.  
  224. /*
  225.     LTableRowSelector::DoSelectRange
  226.     
  227.     Selects a range of rows, where inFrom and inTo can
  228.     be in any order.
  229. */
  230. void
  231. LTableRowSelector::DoSelectRange(    TableIndexT    inFrom, 
  232.                                     TableIndexT inTo, 
  233.                                     Boolean     inSelect,
  234.                                     Boolean        inNotify    )
  235. {
  236.     TableIndexT    top, bottom;
  237.     STableCell    cell;
  238.     
  239.     // figure out our order
  240.     if (inTo > inFrom) 
  241.     {
  242.         top     = inFrom;
  243.         bottom     = inTo;
  244.     }
  245.     else
  246.     {
  247.         top     = inTo;
  248.         bottom  = inFrom;
  249.     }
  250.     cell.col = 1;
  251.     for (cell.row=top; cell.row <= bottom; cell.row++)
  252.         DoSelect(cell.row, inSelect, true, false);
  253.     if (inNotify)
  254.         mTableView->SelectionChanged();
  255. }
  256.  
  257. /*
  258.     LTableRowSelector::ExtendSelection
  259. */
  260. void
  261. LTableRowSelector::ExtendSelection( TableIndexT inRow)
  262. {
  263.     Assert_(mAllowMultiple);
  264.     
  265.     // mExtension row is the row to which we've 
  266.     // currently extended the selection
  267.     
  268.     // mAnchor row is the originally selected row
  269.  
  270.     if (mExtensionRow != inRow)
  271.     {
  272.         if (inRow > mExtensionRow) {
  273.             DoSelectRange(mExtensionRow+1, inRow, true, true);
  274.         }
  275.         else {
  276.              DoSelectRange(inRow, mExtensionRow-1, true, true);
  277.         }
  278.         
  279.         mExtensionRow = inRow;
  280.     }
  281. }
  282.  
  283. /*
  284.     LTableRowSelector::ClickSelect
  285. */
  286. void        
  287. LTableRowSelector::ClickSelect(    const STableCell        &inCell,
  288.                                 const SMouseDownEvent    &inMouseDown)
  289. {
  290.     // This code largely ripped off from PowerPlant's 
  291.     // LTableMultiSelector
  292.     //
  293.     
  294.     // Command-key discontiguous selection....
  295.     if (mAllowMultiple && (inMouseDown.macEvent.modifiers & cmdKey)!= 0)
  296.     {
  297.         //
  298.         
  299.         //
  300.         
  301.         if (CellIsSelected(inCell))
  302.         {
  303.             DoSelect(inCell.row, false, true, true);
  304.             mAnchorRow         = 0;
  305.             mExtensionRow     = 0;
  306.         }
  307.         else
  308.         {
  309.             DoSelect(inCell.row, true, true, true);
  310.             mAnchorRow         = inCell.row;
  311.             mExtensionRow    = mAnchorRow;
  312.         }
  313.     }
  314.     
  315.     // shift-key selection extension
  316.     else if ( mAllowMultiple && 
  317.                 ((inMouseDown.macEvent.modifiers & shiftKey) != 0) &&
  318.                 mAnchorRow != 0 )    
  319.     {    
  320.         ExtendSelection(inCell.row);
  321.     }
  322.     
  323.     // normal selection
  324.     else
  325.     {
  326.         mAnchorRow         = inCell.row;
  327.         mExtensionRow     = mAnchorRow;
  328.         
  329.         if (!CellIsSelected(inCell))
  330.         {
  331.             DoSelectAll(false, false);
  332.             DoSelect(inCell.row, true, true, true);
  333.         }
  334.     }
  335.     
  336. }
  337.                 
  338. /*
  339.     LTableRowSelector::DragSelect
  340. */    
  341. Boolean
  342. LTableRowSelector::DragSelect(    const STableCell        &inCell,
  343.                                 const SMouseDownEvent    &inMouseDown)
  344. {
  345.     // Again, largely ripped off from PowerPlant
  346.     ClickSelect(inCell, inMouseDown);
  347.     
  348.     STableCell    currCell = inCell;    
  349.     while (::StillDown()) 
  350.     {
  351.         STableCell    hitCell;
  352.         SPoint32    imageLoc;
  353.         Point        mouseLoc;
  354.         
  355.         ::GetMouse(&mouseLoc);
  356.         if (mTableView->AutoScrollImage(mouseLoc)) 
  357.         {
  358.             mTableView->FocusDraw();
  359.             Rect    frame;
  360.             mTableView->CalcLocalFrameRect(frame);
  361.             Int32 pt = ::PinRect(&frame, mouseLoc);
  362.             mouseLoc = *(Point*)&pt;
  363.         }
  364.         
  365.         mTableView->LocalToImagePoint(mouseLoc, imageLoc);
  366.         mTableView->GetCellHitBy(imageLoc, hitCell);
  367.         if (mTableView->IsValidCell(hitCell) &&
  368.             (currCell != hitCell)) 
  369.         {
  370.  
  371.             currCell = hitCell;
  372.         }
  373.         
  374.         
  375.         ExtendSelection(currCell.row);
  376.     }    
  377.     
  378.     return true;
  379. }
  380.     
  381. /*
  382.     LTableRowSelector::InsertRows
  383.     
  384.     Add space in our array for tracking the selected state of the new rows
  385. */    
  386. void        
  387. LTableRowSelector::InsertRows(    UInt32        inHowMany,
  388.                                 TableIndexT    inAfterRow)
  389. {
  390.     // Before inserting the cells, check for a selection
  391.     // change message.
  392.  
  393.     Boolean selectionChanged = false;
  394.     UInt32 nRows = GetCount();
  395.         //ÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
  396.         // WARNING: Don't ask the table for its size, it's changed already.
  397.         //ÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
  398.     // We loop from the insertion point to find any selected row.
  399.     for (TableIndexT row = inAfterRow + 1; row <= nRows; row++)
  400.     {
  401.         char item;
  402.         FetchItemAt(row, &item);
  403.         if (item)
  404.         {
  405.             selectionChanged = true;
  406.             break;
  407.         }
  408.     }
  409.     char unselectedItem = 0;
  410.     InsertItemsAt(inHowMany, inAfterRow + 1, &unselectedItem);
  411.         // jrm: I increment inAfterRow, because of the difference between "at" and "after".
  412.  
  413.     // The selection will be changed if we added any row before any selected row
  414.     // (because it will move down).
  415.     if (selectionChanged)
  416.         mTableView->SelectionChanged();
  417. }
  418.  
  419. /*
  420.     LTableRowSelector::RemoveRows
  421.     
  422.     Remove the space from our array.
  423. */    
  424. void
  425. LTableRowSelector::RemoveRows(    Uint32        inHowMany,
  426.                                 TableIndexT    inFromRow )
  427. {
  428.     // Before removing the cells, maintain the row count and check for a selection
  429.     // change message.
  430.     
  431.     TableIndexT lastRemovedRow = inFromRow + inHowMany - 1;
  432.     Boolean selectionChanged = false;
  433.     UInt32 nRows = GetCount();
  434.         //ÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
  435.         // WARNING: Don't ask the table for its size, it's changed already.
  436.         //ÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
  437.     // Loop from the first removed row to the end.
  438.     // Any selected row encountered before the last removed row is deducted
  439.     // from the tally.  Then we continue to find any selected
  440.     // row.  If we find one, then the selection will have changed.
  441.     // In the case when the removed range includes a selected row, this will
  442.     // loop to the end of the removed range, in order to maintain the
  443.     // selected row count.  In the case when the removed range does not include
  444.     // a selected row, this must loop beyond that range till it finds a
  445.     // selected row.
  446.     for (TableIndexT row = inFromRow; row <= nRows; row++)
  447.     {
  448.         char item;
  449.         FetchItemAt(row, &item);
  450.         if (item)
  451.         {
  452.             selectionChanged = true;
  453.             if (row <= lastRemovedRow)
  454.                 mSelectedRowCount--;
  455.             else
  456.                 break;
  457.         }
  458.     }
  459.     RemoveItemsAt(inHowMany, inFromRow);
  460.     // The selection will be changed if we removed any row up to the last selected row
  461.     // (because it will either have been removed, or it will move up).
  462.     if (selectionChanged)
  463.         mTableView->SelectionChanged();
  464. }                                
  465.