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