]> git.saurik.com Git - wxWidgets.git/blame - src/os2/radiobox.cpp
added stipple opaque mask detection
[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
DW
8// Copyright: (c) David Webster
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 );
cdf1e714
DW
39
40// ---------------------------------------------------------------------------
41// global vars
42// ---------------------------------------------------------------------------
43
44// the pointer to standard radio button wnd proc
3c299c3a 45static WXFARPROC fnWndProcRadioBtn = NULL;
cdf1e714
DW
46
47// ===========================================================================
48// implementation
49// ===========================================================================
50
51// ---------------------------------------------------------------------------
52// wxRadioBox
53// ---------------------------------------------------------------------------
54
3c299c3a
DW
55// Radio box item
56wxRadioBox::wxRadioBox()
0367c1c0 57{
3c299c3a
DW
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
0367c1c0 66
3c299c3a 67wxRadioBox::~wxRadioBox()
0367c1c0 68{
3c299c3a 69 m_isBeingDeleted = TRUE;
0367c1c0 70
3c299c3a 71 if (m_ahRadioButtons)
cdf1e714 72 {
3c299c3a
DW
73 int i;
74 for (i = 0; i < m_nNoItems; i++)
75 ::WinDestroyWindow((HWND)m_ahRadioButtons[i]);
76 delete[] m_ahRadioButtons;
cdf1e714 77 }
3c299c3a
DW
78 if (m_pnRadioWidth)
79 delete[] m_pnRadioWidth;
80 if (m_pnRadioHeight)
81 delete[] m_pnRadioHeight;
82} // end of wxRadioBox::~wxRadioBox
83
84void wxRadioBox::AdjustButtons(
85 int nX
86, int nY
87, int nWidth
88, int nHeight
d8a3f66c 89, int nSizeFlags
3c299c3a 90)
cdf1e714 91{
3c299c3a
DW
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++)
cdf1e714 120 {
3c299c3a
DW
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;
cdf1e714 135
3c299c3a
DW
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 }
cdf1e714 145
3c299c3a
DW
146 //
147 // Is this the start of new row/column?
148 //
149 if (i && (i % m_nMajorDim == 0))
cdf1e714 150 {
3c299c3a 151 if (m_windowStyle & wxRA_SPECIFY_ROWS)
cdf1e714 152 {
cdf1e714 153
3c299c3a
DW
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;
cdf1e714
DW
166 }
167 }
168
3c299c3a 169 int nWidthBtn;
cdf1e714 170
3c299c3a 171 if (bIsLastInTheRow)
cdf1e714 172 {
3c299c3a
DW
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;
cdf1e714 186 }
cdf1e714 187
3c299c3a
DW
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 }
cdf1e714 221 }
3c299c3a 222} // end of wxRadioBox::AdjustButtons
cdf1e714 223
3c299c3a
DW
224void wxRadioBox::Command (
225 wxCommandEvent& rEvent
226)
227{
228 SetSelection (rEvent.GetInt());
229 ProcessCommand(rEvent);
230} // end of wxRadioBox::Command
cdf1e714 231
3c299c3a
DW
232bool wxRadioBox::ContainsHWND(
233 WXHWND hWnd
234) const
0e320a79 235{
3c299c3a
DW
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
247bool 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
5d4b632b 257#if wxUSE_VALIDATORS
3c299c3a 258, const wxValidator& rVal
5d4b632b 259#endif
3c299c3a
DW
260, const wxString& rsName
261)
0e320a79 262{
3c299c3a
DW
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
5d4b632b 287#if wxUSE_VALIDATORS
3c299c3a 288 ,rVal
5d4b632b 289#endif
3c299c3a
DW
290 ,rsName
291 ))
0e320a79 292
0e320a79 293
cdf1e714 294
0e320a79 295
3c299c3a
DW
296 if (!OS2CreateControl( "STATIC"
297 ,SS_GROUPBOX | WS_GROUP
298 ,rPos
299 ,rSize
300 ,rsTitle
301 ))
cdf1e714 302
3c299c3a
DW
303#if RADIOBTN_PARENT_IS_RADIOBOX
304 HWND hWndParent = GetHwnd();
305#else
306 HWND hWndParent = GetHwndOf(pParent);
307#endif
308 HFONT hFont;
cdf1e714 309
3c299c3a 310 //
cdf1e714 311 // Some radio boxes test consecutive id.
3c299c3a 312 //
cdf1e714 313 (void)NewControlId();
3c299c3a
DW
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++)
cdf1e714 324 {
3c299c3a
DW
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)
cdf1e714 350 {
3c299c3a 351 return FALSE;
cdf1e714 352 }
3c299c3a
DW
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);
cdf1e714 360 }
0e320a79 361
3c299c3a 362 //
cdf1e714 363 // Create a dummy radio control to end the group.
3c299c3a
DW
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 );
cdf1e714 382 SetSelection(0);
3c299c3a
DW
383 SetSize( rPos.x
384 ,rPos.y
385 ,rSize.x
386 ,rSize.y
387 );
cdf1e714 388 return TRUE;
3c299c3a 389} // end of wxRadioBox::Create
0e320a79 390
3c299c3a 391wxSize wxRadioBox::DoGetBestSize() const
0e320a79 392{
3c299c3a
DW
393 return (GetTotalButtonSize(GetMaxButtonSize()));
394} // end of WinGuiBase_CRadioBox::DoGetBestSize
395
396void 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 }
cdf1e714 470
3c299c3a 471 if (nHeight == -1)
cdf1e714 472 {
3c299c3a
DW
473 if (nSizeFlags & wxSIZE_AUTO_HEIGHT)
474 nHeight = nTotHeight;
475 else
476 nHeight = nHeightOld;
cdf1e714
DW
477 }
478
3c299c3a 479 wxWindowOS2* pParent = (wxWindowOS2*)GetParent();
cdf1e714 480
3c299c3a
DW
481 if (pParent)
482 {
d8a3f66c
DW
483 int nOS2Height = GetOS2ParentHeight(pParent);
484
485 nYy = nOS2Height - (nYy + nHeight);
3c299c3a
DW
486 nYOffset = nYy + nHeight;
487 }
488 else
489 {
490 RECTL vRect;
0e320a79 491
3c299c3a
DW
492 ::WinQueryWindowRect(HWND_DESKTOP, &vRect);
493 nYy = vRect.yTop - (nYy + nHeight);
494 }
495 ::WinSetWindowPos( GetHwnd()
496 ,HWND_TOP
497 ,(LONG)nXx
498 ,(LONG)nYy
499 ,(LONG)nWidth
500 ,(LONG)nHeight
501 ,SWP_ZORDER | SWP_SIZE | SWP_MOVE | SWP_SHOW
502 );
503
504 //
505 // Now position all the buttons: the current button will be put at
506 // wxPoint(x_offset, y_offset) and the new row/column will start at
507 // startX/startY. The size of all buttons will be the same wxSize(maxWidth,
508 // maxHeight) except for the buttons in the last column which should extend
509 // to the right border of radiobox and thus can be wider than this.
510 //
511 // Also, remember that wxRA_SPECIFY_COLS means that we arrange buttons in
512 // left to right order and m_majorDim is the number of columns while
513 // wxRA_SPECIFY_ROWS means that the buttons are arranged top to bottom and
514 // m_majorDim is the number of rows.
515 //
516 nXOffset += nCx1;
517 nYOffset -= (nMaxHeight + ((3*nCy1)/2));
518
519 nStartX = nXOffset;
520 nStartY = nYOffset;
521
522 for (int i = 0; i < m_nNoItems; i++)
523 {
524 //
525 // The last button in the row may be wider than the other ones as the
526 // radiobox may be wider than the sum of the button widths (as it
527 // happens, for example, when the radiobox label is very long)
528 //
529 bool bIsLastInTheRow;
530
531 if (m_windowStyle & wxRA_SPECIFY_COLS)
532 {
533 //
534 // Item is the last in its row if it is a multiple of the number of
535 // columns or if it is just the last item
536 //
537 int n = i + 1;
0367c1c0 538
3c299c3a
DW
539 bIsLastInTheRow = ((n % m_nMajorDim) == 0) || (n == m_nNoItems);
540 }
541 else // winRA_SPECIFY_ROWS
542 {
543 //
544 // Item is the last in the row if it is in the last columns
545 //
546 bIsLastInTheRow = i >= (m_nNoItems/m_nMajorDim) * m_nMajorDim;
547 }
0367c1c0 548
3c299c3a
DW
549 //
550 // Is this the start of new row/column?
551 //
552 if (i && (i % m_nMajorDim == 0))
553 {
554 if (m_windowStyle & wxRA_SPECIFY_ROWS)
555 {
556
557 //
558 // Start of new column
559 //
560 nYOffset = nStartY;
561 nXOffset += nMaxWidth + nCx1;
562 }
563 else // start of new row
564 {
565 nXOffset = nStartX;
566 nYOffset -= nMaxHeight;
567 if (m_pnRadioWidth[0] > 0L)
568 nYOffset -= nCy1/2;
569 }
570 }
571
572 int nWidthBtn;
573
574 if (bIsLastInTheRow)
575 {
576 //
577 // Make the button go to the end of radio box
578 //
579 nWidthBtn = nStartX + nWidth - nXOffset - (2 * nCx1);
580 if (nWidthBtn < nMaxWidth)
581 nWidthBtn = nMaxWidth;
582 }
583 else
584 {
585 //
586 // Normal button, always of the same size
587 //
588 nWidthBtn = nMaxWidth;
589 }
cdf1e714 590
3c299c3a
DW
591 //
592 // Make all buttons of the same, maximal size - like this they
593 // cover the radiobox entirely and the radiobox tooltips are always
594 // shown (otherwise they are not when the mouse pointer is in the
595 // radiobox part not beinting to any radiobutton)
596 //
597 ::WinSetWindowPos( (HWND)m_ahRadioButtons[i]
598 ,HWND_TOP
599 ,(LONG)nXOffset
600 ,(LONG)nYOffset
601 ,(LONG)nWidthBtn
602 ,(LONG)nMaxHeight
603 ,SWP_ZORDER | SWP_SIZE | SWP_MOVE | SWP_SHOW
604 );
605 //
606 // Where do we put the next button?
607 //
608 if (m_windowStyle & wxRA_SPECIFY_ROWS)
609 {
610 //
611 // Below this one
612 //
613 nYOffset -= nMaxHeight;
614 if (m_pnRadioWidth[0] > 0)
615 nYOffset -= nCy1/2;
616 }
617 else
618 {
619 //
620 // To the right of this one
621 //
622 nXOffset += nWidthBtn + nCx1;
623 }
624 }
625} // end of wxRadioBox::DoSetSize
0e320a79 626
3c299c3a
DW
627void wxRadioBox::Enable(
628 int nItem
629, bool bEnable
630)
0e320a79 631{
3c299c3a
DW
632 wxCHECK_RET( nItem >= 0 && nItem < m_nNoItems,
633 wxT("invalid item in wxRadioBox::Enable()") );
cdf1e714 634
3c299c3a
DW
635 ::WinEnableWindow((HWND) m_ahRadioButtons[nItem], bEnable);
636} // end of wxRadioBox::Enable
0e320a79 637
3c299c3a
DW
638bool wxRadioBox::Enable(
639 bool bEnable
640)
0e320a79 641{
3c299c3a
DW
642 if ( !wxControl::Enable(bEnable) )
643 return FALSE;
644 for (int i = 0; i < m_nNoItems; i++)
645 ::WinEnableWindow((HWND)m_ahRadioButtons[i], bEnable);
646 return TRUE;
647} // end of wxRadioBox::Enable
0e320a79 648
3c299c3a
DW
649int wxRadioBox::FindString(
650 const wxString& rsStr
651) const
0e320a79 652{
3c299c3a 653 for (int i = 0; i < m_nNoItems; i++)
cdf1e714 654 {
3c299c3a 655 if (rsStr == wxGetWindowText(m_ahRadioButtons[i]) )
cdf1e714
DW
656 return i;
657 }
cdf1e714 658 return wxNOT_FOUND;
3c299c3a 659} // end of wxRadioBox::FindString
cdf1e714 660
3c299c3a 661int wxRadioBox::GetColumnCount() const
0e320a79 662{
3c299c3a
DW
663 return GetNumHor();
664} // end of wxRadioBox::GetColumnCount
0e320a79 665
3c299c3a 666int wxRadioBox::GetCount() const
0e320a79 667{
3c299c3a
DW
668 return m_nNoItems;
669} // end of wxRadioBox::GetCount
0e320a79 670
3c299c3a
DW
671wxString wxRadioBox::GetLabel(
672 int nItem
673) const
0e320a79 674{
3c299c3a 675 wxCHECK_MSG(nItem >= 0 && nItem < m_nNoItems, wxT(""), wxT("invalid radiobox index") );
cdf1e714 676
3c299c3a
DW
677 return wxGetWindowText(m_ahRadioButtons[nItem]);
678} // end of wxRadioBox::GetLabel
cdf1e714 679
3c299c3a
DW
680wxSize wxRadioBox::GetMaxButtonSize() const
681{
682 int nWidthMax = 0;
683 int nHeightMax = 0;
cdf1e714 684
3c299c3a 685 for (int i = 0 ; i < m_nNoItems; i++)
cdf1e714 686 {
3c299c3a
DW
687 int nWidth;
688 int nHeight;
689
690 if (m_pnRadioWidth[i] < 0L)
cdf1e714 691 {
3c299c3a
DW
692 GetTextExtent( wxGetWindowText(m_ahRadioButtons[i])
693 ,&nWidth
694 ,&nHeight
695 );
696
697 //
698 // Adjust the size to take into account the radio box itself
699 // FIXME this is totally bogus!
700 //
701 nWidth += RADIO_SIZE;
702 nHeight *= 3;
703 nHeight /= 2;
cdf1e714
DW
704 }
705 else
706 {
3c299c3a
DW
707 nWidth = m_pnRadioWidth[i];
708 nHeight = m_pnRadioHeight[i];
cdf1e714 709 }
3c299c3a
DW
710 if (nWidthMax < nWidth )
711 nWidthMax = nWidth;
712 if (nHeightMax < nHeight )
713 nHeightMax = nHeight;
714 }
715 return(wxSize( nWidthMax
716 ,nHeightMax
717 )
718 );
719} // end of wxRadioBox::GetMaxButtonSize
cdf1e714 720
3c299c3a
DW
721int wxRadioBox::GetNumHor() const
722{
723 if ( m_windowStyle & wxRA_SPECIFY_ROWS )
724 {
725 return (m_nNoItems + m_nMajorDim - 1)/m_nMajorDim;
726 }
727 else
728 {
729 return m_nMajorDim;
730 }
731} // end of wxRadioBox::GetNumHor
732
733int wxRadioBox::GetNumVer() const
734{
735 if ( m_windowStyle & wxRA_SPECIFY_ROWS )
736 {
737 return m_nMajorDim;
cdf1e714 738 }
3c299c3a
DW
739 else
740 {
741 return (m_nNoItems + m_nMajorDim - 1)/m_nMajorDim;
742 }
743} // end of wxRadioBox::GetNumVer
cdf1e714 744
3c299c3a
DW
745void wxRadioBox::GetPosition(
746 int* pnX
747, int* pnY
748) const
749{
750 wxWindowOS2* pParent = GetParent();
751 RECT vRect = { -1, -1, -1, -1 };;
752 POINTL vPoint;
753 int i;
754
755 for (i = 0; i < m_nNoItems; i++)
756 wxFindMaxSize( m_ahRadioButtons[i]
757 ,&vRect
758 );
cdf1e714 759 if (m_hWnd)
3c299c3a
DW
760 wxFindMaxSize( m_hWnd
761 ,&vRect
762 );
763
764 //
765 // Since we now have the absolute screen coords, if there's a parent we
766 // must subtract its top left corner
767 //
768 vPoint.x = vRect.xLeft;
769 vPoint.y = vRect.yTop;
770 if (pParent)
cdf1e714 771 {
3c299c3a 772 SWP vSwp;
cdf1e714 773
3c299c3a
DW
774 ::WinQueryWindowPos((HWND)pParent->GetHWND(), &vSwp);
775 vPoint.x = vSwp.x;
776 vPoint.y = vSwp.y;
777 }
cdf1e714 778
3c299c3a
DW
779 //
780 // We may be faking the client origin. So a window that's really at (0, 30)
781 // may appear (to wxWin apps) to be at (0, 0).
782 //
783 if (GetParent())
784 {
785 wxPoint vPt(GetParent()->GetClientAreaOrigin());
cdf1e714 786
3c299c3a
DW
787 vPoint.x = vPt.x;
788 vPoint.y = vPt.y;
789 }
790 *pnX = vPoint.x;
791 *pnX = vPoint.y;
792} // end of wxRadioBox::GetPosition
cdf1e714 793
3c299c3a
DW
794int wxRadioBox::GetRowCount() const
795{
796 return GetNumVer();
797} // end of wxRadioBox::GetRowCount
cdf1e714 798
3c299c3a
DW
799// Get single selection, for single choice list items
800int wxRadioBox::GetSelection() const
801{
802 return m_nSelectedButton;
803} // end of wxRadioBox::GetSelection
cdf1e714 804
3c299c3a
DW
805void wxRadioBox::GetSize(
806 int* pnWidth
807, int* pnHeight
808) const
809{
810 RECT vRect;
811 int i;
cdf1e714 812
3c299c3a
DW
813 vRect.xLeft = -1;
814 vRect.xRight = -1;
815 vRect.yTop = -1;
816 vRect.yBottom = -1;
817
818 if (m_hWnd)
819 wxFindMaxSize( m_hWnd
820 ,&vRect
821 );
822
823 for (i = 0; i < m_nNoItems; i++)
824 wxFindMaxSize( m_ahRadioButtons[i]
825 ,&vRect
826 );
827
828 *pnWidth = vRect.xRight - vRect.xLeft;
829 *pnHeight = vRect.yBottom - vRect.yTop;
830} // end of wxRadioBox::GetSize
cdf1e714 831
3c299c3a
DW
832// Find string for position
833wxString wxRadioBox::GetString(
834 int nNum
835) const
836{
837 return wxGetWindowText(m_ahRadioButtons[nNum]);
838} // end of wxRadioBox::GetString
839
840// For single selection items only
841wxString wxRadioBox::GetStringSelection() const
842{
843 wxString sResult;
844 int nSel = GetSelection();
845
846 if (nSel > -1)
847 sResult = GetString(nSel);
848 return sResult;
849} // end of wxRadioBox::GetStringSelection
850
851wxSize wxRadioBox::GetTotalButtonSize(
852 const wxSize& rSizeBtn
853) const
854{
855 int nCx1;
856 int nCy1;
857 int nExtraHeight;
858 int nHeight;
859 int nWidth;
860 int nWidthLabel;
861
862 wxGetCharSize( m_hWnd
863 ,&nCx1
864 ,&nCy1
865 ,(wxFont*)&GetFont()
866 );
867 nExtraHeight = nCy1;
868
869 nHeight = GetNumVer() * rSizeBtn.y + (2 * nCy1);
870 nWidth = GetNumHor() * (rSizeBtn.x + nCx1) + nCx1;
871
872 //
873 // And also wide enough for its label
874 //
875 GetTextExtent( GetTitle()
876 ,&nWidthLabel
877 ,NULL
878 );
879 nWidthLabel += RADIO_SIZE;
880 if (nWidthLabel > nWidth)
881 nWidth = nWidthLabel;
882
883 return(wxSize( nWidth
884 ,nHeight
885 )
886 );
887} // end of wxRadioBox::GetTotalButtonSize
888
889WXHBRUSH wxRadioBox::OnCtlColor(
890 WXHDC hwinDC
891, WXHWND hWnd
892, WXUINT uCtlColor
893, WXUINT uMessage
894, WXWPARAM wParam
895, WXLPARAM lParam
896)
897{
898 HPS hPS = (HPS)hwinDC; // pass in a PS handle in OS/2
899
900 if (GetParent()->GetTransparentBackground())
901 ::GpiSetBackMix(hPS, BM_LEAVEALONE);
902 else
903 ::GpiSetBackMix(hPS, BM_OVERPAINT);
904
905 wxColour vColBack = GetBackgroundColour();
cdf1e714 906
3c299c3a
DW
907 ::GpiSetBackColor(hPS, vColBack.GetPixel());
908 ::GpiSetColor(hPS, vColBack.GetPixel());
909
910
911 wxBrush* pBrush = wxTheBrushList->FindOrCreateBrush( vColBack
912 ,wxSOLID
913 );
914 return ((WXHBRUSH)pBrush->GetResourceHandle());
915} // end of wxRadioBox::OnCtlColor
916
917bool wxRadioBox::OS2Command(
918 WXUINT uCmd
919, WXWORD wId
920)
921{
922 int nSelectedButton = -1;
923
924 if (uCmd == BN_CLICKED)
cdf1e714 925 {
3c299c3a
DW
926 if (wId == GetId())
927 return TRUE;
928
929
930 for (int i = 0; i < m_nNoItems; i++)
cdf1e714 931 {
3c299c3a 932 if (wId == wxGetWindowId(m_ahRadioButtons[i]))
cdf1e714 933 {
3c299c3a
DW
934 nSelectedButton = i;
935 break;
cdf1e714
DW
936 }
937 }
3c299c3a 938 if (nSelectedButton == -1)
cdf1e714 939 {
3c299c3a
DW
940 //
941 // Just ignore it - due to a hack with WM_NCHITTEST handling in our
942 // wnd proc, we can receive dummy click messages when we click near
943 // the radiobox edge (this is ugly but Julian wouldn't let me get
944 // rid of this...)
945 return FALSE;
cdf1e714 946 }
3c299c3a 947 if (nSelectedButton != m_nSelectedButton)
cdf1e714 948 {
3c299c3a
DW
949 m_nSelectedButton = nSelectedButton;
950 SendNotificationEvent();
cdf1e714 951 }
3c299c3a 952 return TRUE;
cdf1e714 953 }
3c299c3a
DW
954 else
955 return FALSE;
956} // end of wxRadioBox::OS2Command
0e320a79 957
3c299c3a 958void wxRadioBox::SendNotificationEvent()
0e320a79 959{
3c299c3a
DW
960 wxCommandEvent vEvent( wxEVT_COMMAND_RADIOBOX_SELECTED
961 ,m_windowId
962 );
cdf1e714 963
3c299c3a
DW
964 vEvent.SetInt( m_nSelectedButton );
965 vEvent.SetString( GetString(m_nSelectedButton) );
966 vEvent.SetEventObject(this);
967 ProcessCommand(vEvent);
968} // end of wxRadioBox::SendNotificationEvent
0e320a79
DW
969
970void wxRadioBox::SetFocus()
971{
3c299c3a 972 if (m_nNoItems > 0)
cdf1e714 973 {
3c299c3a
DW
974 if (m_nSelectedButton == -1)
975 ::WinSetFocus(HWND_DESKTOP, (HWND)m_ahRadioButtons[0]);
cdf1e714 976 else
3c299c3a 977 ::WinSetFocus(HWND_DESKTOP, (HWND)m_ahRadioButtons[m_nSelectedButton]);
cdf1e714 978 }
3c299c3a 979} // end of wxRadioBox::SetFocus
0e320a79 980
3c299c3a
DW
981bool wxRadioBox::SetFont(
982 const wxFont& rFont
983)
0e320a79 984{
3c299c3a
DW
985 if (!wxControl::SetFont(rFont))
986 {
987 //
988 // Nothing to do
989 //
cdf1e714 990 return FALSE;
3c299c3a
DW
991 }
992 //
993 // Also set the font of our radio buttons
994 //
995 WXHFONT hFont = wxFont(rFont).GetResourceHandle();
cdf1e714 996
3c299c3a 997 for (int n = 0; n < (int)m_nNoItems; n++)
cdf1e714 998 {
3c299c3a 999 HWND hWndBtn = (HWND)m_ahRadioButtons[n];
cdf1e714 1000
3c299c3a
DW
1001 wxOS2SetFont( hWndBtn
1002 ,rFont
1003 );
1004 ::WinInvalidateRect(hWndBtn, NULL, FALSE);
1005 }
cdf1e714 1006 return TRUE;
3c299c3a 1007} // end of wxRadioBox::SetFont
0e320a79 1008
3c299c3a
DW
1009void wxRadioBox::SetSelection(
1010 int nNum
1011)
0e320a79 1012{
3c299c3a 1013 wxCHECK_RET( (nNum >= 0) && (nNum < m_nNoItems), wxT("invalid radiobox index") );
cdf1e714 1014
3c299c3a
DW
1015 if (m_nSelectedButton >= 0 && m_nSelectedButton < m_nNoItems)
1016 ::WinSendMsg((HWND)m_ahRadioButtons[m_nSelectedButton], BM_SETCHECK, (MPARAM)0, (MPARAM)0);
0e320a79 1017
3c299c3a
DW
1018 ::WinSendMsg((HWND)m_ahRadioButtons[nNum], BM_SETCHECK, (MPARAM)1, (MPARAM)0);
1019 ::WinSetFocus(HWND_DESKTOP, (HWND)m_ahRadioButtons[nNum]);
1020 m_nSelectedButton = nNum;
1021} // end of wxRadioBox::SetSelection
0e320a79 1022
3c299c3a
DW
1023void wxRadioBox::SetString(
1024 int nItem
1025, const wxString& rsLabel
1026)
0e320a79 1027{
3c299c3a 1028 wxCHECK_RET( nItem >= 0 && nItem < m_nNoItems, wxT("invalid radiobox index") );
cdf1e714 1029
3c299c3a
DW
1030 m_pnRadioWidth[nItem] = m_pnRadioHeight[nItem] = -1;
1031 ::WinSetWindowText((HWND)m_ahRadioButtons[nItem], rsLabel.c_str());
1032} // end of wxRadioBox::SetString
cdf1e714 1033
3c299c3a
DW
1034bool wxRadioBox::SetStringSelection(
1035 const wxString& rsStr
1036)
cdf1e714 1037{
3c299c3a 1038 int nSel = FindString(rsStr);
0e320a79 1039
3c299c3a 1040 if (nSel > -1)
0e320a79 1041 {
3c299c3a 1042 SetSelection(nSel);
0e320a79
DW
1043 return TRUE;
1044 }
1045 else
1046 return FALSE;
3c299c3a 1047} // end of wxRadioBox::SetStringSelection
0e320a79 1048
3c299c3a
DW
1049bool wxRadioBox::Show(
1050 bool bShow
1051)
cdf1e714 1052{
3c299c3a
DW
1053 int nCmdShow = 0;
1054
1055 if (!wxControl::Show(bShow))
1056 return FALSE;
1057
1058 for (int i = 0; i < m_nNoItems; i++)
cdf1e714 1059 {
3c299c3a 1060 ::WinShowWindow((HWND)m_ahRadioButtons[i], (BOOL)bShow);
cdf1e714 1061 }
3c299c3a
DW
1062 return TRUE;
1063} // end of wxRadioBox::Show
cdf1e714 1064
3c299c3a
DW
1065// Show a specific button
1066void wxRadioBox::Show(
1067 int nItem
1068, bool bShow
1069)
0e320a79 1070{
3c299c3a
DW
1071 wxCHECK_RET( nItem >= 0 && nItem < m_nNoItems,
1072 wxT("invalid item in wxRadioBox::Show()") );
0e320a79 1073
3c299c3a
DW
1074 ::WinShowWindow((HWND)m_ahRadioButtons[nItem], bShow);
1075} // end of wxRadioBox::Show
cdf1e714 1076
3c299c3a
DW
1077void wxRadioBox::SubclassRadioButton(
1078 WXHWND hWndBtn
1079)
1080{
1081 HWND hwndBtn = (HWND)hWndBtn;
cdf1e714 1082
3c299c3a
DW
1083 fnWndProcRadioBtn = (WXFARPROC)::WinSubclassWindow(hWndBtn, (PFNWP)wxRadioBtnWndProc);
1084} // end of wxRadioBox::SubclassRadioButton
cdf1e714 1085
3c299c3a
DW
1086MRESULT wxRadioBox::WindowProc(
1087 WXUINT uMsg
1088, WXWPARAM wParam
1089, WXLPARAM lParam
1090)
cdf1e714 1091{
3c299c3a
DW
1092 return (wxControl::OS2WindowProc( uMsg
1093 ,wParam
1094 ,lParam
1095 ));
1096} // end of wxRadioBox::WindowProc
cdf1e714
DW
1097
1098// ---------------------------------------------------------------------------
1099// window proc for radio buttons
1100// ---------------------------------------------------------------------------
1101
3c299c3a
DW
1102MRESULT wxRadioBtnWndProc(
1103 HWND hWnd
1104, UINT uMessage
1105, MPARAM wParam
1106, MPARAM lParam
1107)
cdf1e714 1108{
3c299c3a 1109 switch (uMessage)
cdf1e714 1110 {
3c299c3a
DW
1111 case WM_CHAR:
1112 {
1113 USHORT uKeyFlags = SHORT1FROMMP((MPARAM)wParam);
cdf1e714 1114
3c299c3a 1115 if (!(uKeyFlags & KC_KEYUP)) // Key Down event
cdf1e714 1116 {
3c299c3a
DW
1117 if (uKeyFlags & KC_VIRTUALKEY)
1118 {
1119 wxRadioBox* pRadiobox = (wxRadioBox *)::WinQueryWindowULong( hWnd
1120 ,QWL_USER
1121 );
1122 USHORT uVk = SHORT2FROMMP((MPARAM)lParam);
1123 bool bProcessed = TRUE;
1124 wxDirection eDir;
1125
1126 switch(uVk)
1127 {
1128 case VK_LEFT:
1129 eDir = wxDOWN;
1130 break;
1131
1132 case VK_RIGHT:
1133 eDir = wxDOWN;
1134 break;
1135
1136 case VK_DOWN:
1137 eDir = wxDOWN;
1138 break;
1139
1140 case VK_UP:
1141 eDir = wxUP;
1142 break;
1143
1144 default:
1145 bProcessed = FALSE;
1146
1147 //
1148 // Just to suppress the compiler warning
1149 //
1150 eDir = wxALL;
1151 }
1152
1153 if (bProcessed)
1154 {
1155 int nSelOld = pRadiobox->GetSelection();
1156 int nSelNew = pRadiobox->GetNextItem( nSelOld
1157 ,eDir
1158 ,pRadiobox->GetWindowStyleFlag()
1159 );
1160
1161 if (nSelNew != nSelOld)
1162 {
1163 pRadiobox->SetSelection(nSelNew);
1164
1165 //
1166 // Emulate the button click
1167 //
1168 pRadiobox->SendNotificationEvent();
1169 return 0;
1170 }
1171 }
1172 }
cdf1e714 1173 }
cdf1e714 1174 }
3c299c3a 1175 break;
cdf1e714
DW
1176 }
1177
3c299c3a
DW
1178 return fnWndProcRadioBtn( hWnd
1179 ,(ULONG)uMessage
1180 ,(MPARAM)wParam
1181 ,(MPARAM)lParam
1182 );
1183} // end of wxRadioBtnWndProc
0e320a79 1184