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