]> git.saurik.com Git - wxWidgets.git/blame - src/os2/radiobox.cpp
fix showing keyboard cues under Win2k/XP
[wxWidgets.git] / src / os2 / radiobox.cpp
CommitLineData
0e320a79
DW
1/////////////////////////////////////////////////////////////////////////////
2// Name: radiobox.cpp
3// Purpose: wxRadioBox
cdf1e714 4// Author: David Webster
0e320a79 5// Modified by:
cdf1e714 6// Created: 10/12/99
0e320a79 7// RCS-ID: $Id$
cdf1e714 8// Copyright: (c) David Webster
65571936 9// Licence: wxWindows licence
0e320a79
DW
10/////////////////////////////////////////////////////////////////////////////
11
cdf1e714
DW
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifndef WX_PRECOMP
16 #include <stdio.h>
17 #include "wx/setup.h"
b59c98dd
SN
18 #include "wx/wxchar.h"
19 #include "wx/string.h"
cdf1e714
DW
20 #include "wx/bitmap.h"
21 #include "wx/brush.h"
22 #include "wx/radiobox.h"
0e320a79
DW
23#endif
24
cdf1e714 25#include "wx/os2/private.h"
0e320a79 26
0e320a79 27IMPLEMENT_DYNAMIC_CLASS(wxRadioBox, wxControl)
0e320a79 28
cdf1e714
DW
29// ---------------------------------------------------------------------------
30// private functions
31// ---------------------------------------------------------------------------
32
33// wnd proc for radio buttons
3c299c3a
DW
34MRESULT EXPENTRY wxRadioBtnWndProc( HWND hWnd
35 ,UINT uMessage
36 ,MPARAM wParam
37 ,MPARAM lParam
38 );
f289196b
DW
39MRESULT EXPENTRY wxRadioBoxWndProc( HWND hWnd
40 ,UINT uMessage
41 ,MPARAM wParam
42 ,MPARAM lParam
43 );
cdf1e714
DW
44
45// ---------------------------------------------------------------------------
46// global vars
47// ---------------------------------------------------------------------------
48
49// the pointer to standard radio button wnd proc
f289196b
DW
50extern void wxAssociateWinWithHandle( HWND hWnd
51 ,wxWindowOS2* pWin
52 );
3c299c3a 53static WXFARPROC fnWndProcRadioBtn = NULL;
f289196b 54static WXFARPROC fnWndProcRadioBox = NULL;
cdf1e714
DW
55
56// ===========================================================================
57// implementation
58// ===========================================================================
59
60// ---------------------------------------------------------------------------
61// wxRadioBox
62// ---------------------------------------------------------------------------
63
3c299c3a
DW
64// Radio box item
65wxRadioBox::wxRadioBox()
0367c1c0 66{
3c299c3a
DW
67 m_nSelectedButton = -1;
68 m_nNoItems = 0;
69 m_nNoRowsOrCols = 0;
70 m_ahRadioButtons = NULL;
71 m_nMajorDim = 0;
72 m_pnRadioWidth = NULL;
73 m_pnRadioHeight = NULL;
74} // end of wxRadioBox::wxRadioBox
0367c1c0 75
3c299c3a 76wxRadioBox::~wxRadioBox()
0367c1c0 77{
1a87edf2 78 m_isBeingDeleted = true;
0367c1c0 79
3c299c3a 80 if (m_ahRadioButtons)
cdf1e714 81 {
3c299c3a
DW
82 int i;
83 for (i = 0; i < m_nNoItems; i++)
84 ::WinDestroyWindow((HWND)m_ahRadioButtons[i]);
85 delete[] m_ahRadioButtons;
cdf1e714 86 }
3c299c3a
DW
87 if (m_pnRadioWidth)
88 delete[] m_pnRadioWidth;
89 if (m_pnRadioHeight)
90 delete[] m_pnRadioHeight;
91} // end of wxRadioBox::~wxRadioBox
92
6670f564
WS
93void wxRadioBox::AdjustButtons( int nX,
94 int nY,
95 int nWidth,
96 int nHeight,
97 int WXUNUSED(nSizeFlags) )
cdf1e714 98{
6670f564
WS
99 wxSize vMaxSize;
100 int nXOffset = nX;
101 int nYOffset = nY + nHeight;
102 int nCx1;
103 int nCy1;
104 int nStartX;
105 int nStartY;
106 int nMaxWidth;
107 int nMaxHeight;
108 wxFont vFont = GetFont();
3c299c3a
DW
109
110 wxGetCharSize( m_hWnd
111 ,&nCx1
112 ,&nCy1
7804d121 113 ,&vFont
3c299c3a
DW
114 );
115 vMaxSize = GetMaxButtonSize();
116 nMaxWidth = vMaxSize.x;
117 nMaxHeight = vMaxSize.y;
118
119 nXOffset += nCx1;
120 nYOffset -= (nMaxHeight + ((3*nCy1)/2));
121
122 nStartX = nXOffset;
123 nStartY = nYOffset;
124
125 for (int i = 0; i < m_nNoItems; i++)
cdf1e714 126 {
3c299c3a
DW
127 //
128 // The last button in the row may be wider than the other ones as the
129 // radiobox may be wider than the sum of the button widths (as it
130 // happens, for example, when the radiobox label is very long)
131 //
132 bool bIsLastInTheRow;
133
134 if (m_windowStyle & wxRA_SPECIFY_COLS)
135 {
136 //
137 // Item is the last in its row if it is a multiple of the number of
138 // columns or if it is just the last item
139 //
140 int n = i + 1;
cdf1e714 141
3c299c3a
DW
142 bIsLastInTheRow = ((n % m_nMajorDim) == 0) || (n == m_nNoItems);
143 }
144 else // winRA_SPECIFY_ROWS
145 {
146 //
147 // Item is the last in the row if it is in the last columns
148 //
149 bIsLastInTheRow = i >= (m_nNoItems/m_nMajorDim) * m_nMajorDim;
150 }
cdf1e714 151
3c299c3a
DW
152 //
153 // Is this the start of new row/column?
154 //
155 if (i && (i % m_nMajorDim == 0))
cdf1e714 156 {
3c299c3a 157 if (m_windowStyle & wxRA_SPECIFY_ROWS)
cdf1e714 158 {
cdf1e714 159
3c299c3a
DW
160 //
161 // Start of new column
162 //
163 nYOffset = nStartY;
164 nXOffset += nMaxWidth + nCx1;
165 }
166 else // start of new row
167 {
168 nXOffset = nStartX;
169 nYOffset -= nMaxHeight;
170 if (m_pnRadioWidth[0] > 0L)
171 nYOffset -= nCy1/2;
cdf1e714
DW
172 }
173 }
174
3c299c3a 175 int nWidthBtn;
cdf1e714 176
3c299c3a 177 if (bIsLastInTheRow)
cdf1e714 178 {
3c299c3a
DW
179 //
180 // Make the button go to the end of radio box
181 //
182 nWidthBtn = nStartX + nWidth - nXOffset - (2 * nCx1);
183 if (nWidthBtn < nMaxWidth)
184 nWidthBtn = nMaxWidth;
185 }
186 else
187 {
188 //
189 // Normal button, always of the same size
190 //
191 nWidthBtn = nMaxWidth;
cdf1e714 192 }
cdf1e714 193
3c299c3a
DW
194 //
195 // Make all buttons of the same, maximal size - like this they
196 // cover the radiobox entirely and the radiobox tooltips are always
197 // shown (otherwise they are not when the mouse pointer is in the
198 // radiobox part not beYInt32ing to any radiobutton)
199 //
200 ::WinSetWindowPos( (HWND)m_ahRadioButtons[i]
201 ,HWND_TOP
202 ,(LONG)nXOffset
203 ,(LONG)nYOffset
204 ,(LONG)nWidthBtn
205 ,(LONG)nMaxHeight
206 ,SWP_ZORDER | SWP_SIZE | SWP_MOVE | SWP_SHOW
207 );
208 //
209 // Where do we put the next button?
210 //
211 if (m_windowStyle & wxRA_SPECIFY_ROWS)
212 {
213 //
214 // Below this one
215 //
216 nYOffset -= nMaxHeight;
217 if (m_pnRadioWidth[0] > 0)
218 nYOffset -= nCy1/2;
219 }
220 else
221 {
222 //
223 // To the right of this one
224 //
225 nXOffset += nWidthBtn + nCx1;
226 }
cdf1e714 227 }
3c299c3a 228} // end of wxRadioBox::AdjustButtons
cdf1e714 229
3c299c3a
DW
230void wxRadioBox::Command (
231 wxCommandEvent& rEvent
232)
233{
234 SetSelection (rEvent.GetInt());
235 ProcessCommand(rEvent);
236} // end of wxRadioBox::Command
cdf1e714 237
3c299c3a
DW
238bool wxRadioBox::ContainsHWND(
239 WXHWND hWnd
240) const
0e320a79 241{
3c299c3a
DW
242 size_t nCount = GetCount();
243 size_t i;
244
245 for (i = 0; i < nCount; i++)
246 {
247 if (GetRadioButtons()[i] == hWnd)
1a87edf2 248 return true;
3c299c3a 249 }
1a87edf2 250 return false;
3c299c3a
DW
251} // end of wxRadioBox::ContainsHWND
252
584ad2a3
MB
253bool wxRadioBox::Create(
254 wxWindow* pParent
255, wxWindowID vId
256, const wxString& rsTitle
257, const wxPoint& rPos
258, const wxSize& rSize
259, const wxArrayString& asChoices
260, int nMajorDim
261, long lStyle
262, const wxValidator& rVal
263, const wxString& rsName
264)
265{
41c54fac 266 wxCArrayString chs(asChoices);
584ad2a3
MB
267
268 return Create(pParent, vId, rsTitle, rPos, rSize, chs.GetCount(),
269 chs.GetStrings(), nMajorDim, lStyle, rVal, rsName);
270}
271
3c299c3a
DW
272bool wxRadioBox::Create(
273 wxWindow* pParent
274, wxWindowID vId
275, const wxString& rsTitle
276, const wxPoint& rPos
277, const wxSize& rSize
278, int nNum
279, const wxString asChoices[]
280, int nMajorDim
281, long lStyle
3c299c3a 282, const wxValidator& rVal
3c299c3a
DW
283, const wxString& rsName
284)
0e320a79 285{
3c299c3a
DW
286 wxColour vColour;
287 LONG lColor;
288
0fba44b4 289 vColour.Set(wxString(wxT("BLACK")));
b389a12d 290 m_backgroundColour = pParent->GetBackgroundColour();
3c299c3a 291 m_nSelectedButton = -1;
b389a12d 292 m_nNoItems = 0;
3c299c3a
DW
293
294 m_nMajorDim = nMajorDim == 0 ? nNum : nMajorDim;
295 m_nNoRowsOrCols = nMajorDim;
296
297 //
298 // Common initialization
299 //
b9b1d6c8
DW
300 if (!CreateControl( pParent
301 ,vId
302 ,rPos
303 ,rSize
304 ,lStyle
b9b1d6c8 305 ,rVal
b9b1d6c8
DW
306 ,rsName
307 ))
1a87edf2 308 return false;
0fba44b4 309 if (!OS2CreateControl( wxT("STATIC")
f289196b 310 ,SS_GROUPBOX
3c299c3a
DW
311 ,rPos
312 ,rSize
313 ,rsTitle
314 ))
1a87edf2 315 return false;
cdf1e714 316
f289196b 317 wxAssociateWinWithHandle(m_hWnd, this);
cdf1e714 318
3c299c3a 319 //
cdf1e714 320 // Some radio boxes test consecutive id.
3c299c3a 321 //
b389a12d 322 m_nNoItems = nNum;
cdf1e714 323 (void)NewControlId();
3c299c3a
DW
324 m_ahRadioButtons = new WXHWND[nNum];
325 m_pnRadioWidth = new int[nNum];
326 m_pnRadioHeight = new int[nNum];
327
3c299c3a 328 for (int i = 0; i < nNum; i++)
cdf1e714 329 {
3c299c3a
DW
330 m_pnRadioWidth[i] = m_pnRadioHeight[i] = -1;
331
332 long lStyleBtn = BS_AUTORADIOBUTTON | WS_TABSTOP | WS_VISIBLE;
333 int nNewId = NewControlId();
334
335 if (i == 0 && lStyle == 0)
336 lStyleBtn |= WS_GROUP;
337
338 HWND hWndBtn = (WXHWND)::WinCreateWindow ( GetHwndOf(pParent)
339 ,WC_BUTTON
0fba44b4 340 ,(PSZ)asChoices[i].c_str()
3c299c3a
DW
341 ,lStyleBtn
342 ,0, 0, 0, 0
343 ,GetWinHwnd(pParent)
344 ,HWND_TOP
345 ,(HMENU)nNewId
346 ,NULL
347 ,NULL
348 );
5d44b24e 349 lColor = (LONG)vColour.GetPixel();
3c299c3a
DW
350 ::WinSetPresParam( hWndBtn
351 ,PP_FOREGROUNDCOLOR
352 ,sizeof(LONG)
353 ,(PVOID)&lColor
354 );
5d44b24e
DW
355 lColor = (LONG)m_backgroundColour.GetPixel();
356
357 ::WinSetPresParam( hWndBtn
358 ,PP_BACKGROUNDCOLOR
359 ,sizeof(LONG)
360 ,(PVOID)&lColor
361 );
3c299c3a 362 if (!hWndBtn)
cdf1e714 363 {
1a87edf2 364 return false;
cdf1e714 365 }
3c299c3a
DW
366 m_ahRadioButtons[i] = (WXHWND)hWndBtn;
367 SubclassRadioButton((WXHWND)hWndBtn);
f289196b 368 wxAssociateWinWithHandle(hWndBtn, this);
3c299c3a 369 wxOS2SetFont( hWndBtn
f289196b 370 ,*wxSMALL_FONT
3c299c3a
DW
371 );
372 ::WinSetWindowULong(hWndBtn, QWL_USER, (ULONG)this);
373 m_aSubControls.Add(nNewId);
cdf1e714 374 }
0e320a79 375
3c299c3a 376 //
cdf1e714 377 // Create a dummy radio control to end the group.
3c299c3a
DW
378 //
379 (void)::WinCreateWindow ( GetHwndOf(pParent)
380 ,WC_BUTTON
381 ,""
382 ,WS_GROUP | BS_AUTORADIOBUTTON
383 ,0, 0, 0, 0
384 ,GetWinHwnd(pParent)
385 ,HWND_TOP
386 ,(HMENU)NewControlId()
387 ,NULL
388 ,NULL
389 );
f289196b
DW
390 SetFont(*wxSMALL_FONT);
391 fnWndProcRadioBox = (WXFARPROC)::WinSubclassWindow( GetHwnd()
392 ,(PFNWP)wxRadioBoxWndProc
393 );
394 ::WinSetWindowULong(GetHwnd(), QWL_USER, (ULONG)this);
5d44b24e 395 lColor = (LONG)vColour.GetPixel();
3c299c3a
DW
396 ::WinSetPresParam( m_hWnd
397 ,PP_FOREGROUNDCOLOR
398 ,sizeof(LONG)
399 ,(PVOID)&lColor
400 );
f289196b
DW
401 ::WinSetPresParam( m_hWnd
402 ,PP_BORDERDARKCOLOR
403 ,sizeof(LONG)
404 ,(PVOID)&lColor
405 );
5d44b24e
DW
406 lColor = (LONG)m_backgroundColour.GetPixel();
407
408 ::WinSetPresParam( m_hWnd
409 ,PP_BACKGROUNDCOLOR
410 ,sizeof(LONG)
411 ,(PVOID)&lColor
412 );
f289196b
DW
413 ::WinSetPresParam( m_hWnd
414 ,PP_BORDERLIGHTCOLOR
415 ,sizeof(LONG)
416 ,(PVOID)&lColor
417 );
b389a12d
DW
418 SetXComp(0);
419 SetYComp(0);
cdf1e714 420 SetSelection(0);
3c299c3a
DW
421 SetSize( rPos.x
422 ,rPos.y
423 ,rSize.x
424 ,rSize.y
425 );
1a87edf2 426 return true;
3c299c3a 427} // end of wxRadioBox::Create
0e320a79 428
3c299c3a 429wxSize wxRadioBox::DoGetBestSize() const
0e320a79 430{
3c299c3a
DW
431 return (GetTotalButtonSize(GetMaxButtonSize()));
432} // end of WinGuiBase_CRadioBox::DoGetBestSize
433
434void wxRadioBox::DoSetSize(
435 int nX
436, int nY
437, int nWidth
438, int nHeight
439, int nSizeFlags
440)
441{
442 int nCurrentX;
443 int nCurrentY;
444 int nWidthOld;
445 int nHeightOld;
446 int nXx = nX;
447 int nYy = nY;
448#if RADIOBTN_PARENT_IS_RADIOBOX
449 int nXOffset = 0;
450 int nYOffset = 0;
451#else
452 int nXOffset = nXx;
453 int nYOffset = nYy;
454#endif
455 int nCx1;
456 int nCy1;
457 wxSize vMaxSize = GetMaxButtonSize();
458 int nMaxWidth;
459 int nMaxHeight;
460 wxSize vTotSize;
461 int nTotWidth;
462 int nTotHeight;
463 int nStartX;
464 int nStartY;
7804d121 465 wxFont vFont = GetFont();
3c299c3a
DW
466
467 m_nSizeFlags = nSizeFlags;
468 GetPosition( &nCurrentX
469 ,&nCurrentY
470 );
471 GetSize( &nWidthOld
472 ,&nHeightOld
473 );
474
fa50c0e3 475 if (nX == wxDefaultCoord && !(nSizeFlags & wxSIZE_ALLOW_MINUS_ONE))
3c299c3a 476 nXx = nCurrentX;
fa50c0e3 477 if (nY == wxDefaultCoord && !(nSizeFlags & wxSIZE_ALLOW_MINUS_ONE))
3c299c3a 478 nYy = nCurrentY;
b389a12d
DW
479 if (nYy < 0)
480 nYy = 0;
481 if (nXx < 0)
482 nXx = 0;
3c299c3a
DW
483
484 wxGetCharSize( m_hWnd
485 ,&nCx1
486 ,&nCy1
7804d121 487 ,&vFont
3c299c3a
DW
488 );
489
490 //
491 // Attempt to have a look coherent with other platforms: We compute the
492 // biggest toggle dim, then we align all items according this value.
493 //
494 vMaxSize = GetMaxButtonSize();
495 nMaxWidth = vMaxSize.x;
496 nMaxHeight = vMaxSize.y;
497
498 vTotSize = GetTotalButtonSize(vMaxSize);
499 nTotWidth = vTotSize.x;
500 nTotHeight = vTotSize.y;
501
502 //
503 // Only change our width/height if asked for
504 //
505 if (nWidth == -1)
506 {
507 if (nSizeFlags & wxSIZE_AUTO_WIDTH )
508 nWidth = nTotWidth;
509 else
510 nWidth = nWidthOld;
511 }
cdf1e714 512
3c299c3a 513 if (nHeight == -1)
cdf1e714 514 {
3c299c3a
DW
515 if (nSizeFlags & wxSIZE_AUTO_HEIGHT)
516 nHeight = nTotHeight;
517 else
518 nHeight = nHeightOld;
cdf1e714
DW
519 }
520
3c299c3a 521 wxWindowOS2* pParent = (wxWindowOS2*)GetParent();
cdf1e714 522
3c299c3a
DW
523 if (pParent)
524 {
d8a3f66c
DW
525 int nOS2Height = GetOS2ParentHeight(pParent);
526
527 nYy = nOS2Height - (nYy + nHeight);
3c299c3a
DW
528 nYOffset = nYy + nHeight;
529 }
530 else
531 {
532 RECTL vRect;
0e320a79 533
3c299c3a
DW
534 ::WinQueryWindowRect(HWND_DESKTOP, &vRect);
535 nYy = vRect.yTop - (nYy + nHeight);
536 }
537 ::WinSetWindowPos( GetHwnd()
538 ,HWND_TOP
539 ,(LONG)nXx
540 ,(LONG)nYy
541 ,(LONG)nWidth
542 ,(LONG)nHeight
543 ,SWP_ZORDER | SWP_SIZE | SWP_MOVE | SWP_SHOW
544 );
545
546 //
547 // Now position all the buttons: the current button will be put at
548 // wxPoint(x_offset, y_offset) and the new row/column will start at
549 // startX/startY. The size of all buttons will be the same wxSize(maxWidth,
550 // maxHeight) except for the buttons in the last column which should extend
551 // to the right border of radiobox and thus can be wider than this.
552 //
553 // Also, remember that wxRA_SPECIFY_COLS means that we arrange buttons in
554 // left to right order and m_majorDim is the number of columns while
555 // wxRA_SPECIFY_ROWS means that the buttons are arranged top to bottom and
556 // m_majorDim is the number of rows.
557 //
558 nXOffset += nCx1;
559 nYOffset -= (nMaxHeight + ((3*nCy1)/2));
560
561 nStartX = nXOffset;
562 nStartY = nYOffset;
563
564 for (int i = 0; i < m_nNoItems; i++)
565 {
566 //
567 // The last button in the row may be wider than the other ones as the
568 // radiobox may be wider than the sum of the button widths (as it
569 // happens, for example, when the radiobox label is very long)
570 //
571 bool bIsLastInTheRow;
572
573 if (m_windowStyle & wxRA_SPECIFY_COLS)
574 {
575 //
576 // Item is the last in its row if it is a multiple of the number of
577 // columns or if it is just the last item
578 //
579 int n = i + 1;
0367c1c0 580
3c299c3a
DW
581 bIsLastInTheRow = ((n % m_nMajorDim) == 0) || (n == m_nNoItems);
582 }
583 else // winRA_SPECIFY_ROWS
584 {
585 //
586 // Item is the last in the row if it is in the last columns
587 //
588 bIsLastInTheRow = i >= (m_nNoItems/m_nMajorDim) * m_nMajorDim;
589 }
0367c1c0 590
3c299c3a
DW
591 //
592 // Is this the start of new row/column?
593 //
594 if (i && (i % m_nMajorDim == 0))
595 {
596 if (m_windowStyle & wxRA_SPECIFY_ROWS)
597 {
598
599 //
600 // Start of new column
601 //
602 nYOffset = nStartY;
603 nXOffset += nMaxWidth + nCx1;
604 }
605 else // start of new row
606 {
607 nXOffset = nStartX;
608 nYOffset -= nMaxHeight;
609 if (m_pnRadioWidth[0] > 0L)
610 nYOffset -= nCy1/2;
611 }
612 }
613
614 int nWidthBtn;
615
616 if (bIsLastInTheRow)
617 {
618 //
619 // Make the button go to the end of radio box
620 //
621 nWidthBtn = nStartX + nWidth - nXOffset - (2 * nCx1);
622 if (nWidthBtn < nMaxWidth)
623 nWidthBtn = nMaxWidth;
624 }
625 else
626 {
627 //
628 // Normal button, always of the same size
629 //
630 nWidthBtn = nMaxWidth;
631 }
cdf1e714 632
3c299c3a
DW
633 //
634 // Make all buttons of the same, maximal size - like this they
635 // cover the radiobox entirely and the radiobox tooltips are always
636 // shown (otherwise they are not when the mouse pointer is in the
637 // radiobox part not beinting to any radiobutton)
638 //
639 ::WinSetWindowPos( (HWND)m_ahRadioButtons[i]
640 ,HWND_TOP
641 ,(LONG)nXOffset
642 ,(LONG)nYOffset
643 ,(LONG)nWidthBtn
644 ,(LONG)nMaxHeight
645 ,SWP_ZORDER | SWP_SIZE | SWP_MOVE | SWP_SHOW
646 );
647 //
648 // Where do we put the next button?
649 //
650 if (m_windowStyle & wxRA_SPECIFY_ROWS)
651 {
652 //
653 // Below this one
654 //
655 nYOffset -= nMaxHeight;
656 if (m_pnRadioWidth[0] > 0)
657 nYOffset -= nCy1/2;
658 }
659 else
660 {
661 //
662 // To the right of this one
663 //
664 nXOffset += nWidthBtn + nCx1;
665 }
666 }
667} // end of wxRadioBox::DoSetSize
0e320a79 668
1a87edf2 669bool wxRadioBox::Enable(int nItem, bool bEnable)
0e320a79 670{
fa50c0e3 671 wxCHECK_MSG( IsValid(nItem), false,
3c299c3a 672 wxT("invalid item in wxRadioBox::Enable()") );
cdf1e714 673
3c299c3a 674 ::WinEnableWindow((HWND) m_ahRadioButtons[nItem], bEnable);
1a87edf2 675 return true;
3c299c3a 676} // end of wxRadioBox::Enable
0e320a79 677
3c299c3a
DW
678bool wxRadioBox::Enable(
679 bool bEnable
680)
0e320a79 681{
3c299c3a 682 if ( !wxControl::Enable(bEnable) )
1a87edf2 683 return false;
3c299c3a
DW
684 for (int i = 0; i < m_nNoItems; i++)
685 ::WinEnableWindow((HWND)m_ahRadioButtons[i], bEnable);
1a87edf2 686 return true;
3c299c3a 687} // end of wxRadioBox::Enable
0e320a79 688
3c299c3a
DW
689int wxRadioBox::FindString(
690 const wxString& rsStr
691) const
0e320a79 692{
3c299c3a 693 for (int i = 0; i < m_nNoItems; i++)
cdf1e714 694 {
3c299c3a 695 if (rsStr == wxGetWindowText(m_ahRadioButtons[i]) )
cdf1e714
DW
696 return i;
697 }
cdf1e714 698 return wxNOT_FOUND;
3c299c3a 699} // end of wxRadioBox::FindString
cdf1e714 700
3c299c3a 701int wxRadioBox::GetColumnCount() const
0e320a79 702{
3c299c3a
DW
703 return GetNumHor();
704} // end of wxRadioBox::GetColumnCount
0e320a79 705
3c299c3a 706int wxRadioBox::GetCount() const
0e320a79 707{
3c299c3a
DW
708 return m_nNoItems;
709} // end of wxRadioBox::GetCount
0e320a79 710
3c299c3a
DW
711wxString wxRadioBox::GetLabel(
712 int nItem
713) const
0e320a79 714{
fa50c0e3 715 wxCHECK_MSG( IsValid(nItem), wxEmptyString, wxT("invalid radiobox index") );
cdf1e714 716
3c299c3a
DW
717 return wxGetWindowText(m_ahRadioButtons[nItem]);
718} // end of wxRadioBox::GetLabel
cdf1e714 719
3c299c3a
DW
720wxSize wxRadioBox::GetMaxButtonSize() const
721{
722 int nWidthMax = 0;
723 int nHeightMax = 0;
cdf1e714 724
3c299c3a 725 for (int i = 0 ; i < m_nNoItems; i++)
cdf1e714 726 {
3c299c3a
DW
727 int nWidth;
728 int nHeight;
729
730 if (m_pnRadioWidth[i] < 0L)
cdf1e714 731 {
3c299c3a
DW
732 GetTextExtent( wxGetWindowText(m_ahRadioButtons[i])
733 ,&nWidth
734 ,&nHeight
735 );
736
737 //
738 // Adjust the size to take into account the radio box itself
739 // FIXME this is totally bogus!
740 //
741 nWidth += RADIO_SIZE;
742 nHeight *= 3;
743 nHeight /= 2;
cdf1e714
DW
744 }
745 else
746 {
3c299c3a
DW
747 nWidth = m_pnRadioWidth[i];
748 nHeight = m_pnRadioHeight[i];
cdf1e714 749 }
3c299c3a
DW
750 if (nWidthMax < nWidth )
751 nWidthMax = nWidth;
752 if (nHeightMax < nHeight )
753 nHeightMax = nHeight;
754 }
6670f564
WS
755 wxSize maxsize( nWidthMax, nHeightMax);
756 return maxsize;
3c299c3a 757} // end of wxRadioBox::GetMaxButtonSize
cdf1e714 758
3c299c3a
DW
759int wxRadioBox::GetNumHor() const
760{
761 if ( m_windowStyle & wxRA_SPECIFY_ROWS )
762 {
763 return (m_nNoItems + m_nMajorDim - 1)/m_nMajorDim;
764 }
765 else
766 {
767 return m_nMajorDim;
768 }
769} // end of wxRadioBox::GetNumHor
770
771int wxRadioBox::GetNumVer() const
772{
773 if ( m_windowStyle & wxRA_SPECIFY_ROWS )
774 {
775 return m_nMajorDim;
cdf1e714 776 }
3c299c3a
DW
777 else
778 {
779 return (m_nNoItems + m_nMajorDim - 1)/m_nMajorDim;
780 }
781} // end of wxRadioBox::GetNumVer
cdf1e714 782
6670f564
WS
783void wxRadioBox::GetPosition( int* pnX,
784 int* WXUNUSED(pnY) ) const
3c299c3a
DW
785{
786 wxWindowOS2* pParent = GetParent();
d0ee33f5 787 RECT vRect = { -1, -1, -1, -1 };
3c299c3a
DW
788 POINTL vPoint;
789 int i;
790
791 for (i = 0; i < m_nNoItems; i++)
792 wxFindMaxSize( m_ahRadioButtons[i]
793 ,&vRect
794 );
cdf1e714 795 if (m_hWnd)
3c299c3a
DW
796 wxFindMaxSize( m_hWnd
797 ,&vRect
798 );
799
800 //
801 // Since we now have the absolute screen coords, if there's a parent we
802 // must subtract its top left corner
803 //
804 vPoint.x = vRect.xLeft;
805 vPoint.y = vRect.yTop;
806 if (pParent)
cdf1e714 807 {
3c299c3a 808 SWP vSwp;
cdf1e714 809
3c299c3a
DW
810 ::WinQueryWindowPos((HWND)pParent->GetHWND(), &vSwp);
811 vPoint.x = vSwp.x;
812 vPoint.y = vSwp.y;
813 }
cdf1e714 814
3c299c3a
DW
815 //
816 // We may be faking the client origin. So a window that's really at (0, 30)
817 // may appear (to wxWin apps) to be at (0, 0).
818 //
819 if (GetParent())
820 {
821 wxPoint vPt(GetParent()->GetClientAreaOrigin());
cdf1e714 822
3c299c3a
DW
823 vPoint.x = vPt.x;
824 vPoint.y = vPt.y;
825 }
826 *pnX = vPoint.x;
827 *pnX = vPoint.y;
828} // end of wxRadioBox::GetPosition
cdf1e714 829
3c299c3a
DW
830int wxRadioBox::GetRowCount() const
831{
832 return GetNumVer();
833} // end of wxRadioBox::GetRowCount
cdf1e714 834
3c299c3a
DW
835// Get single selection, for single choice list items
836int wxRadioBox::GetSelection() const
837{
838 return m_nSelectedButton;
839} // end of wxRadioBox::GetSelection
cdf1e714 840
3c299c3a
DW
841void wxRadioBox::GetSize(
842 int* pnWidth
843, int* pnHeight
844) const
845{
846 RECT vRect;
847 int i;
cdf1e714 848
3c299c3a
DW
849 vRect.xLeft = -1;
850 vRect.xRight = -1;
851 vRect.yTop = -1;
852 vRect.yBottom = -1;
853
854 if (m_hWnd)
855 wxFindMaxSize( m_hWnd
856 ,&vRect
857 );
858
859 for (i = 0; i < m_nNoItems; i++)
860 wxFindMaxSize( m_ahRadioButtons[i]
861 ,&vRect
862 );
863
a00ffdf1
SN
864 if (pnWidth)
865 *pnWidth = vRect.xRight - vRect.xLeft;
866 if (pnHeight)
867 *pnHeight = vRect.yTop - vRect.yBottom;
3c299c3a 868} // end of wxRadioBox::GetSize
cdf1e714 869
3c299c3a
DW
870// Find string for position
871wxString wxRadioBox::GetString(
872 int nNum
873) const
874{
875 return wxGetWindowText(m_ahRadioButtons[nNum]);
876} // end of wxRadioBox::GetString
877
878// For single selection items only
879wxString wxRadioBox::GetStringSelection() const
880{
881 wxString sResult;
882 int nSel = GetSelection();
883
884 if (nSel > -1)
885 sResult = GetString(nSel);
886 return sResult;
887} // end of wxRadioBox::GetStringSelection
888
6670f564 889wxSize wxRadioBox::GetTotalButtonSize( const wxSize& rSizeBtn ) const
3c299c3a 890{
6670f564
WS
891 int nCx1;
892 int nCy1;
893 int nExtraHeight;
894 int nHeight;
895 int nWidth;
896 int nWidthLabel;
897 wxFont vFont = GetFont();
898
899 wxGetCharSize( m_hWnd, &nCx1, &nCy1, &vFont );
3c299c3a
DW
900 nExtraHeight = nCy1;
901
902 nHeight = GetNumVer() * rSizeBtn.y + (2 * nCy1);
903 nWidth = GetNumHor() * (rSizeBtn.x + nCx1) + nCx1;
904
905 //
906 // And also wide enough for its label
907 //
908 GetTextExtent( GetTitle()
909 ,&nWidthLabel
910 ,NULL
911 );
912 nWidthLabel += RADIO_SIZE;
913 if (nWidthLabel > nWidth)
914 nWidth = nWidthLabel;
915
6670f564
WS
916 wxSize total( nWidth, nHeight );
917 return total;
3c299c3a
DW
918} // end of wxRadioBox::GetTotalButtonSize
919
6670f564
WS
920WXHBRUSH wxRadioBox::OnCtlColor( WXHDC hwinDC,
921 WXHWND WXUNUSED(hWnd),
922 WXUINT WXUNUSED(uCtlColor),
923 WXUINT WXUNUSED(uMessage),
924 WXWPARAM WXUNUSED(wParam),
925 WXLPARAM WXUNUSED(lParam) )
3c299c3a 926{
6670f564 927 HPS hPS = (HPS)hwinDC; // pass in a PS handle in OS/2
3c299c3a
DW
928
929 if (GetParent()->GetTransparentBackground())
930 ::GpiSetBackMix(hPS, BM_LEAVEALONE);
931 else
932 ::GpiSetBackMix(hPS, BM_OVERPAINT);
933
6670f564 934 wxColour vColBack = GetBackgroundColour();
cdf1e714 935
3c299c3a
DW
936 ::GpiSetBackColor(hPS, vColBack.GetPixel());
937 ::GpiSetColor(hPS, vColBack.GetPixel());
938
6670f564 939 wxBrush* pBrush = wxTheBrushList->FindOrCreateBrush( vColBack, wxSOLID );
3c299c3a
DW
940 return ((WXHBRUSH)pBrush->GetResourceHandle());
941} // end of wxRadioBox::OnCtlColor
942
6670f564
WS
943bool wxRadioBox::OS2Command( WXUINT uCmd,
944 WXWORD wId)
3c299c3a 945{
6670f564 946 int nSelectedButton = -1;
3c299c3a
DW
947
948 if (uCmd == BN_CLICKED)
cdf1e714 949 {
3c299c3a 950 if (wId == GetId())
1a87edf2 951 return true;
3c299c3a
DW
952
953
954 for (int i = 0; i < m_nNoItems; i++)
cdf1e714 955 {
3c299c3a 956 if (wId == wxGetWindowId(m_ahRadioButtons[i]))
cdf1e714 957 {
3c299c3a
DW
958 nSelectedButton = i;
959 break;
cdf1e714
DW
960 }
961 }
3c299c3a 962 if (nSelectedButton == -1)
cdf1e714 963 {
3c299c3a 964 //
f289196b
DW
965 // Just ignore it
966 //
1a87edf2 967 return false;
cdf1e714 968 }
3c299c3a 969 if (nSelectedButton != m_nSelectedButton)
cdf1e714 970 {
3c299c3a
DW
971 m_nSelectedButton = nSelectedButton;
972 SendNotificationEvent();
cdf1e714 973 }
1a87edf2 974 return true;
cdf1e714 975 }
3c299c3a 976 else
1a87edf2 977 return false;
3c299c3a 978} // end of wxRadioBox::OS2Command
0e320a79 979
3c299c3a 980void wxRadioBox::SendNotificationEvent()
0e320a79 981{
3c299c3a
DW
982 wxCommandEvent vEvent( wxEVT_COMMAND_RADIOBOX_SELECTED
983 ,m_windowId
984 );
cdf1e714 985
3c299c3a
DW
986 vEvent.SetInt( m_nSelectedButton );
987 vEvent.SetString( GetString(m_nSelectedButton) );
988 vEvent.SetEventObject(this);
989 ProcessCommand(vEvent);
990} // end of wxRadioBox::SendNotificationEvent
0e320a79
DW
991
992void wxRadioBox::SetFocus()
993{
3c299c3a 994 if (m_nNoItems > 0)
cdf1e714 995 {
3c299c3a
DW
996 if (m_nSelectedButton == -1)
997 ::WinSetFocus(HWND_DESKTOP, (HWND)m_ahRadioButtons[0]);
cdf1e714 998 else
3c299c3a 999 ::WinSetFocus(HWND_DESKTOP, (HWND)m_ahRadioButtons[m_nSelectedButton]);
cdf1e714 1000 }
3c299c3a 1001} // end of wxRadioBox::SetFocus
0e320a79 1002
3c299c3a
DW
1003bool wxRadioBox::SetFont(
1004 const wxFont& rFont
1005)
0e320a79 1006{
3c299c3a
DW
1007 if (!wxControl::SetFont(rFont))
1008 {
1009 //
1010 // Nothing to do
1011 //
1a87edf2 1012 return false;
3c299c3a
DW
1013 }
1014 //
1015 // Also set the font of our radio buttons
1016 //
3c299c3a 1017 for (int n = 0; n < (int)m_nNoItems; n++)
cdf1e714 1018 {
3c299c3a 1019 HWND hWndBtn = (HWND)m_ahRadioButtons[n];
cdf1e714 1020
3c299c3a
DW
1021 wxOS2SetFont( hWndBtn
1022 ,rFont
1023 );
1024 ::WinInvalidateRect(hWndBtn, NULL, FALSE);
1025 }
1a87edf2 1026 return true;
3c299c3a 1027} // end of wxRadioBox::SetFont
0e320a79 1028
3c299c3a
DW
1029void wxRadioBox::SetSelection(
1030 int nNum
1031)
0e320a79 1032{
fa50c0e3 1033 wxCHECK_RET( IsValid(nNum), wxT("invalid radiobox index") );
cdf1e714 1034
fa50c0e3 1035 if ( IsValid(m_nSelectedButton) )
3c299c3a 1036 ::WinSendMsg((HWND)m_ahRadioButtons[m_nSelectedButton], BM_SETCHECK, (MPARAM)0, (MPARAM)0);
0e320a79 1037
3c299c3a
DW
1038 ::WinSendMsg((HWND)m_ahRadioButtons[nNum], BM_SETCHECK, (MPARAM)1, (MPARAM)0);
1039 ::WinSetFocus(HWND_DESKTOP, (HWND)m_ahRadioButtons[nNum]);
1040 m_nSelectedButton = nNum;
1041} // end of wxRadioBox::SetSelection
0e320a79 1042
3c299c3a
DW
1043void wxRadioBox::SetString(
1044 int nItem
1045, const wxString& rsLabel
1046)
0e320a79 1047{
fa50c0e3 1048 wxCHECK_RET( IsValid(nItem), wxT("invalid radiobox index") );
cdf1e714 1049
3c299c3a 1050 m_pnRadioWidth[nItem] = m_pnRadioHeight[nItem] = -1;
0fba44b4 1051 ::WinSetWindowText((HWND)m_ahRadioButtons[nItem], (PSZ)rsLabel.c_str());
3c299c3a 1052} // end of wxRadioBox::SetString
cdf1e714 1053
3c299c3a
DW
1054bool wxRadioBox::SetStringSelection(
1055 const wxString& rsStr
1056)
cdf1e714 1057{
3c299c3a 1058 int nSel = FindString(rsStr);
0e320a79 1059
3c299c3a 1060 if (nSel > -1)
0e320a79 1061 {
3c299c3a 1062 SetSelection(nSel);
1a87edf2 1063 return true;
0e320a79
DW
1064 }
1065 else
1a87edf2 1066 return false;
3c299c3a 1067} // end of wxRadioBox::SetStringSelection
0e320a79 1068
3c299c3a
DW
1069bool wxRadioBox::Show(
1070 bool bShow
1071)
cdf1e714 1072{
3c299c3a 1073 if (!wxControl::Show(bShow))
1a87edf2 1074 return false;
3c299c3a
DW
1075
1076 for (int i = 0; i < m_nNoItems; i++)
cdf1e714 1077 {
3c299c3a 1078 ::WinShowWindow((HWND)m_ahRadioButtons[i], (BOOL)bShow);
cdf1e714 1079 }
1a87edf2 1080 return true;
3c299c3a 1081} // end of wxRadioBox::Show
cdf1e714 1082
3c299c3a 1083// Show a specific button
fa50c0e3 1084bool wxRadioBox::Show(
3c299c3a
DW
1085 int nItem
1086, bool bShow
1087)
0e320a79 1088{
fa50c0e3 1089 wxCHECK_MSG( IsValid(nItem), false,
3c299c3a 1090 wxT("invalid item in wxRadioBox::Show()") );
0e320a79 1091
3c299c3a 1092 ::WinShowWindow((HWND)m_ahRadioButtons[nItem], bShow);
fa50c0e3
WS
1093
1094 return true;
3c299c3a 1095} // end of wxRadioBox::Show
cdf1e714 1096
3c299c3a
DW
1097void wxRadioBox::SubclassRadioButton(
1098 WXHWND hWndBtn
1099)
1100{
3c299c3a
DW
1101 fnWndProcRadioBtn = (WXFARPROC)::WinSubclassWindow(hWndBtn, (PFNWP)wxRadioBtnWndProc);
1102} // end of wxRadioBox::SubclassRadioButton
cdf1e714 1103
3c299c3a
DW
1104MRESULT wxRadioBox::WindowProc(
1105 WXUINT uMsg
1106, WXWPARAM wParam
1107, WXLPARAM lParam
1108)
cdf1e714 1109{
3c299c3a
DW
1110 return (wxControl::OS2WindowProc( uMsg
1111 ,wParam
1112 ,lParam
1113 ));
1114} // end of wxRadioBox::WindowProc
cdf1e714
DW
1115
1116// ---------------------------------------------------------------------------
1117// window proc for radio buttons
1118// ---------------------------------------------------------------------------
1119
3c299c3a
DW
1120MRESULT wxRadioBtnWndProc(
1121 HWND hWnd
1122, UINT uMessage
1123, MPARAM wParam
1124, MPARAM lParam
1125)
cdf1e714 1126{
3c299c3a 1127 switch (uMessage)
cdf1e714 1128 {
3c299c3a
DW
1129 case WM_CHAR:
1130 {
1131 USHORT uKeyFlags = SHORT1FROMMP((MPARAM)wParam);
cdf1e714 1132
3c299c3a 1133 if (!(uKeyFlags & KC_KEYUP)) // Key Down event
cdf1e714 1134 {
3c299c3a
DW
1135 if (uKeyFlags & KC_VIRTUALKEY)
1136 {
1137 wxRadioBox* pRadiobox = (wxRadioBox *)::WinQueryWindowULong( hWnd
1138 ,QWL_USER
1139 );
1140 USHORT uVk = SHORT2FROMMP((MPARAM)lParam);
1a87edf2 1141 bool bProcessed = true;
3c299c3a
DW
1142 wxDirection eDir;
1143
1144 switch(uVk)
1145 {
1146 case VK_LEFT:
1147 eDir = wxDOWN;
1148 break;
1149
1150 case VK_RIGHT:
1151 eDir = wxDOWN;
1152 break;
1153
1154 case VK_DOWN:
1155 eDir = wxDOWN;
1156 break;
1157
1158 case VK_UP:
1159 eDir = wxUP;
1160 break;
1161
1162 default:
1a87edf2 1163 bProcessed = false;
3c299c3a
DW
1164
1165 //
1166 // Just to suppress the compiler warning
1167 //
1168 eDir = wxALL;
1169 }
1170
1171 if (bProcessed)
1172 {
1173 int nSelOld = pRadiobox->GetSelection();
1174 int nSelNew = pRadiobox->GetNextItem( nSelOld
1175 ,eDir
1176 ,pRadiobox->GetWindowStyleFlag()
1177 );
1178
1179 if (nSelNew != nSelOld)
1180 {
1181 pRadiobox->SetSelection(nSelNew);
1182
1183 //
1184 // Emulate the button click
1185 //
1186 pRadiobox->SendNotificationEvent();
1187 return 0;
1188 }
1189 }
1190 }
cdf1e714 1191 }
cdf1e714 1192 }
3c299c3a 1193 break;
cdf1e714
DW
1194 }
1195
3c299c3a
DW
1196 return fnWndProcRadioBtn( hWnd
1197 ,(ULONG)uMessage
1198 ,(MPARAM)wParam
1199 ,(MPARAM)lParam
1200 );
1201} // end of wxRadioBtnWndProc
0e320a79 1202
f289196b
DW
1203MRESULT EXPENTRY wxRadioBoxWndProc(
1204 HWND hWnd
1205, UINT uMessage
1206, MPARAM wParam
1207, MPARAM lParam
1208)
1209{
1210 return (fnWndProcRadioBox( hWnd
1211 ,(ULONG)uMessage
1212 ,(MPARAM)wParam
1213 ,(MPARAM)lParam
1214 )
1215 );
1216} // end of wxRadioBoxWndProc