home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / yacl-012.zip / ui / combobox.cxx < prev    next >
C/C++ Source or Header  |  1995-04-08  |  10KB  |  392 lines

  1.  
  2.  
  3.  
  4. /*
  5.  *
  6.  *          Copyright (C) 1994, M. A. Sridhar
  7.  *  
  8.  *
  9.  *     This software is Copyright M. A. Sridhar, 1994. You are free
  10.  *     to copy, modify or distribute this software  as you see fit,
  11.  *     and to use  it  for  any  purpose, provided   this copyright
  12.  *     notice and the following   disclaimer are included  with all
  13.  *     copies.
  14.  *
  15.  *                        DISCLAIMER
  16.  *
  17.  *     The author makes no warranties, either expressed or implied,
  18.  *     with respect  to  this  software, its  quality, performance,
  19.  *     merchantability, or fitness for any particular purpose. This
  20.  *     software is distributed  AS IS.  The  user of this  software
  21.  *     assumes all risks  as to its quality  and performance. In no
  22.  *     event shall the author be liable for any direct, indirect or
  23.  *     consequential damages, even if the  author has been  advised
  24.  *     as to the possibility of such damages.
  25.  *
  26.  */
  27.  
  28.  
  29.  
  30. #if defined(__GNUC__)
  31. #pragma implementation
  32. #endif
  33.  
  34.  
  35.  
  36. #include "ui/combobox.h"
  37. #include "ui/strseq.h"
  38.  
  39.  
  40. #if defined(__MS_WINDOWS__)
  41. #include <windows.h>
  42. #endif
  43.  
  44. #if defined(__MS_WINDOWS__)
  45. #define COMBOBOX_STYLE  WS_CHILD | WS_VISIBLE \
  46.         | WS_GROUP | WS_VSCROLL | WS_TABSTOP  | \
  47.         CBS_AUTOHSCROLL
  48. #elif defined(__OS2__)
  49. #define COMBOBOX_STYLE LS_HORZSCROLL | WS_VISIBLE
  50. #endif
  51.  
  52.  
  53. typedef CL_Binding<UI_ComboBox> ComboBoxBind;
  54.  
  55. #if defined(__GNUC__)
  56. template class CL_Binding<UI_ComboBox>;
  57. #endif
  58.  
  59.  
  60.  
  61. UI_ComboBox::UI_ComboBox
  62.     (UI_VObjCollection* p, const UI_Rectangle& shape, UI_ViewID id,
  63.      bool editable)
  64. : UI_StringViewSingleSel (p, shape, id)
  65. {   
  66.     _editable = editable;
  67.     _limit    = 255;
  68. #if defined(__MS_WINDOWS__)
  69.     _style = COMBOBOX_STYLE | (editable ? CBS_DROPDOWN : CBS_DROPDOWNLIST);
  70. #elif defined(__OS2__)
  71.     _style = WS_VISIBLE | (editable ? CBS_DROPDOWN : CBS_DROPDOWNLIST);
  72. #endif
  73.     ComboBoxBind bind (this, &UI_ComboBox::_EditStringChanged);
  74.     _editString.AddDependent (bind, 0);
  75. }
  76.  
  77.  
  78.  
  79.  
  80. #if defined(__MS_WINDOWS__)
  81. UI_ComboBox::UI_ComboBox
  82.     (UI_CompositeVObject* p, UI_ViewID id, UI_ViewHandle h)
  83. : UI_StringViewSingleSel (p, id, h)
  84. {
  85.     _model = new UI_StringSequence;
  86.     ((UI_StringSequence*) _model)->AddClient (this);
  87. }
  88. #endif
  89.  
  90.  
  91. void  UI_ComboBox::ShowDropDown ()
  92. {
  93. #if defined(__MS_WINDOWS__)
  94.     if (_handle)
  95.         SendMessage (_handle, CB_SHOWDROPDOWN, 1, 0);
  96. #elif defined(__OS2__)
  97.     if (_handle)
  98.         WinSendMsg (_handle, CBM_SHOWLIST, (MPARAM) 1, 0);
  99. #endif
  100. }
  101.  
  102.  
  103. void  UI_ComboBox::HideDropDown ()
  104. {
  105. #if defined(__MS_WINDOWS__)
  106.     if (_handle)
  107.         SendMessage (_handle, CB_SHOWDROPDOWN, 0, 0);
  108. #elif defined(__OS2__)
  109.     if (_handle)
  110.         WinSendMsg (_handle, CBM_SHOWLIST, 0, 0);
  111. #endif
  112. }
  113.  
  114.  
  115. bool UI_ComboBox::IsDropDownShowing() const
  116. {
  117. #if defined(__MS_WINDOWS__)
  118.     return _handle ? SendMessage (_handle, CB_GETDROPPEDSTATE, 0, 0) : FALSE;
  119. #elif defined(__OS2__)
  120.     if (!_handle)
  121.         return FALSE;
  122.     return WinSendMsg (_handle, CBM_ISLISTSHOWING, 0, 0) ? TRUE : FALSE;
  123. #endif
  124. }
  125.  
  126.  
  127. #if defined(__MS_WINDOWS__)
  128. static CL_String EditContent (HWND h)
  129. {
  130.     char* data   = NULL;
  131.     short length = 0;
  132.     if (h) {
  133.         length = GetWindowTextLength (h) + 1;
  134.         if (length) {
  135.             data = new char [length];
  136.             if (data)
  137.                 GetWindowText (h, data, length);
  138.         }
  139.     }
  140.     CL_String ret = data ? data : "";
  141.     if (data)
  142.         delete data;
  143.     return ret;
  144. }
  145.  
  146. #elif defined(__OS2__)
  147. static CL_String EditContent (HWND h)
  148. {
  149.     if (!h)
  150.         return "";
  151.     long n = WinQueryWindowTextLength (h);
  152.     char* buf = new char[n+1];
  153.     if (!buf)
  154.         return ""; // No memory
  155.     WinQueryWindowText (h,  n+1, buf);
  156.     CL_String ret (buf);
  157.     delete buf;
  158.     return ret;
  159. }
  160. #endif
  161.  
  162. CL_String& UI_ComboBox::EditString ()
  163. {
  164.     ComboBoxBind bind (this, &UI_ComboBox::_EditStringChanged);
  165.     _editString.RemoveDependent (bind);
  166.     if (_handle && _editable) {
  167.         // If it's not editable, the edit string is always current because
  168.         // UpdateSelection updates it whenever the selection changes.
  169.         _editString = EditContent   (_handle);
  170.     }
  171.     _editString.AddDependent (bind, 1);
  172.     return _editString;
  173. }
  174.  
  175.  
  176.  
  177. void UI_ComboBox::SetLengthLimit (short limit)
  178. {
  179.     _limit = limit;
  180. #if defined(__MS_WINDOWS__)
  181.     if (_handle)
  182.         SendMessage (_handle, CB_LIMITTEXT, limit, 0);
  183. #elif defined(__OS2__)
  184.     if (_handle)
  185.         WinSendMsg  (_handle, EM_SETTEXTLIMIT, MPFROM2SHORT(limit, 0), 0);
  186. #endif
  187. }
  188.  
  189.  
  190.  
  191. long  UI_ComboBox::TopIndex () const
  192. {
  193. #if defined(__MS_WINDOWS__)
  194.     return (_handle) ? SendMessage (_handle, CB_GETCURSEL, 0, 0)
  195.         : -1;
  196. #elif defined(__OS2__)
  197.     return _handle ? (long) WinSendMsg (_handle, LM_QUERYTOPINDEX, 0, 0) : -1;
  198. #endif
  199. }
  200.  
  201.  
  202. short UI_ComboBox::VisibleCount () const
  203. {
  204.     return 1; // Can't really do this. Can we do better at all?
  205. }
  206.  
  207.  
  208. void  UI_ComboBox::ScrollTo (long index)
  209. {
  210. #if defined(__MS_WINDOWS__)
  211.     if (_handle)
  212.         SendMessage (_handle, CB_SETCURSEL, index, 0);
  213. #elif defined(__OS2__)
  214.     if (_handle)
  215.         WinSendMsg (_handle, LM_SETTOPINDEX, (MPARAM) index, 0);
  216. #endif
  217. }
  218.  
  219.  
  220.  
  221.  
  222.  
  223. void UI_ComboBox::ItemInserted (long i)
  224. {
  225.     CL_String s = (*(UI_StringSequence*) _model) [i+1];
  226.  
  227. #if defined(__MS_WINDOWS__)
  228.     if (_handle)
  229.         SendMessage (_handle, CB_INSERTSTRING, i+1, (long)(const char*)s);
  230. #elif defined(__OS2__)
  231.     if (_handle)
  232.         WinInsertLboxItem (_handle, i, s.AsPtr());
  233. #endif
  234.     _UpdateSelection ();
  235. }
  236.  
  237.  
  238.  
  239. void UI_ComboBox::ItemRemoved (long i)
  240. {
  241. #if defined(__MS_WINDOWS__)
  242.     if (_handle)
  243.         SendMessage (_handle, CB_DELETESTRING, i, 0L);
  244. #elif defined(__OS2__)
  245.     if (_handle)
  246.         WinDeleteLboxItem (_handle, i);
  247. #endif
  248.     _UpdateSelection ();
  249. }
  250.  
  251.  
  252.  
  253. void UI_ComboBox::ItemChanged (long i)
  254. {
  255.     CL_String s = (*(UI_StringSequence*)_model)[i];
  256. #if defined(__MS_WINDOWS__)
  257.     SendMessage (_handle, WM_SETREDRAW,  FALSE, 0L);
  258.     SendMessage (_handle, CB_DELETESTRING, i, 0L);
  259.     SendMessage (_handle, CB_INSERTSTRING, i, (long) s.AsPtr());
  260.     SendMessage (_handle, WM_SETREDRAW, TRUE, 0L);
  261. #elif defined(__OS2__)
  262.     if (_handle) {
  263.         WinDeleteLboxItem (_handle, i);
  264.         WinInsertLboxItem (_handle, i, s.AsPtr());
  265.     }
  266. #endif
  267. }
  268.  
  269.  
  270. void UI_ComboBox::ModelEmptied ()
  271. {
  272. #if defined(__MS_WINDOWS__)
  273.     if (_handle)
  274.         SendMessage (_handle, CB_RESETCONTENT, 0,     0);
  275. #elif defined(__OS2__)
  276.     if (_handle)
  277.         WinSendMsg (_handle, LM_DELETEALL, 0, 0);
  278. #endif    
  279. }
  280.  
  281.  
  282. void UI_ComboBox::_PrivateInitialize ()
  283. {
  284.     UI_SimpleVObject::_PrivateInitialize ();
  285.     UI_StringSequence& theModel = *(UI_StringSequence*) _model;
  286.     theModel.AddClient (this);
  287.     long n = theModel.Size();
  288. #if defined(__MS_WINDOWS__)
  289.     if (n) {
  290.         SendMessage (_handle, WM_SETREDRAW,    FALSE, 0);
  291.         SendMessage (_handle, CB_RESETCONTENT, 0,     0);
  292.         for (long i = 0; i < n; i++) {
  293.             SendMessage (_handle, CB_ADDSTRING, 0,
  294.                          (long) theModel[i].AsPtr());
  295.         }
  296.         SendMessage ((HWND)(long)_handle, WM_SETREDRAW, TRUE, 0L);
  297.     }
  298. #elif defined(__OS2__)
  299.     WinSendMsg (_handle, LM_DELETEALL, 0, 0);
  300.     for (long i = 0; i < n; i++)
  301.         WinInsertLboxItem (_handle, LIT_END, theModel[i].AsPtr());
  302. #endif
  303. }
  304.  
  305.  
  306.  
  307. UI_WindowClass UI_ComboBox::WindowClass () const
  308. {
  309. #if defined(__MS_WINDOWS__)
  310.     return "combobox";
  311. #elif defined(__OS2__)
  312.     return WC_COMBOBOX;
  313. #elif defined(__X_MOTIF__)
  314. #error No ComboBox under motif.
  315. #endif
  316. }
  317.  
  318.  
  319. bool UI_ComboBox::Select ()
  320. {
  321.     // Called in response to Event_Select generated when the user changes a
  322.     // selection
  323.     _UpdateSelection ();
  324.     return FALSE; // So that the parent gets a chance to handle this event
  325. }
  326.  
  327.  
  328.  
  329.  
  330.  
  331. void UI_ComboBox::_UpdateSelection ()
  332. {
  333.     ComboBoxBind bind (this, &UI_ComboBox::_SelectionChanged);
  334.     _selection.RemoveDependent (bind);
  335.     ComboBoxBind ebind (this, &UI_ComboBox::_EditStringChanged);
  336.     _editString.RemoveDependent (ebind);
  337.     long pos = 0;
  338.     CL_String editContents;
  339. #if defined(__MS_WINDOWS__)
  340.     pos = SendMessage (_handle, CB_GETCURSEL, 0, 0);
  341.     if (pos == LB_ERR)
  342.         pos = -1;
  343.     _selection = pos;
  344. #elif defined(__OS2__)
  345.     pos = (long) WinSendMsg (_handle, LM_QUERYSELECTION, (MPARAM) -1, 0);
  346.     if (pos == LIT_NONE)
  347.         pos = -1;
  348. #endif
  349.     if (_editable)
  350.         _editString = EditContent (_handle);
  351.     else if (pos >= 0)
  352.         _editString =  (*(UI_StringSequence*) _model) [pos];
  353.     else
  354.         _editString = "";
  355.     _selection.AddDependent (bind, 1);
  356.     _editString.AddDependent (ebind, 1);
  357. }
  358.  
  359.  
  360.  
  361.  
  362. bool UI_ComboBox::_SelectionChanged (CL_Object&, long)
  363. {
  364.     UI_StringSequence& theModel = *(UI_StringSequence*) _model;
  365.     if (_selection < 0 || _selection >= theModel.Size()) {
  366.         ComboBoxBind bind (this, &UI_ComboBox::_SelectionChanged);
  367.         _selection.RemoveDependent (bind);
  368.         _selection = -1; 
  369.         _selection.AddDependent (bind, 1);
  370.     }
  371. #if defined(__MS_WINDOWS__)
  372.     SendMessage (_handle, CB_SETCURSEL, _selection, 0);
  373. #elif defined(__OS2__)
  374.     WinSendMsg (_handle, LM_SELECTITEM, (MPARAM) _selection.Value(),
  375.                 (MPARAM) TRUE);
  376. #endif
  377.     return TRUE;
  378. }
  379.  
  380.  
  381. bool UI_ComboBox::_EditStringChanged (CL_Object&, long)
  382. {
  383. #if defined(__MS_WINDOWS__)
  384.     SetWindowText (_handle, _editString.AsPtr());
  385.     SendMessage   (_handle, CB_SETEDITSEL, 0,
  386.                    MAKELONG (0, _editString.Size()-1));
  387. #elif defined(__OS2__)
  388.     WinSetWindowText (_handle, _editString.AsPtr());
  389. #endif
  390.     return TRUE;
  391. }
  392.