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