home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / OWLSRC.PAK / LISTWIND.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  14.7 KB  |  780 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // Copyright (c) 1995, 1997 by Borland International, All Rights Reserved
  4. //
  5. //$Revision:   10.17  $
  6. //
  7. // Implementation of TListWindow and support classes
  8. //----------------------------------------------------------------------------
  9. #include <owl/pch.h>
  10. #if !defined(OWL_LISTWIND_H)
  11. # include <owl/listwind.h>
  12. #endif
  13. #if !defined(WINSYS_SYSTEM_H)
  14. # include <winsys/system.h>
  15. #endif
  16.  
  17. OWL_DIAGINFO;
  18.  
  19. //
  20. // Constructor that creates a window
  21. //
  22. TListWindow::TListWindow(TWindow* parent, int id,
  23.   int x, int y, int w, int h, TModule* module)
  24. :
  25.   TControl(parent, id, 0, x, y, w, h, module)
  26. {
  27.   if (!TCommCtrl::IsAvailable())
  28.     throw TXCommCtrl();
  29.  
  30. #if defined(BI_PLAT_WIN32)
  31.   if (TSystem::Has3dUI())
  32.     Attr.ExStyle |= WS_EX_CLIENTEDGE;
  33. #endif
  34. }
  35.  
  36. //
  37. // Constructor from resource
  38. //
  39. TListWindow::TListWindow(TWindow* parent, int resourceId, TModule* module)
  40. :
  41.   TControl(parent, resourceId, module)
  42. {
  43.   if (!TCommCtrl::IsAvailable())
  44.     throw TXCommCtrl();
  45. }
  46.  
  47. //
  48. // Destructor
  49. //
  50. TListWindow::~TListWindow()
  51. {
  52. }
  53.  
  54. //----------------------------------------------------------------------------
  55. // TLwFindInfo
  56.  
  57. //
  58. // Constructor
  59. //
  60. TLwFindInfo::TLwFindInfo()
  61. {
  62.   Init();
  63. }
  64.  
  65. //
  66. // Construct based on existing structure.
  67. //
  68. TLwFindInfo::TLwFindInfo(LV_FINDINFO findInfo)
  69. {
  70.   *(LV_FINDINFO*)this = findInfo;
  71. }
  72.  
  73. //
  74. // Private Init to zero out all data members.
  75. //
  76. void
  77. TLwFindInfo::Init()
  78. {
  79.   flags  = 0;
  80.   psz    = 0;
  81.   lParam = 0;
  82. }
  83.  
  84. //
  85. // Set extra information.
  86. //
  87. void
  88. TLwFindInfo::SetData(TParam2 param)
  89. {
  90.   flags |= LVFI_PARAM;
  91.   lParam = param;
  92. }
  93.  
  94. //
  95. // Find partial string.
  96. //
  97. void
  98. TLwFindInfo::SetPartial(char far* text)
  99. {
  100.   flags |= LVFI_PARTIAL;
  101.   SetString(text);
  102. }
  103.  
  104. //
  105. // Find based on string information.
  106. //
  107. void
  108. TLwFindInfo::SetString(char far* text)
  109. {
  110.   flags |= LVFI_STRING;
  111.   psz = text;
  112. }
  113.  
  114. //
  115. // Find exact substring.
  116. //
  117. void
  118. TLwFindInfo::SetSubstring(char far* text)
  119. {
  120.   flags &= ~LVFI_PARTIAL;
  121.   SetString(text);
  122. }
  123.  
  124. //
  125. // Continue to search at beginning if reached the end.
  126. //
  127. void
  128. TLwFindInfo::SetWrap(bool flag)
  129. {
  130.   if (flag) {
  131.     flags |= LVFI_WRAP;
  132.   }
  133.   else {
  134.     flags &= ~LVFI_WRAP;
  135.   }
  136. }
  137.  
  138. //----------------------------------------------------------------------------
  139. // TLwHitTestInfo
  140.  
  141. //
  142. // Private Init() to zero out data members.
  143. //
  144. void
  145. TLwHitTestInfo::Init()
  146. {
  147.   pt.x  = 0;
  148.   pt.y  = 0;
  149.   flags = 0;
  150.   iItem = 0;
  151. }
  152.  
  153. //
  154. // Default constructor. Zero out everything.
  155. //
  156. TLwHitTestInfo::TLwHitTestInfo()
  157. {
  158.   Init();
  159. }
  160.  
  161. //
  162. // Construct based on an existing structure.
  163. //
  164. TLwHitTestInfo::TLwHitTestInfo(LV_HITTESTINFO info)
  165. {
  166.   *(LV_HITTESTINFO*)this = info;
  167. }
  168.  
  169. //
  170. // Initialize the point.
  171. //
  172. TLwHitTestInfo::TLwHitTestInfo(TPoint& p)
  173. {
  174.   Init();
  175.   SetPoint(p);
  176. }
  177.  
  178. //
  179. // Sets the point information
  180. //
  181. void
  182. TLwHitTestInfo::SetPoint(TPoint& p)
  183. {
  184.   pt.x = p.x;
  185.   pt.y = p.y;
  186. }
  187.  
  188. //----------------------------------------------------------------------------
  189. // TListWindItem
  190.  
  191. //
  192. // Create an item structure used primarily for retrieving information about
  193. // existing items within a Listview control.
  194. //
  195. TListWindItem::TListWindItem(uint msk /*= LVIF_ALL*/,
  196.                              bool allocCache /*= true*/)
  197. {
  198.   Init();
  199.   mask = msk;
  200.   if (allocCache) {
  201.     AllocCache(true);
  202.   }
  203. }
  204.  
  205. //
  206. // Construct based on an existing structure.
  207. //
  208. TListWindItem::TListWindItem(const LV_ITEM& item)
  209. {
  210.   // First do a shallow copy
  211.   //
  212.   *((LV_ITEM*)this) = item;
  213.  
  214.   // Deep copy text, if necessary
  215.   //
  216.   if( (item.mask & LVIF_TEXT) &&
  217.       item.pszText &&
  218.       item.pszText != LPSTR_TEXTCALLBACK )
  219.   {
  220.     AllocCache();
  221.     strncpy(pszText, item.pszText, _MAX_PATH);
  222.   }
  223. }
  224.  
  225. //
  226. // Construct based on text, column number, and length of text.
  227. //
  228. TListWindItem::TListWindItem(const char* text, int subItem, int len)
  229. {
  230.   Init();
  231.   SetText(text, len);
  232.   SetSubItem(subItem);
  233. }
  234.  
  235. //
  236. //
  237. //
  238. TListWindItem::TListWindItem(const TListWindow& ctl, int index, int subItem,
  239.                              uint msk /*= LVIF_ALL*/)
  240. {
  241.   PRECONDITION(ctl.GetHandle());
  242.   Init();
  243.   mask = msk;
  244.  
  245.   // Allocate room for text if we're retrieving it
  246.   //
  247.   if (mask & LVIF_TEXT) {
  248.     AllocCache();
  249.   }
  250.   ctl.GetItem(*this, index, subItem);
  251. }
  252.  
  253. //
  254. //
  255. //
  256. TListWindItem::~TListWindItem()
  257. {
  258.   // Cache's self-cleaning
  259. }
  260.  
  261. // Clear out all members
  262. //
  263. void
  264. TListWindItem::Init()
  265. {
  266.   memset((LV_ITEM*)this, 0, sizeof(LV_ITEM));
  267. }
  268.  
  269. //
  270. // Returns the text of the item.
  271. //
  272. void
  273. TListWindItem::GetText(char* buffer, int size) const
  274. {
  275.   if (mask & LVIF_TEXT) {
  276.     strncpy(buffer, pszText, size);
  277.   }
  278. }
  279.  
  280. //
  281. // Sets the text buffer.
  282. //
  283. void
  284. TListWindItem::SetText(const char* buffer, int size)
  285. {
  286.   mask |= LVIF_TEXT;
  287.   pszText = CONST_CAST(char*, buffer);
  288.   cchTextMax = ((size != 0) ? size : (buffer ? lstrlen(buffer) : 0));
  289. }
  290.  
  291. //
  292. // Sets the item's index number.
  293. //
  294. void
  295. TListWindItem::SetIndex(int index)
  296. {
  297.   iItem = index;
  298. }
  299.  
  300. //
  301. // Sets the column number.
  302. //
  303. void
  304. TListWindItem::SetSubItem(int subItem)
  305. {
  306.   iSubItem = subItem;
  307. }
  308.  
  309. //
  310. // Sets the additional data value.
  311. //
  312. void
  313. TListWindItem::SetItemData(uint32 data)
  314. {
  315.   mask  |= LVIF_PARAM;
  316.   lParam = data;
  317. }
  318.  
  319. //
  320. // Returns the additional data value.
  321. //
  322. uint32
  323. TListWindItem::GetItemData() const
  324. {
  325.   if (mask & LVIF_PARAM) {
  326.     return lParam;
  327.   }
  328.   return 0;
  329. }
  330.  
  331. //
  332. // Returns the image list index.
  333. //
  334. int
  335. TListWindItem::GetImageIndex() const
  336. {
  337.   if (mask & LVIF_IMAGE) {
  338.     return iImage;
  339.   }
  340.   return 0;
  341. }
  342.  
  343. //
  344. // Sets the image list index for the item.
  345. //
  346. void
  347. TListWindItem::SetImageIndex(int index)
  348. {
  349.   mask  |= LVIF_IMAGE;
  350.   iImage = index;
  351. }
  352.  
  353. //
  354. // Return the state of the item.
  355. //
  356. int
  357. TListWindItem::GetState() const
  358. {
  359.   if (mask & LVIF_STATE) {
  360.     return state;
  361.   }
  362.   return 0;
  363. }
  364.  
  365. //
  366. // Sets the state of the item.
  367. //
  368. void
  369. TListWindItem::SetState(TListState newState)
  370. {
  371.   mask      |= LVIF_STATE;
  372.   stateMask |= state;
  373.   state      = newState;
  374. }
  375.  
  376. //
  377. // Retrieve the image list index for the state.
  378. //
  379. int
  380. TListWindItem::GetStateImage() const
  381. {
  382.   if ((mask & LVIF_STATE) && (stateMask & LVIS_STATEIMAGEMASK))
  383.     return (state >> 12) - 1;
  384.   return -1;
  385. }
  386.  
  387. //
  388. // Sets the image list index for the state.
  389. //
  390. void
  391. TListWindItem::SetStateImage(int index)
  392. {
  393.   mask      |= LVIF_STATE;
  394.   stateMask |= LVIS_STATEIMAGEMASK;
  395.   state = INDEXTOSTATEIMAGEMASK(index+1);
  396. }
  397.  
  398. //
  399. //
  400. //
  401. void
  402. TListWindItem::AllocCache(bool setpszText /*= true*/)
  403. {
  404.   Cache = new char[_MAX_PATH];
  405.   if (setpszText)
  406.     SetText(Cache, _MAX_PATH);
  407. }
  408.  
  409. //
  410. //
  411. //
  412. void
  413. TListWindItem::FlushCache()
  414. {
  415.   Cache = 0;
  416. }
  417.  
  418. //----------------------------------------------------------------------------
  419. // TListWindColumn
  420.  
  421. //
  422. // Constructs a TListWindColumn object used to retrieve information about
  423. // an existing column. For example,
  424. //    TListWindColumn col;
  425. //    ListWnd->GetColumn(1, col);
  426. //    ShowString(col.GetText()
  427. //
  428. TListWindColumn::TListWindColumn(uint flags /*= 0*/, int subItem /*= 0*/)
  429. {
  430.   Init();
  431.   mask = flags;
  432.   SetSubItem(subItem);
  433.   if (flags & LVCF_TEXT)
  434.     AllocCache();
  435. }
  436.  
  437. //
  438. //
  439. //
  440. TListWindColumn::TListWindColumn(const TListWindow& ctl, int index,
  441.                                  uint flags  /*= LVCF_ALL*/,
  442.                                  int subItem /*= 0 */)
  443. {
  444.   PRECONDITION(ctl.GetHandle());
  445.   Init();
  446.   mask = flags;
  447.   SetSubItem(subItem);
  448.   if (flags & LVCF_TEXT)
  449.     AllocCache();
  450.   ctl.GetColumn(index, *this);
  451. }
  452.  
  453. //
  454. // Construct based on the text, width of the column, alignment, and column number
  455. //
  456. TListWindColumn::TListWindColumn(char* text, int width,
  457.                                  TFormat how /*= Left*/,
  458.                                  int subItem /*= 0*/)
  459. {
  460.   Init();
  461.   SetText(text);
  462.   SetFormat(how);
  463.   SetWidth(width, text);
  464.   SetSubItem(subItem);
  465. }
  466.  
  467. //
  468. //
  469. //
  470. TListWindColumn::~TListWindColumn()
  471. {
  472.   // Cache's self-cleaning
  473. }
  474.  
  475. //
  476. //
  477. //
  478. void
  479. TListWindColumn::Init()
  480. {
  481.   memset((LV_COLUMN*)this, 0, sizeof(LV_COLUMN));
  482. }
  483.  
  484. //
  485. // Construct based on exising structure.
  486. //
  487. TListWindColumn::TListWindColumn(const LV_COLUMN& column)
  488. {
  489.   mask       = column.mask;
  490.   fmt        = column.fmt;
  491.   cx         = column.cx;
  492.   pszText    = column.pszText;
  493.   cchTextMax = column.cchTextMax;
  494.   iSubItem   = column.iSubItem;
  495. }
  496.  
  497. //
  498. // Sets the text and buffer size of the column
  499. //
  500. void
  501. TListWindColumn::SetText(const char* text, int size)
  502. {
  503.   mask      |= LVCF_TEXT;
  504.   pszText    = CONST_CAST(char*, text);
  505.   cchTextMax = (size != 0) ? size : (text ? lstrlen(text) : 0);
  506. }
  507.  
  508. //
  509. // Sets the alignment for the column
  510. //
  511. void
  512. TListWindColumn::SetFormat(TFormat how)
  513. {
  514.   mask |= LVCF_FMT;
  515.   fmt   = int(how);
  516. }
  517.  
  518. //
  519. // Sets the width of the column
  520. // NOTE: Will compute a default width using the system's default GUI
  521. //       font and the text parameter if 'pixels=0' and 'txt != 0'.
  522. //
  523. void
  524. TListWindColumn::SetWidth(int pixels, char* txt /*= 0*/)
  525. {
  526.   mask |= LVCF_WIDTH;
  527.  
  528.   if (pixels) {
  529.     // Use user provided size
  530.     //
  531.     cx = pixels;
  532.   } else if (txt) {
  533.  
  534.     // Compute from text - if provided
  535.     //
  536.     cx = TDefaultGUIFont().GetTextExtent(txt).cx;
  537.   } else {
  538.  
  539.     // Should we use a better default width ??
  540.     //
  541.     cx = 0;
  542.   }
  543. }
  544.  
  545. //
  546. // Sets the column number
  547. //
  548. void
  549. TListWindColumn::SetSubItem(int item)
  550. {
  551.   mask    |= LVCF_SUBITEM;
  552.   iSubItem = item;
  553. }
  554.  
  555. //
  556. //
  557. //
  558. void
  559. TListWindColumn::AllocCache(bool setpszText /*= true*/)
  560. {
  561.   Cache = new char[_MAX_PATH];
  562.   if (setpszText)
  563.     SetText(Cache, _MAX_PATH);
  564. }
  565.  
  566. //
  567. //
  568. //
  569. void
  570. TListWindColumn::FlushCache()
  571. {
  572.   // First make sure 'pszText' does not point to dangling memory
  573.   //
  574.   if (pszText == Cache) {
  575.     pszText = 0;
  576.     mask &= ~LVCF_TEXT;
  577.   }
  578.   Cache = 0;
  579. }
  580.  
  581. //----------------------------------------------------------------------------
  582. // TListWindow
  583.  
  584. //
  585. // Return the proper class name.
  586. //
  587. char far*
  588. TListWindow::GetClassName()
  589. {
  590.   return WC_LISTVIEW;
  591. }
  592.  
  593. //
  594. // Sets the state of the item
  595. //
  596. bool
  597. TListWindow::SetItemState(int index, uint state, uint mask)
  598. {
  599.   LV_ITEM item;
  600.   item.state = state;
  601.   item.stateMask = mask;
  602.   return ToBool(SendMessage(LVM_SETITEMSTATE, index, TParam2(&item)));
  603. }
  604.  
  605. //
  606. // Create a temporary structure to store additional information for the
  607. // comparison object.
  608. //
  609. struct TListCompareThunk {
  610.   const TLwComparator* This;
  611.   uint32               ItemData;
  612. };
  613.  
  614. int CALLBACK OWL_EXPORT16
  615. OwlListViewCompare(uint32 itemData1, uint32 itemData2, uint32 lParam)
  616. {
  617.   TListCompareThunk* ct = (TListCompareThunk*)lParam;
  618.   return ct->This->Compare(itemData1, itemData2, ct->ItemData);
  619. }
  620.  
  621. //
  622. // Sort the items within the List Window.
  623. // TLwComparator is the base class for the comparison function
  624. //
  625. bool
  626. TListWindow::SortItems(const TLwComparator& comparator, uint32 lParam)
  627. {
  628.   TListCompareThunk ct;
  629.   ct.This = &comparator;
  630.   ct.ItemData = lParam;
  631.   return ToBool(SendMessage(LVM_SORTITEMS, TParam1(&ct), TParam2(OwlListViewCompare)));
  632. }
  633.  
  634. //
  635. // Return the number of items currently selected.
  636. // (Useful before calling GetSelIndexes.)
  637. //
  638. int
  639. TListWindow::GetSelCount() const
  640. {
  641.   return CONST_CAST(TListWindow*, this)->SendMessage(LVM_GETSELECTEDCOUNT);
  642. }
  643.  
  644. //
  645. //  Fill an integer array with indexes of selected items.
  646. //  (Note GetSelCount returns the number of selected items.)
  647. //  Returns the number of indexes placed in the indexes array.
  648. //  If the list view uses the LVS_SINGLESEL, multiple selection
  649. //  has been disabled and the function returns -1.
  650. //
  651. int
  652. TListWindow::GetSelIndexes(int* indexes, int maxCount) const
  653. {
  654.   int count = 0;                  // number of selected items found
  655.  
  656.   if (GetStyle() & LVS_SINGLESEL)
  657.     return -1;
  658.  
  659.   // get index of first selected item
  660.   //
  661.   int index = CONST_CAST(TListWindow*, this)->SendMessage(LVM_GETNEXTITEM,
  662.           TParam1(-1), MkParam2(LVNI_ALL|LVNI_SELECTED, 0));
  663.  
  664.   // while index indicates a selected item
  665.   //
  666.   while (index != -1) {
  667.     indexes[count] = index;
  668.     count++;
  669.     if (count > maxCount)
  670.       break;
  671.  
  672.     // get next selected item
  673.     //
  674.     index = CONST_CAST(TListWindow*, this)->SendMessage(LVM_GETNEXTITEM,
  675.             TParam1(index), MkParam2(LVNI_ALL|LVNI_SELECTED, 0));
  676.   }
  677.  
  678.   return count;
  679. }
  680.  
  681. //
  682. // Fill an array with strings from the selected items.
  683. // maxCount is the size of the strs[] array.  maxChars is
  684. // the size of each array element.  subItem indicates which
  685. // item string to return.
  686. //
  687. // Return the number of strings retrieved, or -1 for errors.
  688. //
  689. int
  690. TListWindow::GetSelStrings(char far** strs, int maxCount, int maxChars,
  691.   int subItem /*=0*/) const
  692. {
  693.   // This function is for multiselect list views only.
  694.   //
  695.   if (GetStyle() & LVS_SINGLESEL)
  696.     return -1;
  697.  
  698.   // get index of first selected item
  699.   //
  700.   int index = CONST_CAST(TListWindow*, this)->SendMessage(LVM_GETNEXTITEM,
  701.           TParam1(-1), MkParam2(LVNI_ALL|LVNI_SELECTED, 0));
  702.  
  703.   // loop through selected items
  704.   //
  705.   int count = 0;
  706.   while (index != -1) {
  707.     CONST_CAST(TListWindow*, this)->GetItemText(index, subItem,
  708.       strs[count], maxChars);
  709.     count++;
  710.     if (count > maxCount)
  711.       break;
  712.  
  713.     // get next selected item
  714.     //
  715.     index = CONST_CAST(TListWindow*, this)->SendMessage(LVM_GETNEXTITEM,
  716.             TParam1(index), MkParam2(LVNI_ALL|LVNI_SELECTED, 0));
  717.   }
  718.  
  719.   return count;
  720. }
  721.  
  722. //
  723. //  Determine selection state of an item.
  724. //  Return true if the item is selected.
  725. //
  726. bool
  727. TListWindow::IsSelected(int index) const
  728. {
  729.   return CONST_CAST(TListWindow*, this)->GetItemState(index, LVIS_SELECTED);
  730. }
  731.  
  732. //
  733. //  Select or deselect an item.
  734. //  Returns true for success.
  735. //
  736. bool
  737. TListWindow::SetSel(int index, bool select)
  738. {
  739.   return SetItemState(index, select ? LVIS_SELECTED : 0, LVIS_SELECTED);
  740. }
  741.  
  742. //
  743. //  Select or deselect all the items whose indexes appear in indexes[]
  744. //  Returns true for success.
  745. //
  746. bool
  747. TListWindow::SetSelIndexes(int* indexes, int count, bool select)
  748. {
  749.   // This command is only for multiselect list views.
  750.   //
  751.   if (GetStyle() & LVS_SINGLESEL)
  752.     return false;
  753.  
  754.   for (int i = 0; i < count; i++)
  755.     if (!SetSel(indexes[i], select))
  756.       return false;
  757.  
  758.   return true;
  759. }
  760.  
  761. //
  762. //  Select or deselect all the items in the given range.
  763. //  Returns true for success.
  764. //
  765. bool
  766. TListWindow::SetSelItemRange(bool select, int first, int last)
  767. {
  768.   // This command is only for multiselect list views.
  769.   //
  770.   if (GetStyle() & LVS_SINGLESEL)
  771.     return false;
  772.  
  773.   for (int i = first; i <= last; i++)
  774.     if (!SetSel(i, select))
  775.       return false;
  776.  
  777.   return true;
  778. }
  779.  
  780.