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