Fixed GetSelection to behave the same as for the other ports, added
[wxWidgets.git] / src / os2 / choice.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/choice.cpp
3 // Purpose: wxChoice
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/13/99
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #if wxUSE_CHOICE
16
17 #ifndef WX_PRECOMP
18 #include "wx/choice.h"
19 #include "wx/utils.h"
20 #include "wx/log.h"
21 #include "wx/settings.h"
22 #endif
23
24 #include "wx/os2/private.h"
25
26 IMPLEMENT_DYNAMIC_CLASS(wxChoice, wxControl)
27
28 bool wxChoice::Create(
29 wxWindow* pParent
30 , wxWindowID vId
31 , const wxPoint& rPos
32 , const wxSize& rSize
33 , const wxArrayString& asChoices
34 , long lStyle
35 , const wxValidator& rValidator
36 , const wxString& rsName
37 )
38 {
39 wxCArrayString chs(asChoices);
40
41 return Create(pParent, vId, rPos, rSize, chs.GetCount(), chs.GetStrings(),
42 lStyle, rValidator, rsName);
43 }
44
45 bool wxChoice::Create(
46 wxWindow* pParent
47 , wxWindowID vId
48 , const wxPoint& rPos
49 , const wxSize& rSize
50 , int n
51 , const wxString asChoices[]
52 , long lStyle
53 , const wxValidator& rValidator
54 , const wxString& rsName
55 )
56 {
57 long lSstyle;
58
59 if (!CreateControl( pParent
60 ,vId
61 ,rPos
62 ,rSize
63 ,lStyle
64 ,rValidator
65 ,rsName
66 ))
67 return false;
68 lSstyle = CBS_DROPDOWNLIST |
69 WS_TABSTOP |
70 WS_VISIBLE;
71
72 if (lStyle & wxCLIP_SIBLINGS )
73 lSstyle |= WS_CLIPSIBLINGS;
74
75 wxASSERT_MSG( !(lStyle & wxCB_DROPDOWN) &&
76 !(lStyle & wxCB_READONLY) &&
77 !(lStyle & wxCB_SIMPLE),
78 wxT("this style flag is ignored by wxChoice, you "
79 "probably want to use a wxComboBox") );
80
81 if (!OS2CreateControl( wxT("COMBOBOX")
82 ,lSstyle
83 ))
84 return false;
85
86 //
87 // A choice/combobox normally has a white background (or other, depending
88 // on global settings) rather than inheriting the parent's background colour.
89 //
90 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
91
92 // initialize the controls contents
93 for (int i = 0; i < n; i++)
94 {
95 Append(asChoices[i]);
96 }
97 SetSize( rPos.x
98 ,rPos.y
99 ,rSize.x
100 ,rSize.y
101 );
102 return true;
103 } // end of wxChoice::Create
104
105 wxChoice::~wxChoice()
106 {
107 Free();
108 }
109
110 // ----------------------------------------------------------------------------
111 // adding/deleting items to/from the list
112 // ----------------------------------------------------------------------------
113
114 int wxChoice::DoAppend(
115 const wxString& rsItem
116 )
117 {
118 int nIndex;
119 LONG nIndexType = 0;
120
121 if (m_windowStyle & wxLB_SORT)
122 nIndexType = LIT_SORTASCENDING;
123 else
124 nIndexType = LIT_END;
125 nIndex = (int)::WinSendMsg( GetHwnd()
126 ,LM_INSERTITEM
127 ,(MPARAM)nIndexType
128 ,(MPARAM)rsItem.c_str()
129 );
130 return nIndex;
131 } // end of wxChoice::DoAppend
132
133 int wxChoice::DoInsert( const wxString& rsItem, unsigned int pos )
134 {
135 wxCHECK_MSG(!(GetWindowStyle() & wxCB_SORT), -1, wxT("can't insert into sorted list"));
136 wxCHECK_MSG(IsValidInsert(pos), -1, wxT("invalid index"));
137
138 if (pos == GetCount())
139 return DoAppend(rsItem);
140
141 int nIndex;
142 LONG nIndexType = 0;
143
144 if (m_windowStyle & wxLB_SORT)
145 nIndexType = LIT_SORTASCENDING;
146 else
147 nIndexType = pos;
148 nIndex = (int)::WinSendMsg( GetHwnd()
149 ,LM_INSERTITEM
150 ,(MPARAM)nIndexType
151 ,(MPARAM)rsItem.c_str()
152 );
153 return nIndex;
154 } // end of wxChoice::DoInsert
155
156 void wxChoice::Delete(unsigned int n)
157 {
158 wxCHECK_RET( IsValid(n), wxT("invalid item index in wxChoice::Delete") );
159
160 if ( HasClientObjectData() )
161 {
162 delete GetClientObject(n);
163 }
164
165 ::WinSendMsg(GetHwnd(), LM_DELETEITEM, (MPARAM)n, (MPARAM)0);
166 } // end of wxChoice::Delete
167
168 void wxChoice::Clear()
169 {
170 Free();
171 ::WinSendMsg(GetHwnd(), LM_DELETEALL, (MPARAM)0, (MPARAM)0);
172 } // end of wxChoice::Clear
173
174 // ----------------------------------------------------------------------------
175 // selection
176 // ----------------------------------------------------------------------------
177
178 int wxChoice::GetSelection() const
179 {
180 // if m_lastAcceptedSelection is set, it means that the dropdown is
181 // currently shown and that we want to use the last "permanent" selection
182 // instead of whatever is under the mouse pointer currently
183 //
184 // otherwise, get the selection from the control
185 return m_lastAcceptedSelection == wxID_NONE ? GetCurrentSelection()
186 : m_lastAcceptedSelection;
187 }
188
189 int wxChoice::GetCurrentSelection() const
190 {
191 return((int)LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYSELECTION, (MPARAM)LIT_FIRST, (MPARAM)0)));
192 } // end of wxChoice::GetSelection
193
194 void wxChoice::SetSelection(
195 int n
196 )
197 {
198 ::WinSendMsg( GetHwnd()
199 ,LM_SELECTITEM
200 ,(MPARAM)n
201 ,(MPARAM)TRUE
202 );
203 } // end of wxChoice::SetSelection
204
205 // ----------------------------------------------------------------------------
206 // string list functions
207 // ----------------------------------------------------------------------------
208
209 unsigned int wxChoice::GetCount() const
210 {
211 return((unsigned int)LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYITEMCOUNT, (MPARAM)0, (MPARAM)0)));
212 } // end of wxChoice::GetCount
213
214 void wxChoice::SetString(unsigned int n, const wxString& rsStr)
215 {
216 LONG nIndexType = 0;
217 void* pData;
218
219 if ( m_clientDataItemsType != wxClientData_None )
220 {
221 pData = DoGetItemClientData(n);
222 }
223 else // no client data
224 {
225 pData = NULL;
226 }
227
228 ::WinSendMsg(GetHwnd(), LM_DELETEITEM, (MPARAM)n, 0);
229
230 if (m_windowStyle & wxLB_SORT)
231 nIndexType = LIT_SORTASCENDING;
232 else
233 nIndexType = LIT_END;
234 ::WinSendMsg( GetHwnd()
235 ,LM_INSERTITEM
236 ,(MPARAM)nIndexType
237 ,(MPARAM)rsStr.c_str()
238 );
239
240 if (pData)
241 {
242 DoSetItemClientData(n, pData);
243 }
244 } // end of wxChoice::SetString
245
246 wxString wxChoice::GetString(unsigned int n) const
247 {
248 int nLen = 0;
249 wxString sStr = wxEmptyString;
250 wxChar* zBuf;
251
252 nLen = (size_t)LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYITEMTEXTLENGTH, (MPARAM)n, (MPARAM)0));
253 if (nLen != LIT_ERROR && nLen > 0)
254 {
255 zBuf = new wxChar[nLen + 1];
256 ::WinSendMsg( GetHwnd()
257 ,LM_QUERYITEMTEXT
258 ,MPFROM2SHORT((SHORT)n, (SHORT)nLen)
259 ,(MPARAM)zBuf
260 );
261 sStr = zBuf;
262 delete [] zBuf;
263 }
264 return sStr;
265 } // end of wxChoice::GetString
266
267 // ----------------------------------------------------------------------------
268 // client data
269 // ----------------------------------------------------------------------------
270
271 void wxChoice::DoSetItemClientData(unsigned int n, void* pClientData)
272 {
273 ::WinSendMsg(GetHwnd(), LM_SETITEMHANDLE, (MPARAM)n, MPFROMP(pClientData));
274 } // end of wxChoice::DoSetItemClientData
275
276 void* wxChoice::DoGetItemClientData(unsigned int n) const
277 {
278 MRESULT rc = ::WinSendMsg(GetHwnd(), LM_QUERYITEMHANDLE, (MPARAM)n, (MPARAM)0);
279 return((void*)rc);
280 } // end of wxChoice::DoGetItemClientData
281
282 void wxChoice::DoSetItemClientObject(unsigned int n, wxClientData* pClientData)
283 {
284 DoSetItemClientData(n, pClientData);
285 } // end of wxChoice::DoSetItemClientObject
286
287 wxClientData* wxChoice::DoGetItemClientObject(unsigned int n) const
288 {
289 return (wxClientData *)DoGetItemClientData(n);
290 } // end of wxChoice::DoGetItemClientObject
291
292 // ----------------------------------------------------------------------------
293 // wxOS2 specific helpers
294 // ----------------------------------------------------------------------------
295
296 void wxChoice::DoSetSize(int nX,
297 int nY,
298 int nWidth,
299 int WXUNUSED(nHeight),
300 int nSizeFlags)
301 {
302 //
303 // Ignore height parameter because height doesn't mean 'initially
304 // displayed' height, it refers to the drop-down menu as well. The
305 // wxWidgets interpretation is different; also, getting the size returns
306 // the _displayed_ size (NOT the drop down menu size) so
307 // setting-getting-setting size would not work.
308 //
309 wxControl::DoSetSize( nX
310 ,nY
311 ,nWidth
312 ,wxDefaultCoord
313 ,nSizeFlags
314 );
315 } // end of wxChoice::DoSetSize
316
317 wxSize wxChoice::DoGetBestSize() const
318 {
319 //
320 // Find the widest string
321 //
322 int nLineWidth;
323 int nChoiceWidth = 0;
324 int nCx;
325 int nCy;
326 wxFont vFont = (wxFont)GetFont();
327
328 const unsigned int nItems = GetCount();
329
330 for (unsigned int i = 0; i < nItems; i++)
331 {
332 wxString sStr(GetString(i));
333 GetTextExtent( sStr, &nLineWidth, NULL );
334 if (nLineWidth > nChoiceWidth)
335 nChoiceWidth = nLineWidth;
336 }
337
338 //
339 // Give it some reasonable default value if there are no strings in the
340 // list
341 //
342 if (nChoiceWidth == 0L)
343 nChoiceWidth = 100L;
344
345 //
346 // The combobox should be larger than the widest string
347 //
348 wxGetCharSize( GetHWND(), &nCx, &nCy, &vFont );
349 nChoiceWidth += 5 * nCx;
350
351 //
352 // Choice drop-down list depends on number of items (limited to 10)
353 //
354 size_t nStrings = nItems == 0 ? 10 : wxMin(10, nItems) + 1;
355 int nChoiceHeight = EDIT_HEIGHT_FROM_CHAR_HEIGHT(nCy) * nStrings;
356
357 return wxSize(nChoiceWidth, nChoiceHeight);
358 } // end of wxChoice::DoGetBestSize
359
360 MRESULT wxChoice::OS2WindowProc(
361 WXUINT uMsg
362 , WXWPARAM wParam
363 , WXLPARAM lParam
364 )
365 {
366 return wxWindow::OS2WindowProc( uMsg
367 ,wParam
368 ,lParam
369 );
370 } // end of wxChoice::OS2WindowProc
371
372 bool wxChoice::OS2Command(
373 WXUINT uParam
374 , WXWORD WXUNUSED(wId)
375 )
376 {
377 if (uParam != LN_SELECT)
378 {
379 //
380 // "selection changed" is the only event we're after
381 //
382 return false;
383 }
384 int n = GetSelection();
385
386 if (n > -1)
387 {
388 wxCommandEvent vEvent( wxEVT_COMMAND_CHOICE_SELECTED
389 ,m_windowId
390 );
391
392 vEvent.SetInt(n);
393 vEvent.SetEventObject(this);
394 vEvent.SetString(GetStringSelection());
395 if (HasClientObjectData())
396 vEvent.SetClientObject(GetClientObject(n));
397 else if (HasClientUntypedData())
398 vEvent.SetClientData(GetClientData(n));
399 ProcessCommand(vEvent);
400 }
401 return true;
402 } // end of wxChoice::OS2Command
403
404 void wxChoice::Free()
405 {
406 if (HasClientObjectData())
407 {
408 const unsigned int nCount = GetCount();
409
410 for (unsigned int n = 0; n < nCount; n++)
411 {
412 delete GetClientObject(n);
413 }
414 }
415 } // end of wxChoice::Free
416
417 #endif // wxUSE_CHOICE