Implementing some more controls and an MDI child frame fix for wxFrame.
[wxWidgets.git] / src / os2 / combobox.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: combobox.cpp
3 // Purpose: wxComboBox class
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 #include "wx/combobox.h"
13
14 // For compilers that support precompilation, includes "wx.h".
15 #include "wx/wxprec.h"
16
17 #ifndef WX_PRECOMP
18 #include "wx/setup.h"
19 #endif
20
21 #if wxUSE_COMBOBOX
22
23 #include "wx/combobox.h"
24 #include "wx/clipbrd.h"
25 #include "wx/os2/private.h"
26
27 #define OWNER_DRAWN_LISTBOX_EXTRA_SPACE (1)
28
29 MRESULT EXPENTRY wxComboEditWndProc( HWND hWnd
30 ,UINT uMessage
31 ,MPARAM wParam
32 ,MPARAM lParam
33 );
34 //
35 // The pointer to standard wnd proc
36 //
37 static WXFARPROC gfnWndprocEdit = (WXFARPROC)NULL;
38
39 IMPLEMENT_DYNAMIC_CLASS(wxComboBox, wxControl)
40
41 bool wxComboBox::OS2Command(
42 WXUINT uParam
43 , WXWORD WXUNUSED(wId)
44 )
45 {
46 long lSel = -1L;
47 wxString sValue;
48
49 switch (uParam)
50 {
51 case LN_SELECT:
52 if (GetSelection() > -1)
53 {
54 wxCommandEvent vEvent( wxEVT_COMMAND_COMBOBOX_SELECTED
55 ,GetId()
56 );
57
58 vEvent.SetInt(GetSelection());
59 vEvent.SetEventObject(this);
60 vEvent.SetString((char*)GetStringSelection().c_str());
61 ProcessCommand(vEvent);
62 }
63 break;
64
65 case EN_CHANGE:
66 {
67 wxCommandEvent vEvent( wxEVT_COMMAND_TEXT_UPDATED
68 ,GetId()
69 );
70
71 if (lSel == -1L)
72 sValue = GetValue();
73 else
74 SetValue(sValue);
75 vEvent.SetString((char*)GetValue().c_str());
76 vEvent.SetEventObject(this);
77 ProcessCommand(vEvent);
78 }
79 break;
80 }
81 //
82 // There is no return value for the CBN_ notifications, so always return
83 // FALSE from here to pass the message to DefWindowProc()
84 //
85 return FALSE;
86 } // end of wxComboBox::OS2Command
87
88 bool wxComboBox::Create(
89 wxWindow* pParent
90 , wxWindowID vId
91 , const wxString& rsValue
92 , const wxPoint& rPos
93 , const wxSize& rSize
94 , int n
95 , const wxString asChoices[]
96 , long lStyle
97 #if wxUSE_VALIDATORS
98 , const wxValidator& rValidator
99 #endif
100 , const wxString& rsName
101 )
102 {
103
104 if (!OS2CreateControl( pParent
105 ,vId
106 ,rPos
107 ,rSize
108 ,lStyle
109 #if wxUSE_VALIDATORS
110 ,rValidator
111 #endif
112 ,rsName
113 ))
114 return FALSE;
115
116 //
117 // Get the right style
118 //
119 long lSstyle = 0L;
120
121 lSstyle = WS_TABSTOP |
122 WS_VISIBLE;
123
124 if (lStyle & wxCLIP_SIBLINGS )
125 lSstyle |= WS_CLIPSIBLINGS;
126 if (lStyle & wxCB_READONLY)
127 lSstyle |= CBS_DROPDOWNLIST;
128 else if (lStyle & wxCB_SIMPLE)
129 lSstyle |= CBS_SIMPLE; // A list (shown always) and edit control
130 else
131 lSstyle |= CBS_DROPDOWN;
132
133
134 if (!OS2CreateControl( "COMBOBOX"
135 ,lSstyle
136 ))
137 return FALSE;
138
139 //
140 // A choice/combobox normally has a white background (or other, depending
141 // on global settings) rather than inheriting the parent's background colour.
142 //
143 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW));
144
145 SetFont(pParent->GetFont());
146
147 int i;
148
149 for (i = 0; i < n; i++)
150 {
151 Append(asChoices[i]);
152 }
153
154 SetSize( rPos.x
155 ,rPos.y
156 ,rSize.x
157 ,rSize.y
158 );
159 if (!rsValue.IsEmpty())
160 {
161 SetValue(rsValue);
162 }
163 gfnWndprocEdit = (WXFARPROC)::WinSubclassWindow( (HWND)GetHwnd()
164 ,(PFNWP)wxComboEditWndProc
165 );
166 return TRUE;
167 } // end of wxComboBox::Create
168
169 void wxComboBox::SetValue(
170 const wxString& rsValue
171 )
172 {
173 //
174 // If newlines are denoted by just 10, must stick 13 in front.
175 //
176 int nSingletons = 0;
177 int nLen = rsValue.Length();
178 int i;
179
180 for (i = 0; i < nLen; i ++)
181 {
182 if ((i > 0) && (rsValue[i] == 10) && (rsValue[i - 1] != 13))
183 nSingletons ++;
184 }
185 if (nSingletons > 0)
186 {
187 wxChar* zTmp = new wxChar[nLen + nSingletons + 1];
188 int j = 0;
189
190 for (i = 0; i < nLen; i ++)
191 {
192 if ((i > 0) && (rsValue[i] == 10) && (rsValue[i - 1] != 13))
193 {
194 zTmp[j] = 13;
195 j++;
196 }
197 zTmp[j] = rsValue[i];
198 j++;
199 }
200 zTmp[j] = 0;
201 ::WinSetWindowText(GetHwnd(), zTmp);
202 delete[] zTmp;
203 }
204 else
205 ::WinSetWindowText(GetHwnd(), rsValue.c_str());
206 } // end of wxComboBox::SetValue
207
208 //
209 // Clipboard operations
210 //
211 void wxComboBox::Copy()
212 {
213 HWND hWnd = GetHwnd();
214
215 ::WinSendMsg(hWnd, EM_COPY, (MPARAM)0, (MPARAM)0);
216 } // end of wxComboBox::Copy
217
218 void wxComboBox::Cut()
219 {
220 HWND hWnd = GetHwnd();
221
222 ::WinSendMsg(hWnd, EM_CUT, (MPARAM)0, (MPARAM)0);
223 } // end of wxComboBox::Cut
224
225 void wxComboBox::Paste()
226 {
227 HWND hWnd = GetHwnd();
228
229 ::WinSendMsg(hWnd, EM_PASTE, (MPARAM)0, (MPARAM)0);
230 } // end of wxComboBox::Paste
231
232 void wxComboBox::SetEditable(
233 bool bEditable
234 )
235 {
236 HWND hWnd = GetHwnd();
237
238 ::WinSendMsg(hWnd, EM_SETREADONLY, (MPARAM)!bEditable, (MPARAM)0L);
239 } // end of wxComboBox::SetEditable
240
241 void wxComboBox::SetInsertionPoint(
242 long lPos
243 )
244 {
245 HWND hWnd = GetHwnd();
246
247 ::WinSendMsg(hWnd, EM_SETFIRSTCHAR, MPFROMLONG(lPos), (MPARAM)0);
248 } // end of wxComboBox::SetInsertionPoint
249
250 void wxComboBox::SetInsertionPointEnd()
251 {
252 long lPos = GetLastPosition();
253
254 SetInsertionPoint(lPos);
255 } // end of wxComboBox::SetInsertionPointEnd
256
257 long wxComboBox::GetInsertionPoint() const
258 {
259 long lPos = LONGFROMMR(::WinSendMsg( GetHwnd()
260 ,LM_QUERYSELECTION
261 ,(MPARAM)0
262 ,(MPARAM)0
263 ));
264 if (lPos == LIT_NONE)
265 return wxNOT_FOUND;
266 return lPos;
267 } // end of wxComboBox::GetInsertionPoint
268
269 long wxComboBox::GetLastPosition() const
270 {
271 HWND hEditWnd = GetHwnd();
272 long lLineLength = 0L;
273 WNDPARAMS vParams;
274
275 //
276 // Get number of characters in the last (only) line. We'll add this to the character
277 // index for the last line, 1st position.
278 //
279
280
281 vParams.fsStatus = WPM_CCHTEXT;
282 if (::WinSendMsg( GetHwnd()
283 ,WM_QUERYWINDOWPARAMS
284 ,&vParams
285 ,0
286 ))
287 {
288 lLineLength = (long)vParams.cchText;
289 }
290 else
291 lLineLength = 0L;
292 return lLineLength;
293 } // end of wxComboBox::GetLastPosition
294
295 void wxComboBox::Replace(
296 long lFrom
297 , long lTo
298 , const wxString& rsValue
299 )
300 {
301 #if wxUSE_CLIPBOARD
302 HWND hWnd = GetHwnd();
303 long lFromChar = lFrom;
304 long lToChar = lTo;
305
306 //
307 // Set selection and remove it
308 //
309 ::WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT((USHORT)lFrom, (USHORT)lTo), 0);
310 ::WinSendMsg(hWnd, EM_CUT, (MPARAM)0, (MPARAM)0);
311
312 //
313 // Now replace with 'value', by pasting.
314 //
315 wxSetClipboardData( wxDF_TEXT
316 ,(wxObject *)rsValue.c_str()
317 ,0
318 ,0
319 );
320
321 //
322 // Paste into edit control
323 //
324 ::WinSendMsg(hWnd, EM_PASTE, (MPARAM)0, (MPARAM)0L);
325 #endif
326 } // end of wxComboBox::Replace
327
328 void wxComboBox::Remove(
329 long lFrom
330 , long lTo
331 )
332 {
333 #if wxUSE_CLIPBOARD
334 HWND hWnd = GetHwnd();
335 long lFromChar = lFrom;
336 long lToChar = lTo;
337
338 ::WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT((USHORT)lFrom, (USHORT)lTo), 0);
339 ::WinSendMsg(hWnd, EM_CUT, (MPARAM)0, (MPARAM)0);
340 #endif
341 } // end of wxComboBox::Remove
342
343 void wxComboBox::SetSelection(
344 long lFrom
345 , long lTo
346 )
347 {
348 HWND hWnd = GetHwnd();
349 long lFromChar = lFrom;
350 long lToChar = lTo;
351
352 //
353 // If from and to are both -1, it means
354 // (in wxWindows) that all text should be selected.
355 // This translates into Windows convention
356 //
357 if ((lFrom == -1L) && (lTo == -1L))
358 {
359 lFromChar = 0;
360 lToChar = -1;
361 }
362
363 ::WinSendMsg( hWnd
364 ,EM_SETSEL
365 ,MPFROM2SHORT((USHORT)lFromChar, (USHORT)lToChar)
366 ,(MPARAM)0
367 );
368 } // end of wxComboBox::SetSelection
369
370 void wxComboBox::DoSetSize(
371 int nX
372 , int nY
373 , int nWidth
374 , int nHeight
375 , int nSizeFlags
376 )
377 {
378 wxControl::DoSetSize( nX
379 ,nY
380 ,nWidth
381 ,nHeight
382 ,nSizeFlags
383 );
384 } // end of wxComboBox::DoSetSize
385
386 bool wxComboBox::ProcessEditMsg(
387 WXUINT uMsg
388 , WXWPARAM wParam
389 , WXLPARAM lParam)
390 {
391 SHORT vFlag;
392 switch (uMsg)
393 {
394 case WM_CHAR:
395 vFlag = SHORT1FROMMP(wParam);
396 switch(vFlag)
397 {
398 case KC_CHAR:
399 return (HandleChar( SHORT1FROMMP(wParam)
400 ,lParam
401 ,TRUE /* isASCII */
402 ));
403
404 case KC_PREVDOWN:
405 return (HandleKeyDown( SHORT1FROMMP(wParam)
406 ,lParam
407 ));
408
409 case KC_KEYUP:
410 return (HandleKeyUp( SHORT1FROMMP(wParam)
411 ,lParam
412 ));
413 }
414 break;
415 }
416 return FALSE;
417 } // end of WinGuiBase_CComboBox::ProcessEditMsg
418
419 MRESULT EXPENTRY wxComboEditWndProc(
420 HWND hWnd
421 , UINT uMessage
422 , MPARAM wParam
423 , MPARAM lParam
424 )
425 {
426 HWND hWndCombo;
427 wxWindow* pWin = NULL;
428
429 hWndCombo = ::WinQueryWindow(hWnd, QW_PARENT);
430 pWin = (wxWindow*)wxFindWinFromHandle((WXHWND)hWndCombo);
431 switch (uMessage)
432 {
433 //
434 // Forward some messages to the combobox
435 //
436 case WM_CHAR:
437 {
438 wxComboBox* pCombo = wxDynamicCast( pWin
439 ,wxComboBox
440 );
441
442 if (pCombo->ProcessEditMsg( uMessage
443 ,wParam
444 ,lParam
445 ))
446 return ((MRESULT)0);
447 }
448 break;
449
450 //
451 // TODO: Deal with tooltips here
452 //
453 }
454 return (gfnWndprocEdit(hWnd, (ULONG)uMessage, (MPARAM)wParam, (MPARAM)lParam));
455 } // end of wxComboEditWndProc
456
457 #endif
458 // wxUSE_COMBOBOX
459